shell.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include "sam.h"
  2. #include "parse.h"
  3. extern jmp_buf mainloop;
  4. char errfile[64];
  5. String plan9cmd; /* null terminated */
  6. Buffer plan9buf;
  7. void checkerrs(void);
  8. int
  9. plan9(File *f, int type, String *s, int nest)
  10. {
  11. long l;
  12. int m;
  13. int pid, fd;
  14. int retcode;
  15. int pipe1[2], pipe2[2];
  16. if(s->s[0]==0 && plan9cmd.s[0]==0)
  17. error(Enocmd);
  18. else if(s->s[0])
  19. Strduplstr(&plan9cmd, s);
  20. if(downloaded){
  21. samerr(errfile);
  22. remove(errfile);
  23. }
  24. if(type!='!' && pipe(pipe1)==-1)
  25. error(Epipe);
  26. if(type=='|')
  27. snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1);
  28. if((pid=fork()) == 0){
  29. if(downloaded){ /* also put nasty fd's into errfile */
  30. fd = create(errfile, 1, 0666L);
  31. if(fd < 0)
  32. fd = create("/dev/null", 1, 0666L);
  33. dup(fd, 2);
  34. close(fd);
  35. /* 2 now points at err file */
  36. if(type == '>')
  37. dup(2, 1);
  38. else if(type=='!'){
  39. dup(2, 1);
  40. fd = open("/dev/null", 0);
  41. dup(fd, 0);
  42. close(fd);
  43. }
  44. }
  45. if(type != '!') {
  46. if(type=='<' || type=='|')
  47. dup(pipe1[1], 1);
  48. else if(type == '>')
  49. dup(pipe1[0], 0);
  50. close(pipe1[0]);
  51. close(pipe1[1]);
  52. }
  53. if(type == '|'){
  54. if(pipe(pipe2) == -1)
  55. exits("pipe");
  56. if((pid = fork())==0){
  57. /*
  58. * It's ok if we get SIGPIPE here
  59. */
  60. close(pipe2[0]);
  61. io = pipe2[1];
  62. if(retcode=!setjmp(mainloop)){ /* assignment = */
  63. char *c;
  64. for(l = 0; l<plan9buf.nc; l+=m){
  65. m = plan9buf.nc-l;
  66. if(m>BLOCKSIZE-1)
  67. m = BLOCKSIZE-1;
  68. bufread(&plan9buf, l, genbuf, m);
  69. genbuf[m] = 0;
  70. c = Strtoc(tmprstr(genbuf, m+1));
  71. Write(pipe2[1], c, strlen(c));
  72. free(c);
  73. }
  74. }
  75. exits(retcode? "error" : 0);
  76. }
  77. if(pid==-1){
  78. fprint(2, "Can't fork?!\n");
  79. exits("fork");
  80. }
  81. dup(pipe2[0], 0);
  82. close(pipe2[0]);
  83. close(pipe2[1]);
  84. }
  85. if(type=='<'){
  86. close(0); /* so it won't read from terminal */
  87. open("/dev/null", 0);
  88. }
  89. execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0);
  90. exits("exec");
  91. }
  92. if(pid == -1)
  93. error(Efork);
  94. if(type=='<' || type=='|'){
  95. int nulls;
  96. if(downloaded && addr.r.p1 != addr.r.p2)
  97. outTl(Hsnarflen, addr.r.p2-addr.r.p1);
  98. snarf(f, addr.r.p1, addr.r.p2, &snarfbuf, 0);
  99. logdelete(f, addr.r.p1, addr.r.p2);
  100. close(pipe1[1]);
  101. io = pipe1[0];
  102. f->tdot.p1 = -1;
  103. f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0, FALSE);
  104. f->ndot.r.p1 = addr.r.p2;
  105. closeio((Posn)-1);
  106. }else if(type=='>'){
  107. close(pipe1[0]);
  108. io = pipe1[1];
  109. bpipeok = 1;
  110. writeio(f);
  111. bpipeok = 0;
  112. closeio((Posn)-1);
  113. }
  114. retcode = waitfor(pid);
  115. if(type=='|' || type=='<')
  116. if(retcode!=0)
  117. warn(Wbadstatus);
  118. if(downloaded)
  119. checkerrs();
  120. if(!nest)
  121. dprint("!\n");
  122. return retcode;
  123. }
  124. void
  125. checkerrs(void)
  126. {
  127. char buf[256];
  128. int f, n, nl;
  129. char *p;
  130. long l;
  131. if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){
  132. if((f=open((char *)errfile, 0)) != -1){
  133. if((n=read(f, buf, sizeof buf-1)) > 0){
  134. for(nl=0,p=buf; nl<3 && p<&buf[n]; p++)
  135. if(*p=='\n')
  136. nl++;
  137. *p = 0;
  138. dprint("%s", buf);
  139. if(p-buf < l-1)
  140. dprint("(sam: more in %s)\n", errfile);
  141. }
  142. close(f);
  143. }
  144. }else
  145. remove((char *)errfile);
  146. }