xref: /titanic_50/usr/src/cmd/ttymon/sttydefs.c (revision c77a61a72b5ecdc507d6cf104142edd371a16c84)
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