home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / pcomm2 / part04 / expand.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-14  |  2.6 KB  |  137 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. #include <fcntl.h>
  10. #include "config.h"
  11.  
  12. char *
  13. expand(input)
  14. char *input;
  15. {
  16.     extern char *null_ptr;
  17.     FILE *pfp, *n_popen();
  18.     int last;
  19.     char *ans, buf[1024], *strpbrk(), *strdup();
  20.     void free_ptr();
  21.  
  22.                     /* same rules as strdup() */
  23.     if (input == NULL)
  24.         return(NULL);
  25.     if (*input == NULL)
  26.         return(null_ptr);
  27.                     /* any thing to expand? */
  28.     ans = strdup(input);
  29.     if (!strpbrk(input, "$*{}[]\\?~"))
  30.         return(ans);
  31.                     /* popen an echo */
  32.     sprintf(buf, "echo %s", input);
  33.  
  34.     pfp = n_popen(buf, "r");
  35.     fgets(buf, 1024, pfp);
  36.     n_pclose(pfp);
  37.  
  38.     if (!strlen(buf))
  39.         return(ans);
  40.     /*
  41.      * A horrible kludge...  if the last character is not a line
  42.      * feed, then the csh has returned an error message.  Otherwise
  43.      * zap the line feed.
  44.      */
  45.     last = strlen(buf) -1;
  46.     if (buf[last] != '\n')
  47.         return(ans);
  48.     else
  49.         buf[last] = NULL;
  50.  
  51.     free_ptr(ans);
  52.     ans = strdup(buf);
  53.     return(ans);
  54. }
  55.  
  56. #define    tst(a,b) (*mode == 'r'? (b) : (a))
  57. #define    RDR    0
  58. #define    WTR    1
  59. static int popen_pid[20];
  60.  
  61. FILE *
  62. n_popen(cmd, mode)
  63. char *cmd, *mode;
  64. {
  65.     int myside, hisside, ppid, p[2];
  66.     char *shellpath, *shell, *flags, *getenv(), *strrchr();
  67.     void _exit();
  68.  
  69.     if (pipe(p) < 0)
  70.         return NULL;
  71.  
  72.     myside = tst(p[WTR], p[RDR]);
  73.     hisside = tst(p[RDR], p[WTR]);
  74.                     /* get the environmental variable */
  75.     shellpath = getenv("SHELL");
  76.     if (shellpath == NULL || *shellpath == NULL)
  77.         shellpath = "/bin/sh";
  78.  
  79.     shell = strrchr(shellpath, '/') + 1;
  80.                     /* fix up the flags */
  81.     if (!strcmp(shell, "csh"))
  82.         flags = "-fc";
  83.     else
  84.         flags = "-c";        /* Korn shell too */
  85.  
  86.     if (!(ppid = fork())) {
  87.         int stdio;
  88.                     /* no error messages please */
  89.         close(2);
  90.         open("/dev/null", O_WRONLY);
  91. #ifdef SETUGID
  92.         setgid(getgid());
  93.         setuid(getuid());
  94. #endif /* SETUGID */
  95.         stdio = tst(0, 1);
  96.         close(myside);
  97.         close(stdio);
  98.         fcntl(hisside, F_DUPFD, stdio);
  99.         close(hisside);
  100.         execl(shellpath, shell, flags, cmd, (char *) 0);
  101.         _exit(1);
  102.     }
  103.     if (ppid == -1) {
  104.         close(myside);
  105.         close(hisside);
  106.         return NULL;
  107.     }
  108.  
  109.     popen_pid[myside] = ppid;
  110.  
  111.     close(hisside);
  112.     return(fdopen(myside, mode));
  113. }
  114.  
  115. n_pclose(ptr)
  116. FILE *ptr;
  117. {
  118.     int f, r, (*hstat)(), (*istat)(), (*qstat)(), status;
  119.  
  120.     f = fileno(ptr);
  121.     fclose(ptr);
  122.     istat = signal(SIGINT, SIG_IGN);
  123.     qstat = signal(SIGQUIT, SIG_IGN);
  124.     hstat = signal(SIGHUP, SIG_IGN);
  125.  
  126.     while ((r = wait(&status)) != popen_pid[f] && r != -1)
  127.         ;
  128.  
  129.     if (r == -1)
  130.         status = -1;
  131.  
  132.     signal(SIGINT, istat);
  133.     signal(SIGQUIT, qstat);
  134.     signal(SIGHUP, hstat);
  135.     return(status);
  136. }
  137.