home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / backup / star-1.3.1.tar.gz / star-1.3.1.tar / star-1.3.1 / lib / fexec.c < prev    next >
C/C++ Source or Header  |  2000-05-07  |  8KB  |  385 lines

  1. /* @(#)fexec.c    1.18 00/05/07 Copyright 1985 J. Schilling */
  2. /*
  3.  *    Execute a program with stdio redirection
  4.  *
  5.  *    Copyright (c) 1985 J. Schilling
  6.  */
  7. /*
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2, or (at your option)
  11.  * any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; see the file COPYING.  If not, write to
  20.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. #include <mconfig.h>
  24. #include <stdio.h>
  25. #include <standard.h>
  26. #define    fexecl    __nothing_1_    /* prototype in schily.h is wrong */
  27. #define    fexecle    __nothing_2_    /* prototype in schily.h is wrong */
  28. #include <schily.h>
  29. #undef    fexecl
  30. #undef    fexecle
  31.     int fexecl    __PR((const char *, FILE *, FILE *, FILE *, ...));
  32.     int fexecle    __PR((const char *, FILE *, FILE *, FILE *, ...));
  33. #include <unixstd.h>
  34. #include <stdxlib.h>
  35. #include <strdefs.h>
  36. #include <vadefs.h>
  37.  
  38. #ifdef JOS
  39. #    include <error.h>
  40. #else
  41. #    include <errno.h>
  42. #endif
  43. #include <fctldefs.h>
  44. #include <dirdefs.h>
  45. #include <maxpath.h>
  46.  
  47. #define    MAX_F_ARGS    16
  48.  
  49. extern    char **environ;
  50.  
  51. LOCAL void     fdcopy __PR((int, int));
  52. LOCAL void     fdmove __PR((int, int));
  53. LOCAL const char *chkname __PR((const char *, const char *));
  54. LOCAL const char *getpath __PR((char * const *));
  55.  
  56. #ifdef    PROTOTYPES
  57. int fexecl(const char *name, FILE *in, FILE *out, FILE *err, ...)
  58. #else
  59. int fexecl(name, in, out, err, va_alist)
  60.     char    *name;
  61.     FILE    *in;
  62.     FILE    *out;
  63.     FILE    *err;
  64.     va_dcl
  65. #endif
  66. {
  67.     va_list    args;
  68.     int    ac = 0;
  69.     char    *xav[MAX_F_ARGS];
  70.     char    **av;
  71.     char    **pav;
  72.     char    *p;
  73.     int    ret;
  74.  
  75. #ifdef    PROTOTYPES
  76.     va_start(args, err);
  77. #else
  78.     va_start(args);
  79. #endif
  80.     while (va_arg(args, char *) != NULL)
  81.         ac++;
  82.     va_end(args);
  83.  
  84.     if (ac < MAX_F_ARGS) {
  85.         pav = av = xav;
  86.     } else {
  87.         pav = av = (char **)malloc((ac+1)*sizeof(char *));
  88.         if (av == 0)
  89.             return (-1);
  90.     }
  91.  
  92. #ifdef    PROTOTYPES
  93.     va_start(args, err);
  94. #else
  95.     va_start(args);
  96. #endif
  97.     do {
  98.         p = va_arg(args, char *);
  99.         *pav++ = p;
  100.     } while (p != NULL);
  101.     va_end(args);
  102.  
  103.     ret = fexecv(name, in, out, err, ac, av);
  104.     if (av != xav)
  105.         free(av);
  106.     return (ret);
  107. }
  108.  
  109. #ifdef    PROTOTYPES
  110. int fexecle(const char *name, FILE *in, FILE *out, FILE *err, ...)
  111. #else
  112. int fexecle(name, in, out, err, va_alist)
  113.     char    *name;
  114.     FILE    *in;
  115.     FILE    *out;
  116.     FILE    *err;
  117.     va_dcl
  118. #endif
  119. {
  120.     va_list    args;
  121.     int    ac = 0;
  122.     char    *xav[MAX_F_ARGS];
  123.     char    **av;
  124.     char    **pav;
  125.     char    *p;
  126.     char    **env;
  127.     int    ret;
  128.  
  129. #ifdef    PROTOTYPES
  130.     va_start(args, err);
  131. #else
  132.     va_start(args);
  133. #endif
  134.     while (va_arg(args, char *) != NULL)
  135.         ac++;
  136.     env = va_arg(args, char **);
  137.     va_end(args);
  138.  
  139.     if (ac < MAX_F_ARGS) {
  140.         pav = av = xav;
  141.     } else {
  142.         pav = av = (char **)malloc((ac+1)*sizeof(char *));
  143.         if (av == 0)
  144.             return (-1);
  145.     }
  146.  
  147. #ifdef    PROTOTYPES
  148.     va_start(args, err);
  149. #else
  150.     va_start(args);
  151. #endif
  152.     do {
  153.         p = va_arg(args, char *);
  154.         *pav++ = p;
  155.     } while (p != NULL);
  156.     va_end(args);
  157.  
  158.     ret = fexecve(name, in, out, err, av, env);
  159.     if (av != xav)
  160.         free(av);
  161.     return (ret);
  162. }
  163.  
  164. int fexecv(name, in, out, err, ac, av)
  165.     const char *name;
  166.     FILE *in, *out, *err;
  167.     int ac;
  168.     char *av[];
  169. {
  170.     av[ac] = NULL;            /*  force list to be null terminated */
  171.     return fexecve (name, in, out, err, av, environ);
  172. }
  173.  
  174. int fexecve(name, in, out, err, av, env)
  175.     const char *name;
  176.     FILE *in, *out, *err;
  177.     char * const av[], * const env[];
  178. {
  179.     char    nbuf[MAXPATHNAME+1];
  180.     char    *np;
  181.     const char *path;
  182.     int    ret;
  183.     int    fin;
  184.     int    fout;
  185.     int    ferr;
  186. #ifndef    JOS
  187.     int    o[3];
  188.     int    f[3];
  189.     int    errsav;
  190. #endif
  191.     
  192.     fflush(out);
  193.     fflush(err);
  194.     fin  = fdown(in);
  195.     fout = fdown(out);
  196.     ferr = fdown(err);
  197. #ifdef JOS
  198.  
  199.     /*
  200.      * If name contains a pathdelimiter ('/' on unix)
  201.      * or name is too long ...
  202.      * try exec without path search.
  203.      */
  204.     if (find('/', name) || strlen(name) > MAXFILENAME) {
  205.         ret = exec_env(name, fin, fout, ferr, av, env);
  206.  
  207.     } else if ((path = getpath(env)) == NULL) {
  208.         ret = exec_env(name, fin, fout, ferr, av, env);
  209.         if ((ret == ENOFILE) && strlen (name) <= (sizeof(nbuf) - 6)) {
  210.             strcatl(nbuf, "/bin/", name, NULL);
  211.             ret = exec_env(nbuf, fin, fout, ferr, av, env);
  212.             if (ret == EMISSDIR)
  213.                 ret = ENOFILE;
  214.         }
  215.     } else {
  216.         int    nlen = strlen(name);
  217.  
  218.         for(;;) {
  219.             np = nbuf;
  220.             while (*path != ':' && *path != '\0'
  221.                 && np < &nbuf[MAXPATHNAME-nlen-2])
  222.                   *np++ = *path++;
  223.             *np = '\0';
  224.             if (*nbuf == '\0')
  225.                 strcatl(nbuf, name, NULL);
  226.             else
  227.                 strcatl(nbuf, nbuf, "/", name, NULL);
  228.             ret = exec_env(nbuf, fin, fout, ferr, av, env);
  229.             if (ret == EMISSDIR)
  230.                 ret = ENOFILE;
  231.             if (ret != ENOFILE || *path == '\0')
  232.                 break;
  233.             path++;
  234.         }
  235.     }
  236.     return(ret);
  237. #else
  238.     if (fin != 0) {
  239.         f[0] = fcntl(0, F_GETFD, 0);
  240.         o[0] = dup(0);
  241.         fcntl(o[0], F_SETFD, 1);
  242.         fdcopy(fin, 0);
  243.     }
  244.     if (fout != 1) {
  245.         f[1] = fcntl(1, F_GETFD, 0);
  246.         o[1] = dup(1);
  247.         fcntl(o[1], F_SETFD, 1);
  248.         fdcopy(fout, 1);
  249.     }
  250.     if (ferr != 2) {
  251.         f[2] = fcntl(2, F_GETFD, 0);
  252.         o[2] = dup(2);
  253.         fcntl(o[2], F_SETFD, 1);
  254.         fdcopy(ferr, 2);
  255.     }
  256.     if (fin != 0)
  257.         close(fin);
  258.     if (fout != 1)
  259.         close(fout);
  260.     if (ferr != 2)
  261.         close(ferr);
  262.     
  263.     /*
  264.      * If name contains a pathdelimiter ('/' on unix)
  265.      * or name is too long ...
  266.      * try exec without path search.
  267.      */
  268.     if (strchr(name, '/') || strlen(name) > (unsigned)MAXFILENAME) {
  269.         ret = execve (name, av, env);
  270.  
  271.     } else if ((path = getpath(env)) == NULL) {
  272.         ret = execve (name, av, env);
  273.         if ((errno == ENOENT) && strlen (name) <= (sizeof(nbuf) - 6)) {
  274.             strcatl(nbuf, "/bin/", name, NULL);
  275.             ret = execve (nbuf, av, env);
  276.         }
  277.     } else {
  278.         int    nlen = strlen(name);
  279.  
  280.         for(;;) {
  281.             np = nbuf;
  282.             while (*path != ':' && *path != '\0'
  283.                 && np < &nbuf[MAXPATHNAME-nlen-2])
  284.                   *np++ = *path++;
  285.             *np = '\0';
  286.             if (*nbuf == '\0')
  287.                 strcatl(nbuf, name, NULL);
  288.             else
  289.                 strcatl(nbuf, nbuf, "/", name, NULL);
  290.             ret = execve (nbuf, av, env);
  291.             if (errno != ENOENT || *path == '\0')
  292.                 break;
  293.             path++;
  294.         }
  295.     }
  296.     errsav = errno;
  297.             /* reestablish old files */
  298.     if (ferr != 2) {
  299.         fdmove(2, ferr);
  300.         fdmove(o[2], 2);
  301.         if(f[2] == 0)
  302.             fcntl(2, F_SETFD, 0);
  303.     }
  304.     if (fout != 1) {
  305.         fdmove(1, fout);
  306.         fdmove(o[1], 1);
  307.         if(f[1] == 0)
  308.             fcntl(1, F_SETFD, 0);
  309.     }
  310.     if (fin != 0) {
  311.         fdmove(0, fin);
  312.         fdmove(o[0], 0);
  313.         if(f[0] == 0)
  314.             fcntl(0, F_SETFD, 0);
  315.     }
  316.     errno = errsav;
  317.     return(ret);
  318. #endif
  319. }
  320.  
  321. #ifndef    JOS
  322.  
  323. LOCAL void fdcopy(fd1, fd2)
  324.     int    fd1;
  325.     int    fd2;
  326. {
  327.     close(fd2);
  328.     fcntl(fd1, F_DUPFD, fd2);
  329. }
  330.  
  331. LOCAL void fdmove(fd1, fd2)
  332.     int    fd1;
  333.     int    fd2;
  334. {
  335.     fdcopy(fd1, fd2);
  336.     close(fd1);
  337. }
  338.  
  339. #endif
  340.  
  341. /*----------------------------------------------------------------------------
  342. |
  343. |    get PATH from env 
  344. |
  345. +----------------------------------------------------------------------------*/
  346.  
  347. LOCAL const char *getpath(env)
  348.     char    * const *env;
  349. {
  350.     char * const *p = env;
  351.     const char *p2;
  352.  
  353.     if (p != NULL) {
  354.         while (*p != NULL) {
  355.             if ((p2 = chkname("PATH", *p)) != NULL)
  356.                 return (p2);
  357.             p++;
  358.         }
  359.     }
  360.     return (NULL);
  361. }
  362.  
  363.  
  364. /*----------------------------------------------------------------------------
  365. |
  366. | Check if name is in environment.
  367. | Return pointer to value name is found.
  368. |
  369. +----------------------------------------------------------------------------*/
  370.  
  371. LOCAL const char *chkname(name, ev)
  372.     const char    *name;
  373.     const char    *ev;
  374. {
  375.     for(;;) {
  376.         if (*name != *ev) {
  377.             if (*ev == '=' && *name == '\0')
  378.                 return (++ev);
  379.             return (NULL);
  380.         }
  381.         name++;
  382.         ev++;
  383.     }
  384. }
  385.