home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / pcomm / part03 / expand.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-17  |  2.3 KB  |  124 lines

  1. /*
  2.  * Do file name expansion with 'native' shell.  Using the native shell
  3.  * (as described in the SHELL environmental variable) allows for csh or
  4.  * ksh abbreviations that sh doesn't recognize.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <signal.h>
  9.  
  10. char *
  11. expand(input)
  12. char *input;
  13. {
  14.     FILE *pfp, *native_popen();
  15.     char *ans, buf[1024], *strpbrk(), *strdup();
  16.     extern char *null_ptr;
  17.     void free_ptr();
  18.  
  19.                     /* same rules as strdup() */
  20.     if (input == NULL)
  21.         return(NULL);
  22.     if (*input == NULL)
  23.         return(null_ptr);
  24.                     /* any thing to expand ? */
  25.     ans = strdup(input);
  26.     if (!strpbrk(input, "$*{}[]\\?~"))
  27.         return(ans);
  28.                     /* popen an echo */
  29.     sprintf(buf, "echo %s", input);
  30.  
  31.     pfp = native_popen(buf, "r");
  32.     fgets(buf, 1024, pfp);
  33.     native_pclose(pfp);
  34.  
  35.     if (!strlen(buf))
  36.         return(ans);
  37.                     /* zap the line feed */
  38.     buf[strlen(buf)-1] = NULL;
  39.  
  40.     free_ptr(ans);
  41.     ans = strdup(buf);
  42.     return(ans);
  43. }
  44.  
  45. #define    tst(a,b) (*mode == 'r'? (b) : (a))
  46. #define    RDR    0
  47. #define    WTR    1
  48. static int popen_pid[20];
  49.  
  50. FILE *
  51. native_popen(cmd, mode)
  52. char *cmd, *mode;
  53. {
  54.     int myside, hisside, pid, p[2];
  55.     char *shellpath, *shell, *flags, *getenv(), *strrchr();
  56.     void _exit();
  57.  
  58.     if (pipe(p) < 0)
  59.         return NULL;
  60.  
  61.     myside = tst(p[WTR], p[RDR]);
  62.     hisside = tst(p[RDR], p[WTR]);
  63.                     /* get the environmental variable */
  64.     shellpath = getenv("SHELL");
  65.     if (shellpath == NULL || strlen(shellpath) == 0)
  66.         shellpath = "/bin/sh";
  67.  
  68.     shell = strrchr(shellpath, '/') + 1;
  69.                     /* fix up the flags */
  70.     if (!strcmp(shell, "csh"))
  71.         flags = "-fc";
  72.     else
  73.         flags = "-c";        /* Korn shell too */
  74.  
  75.     if (!(pid = fork())) {
  76.         int stdio;
  77.                     /* no error messages please */
  78.         close(2);
  79. #ifdef SGID
  80.         setgid(getgid());
  81. #endif /* SGID */
  82.         stdio = tst(0, 1);
  83.         close(myside);
  84.         close(stdio);
  85.         fcntl(hisside, 0, stdio);
  86.         close(hisside);
  87.         execl(shellpath, shell, flags, cmd, 0);
  88.         _exit(1);
  89.     }
  90.     if (pid == -1) {
  91.         close(myside);
  92.         close(hisside);
  93.         return NULL;
  94.     }
  95.  
  96.     popen_pid[myside] = pid;
  97.  
  98.     close(hisside);
  99.     return(fdopen(myside, mode));
  100. }
  101.  
  102. native_pclose(ptr)
  103. FILE *ptr;
  104. {
  105.     int f, r, (*hstat)(), (*istat)(), (*qstat)(), status;
  106.  
  107.     f = fileno(ptr);
  108.     fclose(ptr);
  109.     istat = signal(SIGINT, SIG_IGN);
  110.     qstat = signal(SIGQUIT, SIG_IGN);
  111.     hstat = signal(SIGHUP, SIG_IGN);
  112.  
  113.     while ((r = wait(&status)) != popen_pid[f] && r != -1)
  114.         ;
  115.  
  116.     if (r == -1)
  117.         status = -1;
  118.  
  119.     signal(SIGINT, istat);
  120.     signal(SIGQUIT, qstat);
  121.     signal(SIGHUP, hstat);
  122.     return(status);
  123. }
  124.