GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/cron/popen.c Lines: 0 56 0.0 %
Date: 2017-11-07 Branches: 0 35 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: popen.c,v 1.30 2015/11/15 23:24:24 millert Exp $	*/
2
3
/*
4
 * Copyright (c) 1988, 1993, 1994
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * This code is derived from software written by Ken Arnold and
8
 * published in UNIX Review, Vol. 6, No. 8.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. Neither the name of the University nor the names of its contributors
19
 *    may be used to endorse or promote products derived from this software
20
 *    without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 *
34
 */
35
36
/* this came out of the ftpd sources; it's been modified to avoid the
37
 * globbing stuff since we don't need it.  also execvp instead of execv.
38
 */
39
40
#include <sys/types.h>
41
#include <sys/wait.h>
42
43
#include <bitstring.h>		/* for structs.h */
44
#include <err.h>
45
#include <errno.h>
46
#include <login_cap.h>
47
#include <pwd.h>
48
#include <signal.h>
49
#include <stdio.h>
50
#include <stdlib.h>
51
#include <string.h>
52
#include <syslog.h>
53
#include <unistd.h>
54
#include <time.h>		/* for structs.h */
55
56
#include "macros.h"
57
#include "structs.h"
58
#include "funcs.h"
59
60
#define MAX_ARGV	100
61
#define MAX_GARGV	1000
62
63
/*
64
 * Special version of popen which avoids call to shell
65
 */
66
FILE *
67
cron_popen(char *program, char *type, struct passwd *pw, pid_t *pidptr)
68
{
69
	char *cp;
70
	FILE *iop;
71
	int argc, pdes[2];
72
	pid_t pid;
73
	char *argv[MAX_ARGV];
74
75
	if ((*type != 'r' && *type != 'w') || type[1] != '\0')
76
		return (NULL);
77
78
	if (pipe(pdes) < 0)
79
		return (NULL);
80
81
	/* break up string into pieces */
82
	for (argc = 0, cp = program; argc < MAX_ARGV - 1; cp = NULL)
83
		if (!(argv[argc++] = strtok(cp, " \t\n")))
84
			break;
85
	argv[MAX_ARGV-1] = NULL;
86
87
	switch (pid = fork()) {
88
	case -1:			/* error */
89
		(void)close(pdes[0]);
90
		(void)close(pdes[1]);
91
		return (NULL);
92
		/* NOTREACHED */
93
	case 0:				/* child */
94
		if (pw) {
95
			if (setusercontext(0, pw, pw->pw_uid, LOGIN_SETALL) < 0) {
96
				syslog(LOG_ERR,
97
				    "(%s) SETUSERCONTEXT FAILED (%m)",
98
				    pw->pw_name);
99
				warn("setusercontext failed for %s",
100
				    pw->pw_name);
101
				_exit(EXIT_FAILURE);
102
			}
103
		}
104
		if (*type == 'r') {
105
			if (pdes[1] != STDOUT_FILENO) {
106
				dup2(pdes[1], STDOUT_FILENO);
107
				(void)close(pdes[1]);
108
			}
109
			dup2(STDOUT_FILENO, STDERR_FILENO);
110
			(void)close(pdes[0]);
111
		} else {
112
			if (pdes[0] != STDIN_FILENO) {
113
				dup2(pdes[0], STDIN_FILENO);
114
				(void)close(pdes[0]);
115
			}
116
			(void)close(pdes[1]);
117
		}
118
		execvp(argv[0], argv);
119
		_exit(1);
120
	}
121
122
	/* parent; assume fdopen can't fail...  */
123
	if (*type == 'r') {
124
		iop = fdopen(pdes[0], type);
125
		(void)close(pdes[1]);
126
	} else {
127
		iop = fdopen(pdes[1], type);
128
		(void)close(pdes[0]);
129
	}
130
	*pidptr = pid;
131
132
	return (iop);
133
}
134
135
int
136
cron_pclose(FILE *iop, pid_t pid)
137
{
138
	int rv;
139
	int status;
140
	sigset_t sigset, osigset;
141
142
	(void)fclose(iop);
143
	sigemptyset(&sigset);
144
	sigaddset(&sigset, SIGINT);
145
	sigaddset(&sigset, SIGQUIT);
146
	sigaddset(&sigset, SIGHUP);
147
	sigprocmask(SIG_BLOCK, &sigset, &osigset);
148
	while ((rv = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
149
		continue;
150
	sigprocmask(SIG_SETMASK, &osigset, NULL);
151
	if (rv < 0)
152
		return (rv);
153
	if (WIFEXITED(status))
154
		return (WEXITSTATUS(status));
155
	return (1);
156
}