xref: /openbsd-src/usr.sbin/cron/popen.c (revision df69c215c7c66baf660f3f65414fd34796c96152)
1*df69c215Sderaadt /*	$OpenBSD: popen.c,v 1.31 2019/06/28 13:32:47 deraadt Exp $	*/
2622db861Smillert 
3df930be7Sderaadt /*
4622db861Smillert  * Copyright (c) 1988, 1993, 1994
5622db861Smillert  *	The Regents of the University of California.  All rights reserved.
6df930be7Sderaadt  *
7df930be7Sderaadt  * This code is derived from software written by Ken Arnold and
8df930be7Sderaadt  * published in UNIX Review, Vol. 6, No. 8.
9df930be7Sderaadt  *
10622db861Smillert  * Redistribution and use in source and binary forms, with or without
11622db861Smillert  * modification, are permitted provided that the following conditions
12622db861Smillert  * are met:
13622db861Smillert  * 1. Redistributions of source code must retain the above copyright
14622db861Smillert  *    notice, this list of conditions and the following disclaimer.
15622db861Smillert  * 2. Redistributions in binary form must reproduce the above copyright
16622db861Smillert  *    notice, this list of conditions and the following disclaimer in the
17622db861Smillert  *    documentation and/or other materials provided with the distribution.
18929e694fSmillert  * 3. Neither the name of the University nor the names of its contributors
19929e694fSmillert  *    may be used to endorse or promote products derived from this software
20929e694fSmillert  *    without specific prior written permission.
21622db861Smillert  *
22622db861Smillert  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23622db861Smillert  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24622db861Smillert  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25622db861Smillert  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26622db861Smillert  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27622db861Smillert  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28622db861Smillert  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29622db861Smillert  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30622db861Smillert  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31622db861Smillert  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32622db861Smillert  * SUCH DAMAGE.
33df930be7Sderaadt  *
34df930be7Sderaadt  */
35df930be7Sderaadt 
36c95ed473Smillert /* this came out of the ftpd sources; it's been modified to avoid the
37c95ed473Smillert  * globbing stuff since we don't need it.  also execvp instead of execv.
38c95ed473Smillert  */
39c95ed473Smillert 
40fa575ea2Smillert #include <sys/types.h>
41fa575ea2Smillert #include <sys/wait.h>
42fa575ea2Smillert 
43fa575ea2Smillert #include <bitstring.h>		/* for structs.h */
44b8c5c73dSmillert #include <err.h>
45fa575ea2Smillert #include <errno.h>
46fa575ea2Smillert #include <login_cap.h>
47fa575ea2Smillert #include <pwd.h>
48fa575ea2Smillert #include <signal.h>
49fa575ea2Smillert #include <stdio.h>
50fa575ea2Smillert #include <stdlib.h>
51fa575ea2Smillert #include <string.h>
52b8c5c73dSmillert #include <syslog.h>
53fa575ea2Smillert #include <unistd.h>
54fa575ea2Smillert #include <time.h>		/* for structs.h */
55fa575ea2Smillert 
56fa575ea2Smillert #include "macros.h"
57fa575ea2Smillert #include "structs.h"
58fa575ea2Smillert #include "funcs.h"
59840801a7Sderaadt 
60622db861Smillert #define MAX_ARGV	100
61622db861Smillert #define MAX_GARGV	1000
62df930be7Sderaadt 
63df930be7Sderaadt /*
64c8a7a613Stedu  * Special version of popen which avoids call to shell
65df930be7Sderaadt  */
66df930be7Sderaadt FILE *
cron_popen(char * program,char * type,struct passwd * pw,pid_t * pidptr)6794b4a649Stedu cron_popen(char *program, char *type, struct passwd *pw, pid_t *pidptr)
68785ecd14Stedu {
69f454ebdeSmillert 	char *cp;
70d5919ef3Smillert 	FILE *iop;
71df930be7Sderaadt 	int argc, pdes[2];
72afc409ecSmillert 	pid_t pid;
73622db861Smillert 	char *argv[MAX_ARGV];
74df930be7Sderaadt 
75c95ed473Smillert 	if ((*type != 'r' && *type != 'w') || type[1] != '\0')
76df930be7Sderaadt 		return (NULL);
77df930be7Sderaadt 
78*df69c215Sderaadt 	if (pipe(pdes) == -1)
79df930be7Sderaadt 		return (NULL);
80df930be7Sderaadt 
81df930be7Sderaadt 	/* break up string into pieces */
82622db861Smillert 	for (argc = 0, cp = program; argc < MAX_ARGV - 1; cp = NULL)
83df930be7Sderaadt 		if (!(argv[argc++] = strtok(cp, " \t\n")))
84df930be7Sderaadt 			break;
85622db861Smillert 	argv[MAX_ARGV-1] = NULL;
86df930be7Sderaadt 
87622db861Smillert 	switch (pid = fork()) {
88df930be7Sderaadt 	case -1:			/* error */
89df930be7Sderaadt 		(void)close(pdes[0]);
90df930be7Sderaadt 		(void)close(pdes[1]);
91c95ed473Smillert 		return (NULL);
92df930be7Sderaadt 		/* NOTREACHED */
93df930be7Sderaadt 	case 0:				/* child */
942b139a93Smillert 		if (pw) {
95*df69c215Sderaadt 			if (setusercontext(0, pw, pw->pw_uid, LOGIN_SETALL) == -1) {
96b8c5c73dSmillert 				syslog(LOG_ERR,
97b8c5c73dSmillert 				    "(%s) SETUSERCONTEXT FAILED (%m)",
98b8c5c73dSmillert 				    pw->pw_name);
99b8c5c73dSmillert 				warn("setusercontext failed for %s",
1002b139a93Smillert 				    pw->pw_name);
10110ee6820Smillert 				_exit(EXIT_FAILURE);
102fed231abSmillert 			}
1038eda01ecSmillert 		}
1046a399cefSmillert 		if (*type == 'r') {
10510ee6820Smillert 			if (pdes[1] != STDOUT_FILENO) {
10610ee6820Smillert 				dup2(pdes[1], STDOUT_FILENO);
1076a399cefSmillert 				(void)close(pdes[1]);
1086a399cefSmillert 			}
10910ee6820Smillert 			dup2(STDOUT_FILENO, STDERR_FILENO);
1106a399cefSmillert 			(void)close(pdes[0]);
1116a399cefSmillert 		} else {
11210ee6820Smillert 			if (pdes[0] != STDIN_FILENO) {
11310ee6820Smillert 				dup2(pdes[0], STDIN_FILENO);
1146a399cefSmillert 				(void)close(pdes[0]);
1156a399cefSmillert 			}
1166a399cefSmillert 			(void)close(pdes[1]);
1176a399cefSmillert 		}
118df930be7Sderaadt 		execvp(argv[0], argv);
119df930be7Sderaadt 		_exit(1);
120df930be7Sderaadt 	}
1216a399cefSmillert 
122df930be7Sderaadt 	/* parent; assume fdopen can't fail...  */
123df930be7Sderaadt 	if (*type == 'r') {
124df930be7Sderaadt 		iop = fdopen(pdes[0], type);
125df930be7Sderaadt 		(void)close(pdes[1]);
126df930be7Sderaadt 	} else {
127df930be7Sderaadt 		iop = fdopen(pdes[1], type);
128df930be7Sderaadt 		(void)close(pdes[0]);
129df930be7Sderaadt 	}
13094b4a649Stedu 	*pidptr = pid;
131df930be7Sderaadt 
132df930be7Sderaadt 	return (iop);
133df930be7Sderaadt }
134df930be7Sderaadt 
135df930be7Sderaadt int
cron_pclose(FILE * iop,pid_t pid)13694b4a649Stedu cron_pclose(FILE *iop, pid_t pid)
137785ecd14Stedu {
13894b4a649Stedu 	int rv;
139afc409ecSmillert 	int status;
140622db861Smillert 	sigset_t sigset, osigset;
141df930be7Sderaadt 
142df930be7Sderaadt 	(void)fclose(iop);
143622db861Smillert 	sigemptyset(&sigset);
144622db861Smillert 	sigaddset(&sigset, SIGINT);
145622db861Smillert 	sigaddset(&sigset, SIGQUIT);
146622db861Smillert 	sigaddset(&sigset, SIGHUP);
147622db861Smillert 	sigprocmask(SIG_BLOCK, &sigset, &osigset);
148*df69c215Sderaadt 	while ((rv = waitpid(pid, &status, 0)) == -1 && errno == EINTR)
149622db861Smillert 		continue;
150622db861Smillert 	sigprocmask(SIG_SETMASK, &osigset, NULL);
151*df69c215Sderaadt 	if (rv == -1)
15294b4a649Stedu 		return (rv);
153622db861Smillert 	if (WIFEXITED(status))
154622db861Smillert 		return (WEXITSTATUS(status));
155622db861Smillert 	return (1);
156df930be7Sderaadt }
157