17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0ea5e3a5Sjjj * Common Development and Distribution License (the "License").
6*0ea5e3a5Sjjj * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*0ea5e3a5Sjjj * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*0ea5e3a5Sjjj * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/wait.h>
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <signal.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <stdlib.h>
357c478bd9Sstevel@tonic-gate #include <stdio.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include "conf.h"
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate #define CF_DEFSIZE 32 /* Starting table size */
417c478bd9Sstevel@tonic-gate #define CF_GROW 2 /* Table size multiplier on grow */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate static FILE *
open_conf_pipe(const char * cmd,char * argv[],pid_t * pidp)447c478bd9Sstevel@tonic-gate open_conf_pipe(const char *cmd, char *argv[], pid_t *pidp)
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate int pfds[2];
477c478bd9Sstevel@tonic-gate pid_t pid;
487c478bd9Sstevel@tonic-gate struct sigaction act;
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /* Create a pipe and fork a child process to run the command */
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate if (pipe(pfds) == -1) {
537c478bd9Sstevel@tonic-gate logerror("failed to create pipe");
547c478bd9Sstevel@tonic-gate return (NULL);
557c478bd9Sstevel@tonic-gate }
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate if ((pid = fork1()) == -1) {
587c478bd9Sstevel@tonic-gate logerror("failed to fork1");
597c478bd9Sstevel@tonic-gate goto err;
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate /* If we're in the child, run the command and output to the pipe */
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate if (pid == 0) {
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate * We must set up to ignore these signals, which may be
677c478bd9Sstevel@tonic-gate * propogated from the calling process.
687c478bd9Sstevel@tonic-gate */
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate act.sa_handler = SIG_IGN;
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate (void) sigaction(SIGHUP, &act, NULL);
737c478bd9Sstevel@tonic-gate (void) sigaction(SIGALRM, &act, NULL);
747c478bd9Sstevel@tonic-gate (void) sigaction(SIGUSR1, &act, NULL);
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate (void) close(pfds[0]);
777c478bd9Sstevel@tonic-gate (void) close(STDOUT_FILENO);
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate if (dup2(pfds[1], STDOUT_FILENO) == -1) {
807c478bd9Sstevel@tonic-gate logerror("failed to dup to stdout");
817c478bd9Sstevel@tonic-gate (void) close(pfds[1]);
827c478bd9Sstevel@tonic-gate _exit(127);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate (void) execvp(cmd, argv);
867c478bd9Sstevel@tonic-gate logerror("failed to parse configuration file");
877c478bd9Sstevel@tonic-gate _exit(127);
887c478bd9Sstevel@tonic-gate /*NOTREACHED*/
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate /* If we're in the parent, open the read end of the pipe and return */
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate *pidp = pid;
947c478bd9Sstevel@tonic-gate (void) close(pfds[1]);
957c478bd9Sstevel@tonic-gate return (fdopen(pfds[0], "r"));
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate err:
987c478bd9Sstevel@tonic-gate (void) close(pfds[0]);
997c478bd9Sstevel@tonic-gate (void) close(pfds[1]);
1007c478bd9Sstevel@tonic-gate return (NULL);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate static void
close_conf_pipe(FILE * fp,pid_t pid)1047c478bd9Sstevel@tonic-gate close_conf_pipe(FILE *fp, pid_t pid)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate int status;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate while (waitpid(pid, &status, 0) == -1) {
1097c478bd9Sstevel@tonic-gate if (errno != EINTR)
1107c478bd9Sstevel@tonic-gate break;
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate (void) fclose(fp);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate static int
grow_conf_file(conf_t * cf)1177c478bd9Sstevel@tonic-gate grow_conf_file(conf_t *cf)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate int ndsize = cf->cf_dsize ? cf->cf_dsize * CF_GROW : CF_DEFSIZE;
1207c478bd9Sstevel@tonic-gate void *ndtab = realloc(cf->cf_dtab, sizeof (char *) * ndsize);
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate register char *p;
1237c478bd9Sstevel@tonic-gate int odsize, lines, i;
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate if (ndtab == NULL) {
1267c478bd9Sstevel@tonic-gate logerror("failed to allocate config file table");
1277c478bd9Sstevel@tonic-gate return (-1);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate lines = ndsize - cf->cf_dsize;
1317c478bd9Sstevel@tonic-gate odsize = cf->cf_dsize;
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate cf->cf_dtab = (char **)ndtab;
1347c478bd9Sstevel@tonic-gate cf->cf_dsize = ndsize;
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate for (i = 0; i < lines; i++) {
1377c478bd9Sstevel@tonic-gate if ((p = (char *)malloc(BUFSIZ)) == NULL) {
1387c478bd9Sstevel@tonic-gate logerror("failed to allocate config file buffer");
1397c478bd9Sstevel@tonic-gate return (-1);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate cf->cf_dtab[odsize + i] = p;
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate return (0);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate int
conf_open(conf_t * cf,const char * cmd,char * argv[])1497c478bd9Sstevel@tonic-gate conf_open(conf_t *cf, const char *cmd, char *argv[])
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate char *line, *p;
1527c478bd9Sstevel@tonic-gate pid_t pid;
1537c478bd9Sstevel@tonic-gate FILE *fp;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate (void) memset(cf, 0, sizeof (conf_t));
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate if ((fp = open_conf_pipe(cmd, argv, &pid)) == NULL)
1587c478bd9Sstevel@tonic-gate return (-1);
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate for (;;) {
1617c478bd9Sstevel@tonic-gate /* If we need to grow the table, do so now */
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate if (cf->cf_lines >= cf->cf_dsize) {
1647c478bd9Sstevel@tonic-gate if (grow_conf_file(cf) == -1)
1657c478bd9Sstevel@tonic-gate goto err;
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate line = cf->cf_dtab[cf->cf_lines];
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /* Read the next line, and break out if we're done */
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate if (fgets(line, BUFSIZ, fp) == NULL)
1737c478bd9Sstevel@tonic-gate break;
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate /* Strip newline and bump line counter */
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate if ((p = strchr(line, '\n')) != NULL)
1787c478bd9Sstevel@tonic-gate *p = '\0';
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate cf->cf_lines++;
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate close_conf_pipe(fp, pid);
1847c478bd9Sstevel@tonic-gate return (0);
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate err:
1877c478bd9Sstevel@tonic-gate close_conf_pipe(fp, pid);
1887c478bd9Sstevel@tonic-gate return (-1);
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate void
conf_rewind(conf_t * cf)1927c478bd9Sstevel@tonic-gate conf_rewind(conf_t *cf)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate cf->cf_ptr = 0;
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate char *
conf_read(conf_t * cf)1987c478bd9Sstevel@tonic-gate conf_read(conf_t *cf)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate if (cf->cf_ptr < cf->cf_lines)
2017c478bd9Sstevel@tonic-gate return (cf->cf_dtab[cf->cf_ptr++]);
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate return (NULL);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate void
conf_close(conf_t * cf)2077c478bd9Sstevel@tonic-gate conf_close(conf_t *cf)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate int i;
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate if (cf->cf_dtab != NULL) {
2127c478bd9Sstevel@tonic-gate for (i = 0; i < cf->cf_dsize; i++)
2137c478bd9Sstevel@tonic-gate free(cf->cf_dtab[i]);
2147c478bd9Sstevel@tonic-gate free(cf->cf_dtab);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate }
217