home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / LIBSRC.ZOO / libsrc / gen / exec.c < prev    next >
C/C++ Source or Header  |  1992-01-31  |  6KB  |  266 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER 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. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)exec.c    5.9 (Berkeley) 6/17/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/types.h>
  40. #include <errno.h>
  41. #include <unistd.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <stdio.h>
  45. #include <paths.h>
  46.  
  47. #if __STDC__
  48. #include <stdarg.h>
  49. #else
  50. #include <varargs.h>
  51. #endif
  52.  
  53. extern char **environ;
  54.  
  55. static char **
  56. buildargv(ap, arg, envpp)
  57.     va_list ap;
  58.     const char *arg;
  59.     char ***envpp;
  60. {
  61.     register size_t max, off;
  62.     register char **argv = NULL;
  63.  
  64.     for (off = max = 0;; ++off) {
  65.         if (off >= max) {
  66.             max += 50;    /* Starts out at 0. */
  67.             max *= 2;    /* Ramp up fast. */
  68.             if (!(argv = realloc(argv, max * sizeof(char *))))
  69.                 return(NULL);
  70.             if (off == 0) {
  71.                 argv[0] = (char *)arg;
  72.                 off = 1;
  73.             }
  74.         }
  75.         if (!(argv[off] = va_arg(ap, char *)))
  76.             break;
  77.     }
  78.     /* Get environment pointer if user supposed to provide one. */
  79.     if (envpp)
  80.         *envpp = va_arg(ap, char **);
  81.     return(argv);
  82. }
  83.  
  84. int
  85. #if __STDC__
  86. execl(const char *name, const char *arg, ...)
  87. #else
  88. execl(name, arg, va_alist)
  89.     const char *name;
  90.     const char *arg;
  91.     va_dcl
  92. #endif
  93. {
  94.     va_list ap;
  95.     int sverrno;
  96.     char **argv;
  97.  
  98. #if __STDC__
  99.     va_start(ap, arg);
  100. #else
  101.     va_start(ap);
  102. #endif
  103.     if (argv = buildargv(ap, arg, (char ***)NULL))
  104.         (void)execve(name, argv, environ);
  105.     va_end(ap);
  106.     sverrno = errno;
  107.     free(argv);
  108.     errno = sverrno;
  109.     return(-1);
  110. }
  111.  
  112. int
  113. #if __STDC__
  114. execle(const char *name, const char *arg, ...)
  115. #else
  116. execle(name, arg, va_alist)
  117.     const char *name;
  118.     const char *arg;
  119.     va_dcl
  120. #endif
  121. {
  122.     va_list ap;
  123.     int sverrno;
  124.     char **argv, **envp;
  125.  
  126. #if __STDC__
  127.     va_start(ap, arg);
  128. #else
  129.     va_start(ap);
  130. #endif
  131.     if (argv = buildargv(ap, arg, &envp))
  132.         (void)execve(name, argv, envp);
  133.     va_end(ap);
  134.     sverrno = errno;
  135.     free(argv);
  136.     errno = sverrno;
  137.     return(-1);
  138. }
  139.  
  140. int
  141. #if __STDC__
  142. execlp(const char *name, const char *arg, ...)
  143. #else
  144. execlp(name, arg, va_alist)
  145.     const char *name;
  146.     const char *arg;
  147.     va_dcl
  148. #endif
  149. {
  150.     va_list ap;
  151.     int sverrno;
  152.     char **argv;
  153.  
  154. #if __STDC__
  155.     va_start(ap, arg);
  156. #else
  157.     va_start(ap);
  158. #endif
  159.     if (argv = buildargv(ap, arg, (char ***)NULL))
  160.         (void)execvp(name, argv);
  161.     va_end(ap);
  162.     sverrno = errno;
  163.     free(argv);
  164.     errno = sverrno;
  165.     return(-1);
  166. }
  167.  
  168. int
  169. execv(name, argv)
  170.     const char *name;
  171.     char * const *argv;
  172. {
  173.     (void)execve(name, argv, environ);
  174.     return(-1);
  175. }
  176.  
  177. int
  178. execvp(name, argv)
  179.     const char *name;
  180.     char * const *argv;
  181. {
  182.     register int lp, ln;
  183.     register char *p;
  184.     int eacces, etxtbsy;
  185.     char *bp, *cur, *path, buf[MAXPATHLEN];
  186.  
  187.     /* If it's an absolute or relative path name, it's easy. */
  188.     if (index(name, '/')) {
  189.         bp = (char *)name;
  190.         cur = path = NULL;
  191.         goto retry;
  192.     }
  193.     bp = buf;
  194.  
  195.     /* Get the path we're searching. */
  196.     if (!(path = getenv("PATH")))
  197.         path = _PATH_DEFPATH;
  198.     cur = path = strdup(path);
  199.  
  200.     eacces = etxtbsy = 0;
  201.     while (p = strsep(&cur, ":")) {
  202.         /*
  203.          * It's a SHELL path -- double, leading and trailing colons
  204.          * mean the current directory.
  205.          */
  206.         if (!*p) {
  207.             p = ".";
  208.             lp = 1;
  209.         } else
  210.             lp = strlen(p);
  211.         ln = strlen(name);
  212.  
  213.         /*
  214.          * If the path is too long complain.  This is a possible
  215.          * security issue; given a way to make the path too long
  216.          * the user may execute the wrong program.
  217.          */
  218.         if (lp + ln + 2 > sizeof(buf)) {
  219.             (void)write(STDERR_FILENO, "execvp: ", 8);
  220.             (void)write(STDERR_FILENO, p, lp);
  221.             (void)write(STDERR_FILENO, ": path too long\n", 16);
  222.             continue;
  223.         }
  224.         bcopy(p, buf, lp);
  225.         buf[lp] = '/';
  226.         bcopy(name, buf + lp + 1, ln);
  227.         buf[lp + ln + 1] = '\0';
  228.  
  229. retry:        (void)execve(bp, argv, environ);
  230.         switch(errno) {
  231.         case EACCES:
  232.             eacces = 1;
  233.             break;
  234.         case ENOENT:
  235.             break;
  236.         case ENOEXEC: {
  237.             register size_t cnt;
  238.             register char **ap;
  239.  
  240.             for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
  241.             if (ap = malloc((cnt + 2) * sizeof(char *))) {
  242.                 bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
  243.                 ap[0] = "sh";
  244.                 ap[1] = bp;
  245.                 (void)execve(_PATH_BSHELL, ap, environ);
  246.                 free(ap);
  247.             }
  248.             goto done;
  249.         }
  250.         case ETXTBSY:
  251.             if (etxtbsy < 3)
  252.                 (void)sleep(++etxtbsy);
  253.             goto retry;
  254.         default:
  255.             goto done;
  256.         }
  257.     }
  258.     if (eacces)
  259.         errno = EACCES;
  260.     else if (!errno)
  261.         errno = ENOENT;
  262. done:    if (path)
  263.         free(path);
  264.     return(-1);
  265. }
  266.