VirtualBox

source: kBuild/trunk/src/kmk/kmkbuiltin.c@ 2060

Last change on this file since 2060 was 2019, checked in by bird, 16 years ago

GPLv2 -> GPLv3. See Ticket #44 for clarifications. Fixes #44.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/* $Id: kmkbuiltin.c 2019 2008-11-02 00:21:05Z bird $ */
2/** @file
3 * kMk Builtin command execution.
4 */
5
6/*
7 * Copyright (c) 2005-2008 knut st. osmundsen <[email protected]>
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
23 *
24 */
25
26/*******************************************************************************
27* Header Files *
28*******************************************************************************/
29#include <string.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <ctype.h>
33#include <assert.h>
34#ifdef _MSC_VER
35# include <io.h>
36#endif
37#include "kmkbuiltin/err.h"
38#include "kmkbuiltin.h"
39
40#ifndef _MSC_VER
41extern char **environ;
42#endif
43
44int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
45{
46 int argc;
47 char **argv;
48 int rc;
49
50 /*
51 * Check and skip the prefix.
52 */
53 if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
54 {
55 printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
56 return 1;
57 }
58
59 /*
60 * Parse arguments.
61 */
62 argc = 0;
63 argv = NULL;
64 while (*pszCmd)
65 {
66 const char *pszEnd;
67 const char *pszNext;
68 int fEscaped = 0;
69 size_t cch;
70
71 /*
72 * Find start and end of the current command.
73 */
74 if (*pszCmd == '"' || *pszCmd == '\'')
75 {
76 pszEnd = pszCmd;
77 for (;;)
78 {
79 pszEnd = strchr(pszEnd + 1, *pszCmd);
80 if (!pszEnd)
81 {
82 printf("kmk_builtin: Unbalanced quote in argument %d: %s\n", argc + 1, pszCmd);
83 while (argc--)
84 free(argv[argc]);
85 free(argv);
86 return 1;
87 }
88 /* two quotes -> escaped quote. */
89 if (pszEnd[0] != pszEnd[1])
90 break;
91 fEscaped = 1;
92 }
93 pszNext = pszEnd + 1;
94 pszCmd++;
95 }
96 else
97 {
98 pszEnd = pszCmd;
99 while (!isspace(*pszEnd) && *pszEnd)
100 pszEnd++;
101 pszNext = pszEnd;
102 }
103
104 /*
105 * Make argument.
106 */
107 if (!(argc % 16))
108 {
109 void *pv = realloc(argv, sizeof(char *) * (argc + 17));
110 if (!pv)
111 {
112 printf("kmk_builtin: out of memory. argc=%d\n", argc);
113 break;
114 }
115 argv = (char **)pv;
116 }
117 cch = pszEnd - pszCmd;
118 argv[argc] = malloc(cch + 1);
119 if (!argv[argc])
120 {
121 printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, pszEnd - pszCmd + 1);
122 break;
123 }
124 memcpy(argv[argc], pszCmd, cch);
125 argv[argc][cch] = '\0';
126
127 /* unescape quotes? */
128 if (fEscaped)
129 {
130 char ch = pszCmd[-1];
131 char *pszW = argv[argc];
132 char *pszR = argv[argc];
133 while (*pszR)
134 {
135 if (*pszR == ch)
136 pszR++;
137 *pszW++ = *pszR++;
138 }
139 *pszW = '\0';
140 }
141 /* commit it */
142 argv[++argc] = NULL;
143
144 /*
145 * Next
146 */
147 pszCmd = pszNext;
148 if (isspace(*pszCmd) && *pszCmd)
149 pszCmd++;
150 }
151
152 /*
153 * Execute the command if parsing was successful.
154 */
155 if (!*pszCmd)
156 rc = kmk_builtin_command_parsed(argc, argv, ppapszArgvToSpawn, pPidSpawned);
157 else
158 rc = 1;
159
160 /* clean up and return. */
161 while (argc--)
162 free(argv[argc]);
163 free(argv);
164 return rc;
165}
166
167
168int kmk_builtin_command_parsed(int argc, char **argv, char ***ppapszArgvToSpawn, pid_t *pPidSpawned)
169{
170 const char *pszCmd = argv[0];
171 int iumask;
172 int rc;
173
174 /*
175 * Check and skip the prefix.
176 */
177 if (strncmp(pszCmd, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
178 {
179 printf("kmk_builtin: Invalid command prefix '%s'!\n", pszCmd);
180 return 1;
181 }
182 pszCmd += sizeof("kmk_builtin_") - 1;
183
184 /*
185 * String switch on the command.
186 */
187 iumask = umask(0);
188 umask(iumask);
189 if (!strcmp(pszCmd, "append"))
190 rc = kmk_builtin_append(argc, argv, environ);
191 else if (!strcmp(pszCmd, "printf"))
192 rc = kmk_builtin_printf(argc, argv, environ);
193 else if (!strcmp(pszCmd, "echo"))
194 rc = kmk_builtin_echo(argc, argv, environ);
195 else if (!strcmp(pszCmd, "install"))
196 rc = kmk_builtin_install(argc, argv, environ);
197 else if (!strcmp(pszCmd, "kDepIDB"))
198 rc = kmk_builtin_kDepIDB(argc, argv, environ);
199 else if (!strcmp(pszCmd, "mkdir"))
200 rc = kmk_builtin_mkdir(argc, argv, environ);
201 else if (!strcmp(pszCmd, "mv"))
202 rc = kmk_builtin_mv(argc, argv, environ);
203 /*else if (!strcmp(pszCmd, "redirect"))
204 rc = kmk_builtin_redirect(argc, argv, environ, pPidSpawned);*/
205 else if (!strcmp(pszCmd, "rm"))
206 rc = kmk_builtin_rm(argc, argv, environ);
207 else if (!strcmp(pszCmd, "rmdir"))
208 rc = kmk_builtin_rmdir(argc, argv, environ);
209 else if (!strcmp(pszCmd, "test"))
210 rc = kmk_builtin_test(argc, argv, environ, ppapszArgvToSpawn);
211 /* rarely used commands: */
212 else if (!strcmp(pszCmd, "chmod"))
213 rc = kmk_builtin_chmod(argc, argv, environ);
214 else if (!strcmp(pszCmd, "cp"))
215 rc = kmk_builtin_cp(argc, argv, environ);
216 else if (!strcmp(pszCmd, "expr"))
217 rc = kmk_builtin_expr(argc, argv, environ);
218 else if (!strcmp(pszCmd, "ln"))
219 rc = kmk_builtin_ln(argc, argv, environ);
220 else if (!strcmp(pszCmd, "md5sum"))
221 rc = kmk_builtin_md5sum(argc, argv, environ);
222 else if (!strcmp(pszCmd, "cmp"))
223 rc = kmk_builtin_cmp(argc, argv, environ);
224 else if (!strcmp(pszCmd, "cat"))
225 rc = kmk_builtin_cat(argc, argv, environ);
226 else if (!strcmp(pszCmd, "sleep"))
227 rc = kmk_builtin_sleep(argc, argv, environ);
228 else
229 {
230 printf("kmk_builtin: Unknown command '%s'!\n", pszCmd);
231 return 1;
232 }
233
234 /*
235 * Cleanup.
236 */
237 g_progname = "kmk"; /* paranoia, make sure it's not pointing at a freed argv[0]. */
238 umask(iumask);
239
240
241 /*
242 * If we've executed a conditional test or something that wishes to execute
243 * some child process, check if the child is a kmk_builtin thing. We recurse
244 * here, both because I'm lazy and because it's easier to debug a problem then
245 * (the call stack shows what's been going on).
246 */
247 if ( !rc
248 && *ppapszArgvToSpawn
249 && !strncmp(**ppapszArgvToSpawn, "kmk_builtin_", sizeof("kmk_builtin_") - 1))
250 {
251 char **argv_new = *ppapszArgvToSpawn;
252 int argc_new = 1;
253 while (argv_new[argc_new])
254 argc_new++;
255
256 assert(argv_new[0] != argv[0]);
257 assert(!*pPidSpawned);
258
259 *ppapszArgvToSpawn = NULL;
260 rc = kmk_builtin_command_parsed(argc_new, argv_new, ppapszArgvToSpawn, pPidSpawned);
261
262 free(argv_new[0]);
263 free(argv_new);
264 }
265
266 return rc;
267}
268
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette