shell.c 3.1 KB

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