xref: /illumos-gate/usr/src/cmd/syslogd/conf.c (revision 012e6ce759c490003aed29439cc47d3d73a99ad3)
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 #include <sys/types.h>
27 #include <sys/wait.h>
28 
29 #include <unistd.h>
30 #include <signal.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <errno.h>
35 
36 #include "conf.h"
37 
38 #define	CF_DEFSIZE	32	/* Starting table size */
39 #define	CF_GROW		2	/* Table size multiplier on grow */
40 
41 static FILE *
42 open_conf_pipe(const char *cmd, char *argv[], pid_t *pidp)
43 {
44 	int pfds[2];
45 	pid_t pid;
46 	struct sigaction act;
47 
48 	/* Create a pipe and fork a child process to run the command */
49 
50 	if (pipe(pfds) == -1) {
51 		logerror("failed to create pipe");
52 		return (NULL);
53 	}
54 
55 	if ((pid = fork1()) == -1) {
56 		logerror("failed to fork1");
57 		goto err;
58 	}
59 
60 	/* If we're in the child, run the command and output to the pipe */
61 
62 	if (pid == 0) {
63 		/*
64 		 * We must set up to ignore these signals, which may be
65 		 * propogated from the calling process.
66 		 */
67 
68 		act.sa_handler = SIG_IGN;
69 
70 		(void) sigaction(SIGHUP, &act, NULL);
71 		(void) sigaction(SIGALRM, &act, NULL);
72 		(void) sigaction(SIGUSR1, &act, NULL);
73 
74 		(void) close(pfds[0]);
75 		(void) close(STDOUT_FILENO);
76 
77 		if (dup2(pfds[1], STDOUT_FILENO) == -1) {
78 			logerror("failed to dup to stdout");
79 			(void) close(pfds[1]);
80 			_exit(127);
81 		}
82 
83 		(void) execvp(cmd, argv);
84 		logerror("failed to parse configuration file");
85 		_exit(127);
86 		/*NOTREACHED*/
87 	}
88 
89 	/* If we're in the parent, open the read end of the pipe and return */
90 
91 	*pidp = pid;
92 	(void) close(pfds[1]);
93 	return (fdopen(pfds[0], "r"));
94 
95 err:
96 	(void) close(pfds[0]);
97 	(void) close(pfds[1]);
98 	return (NULL);
99 }
100 
101 static void
102 close_conf_pipe(FILE *fp, pid_t pid)
103 {
104 	int status;
105 
106 	while (waitpid(pid, &status, 0) == -1) {
107 		if (errno != EINTR)
108 			break;
109 	}
110 
111 	(void) fclose(fp);
112 }
113 
114 static int
115 grow_conf_file(conf_t *cf)
116 {
117 	int ndsize = cf->cf_dsize ? cf->cf_dsize * CF_GROW : CF_DEFSIZE;
118 	void *ndtab = realloc(cf->cf_dtab, sizeof (char *) * ndsize);
119 
120 	register char *p;
121 	int odsize, lines, i;
122 
123 	if (ndtab == NULL) {
124 		logerror("failed to allocate config file table");
125 		return (-1);
126 	}
127 
128 	lines = ndsize - cf->cf_dsize;
129 	odsize = cf->cf_dsize;
130 
131 	cf->cf_dtab = (char **)ndtab;
132 	cf->cf_dsize = ndsize;
133 
134 	for (i = 0; i < lines; i++) {
135 		if ((p = (char *)malloc(BUFSIZ)) == NULL) {
136 			logerror("failed to allocate config file buffer");
137 			return (-1);
138 		}
139 
140 		cf->cf_dtab[odsize + i] = p;
141 	}
142 
143 	return (0);
144 }
145 
146 int
147 conf_open(conf_t *cf, const char *cmd, char *argv[])
148 {
149 	char *line, *p;
150 	pid_t pid;
151 	FILE *fp;
152 
153 	(void) memset(cf, 0, sizeof (conf_t));
154 
155 	if ((fp = open_conf_pipe(cmd, argv, &pid)) == NULL)
156 		return (-1);
157 
158 	for (;;) {
159 		/* If we need to grow the table, do so now */
160 
161 		if (cf->cf_lines >= cf->cf_dsize) {
162 			if (grow_conf_file(cf) == -1)
163 				goto err;
164 		}
165 
166 		line = cf->cf_dtab[cf->cf_lines];
167 
168 		/* Read the next line, and break out if we're done */
169 
170 		if (fgets(line, BUFSIZ, fp) == NULL)
171 			break;
172 
173 		/* Strip newline and bump line counter */
174 
175 		if ((p = strchr(line, '\n')) != NULL)
176 			*p = '\0';
177 
178 		cf->cf_lines++;
179 	}
180 
181 	close_conf_pipe(fp, pid);
182 	return (0);
183 
184 err:
185 	close_conf_pipe(fp, pid);
186 	return (-1);
187 }
188 
189 void
190 conf_rewind(conf_t *cf)
191 {
192 	cf->cf_ptr = 0;
193 }
194 
195 char *
196 conf_read(conf_t *cf)
197 {
198 	if (cf->cf_ptr < cf->cf_lines)
199 		return (cf->cf_dtab[cf->cf_ptr++]);
200 
201 	return (NULL);
202 }
203 
204 void
205 conf_close(conf_t *cf)
206 {
207 	int i;
208 
209 	if (cf->cf_dtab != NULL) {
210 		for (i = 0; i < cf->cf_dsize; i++)
211 			free(cf->cf_dtab[i]);
212 		free(cf->cf_dtab);
213 	}
214 }
215