You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rb...@hyperreal.org on 1999/10/11 16:20:49 UTC
cvs commit: apache-2.0/src/os/win32 util_win32.c
rbb 99/10/11 07:20:48
Modified: src Configure
src/include http_log.h
src/lib/apr/file_io/unix open.c
src/lib/apr/include apr_file_io.h apr_lib.h
apr_thread_proc.h
src/lib/apr/lib apr_cpystrn.c apr_pools.c
src/lib/apr/threadproc/unix proc.c
src/main http_log.c
src/os/beos os-inline.c os.c
src/os/unix os-inline.c
src/os/win32 util_win32.c
Log:
Make Apache use the new ap_create_process call. This is the first of a
group of patches. This patch, allows the core server to compile and
serve pages. There is a set of patches which will follow to allow the
standard modules to use ap_create_process. This change should make
writing code which spawns new processes easy to read and understand.
Submitted by: Paul Reder
Revision Changes Path
1.12 +1 -1 apache-2.0/src/Configure
Index: Configure
===================================================================
RCS file: /home/cvs/apache-2.0/src/Configure,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Configure 1999/10/10 17:07:53 1.11
+++ Configure 1999/10/11 14:20:36 1.12
@@ -1748,7 +1748,7 @@
fi
cd ../..
APRLIB=""
- for lib in apr file network lock misc sig threadproc time; do
+ for lib in network threadproc file misc apr time lock sig; do
APRLIB="$APRLIB \$(SRCDIR)/lib/apr/libs/lib${lib}.a"
done
CFLAGS="$CFLAGS -I\$(SRCDIR)/lib/apr/include"
1.5 +1 -1 apache-2.0/src/include/http_log.h
Index: http_log.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/include/http_log.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- http_log.h 1999/09/08 14:15:40 1.4
+++ http_log.h 1999/10/11 14:20:37 1.5
@@ -138,7 +138,7 @@
ap_context_t *p;
#ifndef NO_RELIABLE_PIPED_LOGS
char *program;
- int pid;
+ ap_proc_t *pid;
ap_file_t fds[2];
#else
ap_file_t *write_f;
1.14 +14 -0 apache-2.0/src/lib/apr/file_io/unix/open.c
Index: open.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/file_io/unix/open.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- open.c 1999/10/06 23:03:46 1.13
+++ open.c 1999/10/11 14:20:38 1.14
@@ -278,3 +278,17 @@
return APR_SUCCESS;
}
+/* ***APRDOC********************************************************
+ * ap_status_t ap_ferror(ap_file_t *)
+ * Is there an error on the stream?
+ * arg 1) The apr file we are testing.
+ * NOTE: Returns -1 if the error indicator is set, APR_SUCCESS otherwise.
+ */
+ap_status_t ap_ferror(ap_file_t *fptr)
+{
+ if (ferror(fptr->filehand)) {
+ return (-1);
+ }
+
+ return APR_SUCCESS;
+}
1.11 +1 -0 apache-2.0/src/lib/apr/include/apr_file_io.h
Index: apr_file_io.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/include/apr_file_io.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- apr_file_io.h 1999/10/08 13:47:03 1.10
+++ apr_file_io.h 1999/10/11 14:20:38 1.11
@@ -111,6 +111,7 @@
ap_status_t ap_close(ap_file_t *);
ap_status_t ap_remove_file(char *, ap_context_t *);
ap_status_t ap_eof(ap_file_t *);
+ap_status_t ap_ferror(ap_file_t *);
ap_status_t ap_read(ap_file_t *, void *, ap_ssize_t *);
ap_status_t ap_write(ap_file_t *, void *, ap_ssize_t *);
1.12 +3 -2 apache-2.0/src/lib/apr/include/apr_lib.h
Index: apr_lib.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/include/apr_lib.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- apr_lib.h 1999/10/08 13:47:04 1.11
+++ apr_lib.h 1999/10/11 14:20:38 1.12
@@ -164,6 +164,8 @@
* Define the prototypes for the various APR GP routines.
*/
API_EXPORT(char *) ap_cpystrn(char *d, const char *s, size_t l);
+API_EXPORT(int) ap_tokenize_to_argv(ap_context_t *token_context,
+ char *arg_str, char ***argv_out);
/*API_EXPORT(ap_mutex_t *) ap_create_mutex(void *m);*/
API_EXPORT(int) ap_slack(int l, int h);
API_EXPORT_NONSTD(int) ap_execle(const char *c, const char *a, ...);
@@ -371,9 +373,8 @@
API_EXPORT(ap_status_t) ap_getpass(const char *prompt, char *pwbuf, size_t *bufsize);
API_EXPORT_NONSTD(ap_status_t) ap_null_cleanup(void *data);
-/*API_EXPORT(void) ap_note_subprocess(ap_pool_t *a, pid_t pid,
+API_EXPORT(void) ap_note_subprocess(struct context_t *a, pid_t pid,
enum kill_conditions how);
-*/
API_EXPORT(int)
ap_spawn_child(ap_context_t *p,
int (*func) (void *a, ap_child_info_t *c),
1.7 +9 -3 apache-2.0/src/lib/apr/include/apr_thread_proc.h
Index: apr_thread_proc.h
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/include/apr_thread_proc.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- apr_thread_proc.h 1999/10/08 14:45:00 1.6
+++ apr_thread_proc.h 1999/10/11 14:20:39 1.7
@@ -112,7 +112,13 @@
ap_status_t ap_createprocattr_init(ap_procattr_t **, ap_context_t *);
ap_status_t ap_setprocattr_io(ap_procattr_t *, ap_int32_t, ap_int32_t,
ap_int32_t);
-ap_status_t ap_setprocattr_dir(ap_procattr_t *, char *);
+ap_status_t ap_setprocattr_childin(struct procattr_t *, ap_file_t *,
+ ap_file_t *);
+ap_status_t ap_setprocattr_childout(struct procattr_t *, ap_file_t *,
+ ap_file_t *);
+ap_status_t ap_setprocattr_childerr(struct procattr_t *, ap_file_t *,
+ ap_file_t *);
+ap_status_t ap_setprocattr_dir(ap_procattr_t *, const char *);
ap_status_t ap_setprocattr_cmdtype(ap_procattr_t *, ap_cmdtype_e);
ap_status_t ap_setprocattr_detach(ap_procattr_t *, ap_int32_t);
ap_status_t ap_get_procdata(ap_proc_t *, char *, void *);
@@ -124,8 +130,8 @@
ap_status_t ap_get_childerr(ap_file_t **, ap_proc_t *);
ap_status_t ap_fork(ap_proc_t **, ap_context_t *);
-ap_status_t ap_create_process(ap_context_t *, char *, char *const [], char **,
- ap_procattr_t *, ap_proc_t **);
+ap_status_t ap_create_process(ap_proc_t **, ap_context_t *, const char *,
+ char *const [], char **, ap_procattr_t *);
ap_status_t ap_wait_proc(ap_proc_t *, ap_wait_how_e);
ap_status_t ap_kill(ap_proc_t *, ap_int32_t);
1.4 +84 -0 apache-2.0/src/lib/apr/lib/apr_cpystrn.c
Index: apr_cpystrn.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/lib/apr_cpystrn.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- apr_cpystrn.c 1999/10/01 16:18:32 1.3
+++ apr_cpystrn.c 1999/10/11 14:20:40 1.4
@@ -100,3 +100,87 @@
return (d);
}
+
+
+/*
+ * This function provides a way to parse a generic argument string
+ * into a standard argv[] form of argument list. It respects the
+ * usual "whitespace" and quoteing rules. In the future this could
+ * be expanded to include support for the ap_call_exec command line
+ * string processing (including converting '+' to ' ' and doing the
+ * url processing. It does not currently support this function.
+ *
+ * token_context: Context from which pool allocations will occur.
+ * arg_str: Input argument string for conversion to argv[].
+ * argv_out: Output location. This is a pointer to an array
+ * of pointers to strings (ie. &(char *argv[]).
+ * This value will be allocated from the contexts
+ * pool and filled in with copies of the tokens
+ * found during parsing of the arg_str.
+ */
+API_EXPORT(int) ap_tokenize_to_argv(ap_context_t *token_context,
+ char *arg_str, char ***argv_out)
+{
+ char *cp, *tmpCnt;
+ int isquoted, numargs = 0, rc = APR_SUCCESS;
+
+#define SKIP_WHITESPACE(cp) \
+ for ( ; *cp == ' ' || *cp == '\t'; ) { \
+ cp++; \
+ };
+
+#define CHECK_QUOTATION(cp,isquoted) \
+ isquoted = 0; \
+ if (*cp == '"') { \
+ isquoted = 1; \
+ cp++; \
+ }
+
+#define DETERMINE_NEXTSTRING(cp,isquoted) \
+ for ( ; *cp != '\0'; cp++) { \
+ if ( (isquoted && (*cp == ' ' || *cp == '\t')) \
+ || (*cp == '\\' && (*(cp+1) == ' ' || *(cp+1) == '\t'))) { \
+ cp++; \
+ continue; \
+ } \
+ if ( (!isquoted && (*cp == ' ' || *cp == '\t')) \
+ || (isquoted && *cp == '"') ) { \
+ break; \
+ } \
+ }
+
+ cp = arg_str;
+ SKIP_WHITESPACE(cp);
+ tmpCnt = cp;
+
+ /* This is ugly and expensive, but if anyone wants to figure a
+ * way to support any number of args without counting and
+ * allocating, please go ahead and change the code.
+ */
+ while (*tmpCnt != '\0') {
+ CHECK_QUOTATION(tmpCnt, isquoted);
+ DETERMINE_NEXTSTRING(tmpCnt, isquoted);
+ numargs++;
+ SKIP_WHITESPACE(tmpCnt);
+ }
+
+ *argv_out = ap_palloc(token_context, numargs*sizeof(char*));
+ if (*argv_out == NULL) {
+ return (APR_ENOMEM);
+ }
+
+ /* determine first argument */
+ numargs = 0;
+ while (*cp != '\0') {
+ CHECK_QUOTATION(cp, isquoted);
+ tmpCnt = cp;
+ DETERMINE_NEXTSTRING(cp, isquoted);
+ *cp++ = '\0';
+ (*argv_out)[numargs] = ap_pstrdup(token_context, tmpCnt);
+
+ SKIP_WHITESPACE(cp);
+ }
+ *cp++ = '\0';
+
+ return(rc);
+}
1.14 +0 -555 apache-2.0/src/lib/apr/lib/apr_pools.c
Index: apr_pools.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/lib/apr_pools.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- apr_pools.c 1999/10/08 14:26:12 1.13
+++ apr_pools.c 1999/10/11 14:20:41 1.14
@@ -1213,561 +1213,6 @@
#endif
-static pid_t spawn_child_core(ap_context_t *p,
- int (*func) (void *, ap_child_info_t *),
- void *data,enum kill_conditions kill_how,
- int *pipe_in, int *pipe_out, int *pipe_err)
-{
- pid_t pid;
- int in_fds[2];
- int out_fds[2];
- int err_fds[2];
- int save_errno;
-
- if (pipe_in && os_pipe(in_fds) < 0) {
- return 0;
- }
-
- if (pipe_out && os_pipe(out_fds) < 0) {
- save_errno = errno;
- if (pipe_in) {
- close(in_fds[0]);
- close(in_fds[1]);
- }
- errno = save_errno;
- return 0;
- }
-
- if (pipe_err && os_pipe(err_fds) < 0) {
- save_errno = errno;
- if (pipe_in) {
- close(in_fds[0]);
- close(in_fds[1]);
- }
- if (pipe_out) {
- close(out_fds[0]);
- close(out_fds[1]);
- }
- errno = save_errno;
- return 0;
- }
-
-#ifdef WIN32
-
- {
- HANDLE thread_handle;
- int hStdIn, hStdOut, hStdErr;
- int old_priority;
- ap_child_info_t info;
-
- (void) ap_acquire_mutex(spawn_mutex);
- thread_handle = GetCurrentThread(); /* doesn't need to be closed */
- old_priority = GetThreadPriority(thread_handle);
- SetThreadPriority(thread_handle, THREAD_PRIORITY_HIGHEST);
- /* Now do the right thing with your pipes */
- if (pipe_in) {
- hStdIn = dup(fileno(stdin));
- if (dup2(in_fds[0], fileno(stdin))) {
- ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
- "dup2(stdin) failed");
- }
- close(in_fds[0]);
- }
- if (pipe_out) {
- hStdOut = dup(fileno(stdout));
- close(fileno(stdout));
- if (dup2(out_fds[1], fileno(stdout))) {
- ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
- "dup2(stdout) failed");
- }
- close(out_fds[1]);
- }
- if (pipe_err) {
- hStdErr = dup(fileno(stderr));
- if (dup2(err_fds[1], fileno(stderr))) {
- ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
- "dup2(stderr) failed");
- }
- close(err_fds[1]);
- }
-
- info.hPipeInputRead = GetStdHandle(STD_INPUT_HANDLE);
- info.hPipeOutputWrite = GetStdHandle(STD_OUTPUT_HANDLE);
- info.hPipeErrorWrite = GetStdHandle(STD_ERROR_HANDLE);
-
- pid = (*func) (data, &info);
- if (pid == -1) {
- pid = 0; /* map Win32 error code onto Unix default */
- }
-
- if (!pid) {
- save_errno = errno;
- close(in_fds[1]);
- close(out_fds[0]);
- close(err_fds[0]);
- }
-
- /* restore the original stdin, stdout and stderr */
- if (pipe_in) {
- dup2(hStdIn, fileno(stdin));
- close(hStdIn);
- }
- if (pipe_out) {
- dup2(hStdOut, fileno(stdout));
- close(hStdOut);
- }
- if (pipe_err) {
- dup2(hStdErr, fileno(stderr));
- close(hStdErr);
- }
-
- if (pid) {
- ap_note_subprocess(p, pid, kill_how);
- if (pipe_in) {
- *pipe_in = in_fds[1];
- }
- if (pipe_out) {
- *pipe_out = out_fds[0];
- }
- if (pipe_err) {
- *pipe_err = err_fds[0];
- }
- }
- SetThreadPriority(thread_handle, old_priority);
- (void) ap_release_mutex(spawn_mutex);
- /*
- * go on to the end of the function, where you can
- * unblock alarms and return the pid
- */
-
- }
-#elif defined(OS2)
- {
- int save_in=-1, save_out=-1, save_err=-1;
-
- if (pipe_out) {
- save_out = dup(STDOUT_FILENO);
- dup2(out_fds[1], STDOUT_FILENO);
- close(out_fds[1]);
- }
-
- if (pipe_in) {
- save_in = dup(STDIN_FILENO);
- dup2(in_fds[0], STDIN_FILENO);
- close(in_fds[0]);
- }
-
- if (pipe_err) {
- save_err = dup(STDERR_FILENO);
- dup2(err_fds[1], STDERR_FILENO);
- close(err_fds[1]);
- }
-
- pid = func(data, NULL);
-
- if (pid) {
- ap_note_subprocess(p, pid, kill_how);
- }
-
- if (pipe_out) {
- close(STDOUT_FILENO);
- dup2(save_out, STDOUT_FILENO);
- close(save_out);
- *pipe_out = out_fds[0];
- }
-
- if (pipe_in) {
- close(STDIN_FILENO);
- dup2(save_in, STDIN_FILENO);
- close(save_in);
- *pipe_in = in_fds[1];
- }
-
- if (pipe_err) {
- close(STDERR_FILENO);
- dup2(save_err, STDERR_FILENO);
- close(save_err);
- *pipe_err = err_fds[0];
- }
- }
-#elif defined(TPF)
- return (pid = ap_tpf_spawn_child(p, func, data, kill_how,
- pipe_in, pipe_out, pipe_err, out_fds,
- in_fds, err_fds));
-#else
-
- if ((pid = fork()) < 0) {
- save_errno = errno;
- if (pipe_in) {
- close(in_fds[0]);
- close(in_fds[1]);
- }
- if (pipe_out) {
- close(out_fds[0]);
- close(out_fds[1]);
- }
- if (pipe_err) {
- close(err_fds[0]);
- close(err_fds[1]);
- }
- errno = save_errno;
- return 0;
- }
-
- if (!pid) {
- /* Child process */
- RAISE_SIGSTOP(SPAWN_CHILD);
-
- if (pipe_out) {
- close(out_fds[0]);
- dup2(out_fds[1], STDOUT_FILENO);
- close(out_fds[1]);
- }
-
- if (pipe_in) {
- close(in_fds[1]);
- dup2(in_fds[0], STDIN_FILENO);
- close(in_fds[0]);
- }
-
- if (pipe_err) {
- close(err_fds[0]);
- dup2(err_fds[1], STDERR_FILENO);
- close(err_fds[1]);
- }
-
- /*
- * HP-UX SIGCHLD fix goes here, if someone will remind me
- * what it is...
- */
- signal(SIGCHLD, SIG_DFL); /* Was that it? */
-
- func(data, NULL);
- exit(1); /* Should only get here if the exec in func() failed */
- }
-
- /* Parent process */
-
- ap_note_subprocess(p, pid, kill_how);
-
- if (pipe_out) {
- close(out_fds[1]);
- *pipe_out = out_fds[0];
- }
-
- if (pipe_in) {
- close(in_fds[0]);
- *pipe_in = in_fds[1];
- }
-
- if (pipe_err) {
- close(err_fds[1]);
- *pipe_err = err_fds[0];
- }
-#endif /* WIN32 */
-
- return pid;
-}
-
-
-API_EXPORT(int) ap_spawn_child(ap_context_t *p,
- int (*func) (void *v, ap_child_info_t *c),
- void *data, enum kill_conditions kill_how,
- FILE **pipe_in, FILE **pipe_out,
- FILE **pipe_err)
-{
- int fd_in, fd_out, fd_err;
- pid_t pid;
- int save_errno;
-
- ap_block_alarms();
-
- pid = spawn_child_core(p, func, data, kill_how,
- pipe_in ? &fd_in : NULL,
- pipe_out ? &fd_out : NULL,
- pipe_err ? &fd_err : NULL);
-
- if (pid == 0) {
- save_errno = errno;
- ap_unblock_alarms();
- errno = save_errno;
- return 0;
- }
-
- if (pipe_out) {
- *pipe_out = ap_fdopen(fd_out, "r" BINMODE);
- if (*pipe_out) {
- /* remove for now. These go away with the APR abstraction
- * for process spawning.
- * ap_note_cleanups_for_file(p, *pipe_out);
- */
- }
- else {
- close(fd_out);
- }
- }
-
- if (pipe_in) {
- *pipe_in = ap_fdopen(fd_in, "w" BINMODE);
- if (*pipe_in) {
- /* remove for now. These go away with the APR abstraction
- * for process spawning.
- * ap_note_cleanups_for_file(p, *pipe_in);
- */
- }
- else {
- close(fd_in);
- }
- }
-
- if (pipe_err) {
- *pipe_err = ap_fdopen(fd_err, "r" BINMODE);
- if (*pipe_err) {
- /* remove for now. These go away with the APR abstraction
- * for process spawning.
- * ap_note_cleanups_for_file(p, *pipe_err);
- */
- }
- else {
- close(fd_err);
- }
- }
-
- ap_unblock_alarms();
- return pid;
-}
-#if 0
-API_EXPORT(int) ap_bspawn_child(ap_pool_t *p,
- int (*func) (void *v, ap_child_info_t *c),
- void *data, enum kill_conditions kill_how,
- BUFF **pipe_in, BUFF **pipe_out,
- BUFF **pipe_err)
-{
-#ifdef WIN32
- SECURITY_ATTRIBUTES sa = {0};
- HANDLE hPipeOutputRead = NULL;
- HANDLE hPipeOutputWrite = NULL;
- HANDLE hPipeInputRead = NULL;
- HANDLE hPipeInputWrite = NULL;
- HANDLE hPipeErrorRead = NULL;
- HANDLE hPipeErrorWrite = NULL;
- HANDLE hPipeInputWriteDup = NULL;
- HANDLE hPipeOutputReadDup = NULL;
- HANDLE hPipeErrorReadDup = NULL;
- HANDLE hCurrentProcess;
- pid_t pid = 0;
- ap_child_info_t info;
-
- ap_block_alarms();
-
- /*
- * First thing to do is to create the pipes that we will use
- * for stdin, stdout, and stderr in the child process.
- */
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
-
-
- /* Create pipes for standard input/output/error redirection. */
- if (pipe_in && !CreatePipe(&hPipeInputRead, &hPipeInputWrite, &sa, 0)) {
- return 0;
- }
-
- if (pipe_out && !CreatePipe(&hPipeOutputRead, &hPipeOutputWrite, &sa, 0)) {
- if (pipe_in) {
- CloseHandle(hPipeInputRead);
- CloseHandle(hPipeInputWrite);
- }
- return 0;
- }
-
- if (pipe_err && !CreatePipe(&hPipeErrorRead, &hPipeErrorWrite, &sa, 0)) {
- if (pipe_in) {
- CloseHandle(hPipeInputRead);
- CloseHandle(hPipeInputWrite);
- }
- if (pipe_out) {
- CloseHandle(hPipeOutputRead);
- CloseHandle(hPipeOutputWrite);
- }
- return 0;
- }
- /*
- * When the pipe handles are created, the security descriptor
- * indicates that the handle can be inherited. However, we do not
- * want the server side handles to the pipe to be inherited by the
- * child CGI process. If the child CGI does inherit the server
- * side handles, then the child may be left around if the server
- * closes its handles (e.g. if the http connection is aborted),
- * because the child will have a valid copy of handles to both
- * sides of the pipes, and no I/O error will occur. Microsoft
- * recommends using DuplicateHandle to turn off the inherit bit
- * under NT and Win95.
- */
- hCurrentProcess = GetCurrentProcess();
- if ((pipe_in && !DuplicateHandle(hCurrentProcess, hPipeInputWrite,
- hCurrentProcess,
- &hPipeInputWriteDup, 0, FALSE,
- DUPLICATE_SAME_ACCESS))
- || (pipe_out && !DuplicateHandle(hCurrentProcess, hPipeOutputRead,
- hCurrentProcess, &hPipeOutputReadDup,
- 0, FALSE, DUPLICATE_SAME_ACCESS))
- || (pipe_err && !DuplicateHandle(hCurrentProcess, hPipeErrorRead,
- hCurrentProcess, &hPipeErrorReadDup,
- 0, FALSE, DUPLICATE_SAME_ACCESS))) {
- if (pipe_in) {
- CloseHandle(hPipeInputRead);
- CloseHandle(hPipeInputWrite);
- }
- if (pipe_out) {
- CloseHandle(hPipeOutputRead);
- CloseHandle(hPipeOutputWrite);
- }
- if (pipe_err) {
- CloseHandle(hPipeErrorRead);
- CloseHandle(hPipeErrorWrite);
- }
- return 0;
- }
- else {
- if (pipe_in) {
- CloseHandle(hPipeInputWrite);
- hPipeInputWrite = hPipeInputWriteDup;
- }
- if (pipe_out) {
- CloseHandle(hPipeOutputRead);
- hPipeOutputRead = hPipeOutputReadDup;
- }
- if (pipe_err) {
- CloseHandle(hPipeErrorRead);
- hPipeErrorRead = hPipeErrorReadDup;
- }
- }
-
- /* The script writes stdout to this pipe handle */
- info.hPipeOutputWrite = hPipeOutputWrite;
-
- /* The script reads stdin from this pipe handle */
- info.hPipeInputRead = hPipeInputRead;
-
- /* The script writes stderr to this pipe handle */
- info.hPipeErrorWrite = hPipeErrorWrite;
-
- /*
- * Try to launch the CGI. Under the covers, this call
- * will try to pick up the appropriate interpreter if
- * one is needed.
- */
- pid = func(data, &info);
- if (pid == -1) {
- /* Things didn't work, so cleanup */
- pid = 0; /* map Win32 error code onto Unix default */
- CloseHandle(hPipeOutputRead);
- CloseHandle(hPipeInputWrite);
- CloseHandle(hPipeErrorRead);
- }
- else {
- if (pipe_out) {
- /*
- * This pipe represents stdout for the script,
- * so we read from this pipe.
- */
- /* Create a read buffer */
- *pipe_out = ap_bcreate(p, B_RD);
-
- /* Setup the cleanup routine for the handle */
- ap_note_cleanups_for_h(p, hPipeOutputRead);
-
- /* Associate the handle with the new buffer */
- ap_bpushh(*pipe_out, hPipeOutputRead);
- }
-
- if (pipe_in) {
- /*
- * This pipe represents stdin for the script, so we
- * write to this pipe.
- */
- /* Create a write buffer */
- *pipe_in = ap_bcreate(p, B_WR);
-
- /* Setup the cleanup routine for the handle */
- ap_note_cleanups_for_h(p, hPipeInputWrite);
-
- /* Associate the handle with the new buffer */
- ap_bpushh(*pipe_in, hPipeInputWrite);
-
- }
-
- if (pipe_err) {
- /*
- * This pipe represents stderr for the script, so
- * we read from this pipe.
- */
- /* Create a read buffer */
- *pipe_err = ap_bcreate(p, B_RD);
-
- /* Setup the cleanup routine for the handle */
- ap_note_cleanups_for_h(p, hPipeErrorRead);
-
- /* Associate the handle with the new buffer */
- ap_bpushh(*pipe_err, hPipeErrorRead);
- }
- }
-
-
- /*
- * Now that handles have been inherited, close them to be safe.
- * You don't want to read or write to them accidentally, and we
- * sure don't want to have a handle leak.
- */
- CloseHandle(hPipeOutputWrite);
- CloseHandle(hPipeInputRead);
- CloseHandle(hPipeErrorWrite);
-
-#else
- int fd_in, fd_out, fd_err;
- pid_t pid;
- int save_errno;
-
- ap_block_alarms();
-
- pid = spawn_child_core(p, func, data, kill_how,
- pipe_in ? &fd_in : NULL,
- pipe_out ? &fd_out : NULL,
- pipe_err ? &fd_err : NULL);
-
- if (pid == 0) {
- save_errno = errno;
- ap_unblock_alarms();
- errno = save_errno;
- return 0;
- }
-
- if (pipe_out) {
- *pipe_out = ap_bcreate(p, B_RD);
- ap_note_cleanups_for_fd(p, fd_out);
- ap_bpushfd(*pipe_out, fd_out, fd_out);
- }
-
- if (pipe_in) {
- *pipe_in = ap_bcreate(p, B_WR);
- ap_note_cleanups_for_fd(p, fd_in);
- ap_bpushfd(*pipe_in, fd_in, fd_in);
- }
-
- if (pipe_err) {
- *pipe_err = ap_bcreate(p, B_RD);
- ap_note_cleanups_for_fd(p, fd_err);
- ap_bpushfd(*pipe_err, fd_err, fd_err);
- }
-#endif
-
- ap_unblock_alarms();
- return pid;
-}
-#endif
-
static void free_proc_chain(struct process_chain *procs)
{
/* Dispose of the subprocesses we've spawned off in the course of
1.5 +92 -5 apache-2.0/src/lib/apr/threadproc/unix/proc.c
Index: proc.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/threadproc/unix/proc.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- proc.c 1999/10/04 16:37:39 1.4
+++ proc.c 1999/10/11 14:20:43 1.5
@@ -127,6 +127,93 @@
return APR_SUCCESS;
}
+
+/* ***APRDOC********************************************************
+ * ap_status_t ap_setprocattr_childin(ap_procattr_t *, ap_file_t *,
+ * ap_file_t *)
+ * Set the child_in and/or parent_in values to existing ap_file_t
+ * values. This is NOT a required initializer function. This is
+ * useful if you have already opened a pipe (or multiple files)
+ * that you wish to use, perhaps persistently across mutiple
+ * process invocations - such as a log file. You can save some
+ * extra function calls by not creating your own pipe since this
+ * creates one in the process space for you.
+ * arg 1) The procattr we care about.
+ * arg 2) ap_file_t value to use as child_in. Must be a valid file.
+ * arg 3) ap_file_t value to use as parent_in. Must be a valid file.
+ */
+ap_status_t ap_setprocattr_childin(struct procattr_t *attr, ap_file_t *child_in,
+ ap_file_t *parent_in)
+{
+ if (attr->child_in == NULL && attr->parent_in == NULL)
+ ap_create_pipe(&attr->child_in, &attr->parent_in, attr->cntxt);
+
+ if (child_in != NULL)
+ ap_dupfile(&attr->child_in, child_in);
+
+ if (parent_in != NULL)
+ ap_dupfile(&attr->parent_in, parent_in);
+
+ return APR_SUCCESS;
+}
+
+
+/* ***APRDOC********************************************************
+ * ap_status_t ap_setprocattr_childout(ap_procattr_t *, ap_file_t *,
+ * ap_file_t *)
+ * Set the child_out and parent_out values to existing ap_file_t
+ * values. This is NOT a required initializer function. This is
+ * useful if you have already opened a pipe (or multiple files)
+ * that you wish to use, perhaps persistently across mutiple
+ * process invocations - such as a log file.
+ * arg 1) The procattr we care about.
+ * arg 2) ap_file_t value to use as child_out. Must be a valid file.
+ * arg 3) ap_file_t value to use as parent_out. Must be a valid file.
+ */
+ap_status_t ap_setprocattr_childout(struct procattr_t *attr, ap_file_t *child_out,
+ ap_file_t *parent_out)
+{
+ if (attr->child_out == NULL && attr->parent_out == NULL)
+ ap_create_pipe(&attr->child_out, &attr->parent_out, attr->cntxt);
+
+ if (child_out != NULL)
+ ap_dupfile(&attr->child_out, child_out);
+
+ if (parent_out != NULL)
+ ap_dupfile(&attr->parent_out, parent_out);
+
+ return APR_SUCCESS;
+}
+
+
+/* ***APRDOC********************************************************
+ * ap_status_t ap_setprocattr_childerr(ap_procattr_t *, ap_file_t *,
+ * ap_file_t *)
+ * Set the child_err and parent_err values to existing ap_file_t
+ * values. This is NOT a required initializer function. This is
+ * useful if you have already opened a pipe (or multiple files)
+ * that you wish to use, perhaps persistently across mutiple
+ * process invocations - such as a log file.
+ * arg 1) The procattr we care about.
+ * arg 2) ap_file_t value to use as child_err. Must be a valid file.
+ * arg 3) ap_file_t value to use as parent_err. Must be a valid file.
+ */
+ap_status_t ap_setprocattr_childerr(struct procattr_t *attr, ap_file_t *child_err,
+ ap_file_t *parent_err)
+{
+ if (attr->child_err == NULL && attr->parent_err == NULL)
+ ap_create_pipe(&attr->child_err, &attr->parent_err, attr->cntxt);
+
+ if (child_err != NULL)
+ ap_dupfile(&attr->child_err, child_err);
+
+ if (parent_err != NULL)
+ ap_dupfile(&attr->parent_err, parent_err);
+
+ return APR_SUCCESS;
+}
+
+
/* ***APRDOC********************************************************
* ap_status_t ap_setprocattr_dir(ap_procattr_t *, char *)
* Set which directory the child process should start executing in.
@@ -136,7 +223,7 @@
* is made.
*/
ap_status_t ap_setprocattr_dir(struct procattr_t *attr,
- char *dir)
+ const char *dir)
{
attr->currdir = ap_pstrdup(attr->cntxt, dir);
if (attr->currdir) {
@@ -199,7 +286,7 @@
}
/* ***APRDOC********************************************************
- * ap_status_t ap_create_process(ap_context_t *, char *, char *const [],
+ * ap_status_t ap_create_process(ap_context_t *, const char *, char *const [],
char **, ap_procattr_t *, ap_proc_t **)
* Create a new process and execute a new program within that process.
* arg 1) The context to use.
@@ -212,9 +299,9 @@
* process
* arg 6) The resulting process handle.
*/
-ap_status_t ap_create_process(ap_context_t *cont, char *progname,
- char *const args[], char **env,
- struct procattr_t *attr, struct proc_t **new)
+ap_status_t ap_create_process(struct proc_t **new, ap_context_t *cont,
+ const char *progname, char *const args[],
+ char **env, struct procattr_t *attr)
{
int i;
char **newargs;
1.9 +105 -113 apache-2.0/src/main/http_log.c
Index: http_log.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_log.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- http_log.c 1999/10/06 23:04:08 1.8
+++ http_log.c 1999/10/11 14:20:45 1.9
@@ -156,60 +156,84 @@
{NULL, -1},
};
-static int error_log_child(void *cmd, ap_child_info_t *pinfo)
+static int log_child(ap_context_t *p, const char *progname,
+ ap_file_t **fpout, ap_file_t **fpin,
+ ap_file_t **fperr)
{
/* Child process code for 'ErrorLog "|..."';
* may want a common framework for this, since I expect it will
* be common for other foo-loggers to want this sort of thing...
*/
- int child_pid = 0;
+ int rc = -1;
+ ap_procattr_t *procattr;
+ ap_proc_t *procnew;
+ ap_os_proc_t fred;
+ ap_block_alarms();
ap_cleanup_for_exec();
+
#ifdef SIGHUP
/* No concept of a child process on Win32 */
signal(SIGHUP, SIG_IGN);
#endif /* ndef SIGHUP */
-#if defined(WIN32)
- child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
- return(child_pid);
-#elif defined(OS2)
- /* For OS/2 we need to use a '/' and spawn the child rather than exec as
- * we haven't forked */
- child_pid = spawnl(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
- return(child_pid);
-#else
- execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
-#endif
- exit(1);
- /* NOT REACHED */
- return(child_pid);
+
+ if ((ap_createprocattr_init(&procattr, p) != APR_SUCCESS) ||
+ (ap_setprocattr_io(procattr,
+ fpin ? 1 : 0,
+ fpout ? 1 : 0,
+ fperr ? 1 : 0) != APR_SUCCESS) ||
+ (ap_setprocattr_dir(procattr, progname) != APR_SUCCESS)) {
+ /* Something bad happened, give up and go away. */
+ rc = -1;
+ }
+ else {
+ rc = ap_create_process(&procnew, p, progname, NULL, NULL, procattr);
+
+ if (rc == APR_SUCCESS) {
+#ifndef WIN32
+ /* pjr - this is a cheap hack for now to get the basics working in
+ * stages. ap_note_subprocess and free_proc need to be redone
+ * to make use of ap_proc_t instead of pid.
+ */
+ ap_get_os_proc(procnew, &fred);
+ ap_note_subprocess(p, fred, kill_after_timeout);
+#endif
+ if (fpin) {
+ ap_get_childin(fpin, procnew);
+ }
+
+ if (fpout) {
+ ap_get_childout(fpout, procnew);
+ }
+
+ if (fperr) {
+ ap_get_childerr(fperr, procnew);
+ }
+ }
+ }
+
+ ap_unblock_alarms();
+
+ return(rc);
}
static void open_error_log(server_rec *s, ap_context_t *p)
{
const char *fname;
+ int rc;
if (*s->error_fname == '|') {
- FILE *dummy;
- int dummyno;
-#ifdef TPF
- TPF_FORK_CHILD cld;
- cld.filename = s->error_fname+1;
- cld.subprocess_env = NULL;
- cld.prog_type = FORK_NAME;
- if (!ap_spawn_child(p, NULL, &cld,
- kill_after_timeout, &dummy, NULL, NULL)) {
-#else
- if (!ap_spawn_child(p, error_log_child, (void *)(s->error_fname+1),
- kill_after_timeout, &dummy, NULL, NULL)) {
-#endif /* TPF */
+ ap_file_t *dummy;
+
+ /* This starts a new process... */
+ rc = log_child (p, s->error_fname+1, NULL, &dummy, NULL);
+ if (rc != APR_SUCCESS) {
perror("ap_spawn_child");
fprintf(stderr, "Couldn't fork child for ErrorLog process\n");
exit(1);
}
- dummyno = fileno(dummy);
- ap_put_os_file(&s->error_log, &dummyno, p);
+ s->error_log = dummy;
}
#ifdef HAVE_SYSLOG
@@ -276,8 +300,7 @@
}
for (virt = s_main->next; virt; virt = virt->next) {
- if (virt->error_fname)
- {
+ if (virt->error_fname) {
for (q=s_main; q != virt; q = q->next)
if (q->error_fname != NULL &&
strcmp(q->error_fname, virt->error_fname) == 0)
@@ -506,7 +529,7 @@
void ap_log_pid(ap_context_t *p, const char *fname)
{
- FILE *pid_file;
+ ap_file_t *pid_file;
struct stat finfo;
static pid_t saved_pid = -1;
pid_t mypid;
@@ -531,14 +554,14 @@
);
}
- if(!(pid_file = fopen(fname, "w"))) {
+ if(ap_open(&pid_file, p, fname, APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT) != APR_SUCCESS) {
perror("fopen");
fprintf(stderr, "%s: could not log pid to file %s\n",
ap_server_argv0, fname);
exit(1);
}
- fprintf(pid_file, "%ld\n", (long)mypid);
- fclose(pid_file);
+ ap_fprintf(pid_file, "%ld\n", (long)mypid);
+ ap_close(pid_file);
saved_pid = mypid;
}
@@ -592,35 +615,42 @@
static int piped_log_spawn(piped_log *pl)
{
- int pid;
+ int rc;
+ ap_procattr_t *procattr;
+ ap_os_proc_t pid;
+ ap_proc_t *procnew;
+
+ /* pjr - calls to block and unblock alarms weren't here before, was this */
+ /* an oversight or intentional? */
+/* ap_block_alarms(); */
- pid = fork();
- if (pid == 0) {
- /* XXX: this needs porting to OS2 and WIN32 */
- /* XXX: need to check what open fds the logger is actually passed,
- * XXX: and CGIs for that matter ... cleanup_for_exec *should*
- * XXX: close all the relevant stuff, but hey, it could be broken. */
- RAISE_SIGSTOP(PIPED_LOG_SPAWN);
- /* we're now in the child */
- close(STDIN_FILENO);
- dup2(pl->fds[0], STDIN_FILENO);
-
- ap_cleanup_for_exec();
- signal(SIGCHLD, SIG_DFL); /* for HPUX */
- signal(SIGHUP, SIG_IGN);
- execl(SHELL_PATH, SHELL_PATH, "-c", pl->program, NULL);
+ ap_cleanup_for_exec();
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_IGN);
+#endif
+ if ((ap_createprocattr_init(pl->p, &procattr) != APR_SUCCESS) ||
+ (ap_setprocattr_dir(procattr, pl->program) != APR_SUCCESS) ||
+ (ap_set_childin(procattr, pl->fds[0], pl->fds[1]) != APR_SUCCESS)) {
+ /* Something bad happened, give up and go away. */
fprintf(stderr,
"piped_log_spawn: unable to exec %s -c '%s': %s\n",
SHELL_PATH, pl->program, strerror (errno));
- exit(1);
+ rc = -1;
}
- if (pid == -1) {
- fprintf(stderr,
- "piped_log_spawn: unable to fork(): %s\n", strerror (errno));
- return -1;
+ else {
+ rc = ap_create_process(pl->p, pl->program, NULL, NULL, procattr, &procnew);
+
+ if (rc == APR_SUCCESS) { /* pjr - This no longer happens inside the child, */
+ RAISE_SIGSTOP(PIPED_LOG_SPAWN); /* I am assuming that if ap_create_process was */
+ /* successful that the child is running. */
+ pl->pid = procnew;
+ ap_get_os_proc(&procnew, &pid);
+ ap_register_other_child(pid, piped_log_maintenance, pl, pl->fds[1]);
+ }
}
- pl->pid = pid;
- ap_register_other_child(pid, piped_log_maintenance, pl, pl->fds[1]);
+
+/* ap_unblock_alarms(); */
+
return 0;
}
@@ -632,13 +662,13 @@
switch (reason) {
case OC_REASON_DEATH:
case OC_REASON_LOST:
- pl->pid = -1;
+ pl->pid = NULL;
ap_unregister_other_child(pl);
if (pl->program == NULL) {
/* during a restart */
break;
}
- if (piped_log_spawn(pl) == -1) {
+ if (piped_log_spawn(pl) != APR_SUCCESS) {
/* what can we do? This could be the error log we're having
* problems opening up... */
fprintf(stderr,
@@ -648,15 +678,15 @@
break;
case OC_REASON_UNWRITABLE:
- if (pl->pid != -1) {
- kill(pl->pid, SIGTERM);
+ if (pl->pid != NULL) {
+ ap_kill(pl->pid, SIGTERM);
}
break;
case OC_REASON_RESTART:
pl->program = NULL;
- if (pl->pid != -1) {
- kill(pl->pid, SIGTERM);
+ if (pl->pid != NULL) {
+ ap_kill(pl->pid, SIGTERM);
}
break;
@@ -670,8 +700,8 @@
{
piped_log *pl = data;
- if (pl->pid != -1) {
- kill(pl->pid, SIGTERM);
+ if (pl->pid != NULL) {
+ ap_kill(pl->pid, SIGTERM);
}
ap_unregister_other_child(pl);
ap_close(pl->fds[0]);
@@ -695,7 +725,7 @@
pl = ap_palloc(p, sizeof (*pl));
pl->p = p;
pl->program = ap_pstrdup(p, program);
- pl->pid = -1;
+ pl->pid = NULL;
if (ap_create_pipe(p, &pl->fds[0], &pl->fds[1]) != APR_SUCCESS) {
int save_errno = errno;
errno = save_errno;
@@ -720,60 +750,22 @@
}
#else
-static int piped_log_child(void *cmd, ap_child_info_t *pinfo)
-{
- /* Child process code for 'TransferLog "|..."';
- * may want a common framework for this, since I expect it will
- * be common for other foo-loggers to want this sort of thing...
- */
- int child_pid = 1;
-
- ap_cleanup_for_exec();
-#ifdef SIGHUP
- signal(SIGHUP, SIG_IGN);
-#endif
-#if defined(WIN32)
- child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
- return(child_pid);
-#elif defined(OS2)
- /* For OS/2 we need to use a '/' and spawn the child rather than exec as
- * we haven't forked */
- child_pid = spawnl(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
- return(child_pid);
-#else
- execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
-#endif
- perror("exec");
- fprintf(stderr, "Exec of shell for logging failed!!!\n");
- return(child_pid);
-}
-
-
API_EXPORT(piped_log *) ap_open_piped_log(ap_context_t *p, const char *program)
{
piped_log *pl;
- FILE *dummy;
- int dummyno;
-#ifdef TPF
- TPF_FORK_CHILD cld;
- cld.filename = (char *)program;
- cld.subprocess_env = NULL;
- cld.prog_type = FORK_NAME;
+ ap_file_t *dummy;
+ int rc;
- if (!ap_spawn_child (p, NULL, &cld,
- kill_after_timeout, &dummy, NULL, NULL)){
-#else
- if (!ap_spawn_child(p, piped_log_child, (void *)program,
- kill_after_timeout, &dummy, NULL, NULL)) {
-#endif /* TPF */
+ rc = log_child(p, program, NULL, &dummy, NULL);
+ if (rc != APR_SUCCESS) {
perror("ap_spawn_child");
fprintf(stderr, "Couldn't fork child for piped log process\n");
exit (1);
}
+
pl = ap_palloc(p, sizeof (*pl));
pl->p = p;
- dummyno = fileno(dummy);
- ap_put_os_file(&pl->write_f, &dummyno, p);
+ pl->write_f = dummy;
return pl;
}
1.2 +0 -17 apache-2.0/src/os/beos/os-inline.c
Index: os-inline.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/os/beos/os-inline.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- os-inline.c 1999/07/12 22:51:14 1.1
+++ os-inline.c 1999/10/11 14:20:46 1.2
@@ -30,20 +30,3 @@
{
return file[0] == '/';
}
-
-INLINE int ap_spawnvp(const char *file, char *const argv[])
-{
- int pid;
-
- if ((pid = fork()) == -1) {
- return pid;
- } else if (pid == 0) {
- if (execvp(file, argv) == -1)
- return -1;
- else
- return -1; /* If we get, we have a real error, but this keeps
- us from getting a warning during compile time. */
- } else
- return pid;
-}
-
1.4 +0 -16 apache-2.0/src/os/beos/os.c
Index: os.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/os/beos/os.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- os.c 1999/08/31 12:33:04 1.3
+++ os.c 1999/10/11 14:20:46 1.4
@@ -11,22 +11,6 @@
return file[0] == '/';
}
-int ap_spawnvp(const char *file, char *const argv[])
-{
- int pid;
-
- if ((pid = fork()) == -1) {
- return pid;
- } else if (pid == 0) {
- if (execvp(file, argv) == -1)
- return -1;
- else
- return -1; /* If we get, we have a real error, but this keeps
- us from getting a warning during compile time. */
- } else
- return pid;
-}
-
/* some linkers complain unless there's at least one function in each
* .o file... and extra prototype is for gcc -Wmissing-prototypes
1.3 +0 -17 apache-2.0/src/os/unix/os-inline.c
Index: os-inline.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/os/unix/os-inline.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- os-inline.c 1999/08/26 18:06:12 1.2
+++ os-inline.c 1999/10/11 14:20:47 1.3
@@ -30,20 +30,3 @@
{
return file[0] == '/';
}
-
-INLINE int ap_spawnvp(const char *file, char *const argv[])
-{
- int pid;
-
- if ((pid = fork()) == -1) {
- return pid;
- } else if (pid == 0) {
- if (execvp(file, argv) == -1)
- return -1;
- else
- return -1; /* If we get, we have a real error, but this keeps
- us from getting a warning during compile time. */
- } else
- return pid;
-}
-
1.3 +0 -140 apache-2.0/src/os/win32/util_win32.c
Index: util_win32.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/os/win32/util_win32.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- util_win32.c 1999/08/31 05:35:13 1.2
+++ util_win32.c 1999/10/11 14:20:48 1.3
@@ -332,146 +332,6 @@
return stat(szPath, pStat);
}
-/* Fix two really crap problems with Win32 spawn[lv]e*:
- *
- * 1. Win32 doesn't deal with spaces in argv.
- * 2. Win95 doesn't like / in cmdname.
- */
-
-#undef _spawnv
-API_EXPORT(int) os_spawnv(int mode, const char *cmdname,
- const char *const *argv)
-{
- int n;
- char **aszArgs;
- const char *szArg;
- char *szCmd;
- char *s;
-
- szCmd = _alloca(strlen(cmdname)+1);
- strcpy(szCmd, cmdname);
- for (s = szCmd; *s; ++s) {
- if (*s == '/') {
- *s = '\\';
- }
- }
-
- for (n = 0; argv[n]; ++n)
- ;
-
- aszArgs = _alloca((n + 1) * sizeof(const char *));
-
- for (n = 0; szArg = argv[n]; ++n) {
- if (strchr(szArg, ' ')) {
- int l = strlen(szArg);
-
- aszArgs[n] = _alloca(l + 2 + 1);
- aszArgs[n][0] = '"';
- strcpy(&aszArgs[n][1], szArg);
- aszArgs[n][l + 1] = '"';
- aszArgs[n][l + 2] = '\0';
- }
- else {
- aszArgs[n] = (char *)szArg;
- }
- }
-
- aszArgs[n] = NULL;
-
- return _spawnv(mode, szCmd, aszArgs);
-}
-
-#undef _spawnve
-API_EXPORT(int) os_spawnve(int mode, const char *cmdname,
- const char *const *argv, const char *const *envp)
-{
- int n;
- char **aszArgs;
- const char *szArg;
- char *szCmd;
- char *s;
-
- szCmd = _alloca(strlen(cmdname)+1);
- strcpy(szCmd, cmdname);
- for (s = szCmd; *s; ++s) {
- if (*s == '/') {
- *s = '\\';
- }
- }
-
- for (n = 0; argv[n]; ++n)
- ;
-
- aszArgs = _alloca((n + 1)*sizeof(const char *));
-
- for (n = 0; szArg = argv[n]; ++n){
- if (strchr(szArg, ' ')) {
- int l = strlen(szArg);
-
- aszArgs[n] = _alloca(l + 2 + 1);
- aszArgs[n][0] = '"';
- strcpy(&aszArgs[n][1], szArg);
- aszArgs[n][l + 1] = '"';
- aszArgs[n][l + 2] = '\0';
- }
- else {
- aszArgs[n] = (char *)szArg;
- }
- }
-
- aszArgs[n] = NULL;
-
- return _spawnve(mode, szCmd, aszArgs, envp);
-}
-
-API_EXPORT(int) os_spawnle(int mode, const char *cmdname, ...)
-{
- int n;
- va_list vlist;
- char **aszArgs;
- const char *szArg;
- const char *const *aszEnv;
- char *szCmd;
- char *s;
-
- szCmd = _alloca(strlen(cmdname)+1);
- strcpy(szCmd, cmdname);
- for (s = szCmd; *s; ++s) {
- if (*s == '/') {
- *s = '\\';
- }
- }
-
- va_start(vlist, cmdname);
- for (n = 0; va_arg(vlist, const char *); ++n)
- ;
- va_end(vlist);
-
- aszArgs = _alloca((n + 1) * sizeof(const char *));
-
- va_start(vlist, cmdname);
- for (n = 0; szArg = va_arg(vlist, const char *); ++n) {
- if (strchr(szArg, ' ')) {
- int l = strlen(szArg);
-
- aszArgs[n] = _alloca(l + 2 + 1);
- aszArgs[n][0] = '"';
- strcpy(&aszArgs[n][1], szArg);
- aszArgs[n][l + 1] = '"';
- aszArgs[n][l + 2] = '\0';
- }
- else {
- aszArgs[n] = (char *)szArg;
- }
- }
-
- aszArgs[n] = NULL;
-
- aszEnv = va_arg(vlist, const char *const *);
- va_end(vlist);
-
- return _spawnve(mode, szCmd, aszArgs, aszEnv);
-}
#undef strftime