VirtualBox

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

Last change on this file since 1292 was 1292, checked in by bird, 17 years ago

Added kmk_builtin_test and kmk_test - a slightly modified version of /bin/test.

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