unix.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       unix.c (5290B)
       ---
            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 i;
           57         char **p;
           58         static char buf[16384];
           59 
           60         p = 0;
           61         for(i = 0; e->name; e++, i++) {
           62                 p = (char**) Realloc(p, (i+2)*sizeof(char*));
           63                 if(e->values)
           64                         snprint(buf, sizeof buf, "%s=%s", e->name,  wtos(e->values, sh->iws));
           65                 else
           66                         snprint(buf, sizeof buf, "%s=", e->name);
           67                 p[i] = strdup(buf);
           68         }
           69         p[i] = 0;
           70         environ = p;
           71 }
           72 
           73 int
           74 waitfor(char *msg)
           75 {
           76         int status;
           77         int pid;
           78 
           79         *msg = 0;
           80         pid = wait(&status);
           81         if(pid > 0) {
           82                 if(status&0x7f) {
           83                         if(status&0x80)
           84                                 snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f);
           85                         else
           86                                 snprint(msg, ERRMAX, "signal %d", status&0x7f);
           87                 } else if(status&0xff00)
           88                         snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);
           89         }
           90         return pid;
           91 }
           92 
           93 void
           94 expunge(int pid, char *msg)
           95 {
           96         if(strcmp(msg, "interrupt"))
           97                 kill(pid, SIGINT);
           98         else
           99                 kill(pid, SIGHUP);
          100 }
          101 
          102 int mypid;
          103 
          104 int
          105 shargv(Word *cmd, int extra, char ***pargv)
          106 {
          107         char **argv;
          108         int i, n;
          109         Word *w;
          110 
          111         n = 0;
          112         for(w=cmd; w; w=w->next)
          113                 n++;
          114         
          115         argv = Malloc((n+extra+1)*sizeof(argv[0]));
          116         i = 0;
          117         for(w=cmd; w; w=w->next)
          118                 argv[i++] = w->s;
          119         argv[n] = 0;
          120         *pargv = argv;
          121         return n;
          122 }        
          123 
          124 int
          125 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)
          126 {
          127         char *p, **argv;
          128         int tot, n, pid, in[2], out[2];
          129 
          130         if(buf && pipe(out) < 0){
          131                 mkperror("pipe");
          132                 Exit();
          133         }
          134         pid = fork();
          135         mypid = getpid();
          136         if(pid < 0){
          137                 mkperror("mk fork");
          138                 Exit();
          139         }
          140         if(pid == 0){
          141                 if(buf)
          142                         close(out[0]);
          143                 if(pipe(in) < 0){
          144                         mkperror("pipe");
          145                         Exit();
          146                 }
          147                 pid = fork();
          148                 if(pid < 0){
          149                         mkperror("mk fork");
          150                         Exit();
          151                 }
          152                 if(pid != 0){
          153                         dup2(in[0], 0);
          154                         if(buf){
          155                                 dup2(out[1], 1);
          156                                 close(out[1]);
          157                         }
          158                         close(in[0]);
          159                         close(in[1]);
          160                         if (e)
          161                                 exportenv(e, sh);
          162                         n = shargv(shellcmd, 1, &argv);
          163                         argv[n++] = args;
          164                         argv[n] = 0;
          165                         execvp(argv[0], argv);
          166                         mkperror(shell);
          167                         _exit(1);
          168                 }
          169                 close(out[1]);
          170                 close(in[0]);
          171                 if(DEBUG(D_EXEC))
          172                         fprint(1, "starting: %s\n", cmd);
          173                 p = cmd+strlen(cmd);
          174                 while(cmd < p){
          175                         n = write(in[1], cmd, p-cmd);
          176                         if(n < 0)
          177                                 break;
          178                         cmd += n;
          179                 }
          180                 close(in[1]);
          181                 _exit(0);
          182         }
          183         if(buf){
          184                 close(out[1]);
          185                 tot = 0;
          186                 for(;;){
          187                         if (buf->current >= buf->end)
          188                                 growbuf(buf);
          189                         n = read(out[0], buf->current, buf->end-buf->current);
          190                         if(n <= 0)
          191                                 break;
          192                         buf->current += n;
          193                         tot += n;
          194                 }
          195                 if (tot && buf->current[-1] == '\n')
          196                         buf->current--;
          197                 close(out[0]);
          198         }
          199         return pid;
          200 }
          201 
          202 int
          203 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd)
          204 {
          205         int pid, pfd[2];
          206         int n;
          207         char **argv;
          208 
          209         if(DEBUG(D_EXEC))
          210                 fprint(1, "pipecmd='%s'\n", cmd);/**/
          211 
          212         if(fd && pipe(pfd) < 0){
          213                 mkperror("pipe");
          214                 Exit();
          215         }
          216         pid = fork();
          217         if(pid < 0){
          218                 mkperror("mk fork");
          219                 Exit();
          220         }
          221         if(pid == 0){
          222                 if(fd){
          223                         close(pfd[0]);
          224                         dup2(pfd[1], 1);
          225                         close(pfd[1]);
          226                 }
          227                 if(e)
          228                         exportenv(e, sh);
          229                 n = shargv(shellcmd, 2, &argv);
          230                 argv[n++] = "-c";
          231                 argv[n++] = cmd;
          232                 argv[n] = 0;
          233                 execvp(argv[0], argv);
          234                 mkperror(shell);
          235                 _exit(1);
          236         }
          237         if(fd){
          238                 close(pfd[1]);
          239                 *fd = pfd[0];
          240         }
          241         return pid;
          242 }
          243 
          244 void
          245 Exit(void)
          246 {
          247         while(wait(0) >= 0)
          248                 ;
          249         exits("error");
          250 }
          251 
          252 static        struct
          253 {
          254         int        sig;
          255         char        *msg;
          256 }        sigmsgs[] =
          257 {
          258         SIGALRM,        "alarm",
          259         SIGFPE,                "sys: fp: fptrap",
          260         SIGPIPE,        "sys: write on closed pipe",
          261         SIGILL,                "sys: trap: illegal instruction",
          262 /*        SIGSEGV,        "sys: segmentation violation", */
          263         0,                0
          264 };
          265 
          266 static void
          267 notifyf(int sig)
          268 {
          269         int i;
          270 
          271         for(i = 0; sigmsgs[i].msg; i++)
          272                 if(sigmsgs[i].sig == sig)
          273                         killchildren(sigmsgs[i].msg);
          274 
          275         /* should never happen */
          276         signal(sig, SIG_DFL);
          277         kill(getpid(), sig);
          278 }
          279 
          280 void
          281 catchnotes(void)
          282 {
          283         int i;
          284 
          285         for(i = 0; sigmsgs[i].msg; i++)
          286                 signal(sigmsgs[i].sig, notifyf);
          287 }
          288 
          289 char*
          290 maketmp(int *pfd)
          291 {
          292         static char temp[] = "/tmp/mkargXXXXXX";
          293         static char buf[100];
          294         int fd;
          295 
          296         strcpy(buf, temp);
          297         fd = mkstemp(buf);
          298         if(fd < 0)
          299                 return 0;
          300         *pfd = fd;
          301         return buf;
          302 }
          303 
          304 int
          305 chgtime(char *name)
          306 {
          307         if(access(name, 0) >= 0)
          308                 return utimes(name, 0);
          309         return close(creat(name, 0666));
          310 }
          311 
          312 void
          313 rcopy(char **to, Resub *match, int n)
          314 {
          315         int c;
          316         char *p;
          317 
          318         *to = match->s.sp;                /* stem0 matches complete target */
          319         for(to++, match++; --n > 0; to++, match++){
          320                 if(match->s.sp && match->e.ep){
          321                         p = match->e.ep;
          322                         c = *p;
          323                         *p = 0;
          324                         *to = strdup(match->s.sp);
          325                         *p = c;
          326                 }
          327                 else
          328                         *to = 0;
          329         }
          330 }
          331 
          332 unsigned long
          333 mkmtime(char *name)
          334 {
          335         struct stat st;
          336 
          337         if(stat(name, &st) < 0)
          338                 return 0;
          339 
          340         return st.st_mtime;
          341 }