xref: /illumos-gate/usr/src/cmd/ttymon/sttydefs.c (revision bb9b6b3f59b8820022416cea99b49c50fef6e391)
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 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 /*	  All Rights Reserved  	*/
28 
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <ctype.h>
39 #include <string.h>
40 #include <termio.h>
41 #include <sys/stat.h>
42 #include <signal.h>
43 #include <stdarg.h>
44 
45 #include "tmstruct.h"
46 #include "ttymon.h"
47 
48 static	int  nflg = 0;		/* -n seen */
49 static	int  iflg = 0;		/* -i seen */
50 static	int  fflg = 0;		/* -f seen */
51 static	int  lflg = 0;		/* -l seen */
52 
53 struct  Gdef Gdef[MAXDEFS];	/* array to hold entries in /etc/ttydefs */
54 int	Ndefs = 0;		/* highest index to Gdef that was used   */
55 static	struct Gdef DEFAULT = {		/* default terminal settings	*/
56 	"default",
57 	"9600",
58 	"9600 sane",
59 	0,
60 	/*
61 	 * next label is set to 4800 so we can start searching ttydefs.
62 	 * if 4800 is not in ttydefs, we will loop back to use DEFAULT
63 	 */
64 	"4800"
65 };
66 
67 
68 static	void	usage();
69 static	void	check_ref();
70 static	void	add_entry();
71 static	void	remove_entry();
72 static	int	copy_file();
73 static	int	verify();
74 static	FILE	*open_temp();
75 extern  void	read_ttydefs();
76 extern  int	check_version();
77 extern  int	find_label();
78 
79 /*
80  *	sttydefs - add, remove or check entries in /etc/ttydefs
81  *
82  *	Usage:	   sttydefs -a ttylabel [-n nextlabel] [-i initail-flags]
83  *			    [-f final-flags] [-b]
84  *		   sttydefs -r ttylabel
85  *		   sttydefs -l [ttylabel]
86  *
87  */
88 
89 int
90 main(int argc, char *argv[])
91 {
92 	int c;			/* option letter */
93 	int errflg = 0;		/* error indicator */
94 	int  aflg = 0;		/* -a seen */
95 	int  bflg = 0;		/* -b seen */
96 	int	ret;
97 #ifdef __STDC__
98 	const
99 #endif
100 	char	*argtmp;
101 	char	*nextlabel;
102 	struct Gdef ttydef, *ptr;
103 
104 	extern	char	*optarg;
105 	extern	int	optind;
106 
107 	if (argc == 1)
108 		usage();
109 
110         /* Initialize ttydef structure */
111         memset (&ttydef, 0, sizeof(ttydef));
112 
113 	ptr = &ttydef;
114 	while ((c = getopt(argc, argv, "a:n:i:f:br:l")) != -1) {
115 		switch (c) {
116 		case 'a':
117 			aflg = TRUE;
118 			ptr->g_id = optarg;
119 			break;
120 		case 'n':
121 			nflg = TRUE;
122 			ptr->g_nextid = optarg;
123 			break;
124 		case 'i':
125 			iflg = TRUE;
126 			ptr->g_iflags = optarg;
127 			break;
128 		case 'f':
129 			fflg = TRUE;
130 			ptr->g_fflags = optarg;
131 			break;
132 		case 'b':
133 			bflg = TRUE;
134 			ptr->g_autobaud |= A_FLAG;
135 			break;
136 		case 'r':
137 			if ((argc > 3) || (optind < argc))
138 				usage();
139 			remove_entry(optarg);
140 			break;
141 		case 'l':
142 			lflg = TRUE;
143 			if (argc > 3)
144 				usage();
145 			if ((ret = check_version(TTYDEFS_VERS, TTYDEFS)) != 0) {
146 				if (ret != 2) {
147 					(void)fprintf(stderr, "%s version number is incorrect or missing.\n",TTYDEFS);
148 					exit(1);
149 				}
150 				(void)fprintf(stderr, "sttydefs: can't open %s.\n",TTYDEFS);
151 				exit(1);
152 			}
153 			if (argv[optind] == NULL) {
154 				read_ttydefs(NULL,TRUE);
155 				printf("\n");
156 				check_ref();
157 			}
158 			else {
159 				if (argc == 3) { /* -l ttylabel */
160 					if (verify(argv[optind],0) != 0) {
161 						errflg++;
162 						break;
163 					}
164 					argtmp = argv[optind];
165 				}
166 				else { /* -lttylabel */
167 					argtmp = argv[optind]+2;
168 				}
169 				read_ttydefs(argtmp,TRUE);
170 				if (Ndefs == 0) {
171 					(void)fprintf(stderr,
172 					"ttylabel <%s> not found.\n", argtmp);
173 					exit(1);
174 				}
175 				nextlabel = Gdef[--Ndefs].g_nextid;
176 				Ndefs = 0;
177 				read_ttydefs(nextlabel,FALSE);
178 				if (Ndefs == 0) {
179 					(void)printf("\nWarning -- nextlabel <%s> of <%s> does not reference any existing ttylabel.\n",
180 					nextlabel, argtmp);
181 				}
182 			}
183 			exit(0);
184 			break;		/*NOTREACHED*/
185 		case '?':
186 			errflg++;
187 			break;
188 		} /* end switch */
189 		if (errflg)
190 			usage();
191 	} /* end while */
192 	if (optind < argc)
193 		usage();
194 
195 	if (aflg) {
196 		add_entry(ptr); 	/* never return */
197 	}
198 	if ((iflg) || (fflg) || (bflg) || (nflg))
199 		usage();
200 	return (0);
201 }
202 
203 /*
204  *	verify	- to check if arg is valid
205  *		- i.e. arg cannot start with '-' and
206  *		  arg must not longer than maxarglen
207  *		- return 0 if ok. Otherwise return -1
208  */
209 static	int
210 verify(arg,maxarglen)
211 char	*arg;
212 int	maxarglen;
213 {
214 	if (*arg == '-') {
215 		(void)fprintf(stderr, "Invalid argument -- %s.\n", arg);
216 		return(-1);
217 	}
218 	if ((maxarglen) && ((int)strlen(arg) > maxarglen)) {
219 		arg[maxarglen] = '\0';
220 		(void)fprintf(stderr,"string too long, truncated to %s.\n",arg);
221 		return(-1);
222 	}
223 	return(0);
224 }
225 
226 /*
227  * usage - print out a usage message
228  */
229 
230 static	void
231 usage()
232 {
233 	(void)fprintf(stderr, "Usage:\tsttydefs -a ttylabel [-n nextlabel] [-i initial-flags]\n\t\t [-f final-flags] [-b]\n");
234 	(void)fprintf(stderr, "\tsttydefs -r ttylabel\n");
235 	(void)fprintf(stderr, "\tsttydefs -l [ttylabel]\n");
236 	exit(2);
237 }
238 
239 /*
240  *	add_entry - add an entry to /etc/ttydefs
241  */
242 
243 static	void
244 add_entry(ttydef)
245 struct Gdef *ttydef;
246 {
247 	FILE *fp;
248 	int	errflg = 0;
249 	char tbuf[BUFSIZ], *tp;
250 	int  add_version = FALSE;
251 	extern	int	check_flags();
252 
253 	if (getuid()) {
254 		(void)fprintf(stderr, "User not privileged for operation.\n");
255 		exit(1);
256 	}
257 	tp = tbuf;
258 	*tp = '\0';
259 	if ((fp = fopen(TTYDEFS, "r")) != NULL) {
260 		if (check_version(TTYDEFS_VERS, TTYDEFS) != 0) {
261 			(void)fprintf(stderr,
262 			"%s version number is incorrect or missing.\n",TTYDEFS);
263 			exit(1);
264 		}
265 		if (find_label(fp,ttydef->g_id)) {
266 			(void)fclose(fp);
267 			(void)fprintf(stderr,
268 			"Invalid request -- ttylabel <%s> already exists.\n",
269 			ttydef->g_id);
270 			exit(1);
271 		}
272 		(void)fclose(fp);
273 	}
274 	else  {
275 		add_version = TRUE;
276 	}
277 	if ((fp = fopen(TTYDEFS, "a+")) == NULL) {
278 		(void) fprintf(stderr, "Could not open \"%s\": %s", TTYDEFS,
279 		    strerror(errno));
280 		exit(1);
281 	}
282 
283 	if (add_version) {
284 	   (void)fprintf(fp,"# VERSION=%d\n", TTYDEFS_VERS);
285 	}
286 
287 
288 	/* if optional fields are not provided, set to default */
289 	if (!iflg)
290 		ttydef->g_iflags = DEFAULT.g_iflags;
291 	else
292 		if (check_flags(ttydef->g_iflags) != 0 )
293 			errflg++;
294 	if (!fflg)
295 		ttydef->g_fflags = DEFAULT.g_fflags;
296 	else
297 		if (check_flags(ttydef->g_fflags) != 0 )
298 			errflg++;
299 	if (errflg)
300 		exit(1);
301 
302 	if (!nflg)
303 		ttydef->g_nextid = ttydef->g_id;
304 
305 	if (ttydef->g_autobaud & A_FLAG)  {
306 	   (void)fprintf(fp,"%s:%s:%s:A:%s\n", ttydef->g_id, ttydef->g_iflags,
307 		ttydef->g_fflags, ttydef->g_nextid);
308 	}
309 	else {
310 	   (void)fprintf(fp,"%s:%s:%s::%s\n", ttydef->g_id, ttydef->g_iflags,
311 		ttydef->g_fflags, ttydef->g_nextid);
312 	}
313 	(void)fclose(fp);
314 	exit(0);
315 }
316 
317 static	void
318 remove_entry(ttylabel)
319 char	*ttylabel;
320 {
321 	FILE *tfp;		/* file pointer for temp file */
322 	int line;		/* line number entry is on */
323 	FILE *fp;		/* scratch file pointer */
324 	char *tname = "/etc/.ttydefs";
325 
326 	if (getuid()) {
327 		(void)fprintf(stderr, "User not privileged for operation.\n");
328 		exit(1);
329 	}
330 	fp = fopen(TTYDEFS, "r");
331 	if (fp == NULL) {
332 		(void) fprintf(stderr, "Could not open \"%s\": %s", TTYDEFS,
333 		    strerror(errno));
334 		exit(1);
335 	}
336 	if (check_version(TTYDEFS_VERS, TTYDEFS) != 0) {
337 		(void)fprintf(stderr,
338 			"%s version number is incorrect or missing.\n",TTYDEFS);
339 		exit(1);
340 	}
341 	if ((line = find_label(fp, ttylabel)) == 0) {
342 		(void)fprintf(stderr,
343 		"Invalid request, ttylabel <%s> does not exist.\n", ttylabel);
344 		exit(1);
345 	}
346 	tfp = open_temp(tname);
347 	if (line != 1)
348 		if (copy_file(fp, tfp, 1, line - 1)) {
349 			(void)fprintf(stderr,"Error accessing temp file.\n");
350 			exit(1);
351 		}
352 	if (copy_file(fp, tfp, line + 1, -1)) {
353 		(void)fprintf(stderr,"Error accessing temp file.\n");
354 		exit(1);
355 	}
356 	(void)fclose(fp);
357 	if (fclose(tfp) == EOF) {
358 		(void)unlink(tname);
359 		(void)fprintf(stderr,"Error closing temp file.\n");
360 		exit(1);
361 	}
362 	(void)unlink(TTYDEFS);
363 	if (rename(tname, TTYDEFS) != 0 ) {
364 		perror("Rename failed");
365 		(void)unlink(tname);
366 		exit(1);
367 	}
368 	exit(0);
369 }
370 
371 /*
372  * open_temp - open up a temp file
373  *
374  *	args:	tname - temp file name
375  */
376 
377 static	FILE *
378 open_temp(tname)
379 char *tname;
380 {
381 	FILE *fp;			/* fp associated with tname */
382 	struct sigaction sigact;	/* for signal handling */
383 
384 	sigact.sa_flags = 0;
385 	sigact.sa_handler = SIG_IGN;
386 	(void) sigemptyset(&sigact.sa_mask);
387 	(void) sigaddset(&sigact.sa_mask, SIGHUP);
388 	(void) sigaddset(&sigact.sa_mask, SIGINT);
389 	(void) sigaddset(&sigact.sa_mask, SIGQUIT);
390 	(void) sigaction(SIGHUP, &sigact, NULL);
391 	(void) sigaction(SIGINT, &sigact, NULL);
392 	(void) sigaction(SIGQUIT, &sigact, NULL);
393 	(void)umask(0333);
394 	if (access(tname, 0) != -1) {
395 		(void)fprintf(stderr,"tempfile busy; try again later.\n");
396 		exit(1);
397 	}
398 	fp = fopen(tname, "w");
399 	if (fp == NULL) {
400 		perror("Cannot create tempfile");
401 		exit(1);
402 	}
403 	return(fp);
404 }
405 
406 /*
407  * copy_file - copy information from one file to another, return 0 on
408  *	success, -1 on failure
409  *
410  *	args:	fp - source file's file pointer
411  *		tfp - destination file's file pointer
412  *		start - starting line number
413  *		finish - ending line number (-1 indicates entire file)
414  */
415 
416 
417 static	int
418 copy_file(fp, tfp, start, finish)
419 FILE *fp;
420 FILE *tfp;
421 register int start;
422 register int finish;
423 {
424 	register int i;		/* loop variable */
425 	char dummy[BUFSIZ];	/* scratch buffer */
426 
427 /*
428  * always start from the beginning because line numbers are absolute
429  */
430 
431 	rewind(fp);
432 
433 /*
434  * get to the starting point of interest
435  */
436 
437 	if (start != 1) {
438 		for (i = 1; i < start; i++)
439 			if (!fgets(dummy, BUFSIZ, fp))
440 				return(-1);
441 	}
442 
443 /*
444  * copy as much as was requested
445  */
446 
447 	if (finish != -1) {
448 		for (i = start; i <= finish; i++) {
449 			if (!fgets(dummy, BUFSIZ, fp))
450 				return(-1);
451 			if (fputs(dummy, tfp) == EOF)
452 				return(-1);
453 		}
454 	}
455 	else {
456 		for (;;) {
457 			if (fgets(dummy, BUFSIZ, fp) == NULL) {
458 				if (feof(fp))
459 					break;
460 				else
461 					return(-1);
462 			}
463 			if (fputs(dummy, tfp) == EOF)
464 				return(-1);
465 		}
466 	}
467 	return(0);
468 }
469 
470 /*
471  *	check_ref	- to check if nextlabel are referencing
472  *			  existing ttylabel
473  */
474 static	void
475 check_ref()
476 {
477 	int	i;
478 	struct	Gdef	*np;
479 	extern	struct	Gdef	*find_def();
480 	np = &Gdef[0];
481 	for (i = 0; i < Ndefs; i++, np++) {
482 		if (find_def(np->g_nextid) == NULL) {
483 			(void)printf("Warning -- nextlabel <%s> of <%s> does not reference any existing ttylabel.\n",
484 			np->g_nextid, np->g_id);
485 		}
486 	}
487 	return;
488 }
489 
490 /*
491  *	log	- print a message to stdout
492  */
493 
494 void
495 log(const char *msg, ...)
496 {
497 	va_list ap;
498 	if (lflg) {
499 		va_start(ap, msg);
500 		(void) vprintf(msg, ap);
501 		va_end(ap);
502 		(void) printf("\n");
503 	} else {
504 		va_start(ap, msg);
505 		(void) vfprintf(stderr, msg, ap);
506 		va_end(ap);
507 		(void) fprintf(stderr,"\n");
508 	}
509 }
510