home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / stdlib / rcs / exec.c,v < prev    next >
Encoding:
Text File  |  1992-07-04  |  6.7 KB  |  320 lines

  1. head    1.2;
  2. access;
  3. symbols
  4.     version39-41:1.2;
  5. locks;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.2
  10. date    92.07.04.18.58.04;    author mwild;    state Exp;
  11. branches;
  12. next    1.1;
  13.  
  14. 1.1
  15. date    92.06.08.17.01.06;    author mwild;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @initial checkin
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @use `real' environment. Try execve() before searching $PATH to catch
  28. programs on resident list and accessible via process PATH
  29. @
  30. text
  31. @/*-
  32.  * Copyright (c) 1991 The Regents of the University of California.
  33.  * All rights reserved.
  34.  *
  35.  * Redistribution and use in source and binary forms, with or without
  36.  * modification, are permitted provided that the following conditions
  37.  * are met:
  38.  * 1. Redistributions of source code must retain the above copyright
  39.  *    notice, this list of conditions and the following disclaimer.
  40.  * 2. Redistributions in binary form must reproduce the above copyright
  41.  *    notice, this list of conditions and the following disclaimer in the
  42.  *    documentation and/or other materials provided with the distribution.
  43.  * 3. All advertising materials mentioning features or use of this software
  44.  *    must display the following acknowledgement:
  45.  *    This product includes software developed by the University of
  46.  *    California, Berkeley and its contributors.
  47.  * 4. Neither the name of the University nor the names of its contributors
  48.  *    may be used to endorse or promote products derived from this software
  49.  *    without specific prior written permission.
  50.  *
  51.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  52.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  53.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  54.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  55.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  56.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  57.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  58.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  59.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  60.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  61.  * SUCH DAMAGE.
  62.  */
  63.  
  64. #if defined(LIBC_SCCS) && !defined(lint)
  65. static char sccsid[] = "@@(#)exec.c    5.9 (Berkeley) 6/17/91";
  66. #endif /* LIBC_SCCS and not lint */
  67.  
  68. #define KERNEL
  69. #include "ixemul.h"
  70.  
  71. #include <errno.h>
  72. #include <unistd.h>
  73. #include <stdlib.h>
  74. #include <string.h>
  75. #include <paths.h>
  76.  
  77. #ifdef __STDC__
  78. #include <stdarg.h>
  79. #else
  80. #include <varargs.h>
  81. #endif
  82.  
  83. #define environ (*u.u_environ)
  84.  
  85. static char **
  86. buildargv(ap, arg, envpp)
  87.     va_list ap;
  88.     const char *arg;
  89.     char ***envpp;
  90. {
  91.     register size_t max, off;
  92.     register char **argv = NULL;
  93.  
  94.     for (off = max = 0;; ++off) {
  95.         if (off >= max) {
  96.             max += 50;    /* Starts out at 0. */
  97.             max *= 2;    /* Ramp up fast. */
  98.             if (!(argv = realloc(argv, max * sizeof(char *))))
  99.                 return(NULL);
  100.             if (off == 0) {
  101.                 argv[0] = (char *)arg;
  102.                 off = 1;
  103.             }
  104.         }
  105.         if (!(argv[off] = va_arg(ap, char *)))
  106.             break;
  107.     }
  108.     /* Get environment pointer if user supposed to provide one. */
  109.     if (envpp)
  110.         *envpp = va_arg(ap, char **);
  111.     return(argv);
  112. }
  113.  
  114. int
  115. #if __STDC__
  116. execl(const char *name, const char *arg, ...)
  117. #else
  118. execl(name, arg, va_alist)
  119.     const char *name;
  120.     const char *arg;
  121.     va_dcl
  122. #endif
  123. {
  124.     va_list ap;
  125.     int sverrno;
  126.     char **argv;
  127.  
  128. #if __STDC__
  129.     va_start(ap, arg);
  130. #else
  131.     va_start(ap);
  132. #endif
  133.     if (argv = buildargv(ap, arg, (char ***)NULL))
  134.         (void)execve(name, argv, environ);
  135.     va_end(ap);
  136.     sverrno = errno;
  137.     free(argv);
  138.     errno = sverrno;
  139.     return(-1);
  140. }
  141.  
  142. int
  143. #if __STDC__
  144. execle(const char *name, const char *arg, ...)
  145. #else
  146. execle(name, arg, va_alist)
  147.     const char *name;
  148.     const char *arg;
  149.     va_dcl
  150. #endif
  151. {
  152.     va_list ap;
  153.     int sverrno;
  154.     char **argv, **envp;
  155.  
  156. #if __STDC__
  157.     va_start(ap, arg);
  158. #else
  159.     va_start(ap);
  160. #endif
  161.     if (argv = buildargv(ap, arg, &envp))
  162.         (void)execve(name, argv, envp);
  163.     va_end(ap);
  164.     sverrno = errno;
  165.     free(argv);
  166.     errno = sverrno;
  167.     return(-1);
  168. }
  169.  
  170. int
  171. #if __STDC__
  172. execlp(const char *name, const char *arg, ...)
  173. #else
  174. execlp(name, arg, va_alist)
  175.     const char *name;
  176.     const char *arg;
  177.     va_dcl
  178. #endif
  179. {
  180.     va_list ap;
  181.     int sverrno;
  182.     char **argv;
  183.  
  184. #if __STDC__
  185.     va_start(ap, arg);
  186. #else
  187.     va_start(ap);
  188. #endif
  189.     if (argv = buildargv(ap, arg, (char ***)NULL))
  190.         (void)execvp(name, argv);
  191.     va_end(ap);
  192.     sverrno = errno;
  193.     free(argv);
  194.     errno = sverrno;
  195.     return(-1);
  196. }
  197.  
  198. int
  199. execv(name, argv)
  200.     const char *name;
  201.     char * const *argv;
  202. {
  203.     (void)execve(name, argv, environ);
  204.     return(-1);
  205. }
  206.  
  207. int
  208. execvp(name, argv)
  209.     const char *name;
  210.     char * const *argv;
  211. {
  212.     register int lp, ln;
  213.     register char *p;
  214.     int eacces, etxtbsy;
  215.     char *bp, *cur, *path, buf[MAXPATHLEN];
  216.  
  217.     /* If it's an absolute or relative path name, it's easy. */
  218.     if (index(name, '/') || index (name, ':')) {
  219.         bp = (char *)name;
  220.         cur = path = NULL;
  221.         goto retry;
  222.     }
  223.     bp = buf;
  224.  
  225.     /* first try to call execve() without path lookup. execve() walks
  226.        a (possibly provided) CLI PATH, and also supports resident
  227.        programs. If this fails, we can still try to find the program
  228.        along the $PATH */
  229.     execv (name, argv);
  230.     /* if we get here, the execv() failed. So start magic ;-)) */
  231.  
  232.     /* Get the path we're searching. */
  233.     if (!(path = getenv("PATH")))
  234.         path = _PATH_DEFPATH;
  235.     cur = path = strdup(path);
  236.  
  237.     eacces = etxtbsy = 0;
  238.     while (p = strsep(&cur, ",:")) {
  239.         /*
  240.          * It's a SHELL path -- double, leading and trailing colons
  241.          * mean the current directory.
  242.          */
  243.         if (!*p) {
  244.             p = ".";
  245.             lp = 1;
  246.         } else
  247.             lp = strlen(p);
  248.         ln = strlen(name);
  249.  
  250.         /*
  251.          * If the path is too long complain.  This is a possible
  252.          * security issue; given a way to make the path too long
  253.          * the user may execute the wrong program.
  254.          */
  255.         if (lp + ln + 2 > sizeof(buf)) {
  256.             (void)write(STDERR_FILENO, "execvp: ", 8);
  257.             (void)write(STDERR_FILENO, p, lp);
  258.             (void)write(STDERR_FILENO, ": path too long\n", 16);
  259.             continue;
  260.         }
  261.         bcopy(p, buf, lp);
  262.         buf[lp] = '/';
  263.         bcopy(name, buf + lp + 1, ln);
  264.         buf[lp + ln + 1] = '\0';
  265.  
  266. retry:        (void)execve(bp, argv, environ);
  267.         switch(errno) {
  268.         case EACCES:
  269.             eacces = 1;
  270.             break;
  271.         case ENOENT:
  272.             break;
  273.         case ENOEXEC: {
  274.             register size_t cnt;
  275.             register char **ap;
  276.  
  277.             for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
  278.             if (ap = malloc((cnt + 2) * sizeof(char *))) {
  279.                 bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
  280.                 ap[0] = "sh";
  281.                 ap[1] = bp;
  282.                 (void)execve(_PATH_BSHELL, ap, environ);
  283.                 free(ap);
  284.             }
  285.             goto done;
  286.         }
  287.         case ETXTBSY:
  288.             if (etxtbsy < 3)
  289.                 (void)sleep(++etxtbsy);
  290.             goto retry;
  291.         default:
  292.             goto done;
  293.         }
  294.     }
  295.     if (eacces)
  296.         errno = EACCES;
  297.     else if (!errno)
  298.         errno = ENOENT;
  299. done:    if (path)
  300.         free(path);
  301.     return(-1);
  302. }
  303. @
  304.  
  305.  
  306. 1.1
  307. log
  308. @Initial revision
  309. @
  310. text
  311. @d53 1
  312. a53 5
  313. #if later
  314. extern char **environ;
  315. #else
  316. #define environ 0
  317. #endif
  318. d194 7
  319. @
  320.