URI:
       tunix.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tunix.c (5469B)
       ---
            1 #define NOPLAN9DEFINES
            2 #include        "mk.h"
            3 #include        <sys/wait.h>
            4 #include        <signal.h>
            5 #include        <sys/stat.h>
            6 #include        <sys/time.h>
            7 
            8 char        *shell = "/bin/sh";
            9 char        *shellname = "sh";
           10 
           11 extern char **environ;
           12 
           13 static void
           14 mkperror(char *s)
           15 {
           16         fprint(2, "%s: %r\n", s);
           17 }
           18 
           19 void
           20 readenv(void)
           21 {
           22         char **p, *s;
           23         Word *w;
           24 
           25         for(p = environ; *p; p++){
           26 /* rsc 5/5/2004 -- This misparses fn#cd={whatever}
           27                 s = shname(*p);
           28                 if(*s == '=') {
           29                         *s = 0;
           30                         w = newword(s+1);
           31                 } else
           32                         w = newword("");
           33 */
           34                 s = strchr(*p, '=');
           35                 if(s){
           36                         *s = 0;
           37                         w = newword(s+1);
           38                 } else
           39                         w = newword("");
           40                 if (symlook(*p, S_INTERNAL, 0))
           41                         continue;
           42                 s = strdup(*p);
           43                 setvar(s, (void *)w);
           44                 symlook(s, S_EXPORTED, (void*)"")->u.ptr = "";
           45         }
           46 }
           47 
           48 /*
           49  *        done on child side of fork, so parent's env is not affected
           50  *        and we don't care about freeing memory because we're going
           51  *        to exec immediately after this.
           52  */
           53 void
           54 exportenv(Envy *e, Shell *sh)
           55 {
           56         int w, n;
           57         char **p;
           58         Envy *e1;
           59         static char buf[16384];
           60 
           61         n = 0;
           62         for(e1 = e; e1->name; e1++)
           63                 n++;
           64         p = Malloc((n+1)*sizeof(char*));
           65         w = 0;
           66         for(; e->name; e++) {
           67                 if(sh == &rcshell && (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0))
           68                         continue; /* do not write empty string for empty list */
           69                 if(e->values)
           70                         snprint(buf, sizeof buf, "%s=%s", e->name,  wtos(e->values, sh->iws));
           71                 else
           72                         snprint(buf, sizeof buf, "%s=", e->name);
           73                 p[w++] = strdup(buf);
           74         }
           75         p[w] = 0;
           76         environ = p;
           77 }
           78 
           79 int
           80 waitfor(char *msg)
           81 {
           82         int status;
           83         int pid;
           84 
           85         *msg = 0;
           86         pid = wait(&status);
           87         if(pid > 0) {
           88                 if(status&0x7f) {
           89                         if(status&0x80)
           90                                 snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f);
           91                         else
           92                                 snprint(msg, ERRMAX, "signal %d", status&0x7f);
           93                 } else if(status&0xff00)
           94                         snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);
           95         }
           96         return pid;
           97 }
           98 
           99 void
          100 expunge(int pid, char *msg)
          101 {
          102         if(strcmp(msg, "interrupt"))
          103                 kill(pid, SIGINT);
          104         else
          105                 kill(pid, SIGHUP);
          106 }
          107 
          108 int mypid;
          109 
          110 int
          111 shargv(Word *cmd, int extra, char ***pargv)
          112 {
          113         char **argv;
          114         int i, n;
          115         Word *w;
          116 
          117         n = 0;
          118         for(w=cmd; w; w=w->next)
          119                 n++;
          120 
          121         argv = Malloc((n+extra+1)*sizeof(argv[0]));
          122         i = 0;
          123         for(w=cmd; w; w=w->next)
          124                 argv[i++] = w->s;
          125         argv[n] = 0;
          126         *pargv = argv;
          127         return n;
          128 }
          129 
          130 int
          131 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)
          132 {
          133         char *p, **argv;
          134         int tot, n, pid, in[2], out[2];
          135 
          136         if(buf && pipe(out) < 0){
          137                 mkperror("pipe");
          138                 Exit();
          139         }
          140         pid = fork();
          141         mypid = getpid();
          142         if(pid < 0){
          143                 mkperror("mk fork");
          144                 Exit();
          145         }
          146         if(pid == 0){
          147                 if(buf)
          148                         close(out[0]);
          149                 if(pipe(in) < 0){
          150                         mkperror("pipe");
          151                         Exit();
          152                 }
          153                 pid = fork();
          154                 if(pid < 0){
          155                         mkperror("mk fork");
          156                         Exit();
          157                 }
          158                 if(pid != 0){
          159                         dup2(in[0], 0);
          160                         if(buf){
          161                                 dup2(out[1], 1);
          162                                 close(out[1]);
          163                         }
          164                         close(in[0]);
          165                         close(in[1]);
          166                         if (e)
          167                                 exportenv(e, sh);
          168                         n = shargv(shellcmd, 1, &argv);
          169                         argv[n++] = args;
          170                         argv[n] = 0;
          171                         execvp(argv[0], argv);
          172                         mkperror(shell);
          173                         _exit(1);
          174                 }
          175                 close(out[1]);
          176                 close(in[0]);
          177                 if(DEBUG(D_EXEC))
          178                         fprint(1, "starting: %s\n", cmd);
          179                 p = cmd+strlen(cmd);
          180                 while(cmd < p){
          181                         n = write(in[1], cmd, p-cmd);
          182                         if(n < 0)
          183                                 break;
          184                         cmd += n;
          185                 }
          186                 close(in[1]);
          187                 _exit(0);
          188         }
          189         if(buf){
          190                 close(out[1]);
          191                 tot = 0;
          192                 for(;;){
          193                         if (buf->current >= buf->end)
          194                                 growbuf(buf);
          195                         n = read(out[0], buf->current, buf->end-buf->current);
          196                         if(n <= 0)
          197                                 break;
          198                         buf->current += n;
          199                         tot += n;
          200                 }
          201                 if (tot && buf->current[-1] == '\n')
          202                         buf->current--;
          203                 close(out[0]);
          204         }
          205         return pid;
          206 }
          207 
          208 int
          209 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd)
          210 {
          211         int pid, pfd[2];
          212         int n;
          213         char **argv;
          214 
          215         if(DEBUG(D_EXEC))
          216                 fprint(1, "pipecmd='%s'\n", cmd);/**/
          217 
          218         if(fd && pipe(pfd) < 0){
          219                 mkperror("pipe");
          220                 Exit();
          221         }
          222         pid = fork();
          223         if(pid < 0){
          224                 mkperror("mk fork");
          225                 Exit();
          226         }
          227         if(pid == 0){
          228                 if(fd){
          229                         close(pfd[0]);
          230                         dup2(pfd[1], 1);
          231                         close(pfd[1]);
          232                 }
          233                 if(e)
          234                         exportenv(e, sh);
          235                 n = shargv(shellcmd, 2, &argv);
          236                 argv[n++] = "-c";
          237                 argv[n++] = cmd;
          238                 argv[n] = 0;
          239                 execvp(argv[0], argv);
          240                 mkperror(shell);
          241                 _exit(1);
          242         }
          243         if(fd){
          244                 close(pfd[1]);
          245                 *fd = pfd[0];
          246         }
          247         return pid;
          248 }
          249 
          250 void
          251 Exit(void)
          252 {
          253         while(wait(0) >= 0)
          254                 ;
          255         exits("error");
          256 }
          257 
          258 static        struct
          259 {
          260         int        sig;
          261         char        *msg;
          262 }        sigmsgs[] =
          263 {
          264         SIGALRM,        "alarm",
          265         SIGFPE,                "sys: fp: fptrap",
          266         SIGPIPE,        "sys: write on closed pipe",
          267         SIGILL,                "sys: trap: illegal instruction",
          268 /*        SIGSEGV,        "sys: segmentation violation", */
          269         0,                0
          270 };
          271 
          272 static void
          273 notifyf(int sig)
          274 {
          275         int i;
          276 
          277         for(i = 0; sigmsgs[i].msg; i++)
          278                 if(sigmsgs[i].sig == sig)
          279                         killchildren(sigmsgs[i].msg);
          280 
          281         /* should never happen */
          282         signal(sig, SIG_DFL);
          283         kill(getpid(), sig);
          284 }
          285 
          286 void
          287 catchnotes(void)
          288 {
          289         int i;
          290 
          291         for(i = 0; sigmsgs[i].msg; i++)
          292                 signal(sigmsgs[i].sig, notifyf);
          293 }
          294 
          295 char*
          296 maketmp(int *pfd)
          297 {
          298         static char temp[] = "/tmp/mkargXXXXXX";
          299         static char buf[100];
          300         int fd;
          301 
          302         strcpy(buf, temp);
          303         fd = mkstemp(buf);
          304         if(fd < 0)
          305                 return 0;
          306         *pfd = fd;
          307         return buf;
          308 }
          309 
          310 int
          311 chgtime(char *name)
          312 {
          313         if(access(name, 0) >= 0)
          314                 return utimes(name, 0);
          315         return close(creat(name, 0666));
          316 }
          317 
          318 void
          319 rcopy(char **to, Resub *match, int n)
          320 {
          321         int c;
          322         char *p;
          323 
          324         *to = match->s.sp;                /* stem0 matches complete target */
          325         for(to++, match++; --n > 0; to++, match++){
          326                 if(match->s.sp && match->e.ep){
          327                         p = match->e.ep;
          328                         c = *p;
          329                         *p = 0;
          330                         *to = strdup(match->s.sp);
          331                         *p = c;
          332                 }
          333                 else
          334                         *to = 0;
          335         }
          336 }
          337 
          338 unsigned long
          339 mkmtime(char *name)
          340 {
          341         struct stat st;
          342 
          343         if(stat(name, &st) < 0)
          344                 return 0;
          345 
          346         return st.st_mtime;
          347 }