unix.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*
  2. * Unix versions of system-specific functions
  3. * By convention, exported routines herein have names beginning with an
  4. * upper case letter.
  5. */
  6. #include "rc.h"
  7. #include "io.h"
  8. #include "exec.h"
  9. #include "getflags.h"
  10. #include <errno.h>
  11. char *Rcmain = "/usr/lib/rcmain";
  12. char *Fdprefix = "/dev/fd/";
  13. void execfinit(void);
  14. struct builtin Builtin[] = {
  15. "cd", execcd,
  16. "whatis", execwhatis,
  17. "eval", execeval,
  18. "exec", execexec, /* but with popword first */
  19. "exit", execexit,
  20. "shift", execshift,
  21. "wait", execwait,
  22. "umask", execumask,
  23. ".", execdot,
  24. "finit", execfinit,
  25. "flag", execflag,
  26. 0
  27. };
  28. #define SEP '\1'
  29. char **environp;
  30. struct word*
  31. enval(s)
  32. register char *s;
  33. {
  34. char *t, c;
  35. struct word *v;
  36. for(t = s;*t && *t!=SEP;t++);
  37. c=*t;
  38. *t='\0';
  39. v = newword(s, c=='\0'?(struct word *)0:enval(t+1));
  40. *t = c;
  41. return v;
  42. }
  43. void
  44. Vinit(void)
  45. {
  46. extern char **environ;
  47. char *s;
  48. char **env = environ;
  49. environp = env;
  50. for(;*env;env++){
  51. for(s=*env;*s && *s!='(' && *s!='=';s++);
  52. switch(*s){
  53. case '\0':
  54. pfmt(err, "environment %q?\n", *env);
  55. break;
  56. case '=':
  57. *s='\0';
  58. setvar(*env, enval(s+1));
  59. *s='=';
  60. break;
  61. case '(': /* ignore functions for now */
  62. break;
  63. }
  64. }
  65. }
  66. char **envp;
  67. void
  68. Xrdfn(void)
  69. {
  70. char *s;
  71. int len;
  72. for(;*envp;envp++){
  73. for(s=*envp;*s && *s!='(' && *s!='=';s++);
  74. switch(*s){
  75. case '\0':
  76. pfmt(err, "environment %q?\n", *envp);
  77. break;
  78. case '=': /* ignore variables */
  79. break;
  80. case '(': /* Bourne again */
  81. s=*envp+3;
  82. envp++;
  83. len = strlen(s);
  84. s[len]='\n';
  85. execcmds(opencore(s, len+1));
  86. s[len]='\0';
  87. return;
  88. }
  89. }
  90. Xreturn();
  91. }
  92. union code rdfns[4];
  93. void
  94. execfinit(void)
  95. {
  96. static int first = 1;
  97. if(first){
  98. rdfns[0].i = 1;
  99. rdfns[1].f = Xrdfn;
  100. rdfns[2].f = Xjump;
  101. rdfns[3].i = 1;
  102. first = 0;
  103. }
  104. Xpopm();
  105. envp = environp;
  106. start(rdfns, 1, runq->local);
  107. }
  108. int
  109. cmpenv(const void *aa, const void *ab)
  110. {
  111. char **a = aa, **b = ab;
  112. return strcmp(*a, *b);
  113. }
  114. char **
  115. mkenv(void)
  116. {
  117. char **env, **ep, *p, *q;
  118. struct var **h, *v;
  119. struct word *a;
  120. int nvar = 0, nchr = 0, sep;
  121. /*
  122. * Slightly kludgy loops look at locals then globals.
  123. * locals no longer exist - geoff
  124. */
  125. for(h = gvar-1; h != &gvar[NVAR]; h++)
  126. for(v = h >= gvar? *h: runq->local; v ;v = v->next){
  127. if((v==vlook(v->name)) && v->val){
  128. nvar++;
  129. nchr+=strlen(v->name)+1;
  130. for(a = v->val;a;a = a->next)
  131. nchr+=strlen(a->word)+1;
  132. }
  133. if(v->fn){
  134. nvar++;
  135. nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
  136. }
  137. }
  138. env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);
  139. ep = env;
  140. p = (char *)&env[nvar+1];
  141. for(h = gvar-1; h != &gvar[NVAR]; h++)
  142. for(v = h >= gvar? *h: runq->local;v;v = v->next){
  143. if((v==vlook(v->name)) && v->val){
  144. *ep++=p;
  145. q = v->name;
  146. while(*q) *p++=*q++;
  147. sep='=';
  148. for(a = v->val;a;a = a->next){
  149. *p++=sep;
  150. sep = SEP;
  151. q = a->word;
  152. while(*q) *p++=*q++;
  153. }
  154. *p++='\0';
  155. }
  156. if(v->fn){
  157. *ep++=p;
  158. *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
  159. *p++='f'; *p++='n'; *p++=' ';
  160. q = v->name;
  161. while(*q) *p++=*q++;
  162. *p++=' ';
  163. q = v->fn[v->pc-1].s;
  164. while(*q) *p++=*q++;
  165. *p++='\0';
  166. }
  167. }
  168. *ep = 0;
  169. qsort((void *)env, nvar, sizeof ep[0], cmpenv);
  170. return env;
  171. }
  172. char *sigmsg[] = {
  173. /* 0 normal */ 0,
  174. /* 1 SIGHUP */ "Hangup",
  175. /* 2 SIGINT */ 0,
  176. /* 3 SIGQUIT */ "Quit",
  177. /* 4 SIGILL */ "Illegal instruction",
  178. /* 5 SIGTRAP */ "Trace/BPT trap",
  179. /* 6 SIGIOT */ "abort",
  180. /* 7 SIGEMT */ "EMT trap",
  181. /* 8 SIGFPE */ "Floating exception",
  182. /* 9 SIGKILL */ "Killed",
  183. /* 10 SIGBUS */ "Bus error",
  184. /* 11 SIGSEGV */ "Memory fault",
  185. /* 12 SIGSYS */ "Bad system call",
  186. /* 13 SIGPIPE */ 0,
  187. /* 14 SIGALRM */ "Alarm call",
  188. /* 15 SIGTERM */ "Terminated",
  189. /* 16 unused */ "signal 16",
  190. /* 17 SIGSTOP */ "Process stopped",
  191. /* 18 unused */ "signal 18",
  192. /* 19 SIGCONT */ "Process continued",
  193. /* 20 SIGCHLD */ "Child death",
  194. };
  195. void
  196. Waitfor(int pid, int persist)
  197. {
  198. int wpid, sig;
  199. struct thread *p;
  200. int wstat;
  201. char wstatstr[12];
  202. for(;;){
  203. errno = 0;
  204. wpid = wait(&wstat);
  205. if(errno==EINTR && persist)
  206. continue;
  207. if(wpid==-1)
  208. break;
  209. sig = wstat&0177;
  210. if(sig==0177){
  211. pfmt(err, "trace: ");
  212. sig = (wstat>>8)&0177;
  213. }
  214. if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){
  215. if(pid!=wpid)
  216. pfmt(err, "%d: ", wpid);
  217. if(sig<=(sizeof sigmsg/sizeof sigmsg[0]))
  218. pfmt(err, "%s", sigmsg[sig]);
  219. else if(sig==0177) pfmt(err, "stopped by ptrace");
  220. else pfmt(err, "signal %d", sig);
  221. if(wstat&0200)pfmt(err, " -- core dumped");
  222. pfmt(err, "\n");
  223. }
  224. wstat = sig?sig+1000:(wstat>>8)&0xFF;
  225. if(wpid==pid){
  226. inttoascii(wstatstr, wstat);
  227. setstatus(wstatstr);
  228. break;
  229. }
  230. else{
  231. for(p = runq->ret;p;p = p->ret)
  232. if(p->pid==wpid){
  233. p->pid=-1;
  234. inttoascii(p->status, wstat);
  235. break;
  236. }
  237. }
  238. }
  239. }
  240. char **
  241. mkargv(a)
  242. register struct word *a;
  243. {
  244. char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
  245. char **argp = argv+1; /* leave one at front for runcoms */
  246. for(;a;a = a->next)
  247. *argp++=a->word;
  248. *argp = 0;
  249. return argv;
  250. }
  251. void
  252. Updenv(void)
  253. {
  254. }
  255. void
  256. Execute(struct word *args, struct word *path)
  257. {
  258. char *msg="not found";
  259. int txtbusy = 0;
  260. char **env = mkenv();
  261. char **argv = mkargv(args);
  262. char file[512];
  263. for(;path;path = path->next){
  264. strcpy(file, path->word);
  265. if(file[0])
  266. strcat(file, "/");
  267. strcat(file, argv[1]);
  268. ReExec:
  269. execve(file, argv+1, env);
  270. switch(errno){
  271. case ENOEXEC:
  272. pfmt(err, "%s: Bourne again\n", argv[1]);
  273. argv[0]="sh";
  274. argv[1] = strdup(file);
  275. execve("/bin/sh", argv, env);
  276. goto Bad;
  277. case ETXTBSY:
  278. if(++txtbusy!=5){
  279. sleep(txtbusy);
  280. goto ReExec;
  281. }
  282. msg="text busy"; goto Bad;
  283. case EACCES:
  284. msg="no access";
  285. break;
  286. case ENOMEM:
  287. msg="not enough memory"; goto Bad;
  288. case E2BIG:
  289. msg="too big"; goto Bad;
  290. }
  291. }
  292. Bad:
  293. pfmt(err, "%s: %s\n", argv[1], msg);
  294. efree((char *)env);
  295. efree((char *)argv);
  296. }
  297. #define NDIR 14 /* should get this from param.h */
  298. Globsize(p)
  299. register char *p;
  300. {
  301. int isglob = 0, globlen = NDIR+1;
  302. for(;*p;p++){
  303. if(*p==GLOB){
  304. p++;
  305. if(*p!=GLOB)
  306. isglob++;
  307. globlen+=*p=='*'?NDIR:1;
  308. }
  309. else
  310. globlen++;
  311. }
  312. return isglob?globlen:0;
  313. }
  314. #include <sys/types.h>
  315. #include <dirent.h>
  316. #define NDIRLIST 50
  317. DIR *dirlist[NDIRLIST];
  318. Opendir(name)
  319. char *name;
  320. {
  321. DIR **dp;
  322. for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++)
  323. if(*dp==0){
  324. *dp = opendir(name);
  325. return *dp?dp-dirlist:-1;
  326. }
  327. return -1;
  328. }
  329. int
  330. Readdir(int f, char *p, int onlydirs)
  331. {
  332. struct dirent *dp = readdir(dirlist[f]);
  333. if(dp==0)
  334. return 0;
  335. strcpy(p, dp->d_name);
  336. return 1;
  337. }
  338. void
  339. Closedir(int f)
  340. {
  341. closedir(dirlist[f]);
  342. dirlist[f] = 0;
  343. }
  344. char *Signame[] = {
  345. "sigexit", "sighup", "sigint", "sigquit",
  346. "sigill", "sigtrap", "sigiot", "sigemt",
  347. "sigfpe", "sigkill", "sigbus", "sigsegv",
  348. "sigsys", "sigpipe", "sigalrm", "sigterm",
  349. "sig16", "sigstop", "sigtstp", "sigcont",
  350. "sigchld", "sigttin", "sigttou", "sigtint",
  351. "sigxcpu", "sigxfsz", "sig26", "sig27",
  352. "sig28", "sig29", "sig30", "sig31",
  353. 0,
  354. };
  355. void
  356. gettrap(int sig)
  357. {
  358. signal(sig, gettrap);
  359. trap[sig]++;
  360. ntrap++;
  361. if(ntrap>=NSIG){
  362. pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig);
  363. signal(SIGABRT, (void (*)())0);
  364. kill(getpid(), SIGABRT);
  365. }
  366. }
  367. void
  368. Trapinit(void)
  369. {
  370. int i;
  371. void (*sig)();
  372. if(1 || flag['d']){ /* wrong!!! */
  373. sig = signal(SIGINT, gettrap);
  374. if(sig==SIG_IGN)
  375. signal(SIGINT, SIG_IGN);
  376. }
  377. else{
  378. for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){
  379. sig = signal(i, gettrap);
  380. if(sig==SIG_IGN)
  381. signal(i, SIG_IGN);
  382. }
  383. }
  384. }
  385. Unlink(name)
  386. char *name;
  387. {
  388. return unlink(name);
  389. }
  390. Write(fd, buf, cnt)
  391. char *buf;
  392. {
  393. return write(fd, buf, cnt);
  394. }
  395. Read(fd, buf, cnt)
  396. char *buf;
  397. {
  398. return read(fd, buf, cnt);
  399. }
  400. Seek(fd, cnt, whence)
  401. long cnt;
  402. {
  403. return lseek(fd, cnt, whence);
  404. }
  405. Executable(file)
  406. char *file;
  407. {
  408. return(access(file, 01)==0);
  409. }
  410. Creat(file)
  411. char *file;
  412. {
  413. return creat(file, 0666);
  414. }
  415. Dup(a, b){
  416. return dup2(a, b);
  417. }
  418. Dup1(a){
  419. return dup(a);
  420. }
  421. /*
  422. * Wrong: should go through components of a|b|c and return the maximum.
  423. */
  424. void
  425. Exit(char *stat)
  426. {
  427. int n = 0;
  428. while(*stat){
  429. if(*stat!='|'){
  430. if(*stat<'0' || '9'<*stat)
  431. exit(1);
  432. else n = n*10+*stat-'0';
  433. }
  434. stat++;
  435. }
  436. exit(n);
  437. }
  438. Eintr(){
  439. return errno==EINTR;
  440. }
  441. void
  442. Noerror()
  443. {
  444. errno = 0;
  445. }
  446. Isatty(fd){
  447. return isatty(fd);
  448. }
  449. void
  450. Abort()
  451. {
  452. abort();
  453. }
  454. void
  455. execumask(void) /* wrong -- should fork before writing */
  456. {
  457. int m;
  458. struct io out[1];
  459. switch(count(runq->argv->words)){
  460. default:
  461. pfmt(err, "Usage: umask [umask]\n");
  462. setstatus("umask usage");
  463. poplist();
  464. return;
  465. case 2:
  466. umask(octal(runq->argv->words->next->word));
  467. break;
  468. case 1:
  469. umask(m = umask(0));
  470. out->fd = mapfd(1);
  471. out->bufp = out->buf;
  472. out->ebuf=&out->buf[NBUF];
  473. out->strp = 0;
  474. pfmt(out, "%o\n", m);
  475. break;
  476. }
  477. setstatus("");
  478. poplist();
  479. }
  480. void
  481. Memcpy(a, b, n)
  482. char *a, *b;
  483. {
  484. memmove(a, b, n);
  485. }
  486. void*
  487. Malloc(unsigned long n)
  488. {
  489. return (void *)malloc(n);
  490. }
  491. void
  492. errstr(char *buf, int len)
  493. {
  494. strncpy(buf, strerror(errno), len);
  495. }
  496. int
  497. needsrcquote(int c)
  498. {
  499. if(c <= ' ')
  500. return 1;
  501. if(strchr("`^#*[]=|\\?${}()'<>&;", c))
  502. return 1;
  503. return 0;
  504. }
  505. int
  506. rfork(int bits)
  507. {
  508. return fork();
  509. }
  510. int *waitpids;
  511. int nwaitpids;
  512. void
  513. addwaitpid(int pid)
  514. {
  515. waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
  516. if(waitpids == 0)
  517. panic("Can't realloc %d waitpids", nwaitpids+1);
  518. waitpids[nwaitpids++] = pid;
  519. }
  520. void
  521. delwaitpid(int pid)
  522. {
  523. int r, w;
  524. for(r=w=0; r<nwaitpids; r++)
  525. if(waitpids[r] != pid)
  526. waitpids[w++] = waitpids[r];
  527. nwaitpids = w;
  528. }
  529. void
  530. clearwaitpids(void)
  531. {
  532. nwaitpids = 0;
  533. }
  534. int
  535. havewaitpid(int pid)
  536. {
  537. int i;
  538. for(i=0; i<nwaitpids; i++)
  539. if(waitpids[i] == pid)
  540. return 1;
  541. return 0;
  542. }