sash.c 19 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. /*
  2. * Copyright (c) 1993 by David I. Bell
  3. * Permission is granted to use, distribute, or modify this source,
  4. * provided that this copyright notice remains intact.
  5. *
  6. * Stand-alone shell for system maintainance for Linux.
  7. * This program should NOT be built using shared libraries.
  8. *
  9. * 1.1.1, hacked to re-allow cmd line invocation of script file
  10. * Pat Adamo, padamo@unix.asb.com
  11. */
  12. #include "sash.h"
  13. #ifndef CMD_HELP
  14. #define CMD_HELP
  15. #endif
  16. #undef INTERNAL_PATH_EXPANSION
  17. #define FAVOUR_EXTERNAL_COMMANDS
  18. #include <stdlib.h>
  19. #include <signal.h>
  20. #include <errno.h>
  21. #include <unistd.h>
  22. #include <sys/stat.h>
  23. #include <sys/time.h>
  24. #include <sys/wait.h>
  25. static char version[] = "1.1.1";
  26. extern int intflag;
  27. extern void do_test();
  28. typedef struct {
  29. char name[10];
  30. char usage[30];
  31. void (*func)();
  32. int minargs;
  33. int maxargs;
  34. } CMDTAB;
  35. CMDTAB cmdtab[] = {
  36. /*
  37. "alias", "[name [command]]", do_alias,
  38. 1, MAXARGS,
  39. */
  40. "cd", "[dirname]", do_cd,
  41. 1, 2,
  42. "sleep", "seconds", do_sleep,
  43. 1, 2,
  44. "chgrp", "gid filename ...", do_chgrp,
  45. 3, MAXARGS,
  46. "chmod", "mode filename ...", do_chmod,
  47. 3, MAXARGS,
  48. "chown", "uid filename ...", do_chown,
  49. 3, MAXARGS,
  50. "cmp", "filename1 filename2", do_cmp,
  51. 3, 3,
  52. "cp", "srcname ... destname", do_cp,
  53. 3, MAXARGS,
  54. /*
  55. "dd", "if=name of=name [bs=n] [count=n] [skip=n] [seek=n]", do_dd,
  56. 3, MAXARGS,
  57. */
  58. "df", "[file-system]", do_df,
  59. 1, 2,
  60. "echo", "[args] ...", do_echo,
  61. 1, MAXARGS,
  62. /*
  63. "ed", "[filename]", do_ed,
  64. 1, 2,
  65. */
  66. "exec", "filename [args]", do_exec,
  67. 2, MAXARGS,
  68. "exit", "", do_exit,
  69. 1, 1,
  70. "free", "", do_free,
  71. 1, 1,
  72. /*
  73. "-grep", "[-in] word filename ...", do_grep,
  74. 3, MAXARGS,
  75. */
  76. #ifdef CMD_HELP
  77. "help", "", do_help,
  78. 1, MAXARGS,
  79. #endif
  80. "hexdump", "[-s pos] filename", do_hexdump,
  81. 1, 4,
  82. "hostname", "[hostname]", do_hostname,
  83. 1, 2,
  84. "kill", "[-sig] pid ...", do_kill,
  85. 2, MAXARGS,
  86. "ln", "[-s] srcname ... destname", do_ln,
  87. 3, MAXARGS,
  88. "ls", "[-lidC] filename ...", do_ls,
  89. 1, MAXARGS,
  90. "mkdir", "dirname ...", do_mkdir,
  91. 2, MAXARGS,
  92. "mknod", "filename type major minor", do_mknod,
  93. 5, 5,
  94. "more", "filename ...", do_more,
  95. 2, MAXARGS,
  96. "mount", "[-t type] devname dirname", do_mount,
  97. 3, MAXARGS,
  98. "mv", "srcname ... destname", do_mv,
  99. 3, MAXARGS,
  100. "printenv", "[name]", do_printenv,
  101. 1, 2,
  102. "pwd", "", do_pwd,
  103. 1, 1,
  104. "pid", "", do_pid,
  105. 1, 1,
  106. "quit", "", do_exit,
  107. 1, 1,
  108. "rm", "filename ...", do_rm,
  109. 2, MAXARGS,
  110. "rmdir", "dirname ...", do_rmdir,
  111. 2, MAXARGS,
  112. "setenv", "name value", do_setenv,
  113. 3, 3,
  114. "source", "filename", do_source,
  115. 2, 2,
  116. "sync", "", do_sync,
  117. 1, 1,
  118. /* "time", "", do_time,
  119. 1, 1,
  120. */
  121. /*
  122. "tar", "[xtv]f devname filename ...", do_tar,
  123. 2, MAXARGS,
  124. */
  125. "touch", "filename ...", do_touch,
  126. 2, MAXARGS,
  127. "umask", "[mask]", do_umask,
  128. 1, 2,
  129. "umount", "filename", do_umount,
  130. 2, 2,
  131. /*
  132. "unalias", "name", do_unalias,
  133. 2, 2,
  134. */
  135. #ifdef CONFIG_USER_SASH_PS
  136. "ps", "", do_ps,
  137. 1, MAXARGS,
  138. #endif
  139. /* "reboot", "", do_reboot,
  140. 1, MAXARGS,
  141. */
  142. "cat", "filename ...", do_cat,
  143. 2, MAXARGS,
  144. "date", "date [MMDDhhmm[YYYY]]", do_date,
  145. 1, 2,
  146. 0, 0, 0,
  147. 0, 0
  148. };
  149. typedef struct {
  150. char *name;
  151. char *value;
  152. } ALIAS;
  153. static ALIAS *aliastable;
  154. static int aliascount;
  155. static FILE *sourcefiles[MAXSOURCE];
  156. static int sourcecount;
  157. volatile static BOOL intcrlf = TRUE;
  158. static void catchint();
  159. static void catchquit();
  160. static void catchchild();
  161. static void readfile();
  162. static void command();
  163. #ifdef COMMAND_HISTORY
  164. #define do_command(c,h) command(c,h)
  165. #else
  166. #define do_command(c,h) command(c)
  167. #endif
  168. static void runcmd();
  169. static void showprompt();
  170. static BOOL trybuiltin();
  171. static BOOL command_in_path();
  172. static ALIAS *findalias();
  173. extern char ** environ;
  174. /*
  175. char text1[] = "Text";
  176. char * text2 = text1;
  177. char ** text3 = &text2;
  178. */
  179. char buf[CMDLEN];
  180. int exit_code = 0;
  181. main(argc, argv, env)
  182. char **argv;
  183. char *env[];
  184. {
  185. struct sigaction act;
  186. char *cp;
  187. /* char buf[PATHLEN];*/
  188. int dofile = 0;
  189. if ((argc > 1) && !strcmp(argv[1], "-c")) {
  190. /* We are that fancy a shell */
  191. buf[0] = '\0';
  192. for (dofile = 2; dofile < argc; dofile++) {
  193. strncat(buf, argv[dofile], sizeof(buf));
  194. if (dofile + 1 < argc)
  195. strncat(buf, " ", sizeof(buf));
  196. }
  197. do_command(buf, FALSE);
  198. exit(exit_code);
  199. }
  200. //;'pa990523 +
  201. if ((argc > 1) && strcmp(argv[1], "-t"))
  202. {
  203. dofile++;
  204. printf("Shell invoked to run file: %s\n",argv[1]);
  205. }
  206. else
  207. printf("\nSash command shell (version %s)\n", version);
  208. fflush(stdout);
  209. signal(SIGINT, catchint);
  210. signal(SIGQUIT, catchquit);
  211. memset(&act, 0, sizeof(act));
  212. act.sa_handler = catchchild;
  213. act.sa_flags = SA_RESTART;
  214. sigaction(SIGCHLD, &act, NULL);
  215. if (getenv("PATH") == NULL)
  216. putenv("PATH=/bin:/usr/bin:/etc:/sbin:/usr/sbin");
  217. /* cp = getenv("HOME");
  218. if (cp) {
  219. strcpy(buf, cp);
  220. strcat(buf, "/");
  221. strcat(buf, ".aliasrc");
  222. if ((access(buf, 0) == 0) || (errno != ENOENT))
  223. readfile(buf);
  224. }
  225. */
  226. //;'pa990523 -1/+
  227. //readfile(NULL);
  228. if (dofile)
  229. {
  230. //open the file for reading!
  231. readfile(argv[1]);
  232. }
  233. else
  234. {
  235. readfile(NULL); //no arguments!
  236. } //end if arguments supplied
  237. exit(exit_code);
  238. }
  239. /*
  240. * Read commands from the specified file.
  241. * A null name pointer indicates to read from stdin.
  242. */
  243. static void
  244. readfile(name)
  245. char *name;
  246. {
  247. FILE *fp;
  248. int cc;
  249. BOOL ttyflag;
  250. char *ptr;
  251. if (sourcecount >= MAXSOURCE) {
  252. fprintf(stderr, "Too many source files\n");
  253. return;
  254. }
  255. fp = stdin;
  256. if (name) {
  257. fp = fopen(name, "r");
  258. if (fp == NULL) {
  259. perror(name);
  260. return;
  261. }
  262. }
  263. sourcefiles[sourcecount++] = fp;
  264. ttyflag = isatty(fileno(fp));
  265. while (TRUE) {
  266. fflush(stdout);
  267. //;'pa990523 -1/+1
  268. //if (1)
  269. if (fp == stdin) //using terminal, so show prompt
  270. showprompt();
  271. if (intflag && !ttyflag && (fp != stdin)) {
  272. fclose(fp);
  273. sourcecount--;
  274. return;
  275. }
  276. if (fgets(buf, CMDLEN - 1, fp) == NULL) {
  277. if (ferror(fp) && (errno == EINTR)) {
  278. clearerr(fp);
  279. continue;
  280. }
  281. break;
  282. }
  283. cc = strlen(buf);
  284. while ((cc > 0) && isspace(buf[cc - 1]))
  285. cc--;
  286. buf[cc] = '\0';
  287. /* remove leading spaces and look for a '#' */
  288. ptr = &buf[0];
  289. while (*ptr == ' ') {
  290. ptr++;
  291. }
  292. if (*ptr != '#') {
  293. //;'pa990523 +
  294. if (fp != stdin) {
  295. //taking commands from file - echo
  296. printf("Command: %s\n",buf);
  297. } //end if (fp != stdin)
  298. do_command(buf, fp == stdin);
  299. }
  300. }
  301. if (ferror(fp)) {
  302. perror("Reading command line");
  303. if (fp == stdin)
  304. exit(1);
  305. }
  306. clearerr(fp);
  307. if (fp != stdin)
  308. {//;'pa990523 added braces and printf
  309. fclose(fp);
  310. printf("Execution Finished, Exiting\n");
  311. } //end if (fp != stdin)
  312. sourcecount--;
  313. }
  314. /*
  315. * Parse and execute one null-terminated command line string.
  316. * This breaks the command line up into words, checks to see if the
  317. * command is an alias, and expands wildcards.
  318. */
  319. static void
  320. #ifdef COMMAND_HISTORY
  321. command(cmd, do_history)
  322. int do_history;
  323. #else
  324. command(cmd)
  325. #endif
  326. char *cmd;
  327. {
  328. ALIAS *alias;
  329. char **argv;
  330. int argc;
  331. int bg;
  332. char *c;
  333. char last_exit_code[10];
  334. sprintf(last_exit_code, "%d", exit_code);
  335. intflag = FALSE;
  336. exit_code = 0;
  337. freechunks();
  338. while (isblank(*cmd))
  339. cmd++;
  340. #ifdef COMMAND_HISTORY
  341. if (do_history) {
  342. int i;
  343. static char *history[HISTORY_SIZE];
  344. if (*cmd == '!') {
  345. if (cmd[1] == '!')
  346. i = 0;
  347. else {
  348. i = atoi(cmd+1) - 1;
  349. if (i < 0 || i >= HISTORY_SIZE) {
  350. printf("%s: Out of range\n", cmd);
  351. return;
  352. }
  353. }
  354. if (history[i] == NULL) {
  355. printf("%s: Null entry\n", cmd);
  356. return;
  357. }
  358. strcpy(cmd, history[i]);
  359. } else if (*cmd == 'h' && cmd[1] == '\0') {
  360. for (i=0; i<HISTORY_SIZE; i++) {
  361. if (history[i] != NULL)
  362. printf("%2d: %s\n", i+1, history[i]);
  363. }
  364. return;
  365. } else if (*cmd != '\0') {
  366. if (history[HISTORY_SIZE-1] != NULL)
  367. free(history[HISTORY_SIZE-1]);
  368. for (i=HISTORY_SIZE-1; i>0; i--)
  369. history[i] = history[i-1];
  370. history[0] = strdup(cmd);
  371. }
  372. }
  373. #endif
  374. if (c = strchr(cmd, '&')) {
  375. *c = '\0';
  376. bg = 1;
  377. } else
  378. bg = 0;
  379. /* Set the last exit code */
  380. setenv("?", last_exit_code, 1);
  381. if ((cmd = expandenvvar(cmd)) == NULL)
  382. return;
  383. if ((*cmd == '\0') || !makeargs(cmd, &argc, &argv))
  384. return;
  385. /*
  386. * Search for the command in the alias table.
  387. * If it is found, then replace the command name with
  388. * the alias, and append any other arguments to it.
  389. */
  390. alias = findalias(argv[0]);
  391. if (alias) {
  392. cmd = buf;
  393. strcpy(cmd, alias->value);
  394. while (--argc > 0) {
  395. strcat(cmd, " ");
  396. strcat(cmd, *++argv);
  397. }
  398. if (!makeargs(cmd, &argc, &argv))
  399. return;
  400. }
  401. /*
  402. * BASH-style variable setting
  403. */
  404. if (argc == 1) {
  405. c = index(argv[0], '=');
  406. if (c > argv[0]) {
  407. *c++ = '\0';
  408. setenv(argv[0], c, 1);
  409. return;
  410. }
  411. }
  412. /*
  413. * Now look for the command in the builtin table, and execute
  414. * the command if found.
  415. */
  416. #ifdef FAVOUR_EXTERNAL_COMMANDS
  417. if (!command_in_path(argv[0]))
  418. #endif
  419. if (trybuiltin(argc, argv))
  420. return;
  421. /*
  422. * Not found, run the program along the PATH list.
  423. */
  424. runcmd(cmd, bg, argc, argv);
  425. }
  426. #ifdef FAVOUR_EXTERNAL_COMMANDS
  427. /*
  428. * return true if we find this command in our
  429. * path.
  430. */
  431. static BOOL
  432. command_in_path(char *cmd)
  433. {
  434. struct stat stat_buf;
  435. if (strchr(cmd, '/') == 0) {
  436. char * path;
  437. static char path_copy[PATHLEN];
  438. /* Search path for binary */
  439. for (path = getenv("PATH"); path && *path; ) {
  440. char * p2;
  441. strcpy(path_copy, path);
  442. if (p2 = strchr(path_copy, ':')) {
  443. *p2 = '\0';
  444. }
  445. if (strlen(path_copy))
  446. strcat(path_copy, "/");
  447. strcat(path_copy, cmd);
  448. if (!stat(path_copy, &stat_buf) && (stat_buf.st_mode & 0111))
  449. return(TRUE);
  450. p2 = strchr(path, ':');
  451. if (p2)
  452. path = p2 + 1;
  453. else
  454. path = 0;
  455. }
  456. } else if (!stat(cmd, &stat_buf) && (stat_buf.st_mode & 0111))
  457. return(TRUE);
  458. return(FALSE);
  459. }
  460. #endif /* FAVOUR_EXTERNAL_COMMANDS */
  461. /*
  462. * Try to execute a built-in command.
  463. * Returns TRUE if the command is a built in, whether or not the
  464. * command succeeds. Returns FALSE if this is not a built-in command.
  465. */
  466. static BOOL
  467. trybuiltin(argc, argv)
  468. char **argv;
  469. {
  470. CMDTAB *cmdptr;
  471. int oac;
  472. int newargc;
  473. int matches;
  474. int i;
  475. char *newargv[MAXARGS];
  476. char *nametable[MAXARGS];
  477. cmdptr = cmdtab - 1;
  478. do {
  479. cmdptr++;
  480. if (cmdptr->name[0] == 0)
  481. return FALSE;
  482. } while (strcmp(argv[0], cmdptr->name));
  483. /*
  484. * Give a usage string if the number of arguments is too large
  485. * or too small.
  486. */
  487. if ((argc < cmdptr->minargs) || (argc > cmdptr->maxargs)) {
  488. fprintf(stderr, "usage: %s %s\n",
  489. cmdptr->name, cmdptr->usage);
  490. fflush(stderr);
  491. return TRUE;
  492. }
  493. /*
  494. * Check here for several special commands which do not
  495. * have wildcarding done for them.
  496. */
  497. /* if (cmdptr->func == do_prompt) {
  498. (*cmdptr->func)(argc, argv);
  499. return TRUE;
  500. }
  501. */
  502. /*
  503. * Now for each command argument, see if it is a wildcard, and if
  504. * so, replace the argument with the list of matching filenames.
  505. */
  506. newargv[0] = argv[0];
  507. newargc = 1;
  508. oac = 0;
  509. while (++oac < argc) {
  510. if (argv[oac][0] == '"' || argv[oac][0] == '\'') {
  511. argv[oac]++;
  512. matches = 0;
  513. }
  514. else {
  515. matches = expandwildcards(argv[oac], MAXARGS, nametable);
  516. if (matches < 0)
  517. return TRUE;
  518. }
  519. if ((newargc + matches) >= MAXARGS) {
  520. fprintf(stderr, "Too many arguments\n");
  521. return TRUE;
  522. }
  523. if (matches == 0)
  524. newargv[newargc++] = argv[oac];
  525. for (i = 0; i < matches; i++)
  526. newargv[newargc++] = nametable[i];
  527. }
  528. (*cmdptr->func)(newargc, newargv);
  529. return TRUE;
  530. }
  531. /*
  532. * Execute the specified command.
  533. */
  534. static void
  535. runcmd(cmd, bg, argc, argv)
  536. char *cmd;
  537. int bg;
  538. int argc;
  539. char **argv;
  540. {
  541. register char * cp;
  542. BOOL magic;
  543. int pid;
  544. int status;
  545. int oac;
  546. int newargc;
  547. int matches;
  548. int i;
  549. char *newargv[MAXARGS];
  550. char *nametable[MAXARGS];
  551. struct sigaction act;
  552. newargv[0] = argv[0];
  553. #ifdef INTERNAL_PATH_EXPANSION
  554. if (strchr(argv[0], '/') == 0) {
  555. char * path;
  556. struct stat stat_buf;
  557. static char path_copy[PATHLEN];
  558. /* Search path for binary */
  559. for (path = getenv("PATH"); path && *path; ) {
  560. char * p2;
  561. strncpy(path_copy, path, sizeof(path_copy - 1));
  562. if (p2 = strchr(path_copy, ':')) {
  563. *p2 = '\0';
  564. }
  565. if (strlen(path_copy))
  566. strncat(path_copy, "/", sizeof(path_copy));
  567. strncat(path_copy, argv[0], sizeof(path_copy));
  568. if (!stat(path_copy, &stat_buf) && (stat_buf.st_mode & 0111)) {
  569. newargv[0] = path_copy;
  570. break;
  571. }
  572. p2 = strchr(path, ':');
  573. if (p2)
  574. path = p2 + 1;
  575. else
  576. path = 0;
  577. }
  578. }
  579. #endif
  580. /*
  581. * Now for each command argument, see if it is a wildcard, and if
  582. * so, replace the argument with the list of matching filenames.
  583. */
  584. newargc = 1;
  585. oac = 0;
  586. while (++oac < argc) {
  587. if (argv[oac][0] == '"' || argv[oac][0] == '\'') {
  588. argv[oac]++;
  589. matches = 0;
  590. }
  591. else {
  592. matches = expandwildcards(argv[oac], MAXARGS, nametable);
  593. if (matches < 0)
  594. return;
  595. }
  596. if ((newargc + matches) >= MAXARGS) {
  597. fprintf(stderr, "Too many arguments\n");
  598. return;
  599. }
  600. if (matches == 0)
  601. newargv[newargc++] = argv[oac];
  602. for (i = 0; i < matches; i++)
  603. newargv[newargc++] = nametable[i];
  604. }
  605. newargv[newargc] = 0;
  606. magic = FALSE;
  607. /*
  608. for (cp = cmd; *cp; cp++) {
  609. if ((*cp >= 'a') && (*cp <= 'z'))
  610. continue;
  611. if ((*cp >= 'A') && (*cp <= 'Z'))
  612. continue;
  613. if (isdecimal(*cp))
  614. continue;
  615. if (isblank(*cp))
  616. continue;
  617. if ((*cp == '.') || (*cp == '/') || (*cp == '-') ||
  618. (*cp == '+') || (*cp == '=') || (*cp == '_') ||
  619. (*cp == ':') || (*cp == ','))
  620. continue;
  621. magic = TRUE;
  622. }
  623. */
  624. if (magic) {
  625. printf("%s: no such file or directory\n", cmd);
  626. system(cmd);
  627. return;
  628. }
  629. if (!bg)
  630. signal(SIGCHLD, SIG_DFL);
  631. /*
  632. * No magic characters in the expanded command, so do the fork and
  633. * exec ourself. If this fails with ENOEXEC, then run the
  634. * shell anyway since it might be a shell script.
  635. */
  636. if (!(pid = vfork())) {
  637. int ci;
  638. /*
  639. * We are the child, so run the program.
  640. * First close any extra file descriptors we have opened.
  641. * be sure not to modify any globals after the vfork !
  642. */
  643. for (ci = 0; ci < sourcecount; ci++)
  644. if (sourcefiles[ci] != stdin)
  645. close(fileno(sourcefiles[ci]));
  646. signal(SIGINT, SIG_DFL);
  647. signal(SIGQUIT, SIG_DFL);
  648. signal(SIGCHLD, SIG_DFL);
  649. execvp(newargv[0], newargv);
  650. printf("%s: %s\n", newargv[0], (errno == ENOENT) ? "Bad command or file name" : strerror(errno));
  651. _exit(0);
  652. }
  653. if (pid < 0) {
  654. memset(&act, 0, sizeof(act));
  655. act.sa_handler = catchchild;
  656. act.sa_flags = SA_RESTART;
  657. sigaction(SIGCHLD, &act, NULL);
  658. perror("vfork failed");
  659. return;
  660. }
  661. if (bg) {
  662. printf("[%d]\n", pid);
  663. return;
  664. }
  665. if (pid) {
  666. int cpid;
  667. status = 0;
  668. intcrlf = FALSE;
  669. for (;;) {
  670. cpid = wait4(pid, &status, 0, 0);
  671. if ((cpid < 0) && (errno == EINTR))
  672. continue;
  673. if (cpid < 0)
  674. break;
  675. if (cpid != pid) {
  676. fprintf(stderr, "sh %d: child %d died\n", getpid(), cpid);
  677. continue;
  678. }
  679. }
  680. act.sa_handler = catchchild;
  681. memset(&act.sa_mask, 0, sizeof(act.sa_mask));
  682. act.sa_flags = SA_RESTART;
  683. sigaction(SIGCHLD, &act, NULL);
  684. intcrlf = TRUE;
  685. if (WIFEXITED(status)) {
  686. if (WEXITSTATUS(status) == 0)
  687. return;
  688. exit_code = WEXITSTATUS(status);
  689. } else
  690. exit_code = 1;
  691. return;
  692. }
  693. perror(argv[0]);
  694. exit(1);
  695. }
  696. #ifdef CMD_HELP
  697. void
  698. do_help(argc, argv)
  699. char **argv;
  700. {
  701. CMDTAB *cmdptr;
  702. for (cmdptr = cmdtab; cmdptr->name && cmdptr->name[0]; cmdptr++)
  703. printf("%-10s %s\n", cmdptr->name, cmdptr->usage);
  704. }
  705. #endif /* CMD_HELP */
  706. #ifdef CMD_ALIAS
  707. void
  708. do_alias(argc, argv)
  709. char **argv;
  710. {
  711. char *name;
  712. char *value;
  713. ALIAS *alias;
  714. int count;
  715. char buf[CMDLEN];
  716. if (argc < 2) {
  717. count = aliascount;
  718. for (alias = aliastable; count-- > 0; alias++)
  719. printf("%s\t%s\n", alias->name, alias->value);
  720. return;
  721. }
  722. name = argv[1];
  723. if (argc == 2) {
  724. alias = findalias(name);
  725. if (alias)
  726. printf("%s\n", alias->value);
  727. else
  728. fprintf(stderr, "Alias \"%s\" is not defined\n", name);
  729. return;
  730. }
  731. if (strcmp(name, "alias") == 0) {
  732. fprintf(stderr, "Cannot alias \"alias\"\n");
  733. return;
  734. }
  735. if (!makestring(argc - 2, argv + 2, buf, CMDLEN))
  736. return;
  737. value = malloc(strlen(buf) + 1);
  738. if (value == NULL) {
  739. fprintf(stderr, "No memory for alias value\n");
  740. return;
  741. }
  742. strcpy(value, buf);
  743. alias = findalias(name);
  744. if (alias) {
  745. free(alias->value);
  746. alias->value = value;
  747. return;
  748. }
  749. if ((aliascount % ALIASALLOC) == 0) {
  750. count = aliascount + ALIASALLOC;
  751. if (aliastable)
  752. alias = (ALIAS *) realloc(aliastable,
  753. sizeof(ALIAS *) * count);
  754. else
  755. alias = (ALIAS *) malloc(sizeof(ALIAS *) * count);
  756. if (alias == NULL) {
  757. free(value);
  758. fprintf(stderr, "No memory for alias table\n");
  759. return;
  760. }
  761. aliastable = alias;
  762. }
  763. alias = &aliastable[aliascount];
  764. alias->name = malloc(strlen(name) + 1);
  765. if (alias->name == NULL) {
  766. free(value);
  767. fprintf(stderr, "No memory for alias name\n");
  768. return;
  769. }
  770. strcpy(alias->name, name);
  771. alias->value = value;
  772. aliascount++;
  773. }
  774. #endif /* CMD_ALIAS */
  775. /*
  776. * Look up an alias name, and return a pointer to it.
  777. * Returns NULL if the name does not exist.
  778. */
  779. static ALIAS *
  780. findalias(name)
  781. char *name;
  782. {
  783. ALIAS *alias;
  784. int count;
  785. count = aliascount;
  786. for (alias = aliastable; count-- > 0; alias++) {
  787. if (strcmp(name, alias->name) == 0)
  788. return alias;
  789. }
  790. return NULL;
  791. }
  792. void
  793. do_source(argc, argv)
  794. char **argv;
  795. {
  796. readfile(argv[1]);
  797. }
  798. /*void
  799. do_cd(argc, argv)
  800. char **argv;
  801. {
  802. char *name;
  803. name = argv[1];
  804. if (chdir(name))
  805. perror("Unable to chdir to %s");
  806. }*/
  807. void
  808. do_pid(argc, argv)
  809. {
  810. printf("%d\n", getpid());
  811. }
  812. void
  813. do_exec(argc, argv)
  814. char **argv;
  815. {
  816. while (--sourcecount >= 0) {
  817. if (sourcefiles[sourcecount] != stdin)
  818. fclose(sourcefiles[sourcecount]);
  819. }
  820. argv[argc] = NULL;
  821. execvp(argv[1], &argv[1]);
  822. perror(argv[1]);
  823. exit(1);
  824. }
  825. /*void
  826. do_exit(argc, argv)
  827. char **argv;
  828. {
  829. if (argc>1)
  830. exit(atoi(argv[1]));
  831. else
  832. exit(0);
  833. }*/
  834. #ifdef CMD_ALIAS
  835. void
  836. do_unalias(argc, argv)
  837. char **argv;
  838. {
  839. ALIAS *alias;
  840. while (--argc > 0) {
  841. alias = findalias(*++argv);
  842. if (alias == NULL)
  843. continue;
  844. free(alias->name);
  845. free(alias->value);
  846. aliascount--;
  847. alias->name = aliastable[aliascount].name;
  848. alias->value = aliastable[aliascount].value;
  849. }
  850. }
  851. #endif /* CMD_ALIAS */
  852. /*
  853. * Display the prompt string.
  854. */
  855. static void
  856. showprompt()
  857. {
  858. char *cp;
  859. //;'pa990523 changed from 6...
  860. char buf[60];
  861. if ((cp = getenv("PS1")) != NULL) {
  862. printf("%s", cp);
  863. }
  864. else {
  865. *buf = '\0';
  866. getcwd(buf, sizeof(buf) - 1);
  867. printf("%s> ", buf);
  868. }
  869. fflush(stdout);
  870. }
  871. static void
  872. catchint()
  873. {
  874. signal(SIGINT, catchint);
  875. intflag = TRUE;
  876. if (intcrlf)
  877. write(STDOUT, "\n", 1);
  878. }
  879. static void
  880. catchquit()
  881. {
  882. signal(SIGQUIT, catchquit);
  883. intflag = TRUE;
  884. if (intcrlf)
  885. write(STDOUT, "\n", 1);
  886. }
  887. static void
  888. catchchild()
  889. {
  890. char buf[40];
  891. pid_t pid;
  892. int status;
  893. /*signal(SIGCHLD, catchchild);*/ /* Unneeded */
  894. pid = wait4(-1, &status, WUNTRACED, 0);
  895. if (WIFSTOPPED(status))
  896. sprintf(buf, "sh %d: Child %d stopped\n", getpid(), pid);
  897. else
  898. sprintf(buf, "sh %d: Child %d died\n", getpid(), pid);
  899. if (intcrlf)
  900. write(STDOUT, "\n", 1);
  901. write(STDOUT, buf, strlen(buf));
  902. }
  903. /* END CODE */