Added setting position while duplicating file handles with FMF_WRITE mode. It's neede...
[cake.git] / compiler / clib / spawnvp.c
blob7e453f776d6ba90877fbd12d3e20e34c0ebf18b0
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
5 spavnv() function, used to spawn new processes.
6 */
8 #include <proto/dos.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 #include <aros/debug.h>
14 #include "__upath.h"
15 #include "__spawnv.h"
17 /*****************************************************************************
19 NAME */
20 #include <process.h>
22 int spawnvp(
24 /* SYNOPSIS */
25 int mode,
26 const char *command,
27 char *const argv[])
29 /* FUNCTION
30 Spawn a child process, given a vector of arguments. It's like spawnv(), but
31 searches the command in the directories specified by the PATH environment
32 variable.
34 INPUTS
35 mode - the way the child process has to be loaded, and how the parent has to behave
36 after the child process is initiated. Specify one of the following values:
38 P_WAIT - the child program is loaded into memory, then it's executed while
39 the parent process waits for it to terminate, at which point the
40 patent process resumes execution.
42 P_NOWAIT - the parent program is executed concurrently with the new child process.
44 P_OVERLAY - teplace the parent program with the child program in memory and then
45 execute the child. The parent program will never be resumed. This
46 mode is equivalent to calling one of the exec*() functions.
48 command - the command to execute. Unless it's an absolute path name, the command
49 will be searched in the directories specified by the PATH environment
50 variable.
52 argv - a pointer to a NULL terminated array of strings representing arguments to pass
53 to the child process. The first entry in the array is conventionally the name of
54 the program to spawn, but in any case it must _never_ be NULL, and the argv
55 pointer itself must never be NULL either.
57 RESULT
59 If P_WAIT is specified, then the return code of the child program is returned.
60 If instead P_NOWAIT is used, then the pid of the newly created process is returned.
61 Finally, if P_OVERLAY is used, the function doesn't return unless an error has occurred,
62 in which case -1 is returned also for the other modes and the global errno variable will
63 hold the proper error code.
65 NOTES
67 The way the child process behaves regarding parent's file descriptors, signal handlers
68 and so on is the same way it would behave with one of the exec*(3) functions.
69 This, for one, means that all filedescriptors are inherited except the ones which have
70 the close-on-exec flag set.
72 EXAMPLE
74 BUGS
76 SEE ALSO
77 execl(), execle(), execlp(), execlpe(), execv(), execve(), execvp(), execvpe(), getenv(),
78 putenv(), setenv(), spawn(), spawnl(), spawnle(), spawnlp(), spawnlpe(), spawnp(),
79 spawnve(), spawnvp(), spawnvpe(), wait(), waitpid()
81 INTERNALS
83 For now only the stdin, stout and stderr file descriptors are inherited, and signals
84 are not handled yet.
86 ******************************************************************************/
88 const char *acommand;
90 if (command == NULL || argv == NULL || argv[0] == NULL)
92 errno = EFAULT;
94 return -1;
97 acommand = __path_u2a(command);
98 if (!acommand)
99 return -1;
101 /* Does the command contain any reference to directories? If so, then
102 we don't have to wade trough the PATH. */
103 if (strpbrk(acommand, ":/") == NULL)
105 /* Ok, it doesn't contain any such reference. Thus, from now on
106 we can safely use command rather than acommand. */
108 char *colon;
109 char default_PATH[] = "/bin:/usr/bin:";
110 const char *dir = getenv("PATH");
112 if (!dir) dir = default_PATH;
114 while ((colon = strchr(dir, ':')) != NULL || (colon = strchr(dir, '\0')) != NULL)
116 BPTR dirlock;
117 int restore_colon = 0;
119 /* We shouldn't really do this, but it saves some memory and time. */
120 if (*colon == ':')
122 *colon = '\0';
123 restore_colon = 1;
126 dirlock = Lock(__path_u2a(dir), SHARED_LOCK);
128 if (restore_colon)
129 *colon = ':';
131 if (dirlock)
133 BPTR olddir = CurrentDir(dirlock);
134 BPTR seg;
135 int ret;
137 seg = LoadSeg(command);
139 CurrentDir(olddir);
140 UnLock(dirlock);
142 ret = __spawnv(mode, seg, argv);
144 if (ret != -1)
145 return ret;
148 /* Loop until the program is found and executed */
149 if (*colon == '\0')
150 break;
152 dir = colon + 1;
155 /* set acommand properly so that the below LoadSeg() has a chance to succeed. */
156 acommand = command;
159 return __spawnv(mode, LoadSeg(acommand), argv);