home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / stdlib / exec.c < prev    next >
C/C++ Source or Header  |  1996-12-11  |  6KB  |  238 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. #define _KERNEL
  39. #include "ixemul.h"
  40. #include "kprintf.h"
  41.  
  42. #include <errno.h>
  43. #include <unistd.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <paths.h>
  47.  
  48. #ifdef __STDC__
  49. #include <stdarg.h>
  50. #else
  51. #include <varargs.h>
  52. #endif
  53.  
  54. static char **
  55. buildargv(ap, arg, envpp)
  56.     va_list ap;
  57.     const char *arg;
  58.     char ***envpp;
  59. {
  60.     register size_t max, off;
  61.     register char **argv = NULL;
  62.  
  63.     for (off = max = 0;; ++off) {
  64.         if (off >= max) {
  65.             max += 50;    /* Starts out at 0. */
  66.             max *= 2;    /* Ramp up fast. */
  67.             if (!(argv = realloc(argv, max * sizeof(char *))))
  68.                 return(NULL);
  69.             if (off == 0) {
  70.                 argv[0] = (char *)arg;
  71.                 off = 1;
  72.             }
  73.         }
  74.         if (!(argv[off] = va_arg(ap, char *)))
  75.             break;
  76.     }
  77.     /* Get environment pointer if user supposed to provide one. */
  78.     if (envpp)
  79.         *envpp = va_arg(ap, char **);
  80.     return(argv);
  81. }
  82.  
  83. int execl(const char *name, const char *arg, ...)
  84. {
  85.     va_list ap;
  86.     int sverrno;
  87.     char **argv;
  88.  
  89.     va_start(ap, arg);
  90.     if ((argv = buildargv(ap, arg, (char ***)NULL)))
  91.         (void)execve(name, argv, *u.u_environ);
  92.     va_end(ap);
  93.     sverrno = errno;
  94.     free(argv);
  95.     errno = sverrno;
  96.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  97.     return(-1);
  98. }
  99.  
  100. int execle(const char *name, const char *arg, ...)
  101. {
  102.     va_list ap;
  103.     int sverrno;
  104.     char **argv, **envp;
  105.  
  106.     va_start(ap, arg);
  107.     if ((argv = buildargv(ap, arg, &envp)))
  108.         (void)execve(name, argv, envp);
  109.     va_end(ap);
  110.     sverrno = errno;
  111.     free(argv);
  112.     errno = sverrno;
  113.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  114.     return(-1);
  115. }
  116.  
  117. int execlp(const char *name, const char *arg, ...)
  118. {
  119.     va_list ap;
  120.     int sverrno;
  121.     char **argv;
  122.  
  123.     va_start(ap, arg);
  124.     if ((argv = buildargv(ap, arg, (char ***)NULL)))
  125.         (void)execvp(name, argv);
  126.     va_end(ap);
  127.     sverrno = errno;
  128.     free(argv);
  129.     errno = sverrno;
  130.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  131.     return(-1);
  132. }
  133.  
  134. int execv(const char *name, char * const *argv)
  135. {
  136.     execve(name, argv, *u.u_environ);
  137.     return(-1);
  138. }
  139.  
  140. int execvp(const char *name, char * const *argv)
  141. {
  142.     register int lp, ln;
  143.     register char *p;
  144.     int eacces, etxtbsy;
  145.     char *bp, *cur, *path, buf[MAXPATHLEN];
  146.  
  147.     eacces = etxtbsy = 0;
  148.     /* If it's an absolute or relative path name, it's easy. */
  149.     if (index(name, '/') || index (name, ':')) {
  150.         bp = (char *)name;
  151.         cur = path = NULL;
  152.         goto retry;
  153.     }
  154.     bp = buf;
  155.  
  156.     /* first try to call execve() without path lookup. execve() walks
  157.        a (possibly provided) CLI PATH, and also supports resident
  158.        programs. If this fails, we can still try to find the program
  159.        along the $PATH */
  160.     execv (name, argv);
  161.     /* if we get here, the execv() failed. So start magic ;-)) */
  162.     
  163.     /* only continue if execv didn't find the program. */
  164.     if (errno != ENOENT)
  165.       return -1;
  166.  
  167.     /* Get the path we're searching. */
  168.     if (!(path = getenv("PATH")))
  169.         path = _PATH_DEFPATH;
  170.     cur = path = strdup(path);
  171.  
  172.     while ((p = strsep(&cur, ",:"))) {
  173.         /*
  174.          * It's a SHELL path -- double, leading and trailing colons
  175.          * mean the current directory.
  176.          */
  177.         if (!*p) {
  178.             p = ".";
  179.             lp = 1;
  180.         } else
  181.             lp = strlen(p);
  182.         ln = strlen(name);
  183.  
  184.         /*
  185.          * If the path is too long complain.  This is a possible
  186.          * security issue; given a way to make the path too long
  187.          * the user may execute the wrong program.
  188.          */
  189.         if (lp + ln + 2 > sizeof(buf)) {
  190.             syscall(SYS_write, STDERR_FILENO, "execvp: ", 8);
  191.             syscall(SYS_write, STDERR_FILENO, p, lp);
  192.             syscall(SYS_write, STDERR_FILENO, ": path too long\n", 16);
  193.             continue;
  194.         }
  195.         bcopy(p, buf, lp);
  196.         buf[lp] = '/';
  197.         bcopy(name, buf + lp + 1, ln);
  198.         buf[lp + ln + 1] = '\0';
  199.  
  200. retry:        execve(bp, argv, *u.u_environ);
  201.         switch(errno) {
  202.         case EACCES:
  203.             eacces = 1;
  204.             break;
  205.         case ENOENT:
  206.             break;
  207.         case ENOEXEC: {
  208.             register size_t cnt;
  209.             register char **ap;
  210.  
  211.             for (cnt = 0, ap = (char **)argv; *ap; ++ap, ++cnt);
  212.             if ((ap = malloc((cnt + 2) * sizeof(char *)))) {
  213.                 bcopy(argv + 1, ap + 2, cnt * sizeof(char *));
  214.                 ap[0] = "sh";
  215.                 ap[1] = bp;
  216.                 execve(_PATH_BSHELL, ap, *u.u_environ);
  217.                 free(ap);
  218.             }
  219.             goto done;
  220.         }
  221.         case ETXTBSY:
  222.             if (etxtbsy < 3)
  223.                 sleep(++etxtbsy);
  224.             goto retry;
  225.         default:
  226.             goto done;
  227.         }
  228.     }
  229.     if (eacces)
  230.         errno = EACCES;
  231.     else if (!errno)
  232.         errno = ENOENT;
  233.     KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  234. done:    if (path)
  235.         free(path);
  236.     return(-1);
  237. }
  238.