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