VirtualBox

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

Last change on this file since 2132 was 2125, checked in by bird, 16 years ago

kmkbuiltin.c: warning.

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