unix.c 8.5 KB

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