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