unix.c 8.4 KB

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