Home | History | Annotate | Download | only in usr.sbin
      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