xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/soconfig.c (revision 03100a6332bd4edc7a53091fcf7c9a7131bcdaa7)
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) 1991-1996,2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <sys/stat.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <locale.h>
36 
37 #define	MAXLINELEN	4096
38 
39 /*
40  * Usage:
41  *	sonconfig -f <file>
42  *		Reads input from file. The file is structured as
43  *			 <fam> <type> <protocol> <path>
44  *			 <fam> <type> <protocol>
45  *		with the first line registering and the second line
46  *		deregistering.
47  *
48  *	soconfig <fam> <type> <protocol> <path>
49  *		registers
50  *
51  *	soconfig <fam> <type> <protocol>
52  *		deregisters
53  */
54 
55 static int	parse_file(char *filename);
56 
57 static int	split_line(char *line, char *argvec[], int maxargvec);
58 
59 static int	parse_params(char *famstr, char *typestr, char *protostr,
60 				char *path, int line);
61 
62 static int	parse_int(char *str);
63 
64 static void	usage(void);
65 
66 int
67 main(argc, argv)
68 	int argc;
69 	char *argv[];
70 {
71 	int ret;
72 
73 	argc--; argv++;
74 
75 	(void) setlocale(LC_ALL, "");
76 #if !defined(TEXT_DOMAIN)
77 #define	TEXT_DOMAIN "SYS_TEST"
78 #endif
79 	(void) textdomain(TEXT_DOMAIN);
80 
81 	if (argc == 2 && strcmp(argv[0], "-f") == 0) {
82 		ret = parse_file(argv[1]);
83 		exit(ret);
84 	}
85 	if (argc == 3) {
86 		ret = parse_params(argv[0], argv[1], argv[2], NULL, -1);
87 		exit(ret);
88 	}
89 	if (argc == 4) {
90 		ret = parse_params(argv[0], argv[1], argv[2], argv[3], -1);
91 		exit(ret);
92 	}
93 	usage();
94 	exit(1);
95 	/* NOTREACHED */
96 }
97 
98 static void
99 usage(void)
100 {
101 	fprintf(stderr, gettext(
102 		"Usage:	soconfig -f <file>\n"
103 		"\tsoconfig <fam> <type> <protocol> <path>\n"
104 		"\tsoconfig <fam> <type> <protocol>\n"));
105 }
106 
107 /*
108  * Open the specified file and parse each line. Skip comments (everything
109  * after a '#'). Return 1 if at least one error was encountered; otherwise 0.
110  */
111 static int
112 parse_file(char *filename)
113 {
114 	char line[MAXLINELEN];
115 	char pline[MAXLINELEN];
116 	int argcount;
117 	char *argvec[20];
118 	FILE *fp;
119 	int linecount = 0;
120 	int numerror = 0;
121 
122 	fp = fopen(filename, "r");
123 	if (fp == NULL) {
124 		perror("soconfig: open");
125 		fprintf(stderr, "\n");
126 		usage();
127 		return (1);
128 	}
129 
130 	while (fgets(line, sizeof (line) - 1, fp) != NULL) {
131 		linecount++;
132 		strcpy(pline, line);
133 		argcount = split_line(pline, argvec,
134 				sizeof (argvec) / sizeof (argvec[0]));
135 #ifdef DEBUG
136 		{
137 			int i;
138 
139 			printf("scanned %d args\n", argcount);
140 			for (i = 0; i < argcount; i++)
141 				printf("arg[%d]: %s\n", i, argvec[i]);
142 		}
143 #endif /* DEBUG */
144 		switch (argcount) {
145 		case 0:
146 			/* Empty line - or comment only line */
147 			break;
148 		case 3:
149 			numerror += parse_params(argvec[0], argvec[1],
150 					argvec[2], NULL, linecount);
151 			break;
152 		case 4:
153 			numerror += parse_params(argvec[0], argvec[1],
154 					argvec[2], argvec[3], linecount);
155 			break;
156 		default:
157 			numerror++;
158 			fprintf(stderr,
159 				gettext("Malformed line: <%s>\n"), line);
160 			fprintf(stderr,
161 				gettext("\ton line %d\n"), linecount);
162 			break;
163 		}
164 	}
165 	(void) fclose(fp);
166 
167 	if (numerror > 0)
168 		return (1);
169 	else
170 		return (0);
171 }
172 
173 /*
174  * Parse a line splitting it off at whitspace characters.
175  * Modifies the content of the string by inserting NULLs.
176  */
177 static int
178 split_line(char *line, char *argvec[], int maxargvec)
179 {
180 	int i = 0;
181 	char *cp;
182 
183 	/* Truncate at the beginning of a comment */
184 	cp = strchr(line, '#');
185 	if (cp != NULL)
186 		*cp = NULL;
187 
188 	/* CONSTCOND */
189 	while (1) {
190 		/* Skip any whitespace */
191 		while (isspace(*line) && *line != NULL)
192 			line++;
193 
194 		if (i >= maxargvec)
195 			return (i);
196 
197 		argvec[i] = line;
198 		if (*line == NULL)
199 			return (i);
200 		i++;
201 		/* Skip until next whitespace */
202 		while (!isspace(*line) && *line != NULL)
203 			line++;
204 		if (*line != NULL) {
205 			/* Break off argument */
206 			*line++ = NULL;
207 		}
208 	}
209 	/* NOTREACHED */
210 }
211 
212 /*
213  * Parse the set of parameters and issues the sockconfig syscall.
214  * If line is not -1 it is assumed to be the line number in the file.
215  */
216 static int
217 parse_params(char *famstr, char *typestr, char *protostr, char *path, int line)
218 {
219 	int fam, type, protocol;
220 
221 	fam = parse_int(famstr);
222 	if (fam == -1) {
223 		fprintf(stderr, gettext("Bad family number: %s\n"), famstr);
224 		if (line != -1)
225 			fprintf(stderr,
226 				gettext("\ton line %d\n"), line);
227 		else {
228 			fprintf(stderr, "\n");
229 			usage();
230 		}
231 		return (1);
232 	}
233 
234 	type = parse_int(typestr);
235 	if (type == -1) {
236 		fprintf(stderr,
237 			gettext("Bad socket type number: %s\n"), typestr);
238 		if (line != -1)
239 			fprintf(stderr,
240 				gettext("\ton line %d\n"), line);
241 		else {
242 			fprintf(stderr, "\n");
243 			usage();
244 		}
245 		return (1);
246 	}
247 
248 	protocol = parse_int(protostr);
249 	if (protocol == -1) {
250 		fprintf(stderr,
251 			gettext("Bad protocol number: %s\n"), protostr);
252 		if (line != -1)
253 			fprintf(stderr,
254 				gettext("\ton line %d\n"), line);
255 		else {
256 			fprintf(stderr, "\n");
257 			usage();
258 		}
259 		return (1);
260 	}
261 
262 
263 	if (path != NULL) {
264 		struct stat stats;
265 
266 		if (stat(path, &stats) == -1) {
267 			perror(path);
268 			if (line != -1)
269 				fprintf(stderr,
270 					gettext("\ton line %d\n"), line);
271 			else {
272 				fprintf(stderr, "\n");
273 				usage();
274 			}
275 			return (1);
276 		}
277 	}
278 
279 #ifdef DEBUG
280 	printf("not calling sockconfig(%d, %d, %d, %s)\n",
281 		fam, type, protocol, path == NULL ? "(null)" : path);
282 #else
283 	if (_sockconfig(fam, type, protocol, path) == -1) {
284 		perror("sockconfig");
285 		return (1);
286 	}
287 #endif
288 	return (0);
289 }
290 
291 static int
292 parse_int(char *str)
293 {
294 	char *end;
295 	int res;
296 
297 	res = strtol(str, &end, 0);
298 	if (end == str)
299 		return (-1);
300 	return (res);
301 }
302