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