]>
Commit | Line | Data |
---|---|---|
cd1a2927 MT |
1 | /*\r |
2 | * nash.c\r | |
3 | * \r | |
4 | * Simple code to load modules, mount root, and get things going. Uses\r | |
5 | * dietlibc to keep things small.\r | |
6 | *\r | |
7 | * Erik Troan (ewt@redhat.com)\r | |
8 | *\r | |
9 | * Copyright 2002 Red Hat Software \r | |
10 | *\r | |
11 | * This software may be freely redistributed under the terms of the GNU\r | |
12 | * public license.\r | |
13 | *\r | |
14 | * You should have received a copy of the GNU General Public License\r | |
15 | * along with this program; if not, write to the Free Software\r | |
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r | |
17 | *\r | |
18 | */\r | |
19 | \r | |
20 | /* We internalize losetup, mount, raidautorun, and echo commands. Other\r | |
21 | commands are run from the filesystem. Comments and blank lines work as \r | |
22 | well, argument parsing is screwy. */\r | |
23 | \r | |
24 | #include <ctype.h>\r | |
25 | #include <dirent.h>\r | |
26 | #include <errno.h>\r | |
27 | #include <fcntl.h>\r | |
28 | #include <net/if.h>\r | |
29 | #include <signal.h>\r | |
30 | #include <stdio.h>\r | |
31 | #include <stdlib.h>\r | |
32 | #include <string.h>\r | |
33 | #include <sys/ioctl.h>\r | |
34 | #include <sys/mount.h>\r | |
35 | #include <sys/socket.h>\r | |
36 | #include <sys/stat.h>\r | |
37 | #include <sys/time.h>\r | |
38 | #include <sys/types.h>\r | |
39 | #include <sys/un.h>\r | |
40 | #include <sys/wait.h>\r | |
41 | #include <unistd.h>\r | |
42 | #include <sys/ioctl.h>\r | |
43 | #include <sys/reboot.h>\r | |
44 | #include <termios.h>\r | |
45 | \r | |
46 | #include <asm/unistd.h>\r | |
47 | \r | |
48 | #include "mount_by_label.h"\r | |
49 | \r | |
50 | /* Need to tell loop.h what the actual dev_t type is. */\r | |
51 | #undef dev_t\r | |
52 | #if defined(__alpha) || (defined(__sparc__) && defined(__arch64__))\r | |
53 | #define dev_t unsigned int\r | |
54 | #else\r | |
55 | #define dev_t unsigned short\r | |
56 | #endif\r | |
57 | #include <linux/loop.h>\r | |
58 | #undef dev_t\r | |
59 | #define dev_t dev_t\r | |
60 | \r | |
61 | #define syslog klogctl\r | |
62 | \r | |
63 | #include <linux/cdrom.h>\r | |
64 | #define MD_MAJOR 9\r | |
65 | #include <linux/raid/md_u.h>\r | |
66 | \r | |
67 | #ifndef RAID_AUTORUN\r | |
68 | #define RAID_AUTORUN _IO (MD_MAJOR, 0x14)\r | |
69 | #endif\r | |
70 | \r | |
71 | #ifndef MS_REMOUNT\r | |
72 | #define MS_REMOUNT 32\r | |
73 | #endif\r | |
74 | \r | |
75 | #ifdef USE_DIET\r | |
76 | static inline _syscall2(int,pivot_root,const char *,one,const char *,two)\r | |
77 | #endif\r | |
78 | \r | |
79 | #define MAX(a, b) ((a) > (b) ? a : b)\r | |
80 | \r | |
81 | int testing = 0, quiet = 0;\r | |
82 | \r | |
83 | #define PATH "/usr/bin:/bin:/sbin:/usr/sbin"\r | |
84 | \r | |
85 | char * env[] = {\r | |
86 | "PATH=" PATH,\r | |
87 | NULL\r | |
88 | };\r | |
89 | \r | |
90 | int smartmknod(char * device, mode_t mode, dev_t dev) {\r | |
91 | char buf[256];\r | |
92 | char * end;\r | |
93 | \r | |
94 | strcpy(buf, device);\r | |
95 | \r | |
96 | end = buf;\r | |
97 | while (*end) {\r | |
98 | if (*end == '/') {\r | |
99 | *end = '\0';\r | |
100 | if (access(buf, F_OK) && errno == ENOENT) \r | |
101 | mkdir(buf, 0700);\r | |
102 | *end = '/';\r | |
103 | }\r | |
104 | \r | |
105 | end++;\r | |
106 | }\r | |
107 | \r | |
108 | return mknod(device, mode, dev);\r | |
109 | }\r | |
110 | \r | |
111 | char * getArg(char * cmd, char * end, char ** arg) {\r | |
112 | char quote = '\0';\r | |
113 | \r | |
114 | if (cmd >= end) return NULL;\r | |
115 | \r | |
116 | while (isspace(*cmd) && cmd < end) cmd++;\r | |
117 | if (cmd >= end) return NULL;\r | |
118 | \r | |
119 | if (*cmd == '"')\r | |
120 | cmd++, quote = '"';\r | |
121 | else if (*cmd == '\'')\r | |
122 | cmd++, quote = '\'';\r | |
123 | \r | |
124 | if (quote) {\r | |
125 | *arg = cmd;\r | |
126 | \r | |
127 | /* This doesn't support \ escapes */\r | |
128 | while (cmd < end && *cmd != quote) cmd++;\r | |
129 | \r | |
130 | if (cmd == end) {\r | |
131 | printf("error: quote mismatch for %s\n", *arg);\r | |
132 | return NULL;\r | |
133 | }\r | |
134 | \r | |
135 | *cmd = '\0';\r | |
136 | cmd++;\r | |
137 | } else {\r | |
138 | *arg = cmd;\r | |
139 | while (!isspace(*cmd) && cmd < end) cmd++;\r | |
140 | *cmd = '\0';\r | |
141 | }\r | |
142 | \r | |
143 | cmd++;\r | |
144 | \r | |
145 | while (isspace(*cmd)) cmd++;\r | |
146 | \r | |
147 | return cmd;\r | |
148 | }\r | |
149 | \r | |
150 | int mountCommand(char * cmd, char * end) {\r | |
151 | char * fsType = NULL;\r | |
152 | char * device;\r | |
153 | char * mntPoint;\r | |
154 | char * deviceDir;\r | |
155 | char * options = NULL;\r | |
156 | int mustRemove = 0;\r | |
157 | int mustRemoveDir = 0;\r | |
158 | int rc;\r | |
159 | int flags = MS_MGC_VAL;\r | |
160 | char * newOpts;\r | |
161 | \r | |
162 | cmd = getArg(cmd, end, &device);\r | |
163 | if (!cmd) {\r | |
164 | printf("usage: mount [--ro] [-o <opts>] -t <type> <device> <mntpoint>\n");\r | |
165 | return 1;\r | |
166 | }\r | |
167 | \r | |
168 | while (cmd && *device == '-') {\r | |
169 | if (!strcmp(device, "--ro")) {\r | |
170 | flags |= MS_RDONLY;\r | |
171 | } else if (!strcmp(device, "-o")) {\r | |
172 | cmd = getArg(cmd, end, &options);\r | |
173 | if (!cmd) {\r | |
174 | printf("mount: -o requires arguments\n");\r | |
175 | return 1;\r | |
176 | }\r | |
177 | } else if (!strcmp(device, "-t")) {\r | |
178 | if (!(cmd = getArg(cmd, end, &fsType))) {\r | |
179 | printf("mount: missing filesystem type\n");\r | |
180 | return 1;\r | |
181 | }\r | |
182 | }\r | |
183 | \r | |
184 | cmd = getArg(cmd, end, &device);\r | |
185 | }\r | |
186 | \r | |
187 | if (!cmd) {\r | |
188 | printf("mount: missing device\n");\r | |
189 | return 1;\r | |
190 | }\r | |
191 | \r | |
192 | if (!(cmd = getArg(cmd, end, &mntPoint))) {\r | |
193 | printf("mount: missing mount point\n");\r | |
194 | return 1;\r | |
195 | }\r | |
196 | \r | |
197 | if (!fsType) {\r | |
198 | printf("mount: filesystem type expected\n");\r | |
199 | return 1;\r | |
200 | }\r | |
201 | \r | |
202 | if (cmd < end) {\r | |
203 | printf("mount: unexpected arguments\n");\r | |
204 | return 1;\r | |
205 | }\r | |
206 | \r | |
207 | /* need to deal with options */ \r | |
208 | if (options) {\r | |
209 | char * end;\r | |
210 | char * start = options;\r | |
211 | \r | |
212 | newOpts = alloca(strlen(options) + 1);\r | |
213 | *newOpts = '\0';\r | |
214 | \r | |
215 | while (*start) {\r | |
216 | end = strchr(start, ',');\r | |
217 | if (!end) {\r | |
218 | end = start + strlen(start);\r | |
219 | } else {\r | |
220 | *end = '\0';\r | |
221 | end++;\r | |
222 | }\r | |
223 | \r | |
224 | if (!strcmp(start, "ro"))\r | |
225 | flags |= MS_RDONLY;\r | |
226 | else if (!strcmp(start, "rw"))\r | |
227 | flags &= ~MS_RDONLY;\r | |
228 | else if (!strcmp(start, "nosuid"))\r | |
229 | flags |= MS_NOSUID;\r | |
230 | else if (!strcmp(start, "suid"))\r | |
231 | flags &= ~MS_NOSUID;\r | |
232 | else if (!strcmp(start, "nodev"))\r | |
233 | flags |= MS_NODEV;\r | |
234 | else if (!strcmp(start, "dev"))\r | |
235 | flags &= ~MS_NODEV;\r | |
236 | else if (!strcmp(start, "noexec"))\r | |
237 | flags |= MS_NOEXEC;\r | |
238 | else if (!strcmp(start, "exec"))\r | |
239 | flags &= ~MS_NOEXEC;\r | |
240 | else if (!strcmp(start, "sync"))\r | |
241 | flags |= MS_SYNCHRONOUS;\r | |
242 | else if (!strcmp(start, "async"))\r | |
243 | flags &= ~MS_SYNCHRONOUS;\r | |
244 | else if (!strcmp(start, "nodiratime"))\r | |
245 | flags |= MS_NODIRATIME;\r | |
246 | else if (!strcmp(start, "diratime"))\r | |
247 | flags &= ~MS_NODIRATIME;\r | |
248 | else if (!strcmp(start, "noatime"))\r | |
249 | flags |= MS_NOATIME;\r | |
250 | else if (!strcmp(start, "atime"))\r | |
251 | flags &= ~MS_NOATIME;\r | |
252 | else if (!strcmp(start, "remount"))\r | |
253 | flags |= MS_REMOUNT;\r | |
254 | else if (!strcmp(start, "defaults"))\r | |
255 | ;\r | |
256 | else {\r | |
257 | if (*newOpts)\r | |
258 | strcat(newOpts, ",");\r | |
259 | strcat(newOpts, start);\r | |
260 | }\r | |
261 | \r | |
262 | start = end;\r | |
263 | }\r | |
264 | \r | |
265 | options = newOpts;\r | |
266 | }\r | |
267 | \r | |
268 | if (!strncmp("LABEL=", device, 6)) {\r | |
269 | int major, minor;\r | |
270 | char * devName;\r | |
271 | char * ptr;\r | |
272 | int i;\r | |
273 | \r | |
274 | devName = get_spec_by_volume_label(device + 6, &major, &minor);\r | |
275 | \r | |
276 | if (devName) {\r | |
277 | device = devName;\r | |
278 | if (access(device, F_OK)) {\r | |
279 | ptr = device;\r | |
280 | i = 0;\r | |
281 | while (*ptr)\r | |
282 | if (*ptr++ == '/')\r | |
283 | i++;\r | |
284 | if (i > 2) {\r | |
285 | deviceDir = alloca(strlen(device) + 1);\r | |
286 | strcpy(deviceDir, device);\r | |
287 | ptr = deviceDir + (strlen(device) - 1);\r | |
288 | while (*ptr != '/')\r | |
289 | *ptr-- = '\0';\r | |
290 | if (mkdir(deviceDir, 0644)) {\r | |
291 | printf("mkdir: cannot create directory %s\n", deviceDir);\r | |
292 | } else {\r | |
293 | mustRemoveDir = 1;\r | |
294 | }\r | |
295 | }\r | |
296 | if (smartmknod(device, S_IFBLK | 0600, makedev(major, minor))) {\r | |
297 | printf("mount: cannot create device %s (%d,%d)\n",\r | |
298 | device, major, minor);\r | |
299 | return 1;\r | |
300 | }\r | |
301 | mustRemove = 1;\r | |
302 | }\r | |
303 | }\r | |
304 | }\r | |
305 | \r | |
306 | if (testing) {\r | |
307 | printf("mount %s%s%s-t '%s' '%s' '%s' (%s%s%s%s%s%s%s)\n", \r | |
308 | options ? "-o '" : "", \r | |
309 | options ? options : "", \r | |
310 | options ? "\' " : "", \r | |
311 | fsType, device, mntPoint,\r | |
312 | (flags & MS_RDONLY) ? "ro " : "",\r | |
313 | (flags & MS_NOSUID) ? "nosuid " : "",\r | |
314 | (flags & MS_NODEV) ? "nodev " : "",\r | |
315 | (flags & MS_NOEXEC) ? "noexec " : "",\r | |
316 | (flags & MS_SYNCHRONOUS) ? "sync " : "",\r | |
317 | (flags & MS_REMOUNT) ? "remount " : "",\r | |
318 | (flags & MS_NOATIME) ? "noatime " : ""\r | |
319 | );\r | |
320 | } else {\r | |
321 | if (mount(device, mntPoint, fsType, flags, options)) {\r | |
322 | printf("mount: error %d mounting %s\n", errno, fsType);\r | |
323 | rc = 1;\r | |
324 | }\r | |
325 | }\r | |
326 | \r | |
327 | if (mustRemove) unlink(device);\r | |
328 | if (mustRemoveDir) rmdir(deviceDir);\r | |
329 | \r | |
330 | return rc;\r | |
331 | }\r | |
332 | \r | |
333 | int otherCommand(char * bin, char * cmd, char * end, int doFork) {\r | |
334 | char * args[128];\r | |
335 | char ** nextArg;\r | |
336 | int pid;\r | |
337 | int status;\r | |
338 | char fullPath[255];\r | |
339 | const static char * sysPath = PATH;\r | |
340 | const char * pathStart;\r | |
341 | const char * pathEnd;\r | |
342 | char * stdoutFile = NULL;\r | |
343 | int stdoutFd = 0;\r | |
344 | \r | |
345 | nextArg = args;\r | |
346 | \r | |
347 | if (!strchr(bin, '/')) {\r | |
348 | pathStart = sysPath;\r | |
349 | while (*pathStart) {\r | |
350 | pathEnd = strchr(pathStart, ':');\r | |
351 | \r | |
352 | if (!pathEnd) pathEnd = pathStart + strlen(pathStart);\r | |
353 | \r | |
354 | strncpy(fullPath, pathStart, pathEnd - pathStart);\r | |
355 | fullPath[pathEnd - pathStart] = '/';\r | |
356 | strcpy(fullPath + (pathEnd - pathStart + 1), bin); \r | |
357 | \r | |
358 | pathStart = pathEnd;\r | |
359 | if (*pathStart) pathStart++;\r | |
360 | \r | |
361 | if (!access(fullPath, X_OK)) {\r | |
362 | bin = fullPath;\r | |
363 | break;\r | |
364 | }\r | |
365 | }\r | |
366 | }\r | |
367 | \r | |
368 | *nextArg = bin;\r | |
369 | \r | |
370 | while (cmd && cmd < end) {\r | |
371 | nextArg++;\r | |
372 | cmd = getArg(cmd, end, nextArg);\r | |
373 | }\r | |
374 | \r | |
375 | if (cmd) nextArg++;\r | |
376 | *nextArg = NULL;\r | |
377 | \r | |
378 | /* if the next-to-last arg is a >, redirect the output properly */\r | |
379 | if (((nextArg - args) >= 2) && !strcmp(*(nextArg - 2), ">")) {\r | |
380 | stdoutFile = *(nextArg - 1);\r | |
381 | *(nextArg - 2) = NULL;\r | |
382 | \r | |
383 | stdoutFd = open(stdoutFile, O_CREAT | O_RDWR | O_TRUNC, 0600);\r | |
384 | if (stdoutFd < 0) {\r | |
385 | printf("nash: failed to open %s: %d\n", stdoutFile, errno);\r | |
386 | return 1;\r | |
387 | }\r | |
388 | }\r | |
389 | \r | |
390 | if (testing) {\r | |
391 | printf("%s ", bin);\r | |
392 | nextArg = args + 1;\r | |
393 | while (*nextArg)\r | |
394 | printf(" '%s'", *nextArg++);\r | |
395 | if (stdoutFile)\r | |
396 | printf(" (> %s)", stdoutFile);\r | |
397 | printf("\n");\r | |
398 | } else {\r | |
399 | if (!doFork || !(pid = fork())) {\r | |
400 | /* child */\r | |
401 | dup2(stdoutFd, 1);\r | |
402 | execve(args[0], args, env);\r | |
403 | printf("ERROR: failed in exec of %s\n", args[0]);\r | |
404 | return 1;\r | |
405 | }\r | |
406 | \r | |
407 | close(stdoutFd);\r | |
408 | \r | |
409 | wait4(-1, &status, 0, NULL);\r | |
410 | if (!WIFEXITED(status) || WEXITSTATUS(status)) {\r | |
411 | printf("ERROR: %s exited abnormally!\n", args[0]);\r | |
412 | return 1;\r | |
413 | }\r | |
414 | }\r | |
415 | \r | |
416 | return 0;\r | |
417 | }\r | |
418 | \r | |
419 | int execCommand(char * cmd, char * end) {\r | |
420 | char * bin;\r | |
421 | \r | |
422 | if (!(cmd = getArg(cmd, end, &bin))) {\r | |
423 | printf("exec: argument expected\n");\r | |
424 | return 1;\r | |
425 | }\r | |
426 | \r | |
427 | return otherCommand(bin, cmd, end, 0);\r | |
428 | }\r | |
429 | \r | |
430 | int losetupCommand(char * cmd, char * end) {\r | |
431 | char * device;\r | |
432 | char * file;\r | |
433 | int fd;\r | |
434 | struct loop_info loopInfo;\r | |
435 | int dev;\r | |
436 | \r | |
437 | if (!(cmd = getArg(cmd, end, &device))) {\r | |
438 | printf("losetup: missing device\n");\r | |
439 | return 1;\r | |
440 | }\r | |
441 | \r | |
442 | if (!(cmd = getArg(cmd, end, &file))) {\r | |
443 | printf("losetup: missing file\n");\r | |
444 | return 1;\r | |
445 | }\r | |
446 | \r | |
447 | if (cmd < end) {\r | |
448 | printf("losetup: unexpected arguments\n");\r | |
449 | return 1;\r | |
450 | }\r | |
451 | \r | |
452 | if (testing) {\r | |
453 | printf("losetup '%s' '%s'\n", device, file);\r | |
454 | } else {\r | |
455 | dev = open(device, O_RDWR, 0);\r | |
456 | if (dev < 0) {\r | |
457 | printf("losetup: failed to open %s: %d\n", device, errno);\r | |
458 | return 1;\r | |
459 | }\r | |
460 | \r | |
461 | fd = open(file, O_RDWR, 0);\r | |
462 | if (fd < 0) {\r | |
463 | printf("losetup: failed to open %s: %d\n", file, errno);\r | |
464 | close(dev);\r | |
465 | return 1;\r | |
466 | }\r | |
467 | \r | |
468 | if (ioctl(dev, LOOP_SET_FD, (long) fd)) {\r | |
469 | printf("losetup: LOOP_SET_FD failed: %d\n", errno);\r | |
470 | close(dev);\r | |
471 | close(fd);\r | |
472 | return 1;\r | |
473 | }\r | |
474 | \r | |
475 | close(fd);\r | |
476 | \r | |
477 | memset(&loopInfo, 0, sizeof(loopInfo));\r | |
478 | strcpy(loopInfo.lo_name, file);\r | |
479 | \r | |
480 | if (ioctl(dev, LOOP_SET_STATUS, &loopInfo)) \r | |
481 | printf("losetup: LOOP_SET_STATUS failed: %d\n", errno);\r | |
482 | \r | |
483 | close(dev);\r | |
484 | }\r | |
485 | \r | |
486 | return 0;\r | |
487 | }\r | |
488 | \r | |
489 | int raidautorunCommand(char * cmd, char * end) {\r | |
490 | char * device;\r | |
491 | int fd;\r | |
492 | \r | |
493 | if (!(cmd = getArg(cmd, end, &device))) {\r | |
494 | printf("raidautorun: raid device expected as first argument\n");\r | |
495 | return 1;\r | |
496 | }\r | |
497 | \r | |
498 | if (cmd < end) {\r | |
499 | printf("raidautorun: unexpected arguments\n");\r | |
500 | return 1;\r | |
501 | }\r | |
502 | \r | |
503 | fd = open(device, O_RDWR, 0);\r | |
504 | if (fd < 0) {\r | |
505 | printf("raidautorun: failed to open %s: %d\n", device, errno);\r | |
506 | return 1;\r | |
507 | }\r | |
508 | \r | |
509 | if (ioctl(fd, RAID_AUTORUN, 0)) {\r | |
510 | printf("raidautorun: RAID_AUTORUN failed: %d\n", errno);\r | |
511 | close(fd);\r | |
512 | return 1;\r | |
513 | }\r | |
514 | \r | |
515 | close(fd);\r | |
516 | return 0;\r | |
517 | }\r | |
518 | \r | |
519 | static int my_pivot_root(char * one, char * two) {\r | |
520 | #ifdef USE_DIET\r | |
521 | return pivot_root(one, two);\r | |
522 | #else\r | |
523 | return syscall(__NR_pivot_root, one, two);\r | |
524 | #endif\r | |
525 | }\r | |
526 | \r | |
527 | int pivotrootCommand(char * cmd, char * end) {\r | |
528 | char * new;\r | |
529 | char * old;\r | |
530 | \r | |
531 | if (!(cmd = getArg(cmd, end, &new))) {\r | |
532 | printf("pivotroot: new root mount point expected\n");\r | |
533 | return 1;\r | |
534 | }\r | |
535 | \r | |
536 | if (!(cmd = getArg(cmd, end, &old))) {\r | |
537 | printf("pivotroot: old root mount point expected\n");\r | |
538 | return 1;\r | |
539 | }\r | |
540 | \r | |
541 | if (cmd < end) {\r | |
542 | printf("pivotroot: unexpected arguments\n");\r | |
543 | return 1;\r | |
544 | }\r | |
545 | \r | |
546 | if (my_pivot_root(new, old)) {\r | |
547 | printf("pivotroot: pivot_root(%s,%s) failed: %d\n", new, old, errno);\r | |
548 | return 1;\r | |
549 | }\r | |
550 | \r | |
551 | return 0;\r | |
552 | }\r | |
553 | \r | |
554 | int echoCommand(char * cmd, char * end) {\r | |
555 | char * args[256];\r | |
556 | char ** nextArg = args;\r | |
557 | int outFd = 1;\r | |
558 | int num = 0;\r | |
559 | int i;\r | |
560 | \r | |
561 | if (testing && !quiet) {\r | |
562 | printf("(echo) ");\r | |
563 | fflush(stdout);\r | |
564 | }\r | |
565 | \r | |
566 | while ((cmd = getArg(cmd, end, nextArg)))\r | |
567 | nextArg++, num++;\r | |
568 | \r | |
569 | if ((nextArg - args >= 2) && !strcmp(*(nextArg - 2), ">")) {\r | |
570 | outFd = open(*(nextArg - 1), O_RDWR | O_CREAT | O_TRUNC, 0644);\r | |
571 | if (outFd < 0) {\r | |
572 | printf("echo: cannot open %s for write: %d\n", \r | |
573 | *(nextArg - 1), errno);\r | |
574 | return 1;\r | |
575 | }\r | |
576 | \r | |
577 | num -= 2;\r | |
578 | }\r | |
579 | \r | |
580 | for (i = 0; i < num;i ++) {\r | |
581 | if (i)\r | |
582 | write(outFd, " ", 1);\r | |
583 | write(outFd, args[i], strlen(args[i]));\r | |
584 | }\r | |
585 | \r | |
586 | write(outFd, "\n", 1);\r | |
587 | \r | |
588 | if (outFd != 1) close(outFd);\r | |
589 | \r | |
590 | return 0;\r | |
591 | }\r | |
592 | \r | |
593 | int umountCommand(char * cmd, char * end) {\r | |
594 | char * path;\r | |
595 | \r | |
596 | if (!(cmd = getArg(cmd, end, &path))) {\r | |
597 | printf("umount: path expected\n");\r | |
598 | return 1;\r | |
599 | }\r | |
600 | \r | |
601 | if (cmd < end) {\r | |
602 | printf("umount: unexpected arguments\n");\r | |
603 | return 1;\r | |
604 | }\r | |
605 | \r | |
606 | if (umount(path)) {\r | |
607 | printf("umount %s failed: %d\n", path, errno);\r | |
608 | return 1;\r | |
609 | }\r | |
610 | \r | |
611 | return 0;\r | |
612 | }\r | |
613 | \r | |
614 | int mkrootdevCommand(char * cmd, char * end) {\r | |
615 | char * path;\r | |
616 | char * start, * chptr;\r | |
617 | unsigned int devNum = 0;\r | |
618 | int fd;\r | |
619 | int i;\r | |
620 | char buf[1024];\r | |
621 | int major, minor;\r | |
622 | \r | |
623 | if (!(cmd = getArg(cmd, end, &path))) {\r | |
624 | printf("mkrootdev: path expected\n");\r | |
625 | return 1;\r | |
626 | }\r | |
627 | \r | |
628 | if (cmd < end) {\r | |
629 | printf("mkrootdev: unexpected arguments\n");\r | |
630 | return 1;\r | |
631 | }\r | |
632 | \r | |
633 | fd = open("/proc/cmdline", O_RDONLY, 0);\r | |
634 | if (fd < 0) {\r | |
635 | printf("mkrootdev: failed to open /proc/cmdline: %d\n", errno);\r | |
636 | return 1;\r | |
637 | }\r | |
638 | \r | |
639 | i = read(fd, buf, sizeof(buf));\r | |
640 | if (i < 0) {\r | |
641 | printf("mkrootdev: failed to read /proc/cmdline: %d\n", errno);\r | |
642 | close(fd);\r | |
643 | return 1;\r | |
644 | }\r | |
645 | \r | |
646 | close(fd);\r | |
647 | buf[i - 1] = '\0';\r | |
648 | \r | |
649 | start = buf;\r | |
650 | while (*start && isspace(*start)) start++;\r | |
651 | while (*start && strncmp(start, "root=", 5)) {\r | |
652 | while (*start && !isspace(*start)) start++;\r | |
653 | while (*start && isspace(*start)) start++;\r | |
654 | }\r | |
655 | \r | |
656 | start += 5;\r | |
657 | chptr = start;\r | |
658 | while (*chptr && !isspace(*chptr)) chptr++;\r | |
659 | *chptr = '\0';\r | |
660 | \r | |
661 | if (!strncmp(start, "LABEL=", 6)) {\r | |
662 | if (get_spec_by_volume_label(start + 6, &major, &minor)) {\r | |
663 | if (smartmknod(path, S_IFBLK | 0600, makedev(major, minor))) {\r | |
664 | printf("mount: cannot create device %s (%d,%d)\n",\r | |
665 | path, major, minor);\r | |
666 | return 1;\r | |
667 | }\r | |
668 | \r | |
669 | return 0;\r | |
670 | }\r | |
671 | \r | |
672 | printf("mkrootdev: label %s not found\n", start + 6);\r | |
673 | \r | |
674 | return 1;\r | |
675 | }\r | |
676 | \r | |
677 | fd = open("/proc/sys/kernel/real-root-dev", O_RDONLY, 0);\r | |
678 | if (fd < 0) {\r | |
679 | printf("mkrootdev: failed to open /proc/sys/kernel/real-root-dev: %d\n", errno);\r | |
680 | return 1;\r | |
681 | }\r | |
682 | \r | |
683 | i = read(fd, buf, sizeof(buf));\r | |
684 | if (i < 0) {\r | |
685 | printf("mkrootdev: failed to read real-root-dev: %d\n", errno);\r | |
686 | close(fd);\r | |
687 | return 1;\r | |
688 | }\r | |
689 | \r | |
690 | close(fd);\r | |
691 | buf[i - 1] = '\0';\r | |
692 | \r | |
693 | devNum = atoi(buf);\r | |
694 | if (devNum < 0) {\r | |
695 | printf("mkrootdev: bad device %s\n", buf);\r | |
696 | return 1;\r | |
697 | }\r | |
698 | \r | |
699 | if (smartmknod(path, S_IFBLK | 0700, devNum)) {\r | |
700 | printf("mkrootdev: mknod failed: %d\n", errno);\r | |
701 | return 1;\r | |
702 | }\r | |
703 | \r | |
704 | return 0;\r | |
705 | }\r | |
706 | \r | |
707 | int mkdirCommand(char * cmd, char * end) {\r | |
708 | char * dir;\r | |
709 | int ignoreExists = 0;\r | |
710 | \r | |
711 | cmd = getArg(cmd, end, &dir);\r | |
712 | \r | |
713 | if (cmd && !strcmp(dir, "-p")) {\r | |
714 | ignoreExists = 1;\r | |
715 | cmd = getArg(cmd, end, &dir);\r | |
716 | }\r | |
717 | \r | |
718 | if (!cmd) {\r | |
719 | printf("mkdir: directory expected\n");\r | |
720 | return 1;\r | |
721 | }\r | |
722 | \r | |
723 | if (mkdir(dir, 0755)) {\r | |
724 | if (!ignoreExists && errno == EEXIST) {\r | |
725 | printf("mkdir: failed to create %s: %d\n", dir, errno);\r | |
726 | return 1;\r | |
727 | }\r | |
728 | }\r | |
729 | \r | |
730 | return 0;\r | |
731 | }\r | |
732 | \r | |
733 | int accessCommand(char * cmd, char * end) {\r | |
734 | char * permStr;\r | |
735 | int perms = 0;\r | |
736 | char * file;\r | |
737 | \r | |
738 | cmd = getArg(cmd, end, &permStr);\r | |
739 | if (cmd) cmd = getArg(cmd, end, &file);\r | |
740 | \r | |
741 | if (!cmd || *permStr != '-') {\r | |
742 | printf("usage: access -[perm] file\n");\r | |
743 | return 1;\r | |
744 | }\r | |
745 | \r | |
746 | permStr++;\r | |
747 | while (*permStr) {\r | |
748 | switch (*permStr) {\r | |
749 | case 'r': perms |= R_OK; break;\r | |
750 | case 'w': perms |= W_OK; break;\r | |
751 | case 'x': perms |= X_OK; break;\r | |
752 | case 'f': perms |= F_OK; break;\r | |
753 | default:\r | |
754 | printf("perms must be -[r][w][x][f]\n");\r | |
755 | return 1;\r | |
756 | }\r | |
757 | \r | |
758 | permStr++;\r | |
759 | }\r | |
760 | \r | |
761 | if (access(file, perms))\r | |
762 | return 1;\r | |
763 | \r | |
764 | return 0;\r | |
765 | }\r | |
766 | \r | |
767 | int sleepCommand(char * cmd, char * end) {\r | |
768 | char *delaystr;\r | |
769 | int delay;\r | |
770 | \r | |
771 | if (!(cmd = getArg(cmd, end, &delaystr))) {\r | |
772 | printf("sleep: delay expected\n");\r | |
773 | return 1;\r | |
774 | }\r | |
775 | \r | |
776 | delay = atoi(delaystr);\r | |
777 | sleep(delay);\r | |
778 | \r | |
779 | return 0;\r | |
780 | }\r | |
781 | \r | |
782 | int readlinkCommand(char * cmd, char * end) {\r | |
783 | char * path;\r | |
784 | char * buf, * respath, * fullpath;\r | |
785 | struct stat sb;\r | |
786 | \r | |
787 | if (!(cmd = getArg(cmd, end, &path))) {\r | |
788 | printf("readlink: file expected\n");\r | |
789 | return 1;\r | |
790 | }\r | |
791 | \r | |
792 | if (lstat(path, &sb) == -1) {\r | |
793 | fprintf(stderr, "unable to stat %s: %d\n", path, errno);\r | |
794 | return 1;\r | |
795 | }\r | |
796 | \r | |
797 | if (!S_ISLNK(sb.st_mode)) {\r | |
798 | printf("%s\n", path);\r | |
799 | return 0;\r | |
800 | }\r | |
801 | \r | |
802 | buf = malloc(512);\r | |
803 | if (readlink(path, buf, 512) == -1) {\r | |
804 | fprintf(stderr, "error readlink %s: %d\n", path, errno);\r | |
805 | return 1;\r | |
806 | }\r | |
807 | \r | |
808 | /* symlink is absolute */\r | |
809 | if (buf[0] == '/') {\r | |
810 | printf("%s\n", buf);\r | |
811 | return 0;\r | |
812 | } \r | |
813 | \r | |
814 | /* nope, need to handle the relative symlink case too */\r | |
815 | respath = strrchr(path, '/');\r | |
816 | if (respath) {\r | |
817 | *respath = '\0';\r | |
818 | }\r | |
819 | \r | |
820 | fullpath = malloc(512);\r | |
821 | /* and normalize it */\r | |
822 | snprintf(fullpath, 512, "%s/%s", path, buf);\r | |
823 | respath = malloc(PATH_MAX);\r | |
824 | if (!(respath = realpath(fullpath, respath))) {\r | |
825 | fprintf(stderr, "error realpath %s: %d\n", fullpath, errno);\r | |
826 | return 1;\r | |
827 | }\r | |
828 | \r | |
829 | printf("%s\n", respath);\r | |
830 | return 0;\r | |
831 | }\r | |
832 | \r | |
833 | int doFind(char * dirName, char * name) {\r | |
834 | struct stat sb;\r | |
835 | DIR * dir;\r | |
836 | struct dirent * d;\r | |
837 | char * strBuf = alloca(strlen(dirName) + 1024);\r | |
838 | \r | |
839 | if (!(dir = opendir(dirName))) {\r | |
840 | fprintf(stderr, "error opening %s: %d\n", dirName, errno);\r | |
841 | return 0;\r | |
842 | }\r | |
843 | \r | |
844 | errno = 0;\r | |
845 | while ((d = readdir(dir))) {\r | |
846 | errno = 0;\r | |
847 | \r | |
848 | strcpy(strBuf, dirName);\r | |
849 | strcat(strBuf, "/");\r | |
850 | strcat(strBuf, d->d_name);\r | |
851 | \r | |
852 | if (!strcmp(d->d_name, name))\r | |
853 | printf("%s\n", strBuf);\r | |
854 | \r | |
855 | if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {\r | |
856 | errno = 0;\r | |
857 | continue;\r | |
858 | }\r | |
859 | \r | |
860 | if (lstat(strBuf, &sb)) {\r | |
861 | fprintf(stderr, "failed to stat %s: %d\n", strBuf, errno);\r | |
862 | errno = 0;\r | |
863 | continue;\r | |
864 | }\r | |
865 | \r | |
866 | if (S_ISDIR(sb.st_mode))\r | |
867 | doFind(strBuf, name);\r | |
868 | }\r | |
869 | \r | |
870 | if (errno) {\r | |
871 | closedir(dir);\r | |
872 | printf("error reading from %s: %d\n", dirName, errno);\r | |
873 | return 1;\r | |
874 | }\r | |
875 | \r | |
876 | closedir(dir);\r | |
877 | \r | |
878 | return 0;\r | |
879 | }\r | |
880 | \r | |
881 | int findCommand(char * cmd, char * end) {\r | |
882 | char * dir;\r | |
883 | char * name;\r | |
884 | \r | |
885 | cmd = getArg(cmd, end, &dir);\r | |
886 | if (cmd) cmd = getArg(cmd, end, &name);\r | |
887 | if (cmd && strcmp(name, "-name")) {\r | |
888 | printf("usage: find [path] -name [file]\n");\r | |
889 | return 1;\r | |
890 | }\r | |
891 | \r | |
892 | if (cmd) cmd = getArg(cmd, end, &name);\r | |
893 | if (!cmd) {\r | |
894 | printf("usage: find [path] -name [file]\n");\r | |
895 | return 1;\r | |
896 | }\r | |
897 | \r | |
898 | return doFind(dir, name);\r | |
899 | }\r | |
900 | \r | |
901 | int findlodevCommand(char * cmd, char * end) {\r | |
902 | char devName[20];\r | |
903 | int devNum;\r | |
904 | int fd;\r | |
905 | struct loop_info loopInfo;\r | |
906 | char separator[2] = "";\r | |
907 | \r | |
908 | if (*end != '\n') {\r | |
909 | printf("usage: findlodev\n");\r | |
910 | return 1;\r | |
911 | }\r | |
912 | \r | |
913 | if (!access("/dev/.devfsd", X_OK))\r | |
914 | strcpy(separator, "/");\r | |
915 | \r | |
916 | for (devNum = 0; devNum < 256; devNum++) {\r | |
917 | sprintf(devName, "/dev/loop%s%d", separator, devNum);\r | |
918 | if ((fd = open(devName, O_RDONLY)) < 0) return 0;\r | |
919 | \r | |
920 | if (ioctl(fd, LOOP_GET_STATUS, &loopInfo)) {\r | |
921 | close(fd);\r | |
922 | printf("%s\n", devName);\r | |
923 | return 0;\r | |
924 | }\r | |
925 | \r | |
926 | close(fd);\r | |
927 | }\r | |
928 | \r | |
929 | return 0;\r | |
930 | }\r | |
931 | \r | |
932 | int mknodCommand(char * cmd, char * end) {\r | |
933 | char * path, * type;\r | |
934 | char * majorStr, * minorStr;\r | |
935 | int major;\r | |
936 | int minor;\r | |
937 | char * chptr;\r | |
938 | mode_t mode;\r | |
939 | \r | |
940 | cmd = getArg(cmd, end, &path);\r | |
941 | cmd = getArg(cmd, end, &type);\r | |
942 | cmd = getArg(cmd, end, &majorStr);\r | |
943 | cmd = getArg(cmd, end, &minorStr);\r | |
944 | if (!minorStr) {\r | |
945 | printf("mknod: usage mknod <path> [c|b] <major> <minor>\n");\r | |
946 | return 1;\r | |
947 | }\r | |
948 | \r | |
949 | if (!strcmp(type, "b")) {\r | |
950 | mode = S_IFBLK;\r | |
951 | } else if (!strcmp(type, "c")) {\r | |
952 | mode = S_IFCHR;\r | |
953 | } else {\r | |
954 | printf("mknod: invalid type\n");\r | |
955 | return 1;\r | |
956 | }\r | |
957 | \r | |
958 | major = strtol(majorStr, &chptr, 10);\r | |
959 | if (*chptr) {\r | |
960 | printf("invalid major number\n");\r | |
961 | return 1;\r | |
962 | }\r | |
963 | \r | |
964 | minor = strtol(minorStr, &chptr, 10);\r | |
965 | if (*chptr) {\r | |
966 | printf("invalid minor number\n");\r | |
967 | return 1;\r | |
968 | }\r | |
969 | \r | |
970 | if (smartmknod(path, mode | 0600, makedev(major, minor))) {\r | |
971 | printf("mknod: failed to create %s: %d\n", path, errno);\r | |
972 | return 1;\r | |
973 | }\r | |
974 | \r | |
975 | return 0;\r | |
976 | }\r | |
977 | \r | |
978 | int mkdevicesCommand(char * cmd, char * end) {\r | |
979 | int fd;\r | |
980 | char buf[32768];\r | |
981 | int i;\r | |
982 | char * start, * chptr;\r | |
983 | int major, minor;\r | |
984 | char old;\r | |
985 | char devName[128];\r | |
986 | char * prefix;\r | |
987 | \r | |
988 | if (!(cmd = getArg(cmd, end, &prefix))) {\r | |
989 | printf("mkdevices: path expected\n");\r | |
990 | return 1;\r | |
991 | }\r | |
992 | \r | |
993 | if (cmd < end) {\r | |
994 | printf("mkdevices: unexpected arguments\n");\r | |
995 | return 1;\r | |
996 | }\r | |
997 | \r | |
998 | if ((fd = open("/proc/partitions", O_RDONLY)) < 0) {\r | |
999 | printf("mkrootdev: failed to open /proc/partitions: %d\n", errno);\r | |
1000 | return 1;\r | |
1001 | }\r | |
1002 | \r | |
1003 | i = read(fd, buf, sizeof(buf));\r | |
1004 | if (i < 1) {\r | |
1005 | close(fd);\r | |
1006 | printf("failed to read /proc/partitions: %d\n", errno);\r | |
1007 | return 1;\r | |
1008 | }\r | |
1009 | buf[i] = '\0';\r | |
1010 | close(fd);\r | |
1011 | \r | |
1012 | start = strchr(buf, '\n');\r | |
1013 | if (start) {\r | |
1014 | start++;\r | |
1015 | start = strchr(buf, '\n');\r | |
1016 | }\r | |
1017 | if (!start) return 1;\r | |
1018 | \r | |
1019 | start = start + 1;\r | |
1020 | while (*start) {\r | |
1021 | while (*start && isspace(*start)) start++;\r | |
1022 | major = strtol(start, &chptr, 10);\r | |
1023 | \r | |
1024 | if (start != chptr) {\r | |
1025 | start = chptr;\r | |
1026 | while (*start && isspace(*start)) start++;\r | |
1027 | minor = strtol(start, &chptr, 10);\r | |
1028 | \r | |
1029 | if (start != chptr) {\r | |
1030 | start = chptr;\r | |
1031 | while (*start && isspace(*start)) start++;\r | |
1032 | while (*start && !isspace(*start)) start++;\r | |
1033 | while (*start && isspace(*start)) start++;\r | |
1034 | \r | |
1035 | if (*start) {\r | |
1036 | \r | |
1037 | chptr = start;\r | |
1038 | while (!isspace(*chptr)) chptr++;\r | |
1039 | old = *chptr;\r | |
1040 | *chptr = '\0';\r | |
1041 | \r | |
1042 | if (testing) {\r | |
1043 | printf("% 3d % 3d %s\n", major, minor, start);\r | |
1044 | } else {\r | |
1045 | char * ptr, * deviceDir;\r | |
1046 | int i;\r | |
1047 | \r | |
1048 | sprintf(devName, "%s/%s", prefix, start);\r | |
1049 | unlink(devName);\r | |
1050 | \r | |
1051 | ptr = devName;\r | |
1052 | i = 0;\r | |
1053 | while (*ptr)\r | |
1054 | if (*ptr++ == '/')\r | |
1055 | i++;\r | |
1056 | if (i > 2) {\r | |
1057 | deviceDir = alloca(strlen(devName) + 1);\r | |
1058 | strcpy(deviceDir, devName);\r | |
1059 | ptr = deviceDir + (strlen(devName) - 1);\r | |
1060 | while (*ptr != '/')\r | |
1061 | *ptr-- = '\0';\r | |
1062 | if (access(deviceDir, X_OK) && mkdir(deviceDir, 0644)) {\r | |
1063 | printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);\r | |
1064 | }\r | |
1065 | }\r | |
1066 | if (smartmknod(devName, S_IFBLK | 0600, \r | |
1067 | makedev(major, minor))) {\r | |
1068 | printf("failed to create %s\n", devName);\r | |
1069 | }\r | |
1070 | }\r | |
1071 | \r | |
1072 | *chptr = old;\r | |
1073 | start = chptr;\r | |
1074 | }\r | |
1075 | \r | |
1076 | }\r | |
1077 | }\r | |
1078 | \r | |
1079 | start = strchr(start, '\n');\r | |
1080 | if (!*start) return 1;\r | |
1081 | start = start + 1;\r | |
1082 | }\r | |
1083 | \r | |
1084 | return 0;\r | |
1085 | }\r | |
1086 | \r | |
1087 | int runStartup(int fd) {\r | |
1088 | char contents[32768];\r | |
1089 | int i;\r | |
1090 | char * start, * end;\r | |
1091 | char * chptr;\r | |
1092 | int rc;\r | |
1093 | \r | |
1094 | i = read(fd, contents, sizeof(contents) - 1);\r | |
1095 | if (i == (sizeof(contents) - 1)) {\r | |
1096 | printf("Failed to read /startup.rc -- file too large.\n");\r | |
1097 | return 1;\r | |
1098 | }\r | |
1099 | \r | |
1100 | contents[i] = '\0';\r | |
1101 | \r | |
1102 | start = contents;\r | |
1103 | while (*start) {\r | |
1104 | while (isspace(*start) && *start && (*start != '\n')) start++;\r | |
1105 | \r | |
1106 | if (*start == '#')\r | |
1107 | while (*start && (*start != '\n')) start++;\r | |
1108 | \r | |
1109 | if (*start == '\n') {\r | |
1110 | start++;\r | |
1111 | continue;\r | |
1112 | }\r | |
1113 | \r | |
1114 | if (!*start) {\r | |
1115 | printf("(last line in /startup.rc is empty)\n");\r | |
1116 | continue;\r | |
1117 | }\r | |
1118 | \r | |
1119 | /* start points to the beginning of the command */\r | |
1120 | end = start + 1;\r | |
1121 | while (*end && (*end != '\n')) end++;\r | |
1122 | if (!*end) {\r | |
1123 | printf("(last line in /startup.rc missing \\n -- skipping)\n");\r | |
1124 | start = end;\r | |
1125 | continue;\r | |
1126 | }\r | |
1127 | \r | |
1128 | /* end points to the \n at the end of the command */\r | |
1129 | \r | |
1130 | chptr = start;\r | |
1131 | while (chptr < end && !isspace(*chptr)) chptr++;\r | |
1132 | \r | |
1133 | if (!strncmp(start, "mount", MAX(5, chptr - start)))\r | |
1134 | rc = mountCommand(chptr, end);\r | |
1135 | else if (!strncmp(start, "losetup", MAX(7, chptr - start)))\r | |
1136 | rc = losetupCommand(chptr, end);\r | |
1137 | else if (!strncmp(start, "echo", MAX(4, chptr - start)))\r | |
1138 | rc = echoCommand(chptr, end);\r | |
1139 | else if (!strncmp(start, "raidautorun", MAX(11, chptr - start)))\r | |
1140 | rc = raidautorunCommand(chptr, end);\r | |
1141 | else if (!strncmp(start, "pivot_root", MAX(10, chptr - start)))\r | |
1142 | rc = pivotrootCommand(chptr, end);\r | |
1143 | else if (!strncmp(start, "mkrootdev", MAX(9, chptr - start)))\r | |
1144 | rc = mkrootdevCommand(chptr, end);\r | |
1145 | else if (!strncmp(start, "umount", MAX(6, chptr - start)))\r | |
1146 | rc = umountCommand(chptr, end);\r | |
1147 | else if (!strncmp(start, "exec", MAX(4, chptr - start)))\r | |
1148 | rc = execCommand(chptr, end);\r | |
1149 | else if (!strncmp(start, "mkdir", MAX(5, chptr - start)))\r | |
1150 | rc = mkdirCommand(chptr, end);\r | |
1151 | else if (!strncmp(start, "access", MAX(6, chptr - start)))\r | |
1152 | rc = accessCommand(chptr, end);\r | |
1153 | else if (!strncmp(start, "find", MAX(4, chptr - start)))\r | |
1154 | rc = findCommand(chptr, end);\r | |
1155 | else if (!strncmp(start, "findlodev", MAX(7, chptr - start)))\r | |
1156 | rc = findlodevCommand(chptr, end);\r | |
1157 | else if (!strncmp(start, "showlabels", MAX(10, chptr-start)))\r | |
1158 | rc = display_uuid_cache();\r | |
1159 | else if (!strncmp(start, "mkdevices", MAX(9, chptr-start)))\r | |
1160 | rc = mkdevicesCommand(chptr, end);\r | |
1161 | else if (!strncmp(start, "sleep", MAX(5, chptr-start)))\r | |
1162 | rc = sleepCommand(chptr, end);\r | |
1163 | else if (!strncmp(start, "mknod", MAX(5, chptr-start)))\r | |
1164 | rc = mknodCommand(chptr, end);\r | |
1165 | else if (!strncmp(start, "readlink", MAX(8, chptr-start)))\r | |
1166 | rc = readlinkCommand(chptr, end);\r | |
1167 | else {\r | |
1168 | *chptr = '\0';\r | |
1169 | rc = otherCommand(start, chptr + 1, end, 1);\r | |
1170 | }\r | |
1171 | \r | |
1172 | start = end + 1;\r | |
1173 | }\r | |
1174 | \r | |
1175 | return rc;\r | |
1176 | }\r | |
1177 | \r | |
1178 | int main(int argc, char **argv) {\r | |
1179 | int fd = 0;\r | |
1180 | char * name;\r | |
1181 | int rc;\r | |
1182 | int force = 0;\r | |
1183 | \r | |
1184 | name = strrchr(argv[0], '/');\r | |
1185 | if (!name) \r | |
1186 | name = argv[0];\r | |
1187 | else\r | |
1188 | name++;\r | |
1189 | \r | |
1190 | if (!strcmp(name, "modprobe"))\r | |
1191 | exit(0);\r | |
1192 | \r | |
1193 | testing = (getppid() != 0) && (getppid() != 1);\r | |
1194 | argv++, argc--;\r | |
1195 | \r | |
1196 | while (argc && **argv == '-') {\r | |
1197 | if (!strcmp(*argv, "--force")) {\r | |
1198 | force = 1;\r | |
1199 | argv++, argc--;\r | |
1200 | testing = 0;\r | |
1201 | } else if (!strcmp(*argv, "--quiet")) {\r | |
1202 | quiet = 1;\r | |
1203 | argv++, argc--;\r | |
1204 | } else {\r | |
1205 | printf("unknown argument %s\n", *argv);\r | |
1206 | return 1;\r | |
1207 | }\r | |
1208 | }\r | |
1209 | \r | |
1210 | if (force && !quiet)\r | |
1211 | printf("(forcing normal run)\n");\r | |
1212 | \r | |
1213 | if (testing && !quiet)\r | |
1214 | printf("(running in test mode).\n");\r | |
1215 | \r | |
1216 | if (!quiet) printf("Red Hat nash version %s starting\n", VERSION);\r | |
1217 | \r | |
1218 | if (*argv) {\r | |
1219 | fd = open(*argv, O_RDONLY, 0);\r | |
1220 | if (fd < 0) {\r | |
1221 | printf("nash: cannot open %s: %d\n", *argv, errno);\r | |
1222 | exit(1);\r | |
1223 | }\r | |
1224 | }\r | |
1225 | \r | |
1226 | rc = runStartup(fd);\r | |
1227 | close(fd);\r | |
1228 | \r | |
1229 | return rc;\r | |
1230 | }\r |