xref: /illumos-gate/usr/src/cmd/syslogd/conf.c (revision f012ee0c3db17469b492c2cf757226f3d7b1ebbc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 
31 #include <unistd.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <errno.h>
37 
38 #include "conf.h"
39 
40 #define	CF_DEFSIZE	32	/* Starting table size */
41 #define	CF_GROW		2	/* Table size multiplier on grow */
42 
43 static FILE *
44 open_conf_pipe(const char *cmd, char *argv[], pid_t *pidp)
45 {
46 	int pfds[2];
47 	pid_t pid;
48 	struct sigaction act;
49 
50 	/* Create a pipe and fork a child process to run the command */
51 
52 	if (pipe(pfds) == -1) {
53 		logerror("failed to create pipe");
54 		return (NULL);
55 	}
56 
57 	if ((pid = fork1()) == -1) {
58 		logerror("failed to fork1");
59 		goto err;
60 	}
61 
62 	/* If we're in the child, run the command and output to the pipe */
63 
64 	if (pid == 0) {
65 		/*
66 		 * We must set up to ignore these signals, which may be
67 		 * propogated from the calling process.
68 		 */
69 
70 		act.sa_handler = SIG_IGN;
71 
72 		(void) sigaction(SIGHUP, &act, NULL);
73 		(void) sigaction(SIGALRM, &act, NULL);
74 		(void) sigaction(SIGUSR1, &act, NULL);
75 
76 		(void) close(pfds[0]);
77 		(void) close(STDOUT_FILENO);
78 
79 		if (dup2(pfds[1], STDOUT_FILENO) == -1) {
80 			logerror("failed to dup to stdout");
81 			(void) close(pfds[1]);
82 			_exit(127);
83 		}
84 
85 		(void) execvp(cmd, argv);
86 		logerror("failed to parse configuration file");
87 		_exit(127);
88 		/*NOTREACHED*/
89 	}
90 
91 	/* If we're in the parent, open the read end of the pipe and return */
92 
93 	*pidp = pid;
94 	(void) close(pfds[1]);
95 	return (fdopen(pfds[0], "r"));
96 
97 err:
98 	(void) close(pfds[0]);
99 	(void) close(pfds[1]);
100 	return (NULL);
101 }
102 
103 static void
104 close_conf_pipe(FILE *fp, pid_t pid)
105 {
106 	int status;
107 
108 	while (waitpid(pid, &status, 0) == -1) {
109 		if (errno != EINTR)
110 			break;
111 	}
112 
113 	(void) fclose(fp);
114 }
115 
116 static int
117 grow_conf_file(conf_t *cf)
118 {
119 	int ndsize = cf->cf_dsize ? cf->cf_dsize * CF_GROW : CF_DEFSIZE;
120 	void *ndtab = realloc(cf->cf_dtab, sizeof (char *) * ndsize);
121 
122 	register char *p;
123 	int odsize, lines, i;
124 
125 	if (ndtab == NULL) {
126 		logerror("failed to allocate config file table");
127 		return (-1);
128 	}
129 
130 	lines = ndsize - cf->cf_dsize;
131 	odsize = cf->cf_dsize;
132 
133 	cf->cf_dtab = (char **)ndtab;
134 	cf->cf_dsize = ndsize;
135 
136 	for (i = 0; i < lines; i++) {
137 		if ((p = (char *)malloc(BUFSIZ)) == NULL) {
138 			logerror("failed to allocate config file buffer");
139 			return (-1);
140 		}
141 
142 		cf->cf_dtab[odsize + i] = p;
143 	}
144 
145 	return (0);
146 }
147 
148 int
149 conf_open(conf_t *cf, const char *cmd, char *argv[])
150 {
151 	char *line, *p;
152 	pid_t pid;
153 	FILE *fp;
154 
155 	(void) memset(cf, 0, sizeof (conf_t));
156 
157 	if ((fp = open_conf_pipe(cmd, argv, &pid)) == NULL)
158 		return (-1);
159 
160 	for (;;) {
161 		/* If we need to grow the table, do so now */
162 
163 		if (cf->cf_lines >= cf->cf_dsize) {
164 			if (grow_conf_file(cf) == -1)
165 				goto err;
166 		}
167 
168 		line = cf->cf_dtab[cf->cf_lines];
169 
170 		/* Read the next line, and break out if we're done */
171 
172 		if (fgets(line, BUFSIZ, fp) == NULL)
173 			break;
174 
175 		/* Strip newline and bump line counter */
176 
177 		if ((p = strchr(line, '\n')) != NULL)
178 			*p = '\0';
179 
180 		cf->cf_lines++;
181 	}
182 
183 	close_conf_pipe(fp, pid);
184 	return (0);
185 
186 err:
187 	close_conf_pipe(fp, pid);
188 	return (-1);
189 }
190 
191 void
192 conf_rewind(conf_t *cf)
193 {
194 	cf->cf_ptr = 0;
195 }
196 
197 char *
198 conf_read(conf_t *cf)
199 {
200 	if (cf->cf_ptr < cf->cf_lines)
201 		return (cf->cf_dtab[cf->cf_ptr++]);
202 
203 	return (NULL);
204 }
205 
206 void
207 conf_close(conf_t *cf)
208 {
209 	int i;
210 
211 	if (cf->cf_dtab != NULL) {
212 		for (i = 0; i < cf->cf_dsize; i++)
213 			free(cf->cf_dtab[i]);
214 		free(cf->cf_dtab);
215 	}
216 }
217