home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / wu-ftpd-.000 / wu-ftpd- / wu-ftpd-2.4 / src / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-01  |  6.7 KB  |  228 lines

  1. /* Copyright (c) 1988 The Regents of the University of California. All rights
  2.  * reserved.
  3.  *
  4.  * This code is derived from software written by Ken Arnold and published in
  5.  * UNIX Review, Vol. 6, No. 8.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions are
  9.  * met: 1. Redistributions of source code must retain the above copyright
  10.  * notice, this list of conditions and the following disclaimer. 2.
  11.  * Redistributions in binary form must reproduce the above copyright notice,
  12.  * this list of conditions and the following disclaimer in the documentation
  13.  * and/or other materials provided with the distribution. 3. All advertising
  14.  * materials mentioning features or use of this software must display the
  15.  * following acknowledgement: This product includes software developed by the
  16.  * University of California, Berkeley and its contributors. 4. Neither the
  17.  * name of the University nor the names of its contributors may be used to
  18.  * endorse or promote products derived from this software without specific
  19.  * prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
  22.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  24.  * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
  25.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  27.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  28.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  */
  34.  
  35. #ifndef lint
  36. static char sccsid[] = "@(#)popen.c 5.9 (Berkeley) 2/25/91";
  37. #endif /* not lint */
  38.  
  39. #include "config.h"
  40.  
  41. #include <sys/types.h>
  42. #include <sys/wait.h>
  43. #include <signal.h>
  44. #include <stdio.h>
  45. #include <string.h>
  46. #ifdef SVR4
  47. #include <sys/resource.h>
  48. #endif
  49.  
  50. /* Special version of popen which avoids call to shell.  This insures noone
  51.  * may create a pipe to a hidden program as a side effect of a list or dir
  52.  * command. */
  53. static int *pids;
  54. static int fds;
  55.  
  56. FILE *
  57. ftpd_popen(char *program, char *type, int closestderr)
  58. {
  59.     register char *cp;
  60.     FILE *iop;
  61.     int argc,
  62.       gargc,
  63.       pdes[2],
  64.       pid;
  65.     char **pop,
  66.      *argv[100],
  67.      *gargv[1000],
  68.      *vv[2];
  69.     extern char **ftpglob(register char *v),
  70.     **copyblk(register char **v),
  71.      *strspl(register char *cp, register char *dp);
  72.  
  73.     if (*type != 'r' && *type != 'w' || type[1])
  74.         return (NULL);
  75.  
  76.     if (!pids) {
  77. #ifndef HAVE_GETDTABLESIZE
  78.         struct rlimit rlp;
  79.  
  80.         rlp.rlim_cur = rlp.rlim_max = RLIM_INFINITY;
  81.         if (getrlimit( RLIMIT_NOFILE, &rlp ) )
  82.             return(NULL);
  83.         fds = rlp.rlim_cur;
  84. #else
  85.         if ((fds = getdtablesize()) <= 0)
  86.             return (NULL);
  87. #endif
  88.  
  89.         if ((pids = (int *) malloc((u_int) (fds * sizeof(int)))) == NULL)
  90.               return (NULL);
  91. #ifdef USG
  92.         (void) memset((char *)pids, fds * sizeof(int), 0);
  93. #else
  94.         bzero((char *) pids, fds * sizeof(int));
  95. #endif
  96.     }
  97.     if (pipe(pdes) < 0)
  98.         return (NULL);
  99.  
  100.     /* break up string into pieces */
  101.     for (argc = 0, cp = program;; cp = NULL)
  102.         if (!(argv[argc++] = strtok(cp, " \t\n")))
  103.             break;
  104.  
  105.     /* glob each piece */
  106.     gargv[0] = argv[0];
  107.     for (gargc = argc = 1; argv[argc]; argc++) {
  108.         if (!(pop = ftpglob(argv[argc]))) { /* globbing failed */
  109.             vv[0] = strspl(argv[argc], "");
  110.             vv[1] = NULL;
  111.             pop = copyblk(vv);
  112.         }
  113.         argv[argc] = (char *) pop;  /* save to free later */
  114.         while (*pop && gargc < 1000)
  115.             gargv[gargc++] = *pop++;
  116.     }
  117.     gargv[gargc] = NULL;
  118.  
  119.     iop = NULL;
  120.     switch (pid = vfork()) {
  121.     case -1:                    /* error */
  122.         (void) close(pdes[0]);
  123.         (void) close(pdes[1]);
  124.         goto pfree;
  125.         /* NOTREACHED */
  126.     case 0:                 /* child */
  127.         if (*type == 'r') {
  128.             if (pdes[1] != 1) {
  129.                 dup2(pdes[1], 1);
  130.                 if (closestderr)
  131.                     (void) close(2);
  132.                 else 
  133.                     dup2(pdes[1], 2);  /* stderr, too! */
  134.                 (void) close(pdes[1]);
  135.             }
  136.             (void) close(pdes[0]);
  137.         } else {
  138.             if (pdes[0] != 0) {
  139.                 dup2(pdes[0], 0);
  140.                 (void) close(pdes[0]);
  141.             }
  142.             (void) close(pdes[1]);
  143.         }
  144.         execv(gargv[0], gargv);
  145.         _exit(1);
  146.     }
  147.     /* parent; assume fdopen can't fail...  */
  148.     if (*type == 'r') {
  149.         iop = fdopen(pdes[0], type);
  150.         (void) close(pdes[1]);
  151.     } else {
  152.         iop = fdopen(pdes[1], type);
  153.         (void) close(pdes[0]);
  154.     }
  155.     pids[fileno(iop)] = pid;
  156.  
  157.   pfree:for (argc = 1; argv[argc] != NULL; argc++) {
  158.         blkfree((char **) argv[argc]);
  159.         free((char *) argv[argc]);
  160.     }
  161.     return (iop);
  162. }
  163.  
  164. ftpd_pclose(FILE * iop)
  165. {
  166.     register int fdes;
  167.     int pid;
  168. #if defined (SVR4)
  169.     sigset_t sig, omask;
  170.     int stat_loc;
  171.     sigemptyset(&sig);
  172.     sigaddset(&sig, SIGINT); sigaddset(&sig,SIGQUIT); sigaddset(&sig, SIGHUP);
  173. #elif defined (_OSF_SOURCE)
  174.     int omask;
  175.     int status;
  176. #elif defined(M_UNIX)
  177.     int stat_loc;
  178.     sigset_t oldmask, newmask;
  179. #else
  180.     int omask;
  181.     union wait stat_loc;
  182. #endif
  183.  
  184.  
  185.     /* pclose returns -1 if stream is not associated with a `popened'
  186.      * command, or, if already `pclosed'. */
  187.     if (pids == 0 || pids[fdes = fileno(iop)] == 0)
  188.         return (-1);
  189.     (void) fclose(iop);
  190. #ifdef SVR4
  191.     sigprocmask( SIG_BLOCK, &sig, &omask);
  192. #elif defined(M_UNIX)
  193.     sigemptyset(&newmask);
  194.     sigaddset(&newmask, SIGINT);
  195.     sigaddset(&newmask, SIGQUIT);
  196.     sigaddset(&newmask, SIGHUP);
  197.     (void) sigprocmask(SIG_BLOCK, &newmask ,&oldmask);
  198. #else
  199.     omask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP));
  200. #endif
  201.  
  202. #ifdef _OSF_SOURCE
  203.     while ((pid = wait(&status)) != pids[fdes] && pid != -1) ;
  204. #else
  205. #ifndef NeXT
  206.     while ((pid = wait((int *) &stat_loc)) != pids[fdes] && pid != -1) ;
  207. #else
  208.     while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1) ;
  209. #endif
  210. #endif
  211.     pids[fdes] = 0;
  212. #ifdef SVR4
  213.     sigprocmask( SIG_SETMASK, &omask, (sigset_t *)NULL);
  214.     return(pid == -1 ? -1 : WEXITSTATUS(stat_loc));
  215. #elif defined(M_UNIX)
  216.     (void) sigprocmask(SIG_SETMASK, &oldmask, (sigset_t)0);
  217. #else
  218.     (void)sigsetmask(omask);
  219. #ifdef _OSF_SOURCE
  220.     return (pid == -1 ? -1 : status);
  221. #elif defined(M_UNIX) || defined(LINUX)
  222.     return (pid == -1 ? -1 : WEXITSTATUS(stat_loc));
  223. #else
  224.     return (pid == -1 ? -1 : stat_loc.w_status);
  225. #endif
  226. #endif
  227. }
  228.