summaryrefslogtreecommitdiff
path: root/usr.sbin/cron/popen.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2001-06-02 21:56:18 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2001-06-02 21:56:18 +0000
commit5690be50e3e732087a3009facf1b033520766901 (patch)
tree9c892cbffdf2e314aea6e8cdb5a3d403852e23e4 /usr.sbin/cron/popen.c
parent4431e3e30c10e5302af5119bfc30e4fc910b3f93 (diff)
Version derived from new ftpd code which has an updated UCB license.
Diffstat (limited to 'usr.sbin/cron/popen.c')
-rw-r--r--usr.sbin/cron/popen.c145
1 files changed, 87 insertions, 58 deletions
diff --git a/usr.sbin/cron/popen.c b/usr.sbin/cron/popen.c
index e13db8842b4..57242e57cae 100644
--- a/usr.sbin/cron/popen.c
+++ b/usr.sbin/cron/popen.c
@@ -1,42 +1,55 @@
-/* $OpenBSD: popen.c,v 1.8 2001/02/18 19:48:36 millert Exp $ */
+/* $OpenBSD: popen.c,v 1.9 2001/06/02 21:56:17 millert Exp $ */
+
/*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software written by Ken Arnold and
* published in UNIX Review, Vol. 6, No. 8.
*
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*
- */
-
-/* this came out of the ftpd sources; it's been modified to avoid the
- * globbing stuff since we don't need it. also execvp instead of execv.
*/
#ifndef lint
-static char rcsid[] = "$OpenBSD: popen.c,v 1.8 2001/02/18 19:48:36 millert Exp $";
-static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 2/14/89";
+#if 0
+static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94";
+#else
+static char rcsid[] = "$OpenBSD: popen.c,v 1.9 2001/06/02 21:56:17 millert Exp $";
+#endif
#endif /* not lint */
#include "cron.h"
-#define MAX_ARGS 100
-#define MAX_GARGS 1000
+#define MAX_ARGV 100
+#define MAX_GARGV 1000
#define WANT_GLOBBING 0
/*
- * Special version of popen which avoids call to shell. This insures noone
+ * Special version of popen which avoids call to shell. This ensures noone
* may create a pipe to a hidden program as a side effect of a list or dir
* command.
*/
@@ -53,51 +66,61 @@ cron_popen(program, type, e)
FILE * volatile iop;
int argc, pdes[2];
PID_T pid;
- char *argv[MAX_ARGS + 1];
+ char *argv[MAX_ARGV];
#if WANT_GLOBBING
- char **pop, *vv[2];
+ char **pop, *gargv[MAX_GARGV];
int gargc;
- char *gargv[MAX_GARGS];
- extern char **glob(), **copyblk();
#endif
- if ((*type != 'r' && *type != 'w') || type[1] != '\0')
+ if ((*type != 'r' && *type != 'w') || type[1])
return (NULL);
if (!pids) {
if ((fds = sysconf(_SC_OPEN_MAX)) <= 0)
return (NULL);
- if (!(pids = (PID_T *)malloc((size_t)(fds * sizeof(PID_T)))))
+ if (!(pids = (PID_T *)malloc((size_t)(fds * sizeof(int)))))
return (NULL);
- bzero((char *)pids, fds * sizeof(PID_T));
+ bzero(pids, fds * sizeof(PID_T));
}
if (pipe(pdes) < 0)
return (NULL);
/* break up string into pieces */
- for (argc = 0, cp = program; argc < MAX_ARGS; cp = NULL)
+ for (argc = 0, cp = program;argc < MAX_ARGV-1; cp = NULL)
if (!(argv[argc++] = strtok(cp, " \t\n")))
break;
- argv[MAX_ARGS] = NULL;
+ argv[MAX_ARGV-1] = NULL;
#if WANT_GLOBBING
/* glob each piece */
gargv[0] = argv[0];
for (gargc = argc = 1; argv[argc]; argc++) {
- if (!(pop = glob(argv[argc]))) { /* globbing failed */
- vv[0] = argv[argc];
- vv[1] = NULL;
- pop = copyblk(vv);
- }
- argv[argc] = (char *)pop; /* save to free later */
- while (*pop && gargc < MAX_GARGS)
- gargv[gargc++] = *pop++;
+ glob_t gl;
+
+ bzero(&gl, sizeof(gl));
+ if (glob(argv[argc],
+ GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|GLOB_LIMIT,
+ NULL, &gl)) {
+ if (gargc < MAX_GARGV-1) {
+ gargv[gargc++] = strdup(argv[argc]);
+ if (gargv[gargc -1] == NULL)
+ fatal ("Out of memory");
+ }
+
+ } else
+ for (pop = gl.gl_pathv; *pop && gargc < MAX_GARGV-1; pop++) {
+ gargv[gargc++] = strdup(*pop);
+ if (gargv[gargc - 1] == NULL)
+ fatal ("Out of memory");
+ }
+ globfree(&gl);
}
gargv[gargc] = NULL;
#endif
iop = NULL;
- switch(pid = vfork()) {
+
+ switch(pid = fork()) {
case -1: /* error */
(void)close(pdes[0]);
(void)close(pdes[1]);
@@ -106,15 +129,15 @@ cron_popen(program, type, e)
case 0: /* child */
closelog();
if (*type == 'r') {
- if (pdes[1] != 1) {
- dup2(pdes[1], 1);
- dup2(pdes[1], 2); /* stderr, too! */
+ if (pdes[1] != STDOUT_FILENO) {
+ dup2(pdes[1], STDOUT_FILENO);
(void)close(pdes[1]);
}
+ dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */
(void)close(pdes[0]);
} else {
- if (pdes[0] != 0) {
- dup2(pdes[0], 0);
+ if (pdes[0] != STDIN_FILENO) {
+ dup2(pdes[0], STDIN_FILENO);
(void)close(pdes[0]);
}
(void)close(pdes[1]);
@@ -144,7 +167,7 @@ cron_popen(program, type, e)
#endif /* LOGIN_CAP */
}
#if WANT_GLOBBING
- execvp(gargv[0], gargv);
+ execv(gargv[0], gargv);
#else
execvp(argv[0], argv);
#endif
@@ -162,10 +185,8 @@ cron_popen(program, type, e)
pfree:
#if WANT_GLOBBING
- for (argc = 1; argv[argc] != NULL; argc++) {
-/* blkfree((char **)argv[argc]); */
- free((char *)argv[argc]);
- }
+for (argc = 1; gargv[argc] != NULL; argc++)
+ free(gargv[argc]);
#endif
return (iop);
}
@@ -175,9 +196,9 @@ cron_pclose(iop)
FILE *iop;
{
int fdes;
- int omask;
- WAIT_T stat_loc;
PID_T pid;
+ WAIT_T status;
+ sigset_t sigset, osigset;
/*
* pclose returns -1 if stream is not associated with a
@@ -186,10 +207,18 @@ cron_pclose(iop)
if (pids == 0 || pids[fdes = fileno(iop)] == 0)
return (-1);
(void)fclose(iop);
- omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
- while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1)
- ;
- (void)sigsetmask(omask);
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
+ sigaddset(&sigset, SIGQUIT);
+ sigaddset(&sigset, SIGHUP);
+ sigprocmask(SIG_BLOCK, &sigset, &osigset);
+ while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
+ continue;
+ sigprocmask(SIG_SETMASK, &osigset, NULL);
pids[fdes] = 0;
- return (pid == -1 ? -1 : WEXITSTATUS(stat_loc));
+ if (pid < 0)
+ return (pid);
+ if (WIFEXITED(status))
+ return (WEXITSTATUS(status));
+ return (1);
}