home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / tcpip / amitcp-support / wustl-ftpdaemon / src / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-29  |  6.9 KB  |  241 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. #ifdef AMIGA
  42. #include <stdio.h>
  43. FILE *
  44. ftpd_popen(char *program, char *type, int closestderr)
  45. {
  46.   return(popen(program,type));
  47. }
  48. ftpd_pclose(FILE * iop)
  49. {
  50.   pclose(iop);
  51. }
  52. #else /* !AMIGA */
  53. #include <sys/types.h>
  54. #include <sys/wait.h>
  55. #include <signal.h>
  56. #include <stdio.h>
  57. #include <string.h>
  58. #ifdef SVR4
  59. #include <sys/resource.h>
  60. #endif
  61.  
  62. /* Special version of popen which avoids call to shell.  This insures noone
  63.  * may create a pipe to a hidden program as a side effect of a list or dir
  64.  * command. */
  65. static int *pids;
  66. static int fds;
  67.  
  68. FILE *
  69. ftpd_popen(char *program, char *type, int closestderr)
  70. {
  71.     register char *cp;
  72.     FILE *iop;
  73.     int argc,
  74.       gargc,
  75.       pdes[2],
  76.       pid;
  77.     char **pop,
  78.      *argv[100],
  79.      *gargv[1000],
  80.      *vv[2];
  81.     extern char **ftpglob(register char *v),
  82.     **copyblk(register char **v),
  83.      *strspl(register char *cp, register char *dp);
  84.  
  85.     if (*type != 'r' && *type != 'w' || type[1])
  86.         return (NULL);
  87.  
  88.     if (!pids) {
  89. #ifndef HAVE_GETDTABLESIZE
  90.         struct rlimit rlp;
  91.  
  92.         rlp.rlim_cur = rlp.rlim_max = RLIM_INFINITY;
  93.         if (getrlimit( RLIMIT_NOFILE, &rlp ) )
  94.             return(NULL);
  95.         fds = rlp.rlim_cur;
  96. #else
  97.         if ((fds = getdtablesize()) <= 0)
  98.             return (NULL);
  99. #endif
  100.  
  101.         if ((pids = (int *) malloc((u_int) (fds * sizeof(int)))) == NULL)
  102.               return (NULL);
  103. #ifdef USG
  104.         (void) memset((char *)pids, fds * sizeof(int), 0);
  105. #else
  106.         bzero((char *) pids, fds * sizeof(int));
  107. #endif
  108.     }
  109.     if (pipe(pdes) < 0)
  110.         return (NULL);
  111.  
  112.     /* break up string into pieces */
  113.     for (argc = 0, cp = program;; cp = NULL)
  114.         if (!(argv[argc++] = strtok(cp, " \t\n")))
  115.             break;
  116.  
  117.     /* glob each piece */
  118.     gargv[0] = argv[0];
  119.     for (gargc = argc = 1; argv[argc]; argc++) {
  120.         if (!(pop = ftpglob(argv[argc]))) { /* globbing failed */
  121.             vv[0] = strspl(argv[argc], "");
  122.             vv[1] = NULL;
  123.             pop = copyblk(vv);
  124.         }
  125.         argv[argc] = (char *) pop;  /* save to free later */
  126.         while (*pop && gargc < 1000)
  127.             gargv[gargc++] = *pop++;
  128.     }
  129.     gargv[gargc] = NULL;
  130.  
  131.     iop = NULL;
  132.     switch (pid = vfork()) {
  133.     case -1:                    /* error */
  134.         (void) close(pdes[0]);
  135.         (void) close(pdes[1]);
  136.         goto pfree;
  137.         /* NOTREACHED */
  138.     case 0:                 /* child */
  139.         if (*type == 'r') {
  140.             if (pdes[1] != 1) {
  141.                 dup2(pdes[1], 1);
  142.                 if (closestderr)
  143.                     (void) close(2);
  144.                 else 
  145.                     dup2(pdes[1], 2);  /* stderr, too! */
  146.                 (void) close(pdes[1]);
  147.             }
  148.             (void) close(pdes[0]);
  149.         } else {
  150.             if (pdes[0] != 0) {
  151.                 dup2(pdes[0], 0);
  152.                 (void) close(pdes[0]);
  153.             }
  154.             (void) close(pdes[1]);
  155.         }
  156.         execv(gargv[0], gargv);
  157.         _exit(1);
  158.     }
  159.     /* parent; assume fdopen can't fail...  */
  160.     if (*type == 'r') {
  161.         iop = fdopen(pdes[0], type);
  162.         (void) close(pdes[1]);
  163.     } else {
  164.         iop = fdopen(pdes[1], type);
  165.         (void) close(pdes[0]);
  166.     }
  167.     pids[fileno(iop)] = pid;
  168.  
  169.   pfree:for (argc = 1; argv[argc] != NULL; argc++) {
  170.         blkfree((char **) argv[argc]);
  171.         free((char *) argv[argc]);
  172.     }
  173.     return (iop);
  174. }
  175.  
  176. ftpd_pclose(FILE * iop)
  177. {
  178.     register int fdes;
  179.     int pid;
  180. #if defined (SVR4)
  181.     sigset_t sig, omask;
  182.     int stat_loc;
  183.     sigemptyset(&sig);
  184.     sigaddset(&sig, SIGINT); sigaddset(&sig,SIGQUIT); sigaddset(&sig, SIGHUP);
  185. #elif defined (_OSF_SOURCE)
  186.     int omask;
  187.     int status;
  188. #elif defined(M_UNIX)
  189.     int stat_loc;
  190.     sigset_t oldmask, newmask;
  191. #else
  192.     int omask;
  193.     union wait stat_loc;
  194. #endif
  195.  
  196.  
  197.     /* pclose returns -1 if stream is not associated with a `popened'
  198.      * command, or, if already `pclosed'. */
  199.     if (pids == 0 || pids[fdes = fileno(iop)] == 0)
  200.         return (-1);
  201.     (void) fclose(iop);
  202. #ifdef SVR4
  203.     sigprocmask( SIG_BLOCK, &sig, &omask);
  204. #elif defined(M_UNIX)
  205.     sigemptyset(&newmask);
  206.     sigaddset(&newmask, SIGINT);
  207.     sigaddset(&newmask, SIGQUIT);
  208.     sigaddset(&newmask, SIGHUP);
  209.     (void) sigprocmask(SIG_BLOCK, &newmask ,&oldmask);
  210. #else
  211.     omask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP));
  212. #endif
  213.  
  214. #if defined(_OSF_SOURCE)
  215.     while ((pid = wait(&status)) != pids[fdes] && pid != -1) ;
  216. #else
  217. #ifndef NeXT
  218.     while ((pid = wait((int *) &stat_loc)) != pids[fdes] && pid != -1) ;
  219. #else
  220.     while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1) ;
  221. #endif
  222. #endif
  223.     pids[fdes] = 0;
  224. #ifdef SVR4
  225.     sigprocmask( SIG_SETMASK, &omask, (sigset_t *)NULL);
  226.     return(pid == -1 ? -1 : WEXITSTATUS(stat_loc));
  227. #elif defined(M_UNIX)
  228.     (void) sigprocmask(SIG_SETMASK, &oldmask, (sigset_t)0);
  229. #else
  230.     (void)sigsetmask(omask);
  231. #if defined(_OSF_SOURCE)
  232.     return (pid == -1 ? -1 : status);
  233. #elif defined(M_UNIX) || defined(LINUX)
  234.     return (pid == -1 ? -1 : WEXITSTATUS(stat_loc));
  235. #else
  236.     return (pid == -1 ? -1 : stat_loc.w_status);
  237. #endif
  238. #endif
  239. }
  240. #endif /* !AMIGA */
  241.