xref: /csrg-svn/old/configttys/configttys.c (revision 12530)
1 /*
2  * configttys - configure "tty" ports
3  *
4  * David L. Wasley
5  * U.C.Berkeley
6  */
7 
8 #ifndef	lint
9 char	sccsid[]	= "@(#)configttys.c	4.1 Berkeley 05/18/83";
10 #endif
11 
12 #include <stdio.h>
13 #include <getty.h>
14 #include <signal.h>
15 
16 #define	exists(file)	(access(file, 0) == 0)
17 
18 char	*etc_ttys	= "/etc/ttys";		/* active port speed table */
19 char	*etc_ttytype	= "/etc/ttytype";	/* terminal type table */
20 char	*etc_conf	= "/etc/ttyconf";	/* master config file */
21 char	*lockfile	= "/etc/ttyconf.lock";	/* interlock file */
22 
23 struct ttys {
24 	char	ty_active;	/* active login port */
25 	char	ty_speed;	/* speed table character */
26 	char	ty_port[32];	/* port name */
27 } ttys[256];
28 
29 struct ttytype {
30 	char	tp_term[64];	/* terminal type name */
31 	char	tp_port[32];	/* port name */
32 } ttytype[256];
33 
34 char	conformat[]	= "%s\t%s\t%s\t%s\n";
35 
36 int	error	= 0;
37 int	renamed = 0;
38 int	debug	= 0;			/* debug mode */
39 int	backup	= 0;			/* create backup copies of old data */
40 int	interactive = 1;		/* interactive mode */
41 
42 char	*speedname();			/* port speed code name */
43 char	speedchar();			/* getty table name */
44 char	*termname();			/* name of terminal on this port */
45 char	*rindex();
46 struct ttytype	*type();		/* find ttytype for port */
47 FILE	*fopen();
48 
49 main (argc, argv)
50 int	argc;
51 char	**argv;
52 {
53 	int		lineno;
54 	int		child;
55 	int		status;
56 	char		c;
57 	struct ttys	*ty;
58 	struct ttytype	*tp;
59 	char		port[32];
60 	char		active[16];
61 	char		speed[32];
62 	char		term[64];
63 	FILE		*tyf, *tpf, *conf;
64 	char		buf[1024];
65 	char		ans[32];
66 
67 	while (--argc > 0)
68 	{
69 		if (**++argv == '-') switch (*++*argv)
70 		{
71 			case 'd':
72 				debug = 1;
73 				break;
74 
75 			case 'n':		/* non-interactive */
76 				interactive = 0;
77 				break;
78 
79 			case 'b':		/* backup old databases */
80 				backup = 1;
81 				break;
82 
83 			default:
84 				fprintf(stderr, "unknown option %c\n", **argv);
85 				exit(1);
86 		}
87 	}
88 
89 	if (debug)
90 	{
91 		etc_ttys = rindex(etc_ttys, '/') + 1;
92 		etc_ttytype = rindex(etc_ttytype, '/') + 1;
93 		etc_conf = rindex(etc_conf, '/') + 1;
94 		lockfile = rindex(lockfile, '/') + 1;
95 	}
96 
97 	/*
98 	 * create backup copies of the databases?
99 	 */
100 	if (backup)
101 	{
102 		if (exists(etc_ttys))
103 		{
104 			sprintf(buf, "/bin/cp %s %s.bak", etc_ttys, etc_ttys);
105 			system(buf);
106 		}
107 		if (exists(etc_ttys))
108 		{
109 			sprintf(buf, "/bin/cp %s %s.bak", etc_ttytype, etc_ttytype);
110 			system(buf);
111 		}
112 		if (exists(etc_conf))
113 		{
114 			sprintf(buf, "/bin/cp %s %s.bak", etc_conf, etc_conf);
115 			system(buf);
116 		}
117 	}
118 
119 	/*
120 	 * create interlock file
121 	 */
122 	getlockfile(lockfile);
123 
124 	/*
125 	 * always read ttys file for comparison
126 	 * It is afterall what really counts!
127 	 */
128 	if (readttys() != 0)
129 		quit(1);
130 
131 	/*
132 	 * read old ttytypes if necessary
133 	 */
134 	if (! exists(etc_conf))
135 	{
136 		/*
137 		 * open old ttytype file
138 		 */
139 		if ((tpf = fopen(etc_ttytype, "r")) == NULL)
140 		{
141 			perror(etc_ttytype);
142 			quit(1);
143 		}
144 
145 		/*
146 		 * read ttytype file
147 		 */
148 		lineno = 0;
149 		tp = ttytype;
150 		while (fgets(buf, sizeof buf, tpf))
151 		{
152 			lineno++;
153 			if (sscanf(buf, "%s %s", tp->tp_term, tp->tp_port) == 2)
154 				tp++;
155 			else
156 			{
157 				error++;
158 				fprintf(stderr, "bad line %d in %s: %s",
159 					lineno, etc_ttytype, buf);
160 			}
161 		}
162 		fclose(tpf);
163 		tp->tp_term[0] = '\0';
164 
165 		if (error > 0)
166 			quit(1);
167 
168 		/*
169 		 * create master config file
170 		 */
171 		if ((conf = fopen(etc_conf, "w")) == NULL)
172 		{
173 			perror(etc_conf);
174 			quit(1);
175 		}
176 
177 		fprintf(conf, conformat, "port", "active", "speed\t", "terminal name");
178 		fprintf(conf, conformat, "----", "------", "-----\t", "-------------");
179 		for (ty = ttys; ty->ty_active; ty++)
180 		{
181 			fprintf(conf, conformat, ty->ty_port,
182 				ty->ty_active == '1'? "active":"-",
183 				speedname(ty->ty_speed),
184 				termname(ty->ty_port));
185 		}
186 		fclose(conf);
187 	}
188 
189 	/*
190 	 * open master config file
191 	 */
192 	if ((conf = fopen(etc_conf, "r")) == NULL)
193 	{
194 		perror(etc_conf);
195 		quit(1);
196 	}
197 
198 	if (interactive)
199 		edit();
200 
201 	/*
202 	 * read conf file
203 	 */
204 re_read:
205 	rewind(conf);
206 	ty = ttys;
207 	renamed = 0;
208 	error = 0;
209 	lineno = 0;
210 
211 	while (fgets(buf, sizeof buf, conf))	/* skip heading */
212 	{
213 		lineno++;
214 		if (buf[0] == '-')
215 			break;
216 	}
217 
218 	while (fgets(buf, sizeof buf, conf))
219 	{
220 		lineno++;
221 		if (sscanf(buf, "%s %s %s %s", port, active, speed, term) < 4)
222 		{
223 			fprintf(stderr, "line %d: field(s) missing: %s",
224 				lineno, buf);
225 			error++;
226 			break;
227 		}
228 
229 		if (strcmp(port, ty->ty_port) != 0)
230 		{
231 			if (! ty->ty_active || renamed)
232 				strcpy(ty->ty_port, port);
233 			else
234 			{
235 				fprintf(stderr, "line %d: port name changed! %s -> %s\n",
236 					lineno, ty->ty_port, port);
237 				fprintf(stderr, "Are you sure this is OK? ");
238 				gets(ans);
239 				if (ans[0] != 'y')
240 				{
241 					edit();
242 					goto re_read;
243 				}
244 				renamed++;
245 				strcpy(ty->ty_port, port);
246 			}
247 		}
248 
249 		if (strcmp(active, "active") == 0)
250 			ty->ty_active = '1';
251 		else
252 			ty->ty_active = '0';
253 
254 		if (c = speedchar(speed))
255 			ty->ty_speed = c;
256 		else
257 		{
258 			fprintf(stderr, "line %d: speed name not known: %s\n",
259 				lineno, speed);
260 			error++;
261 		}
262 
263 		if (tp = type(port))
264 			strcpy(tp->tp_term, term);
265 		/* else ?? */
266 
267 		ty++;
268 	}
269 
270 	if (ty == ttys)
271 	{
272 		fprintf(stderr, "%s empty??\n", etc_conf);
273 		error++;
274 	}
275 
276 	if (error)
277 	{
278 		if (interactive)
279 		{
280 			fprintf(stderr, "re-edit? ");
281 			gets(ans);
282 			if (ans[0] == 'y')
283 			{
284 				edit();
285 				goto re_read;
286 			}
287 		}
288 		fprintf(stderr, "Files not modified.\n");
289 		quit(1);
290 	}
291 
292 	writettys();
293 	quit(0);
294 }
295 
296 readttys()
297 {
298 	/*
299 	 * read ttys file
300 	 */
301 	FILE			*tyf;
302 	register struct ttys	*ty;
303 	char			buf[1024];
304 	int			lineno;
305 	int			error	= 0;
306 
307 	if ((tyf = fopen(etc_ttys, "r")) == NULL)
308 	{
309 		perror(etc_ttys);
310 		quit(1);
311 	}
312 
313 	lineno = 0;
314 	ty = ttys;
315 	while (fgets(buf, sizeof buf, tyf))
316 	{
317 		lineno++;
318 		if (sscanf(buf, "%c%c%s",
319 			&ty->ty_active, &ty->ty_speed, ty->ty_port) == 3)
320 			ty++;
321 		else
322 		{
323 			error++;
324 			fprintf(stderr, "bad line %d in %s: %s",
325 				lineno, etc_ttys, buf);
326 		}
327 	}
328 	fclose(tyf);
329 	ty->ty_active = '\0';
330 	return(error);
331 }
332 
333 writettys()
334 {
335 	int	rtn = 0;
336 	char	temp[1024];
337 	FILE	*tyf, *tpf;
338 	register struct ttys	*ty;
339 
340 	sprintf(temp, "%s.tmp", etc_ttys);
341 	if ((tyf = fopen(temp, "w")) == NULL)
342 	{
343 		perror(temp);
344 		quit(1);
345 	}
346 
347 	for (ty = ttys; ty->ty_active; ty++)
348 		fprintf(tyf, "%c%c%s\n",
349 			ty->ty_active, ty->ty_speed, ty->ty_port);
350 	fclose(tyf);
351 
352 	if (rename(temp, etc_ttys) != 0)
353 	{
354 		fprintf(stderr, "Can't rename %s\n", temp);
355 		rtn = 1;
356 	}
357 
358 	sprintf(temp, "%s.tmp", etc_ttytype);
359 	if ((tpf = fopen(temp, "w")) == NULL)
360 	{
361 		perror(temp);
362 		quit(1);
363 	}
364 
365 	for (ty = ttys; ty->ty_active; ty++)	/* same ports! */
366 		fprintf(tpf, "%s %s\n",
367 			type(ty->ty_port)->tp_term, ty->ty_port);
368 	fclose(tpf);
369 
370 	if (rename(temp, etc_ttytype) != 0)
371 	{
372 		fprintf(stderr, "Can't rename %s\n", temp);
373 		rtn = 1;
374 	}
375 
376 	return (rtn);
377 }
378 
379 
380 edit()
381 {
382 	/*
383 	 * invoke editor
384 	 */
385 	int	child;
386 	int	status;
387 
388 	if ((child = fork()) == 0)
389 	{
390 		execl("/usr/ucb/vi", "vi", etc_conf, 0);
391 		execl("/bin/ed", "ed", etc_conf, 0);
392 		exit(1);
393 	}
394 
395 	if (child < 0)
396 	{
397 		perror("can't fork editor");
398 		quit(1);
399 	}
400 
401 	/*
402 	 * wait for editor
403 	 */
404 	while (wait(&status) >= 0)
405 		;
406 
407 	return (status);
408 }
409 
410 
411 quit (n)
412 int	n;
413 {
414 	unlink (lockfile);
415 	if (n > 1)
416 	{
417 		signal (n, SIG_DFL);
418 		kill (getpid(), n);
419 	}
420 	exit (n);
421 }
422 
423 getlockfile ()
424 {
425 	char	*p;
426 	char	locktmp[64];
427 	int	fd;
428 
429 	strcpy(locktmp, lockfile);
430 	if (p = rindex(locktmp, '/'))
431 		p++;
432 	else
433 		p = locktmp;
434 	strcpy(p, "confttysXXXXXX");
435 	mktemp(locktmp);
436 
437 	if ((fd = creat(locktmp, 0600)) < 0)
438 	{
439 		perror(locktmp);
440 		exit(1);
441 	}
442 
443 	if (link(locktmp, lockfile) < 0)
444 	{
445 		perror(lockfile);
446 		unlink(locktmp);
447 		exit(1);
448 	}
449 
450 	signal(SIGINT,	quit);
451 	signal(SIGQUIT,	quit);
452 
453 	unlink(locktmp);
454 	return(0);
455 }
456 
457 struct speeds {
458 	char	*sp_name;	/* human readable name */
459 	char	sp_table;	/* getty table name */
460 } speeds[] = {
461 	{ "dialup",	GT_DIALUP },	/* normal dialup rotation */
462 	{ "selector",	GT_SELECTOR },	/* port selector pseudo-table autobaud*/
463 	{ "b110",	GT_B110 },	/* 110 baud */
464 	{ "b134",	GT_B134 },	/* 134.5 baud selectric */
465 	{ "b150",	GT_B150 },	/* 150 baud */
466 	{ "b300",	GT_B300 },	/* 300 baud */
467 	{ "b600",	GT_B600 },	/* 600 baud */
468 	{ "b1200",	GT_B1200 },	/* 1200 baud */
469 	{ "b2400",	GT_B2400 },	/* 2400 baud */
470 	{ "b4800",	GT_B4800 },	/* 4800 baud */
471 	{ "b9600",	GT_B9600 },	/* 9600 baud */
472 	{ "dw2console",	GT_DW2CONSOLE },/* Decwriter Console - 300 baud */
473 	{ "fastdialup",	GT_FASTDIALUP },/* 1200-300 baud rotation for dialup */
474 	{ "fastdialup1",GT_FASTDIALUP1},/* 300-1200  "     "       "     "    */
475 	{ "crt_hcpy",	GT_CRT_HCPY },	/* 9600-300 CRT + hardcopy rotation */
476 	{ "hcpy_crt",	GT_HCPY_CRT },	/* 300-9600  "      "        "      */
477 	{ "plugboard",	GT_PLUGBOARD },	/* 9600-300-1200 rotation */
478 	{ "plugboard1",	GT_PLUGBOARD2 },/* 300-1200-9600 rotation */
479 	{ "plugboard2",	GT_PLUGBOARD2 },/* 1200-9600-300 rotation */
480 	{ "interdata",	GT_INTERDATA },	/* Interdata Console */
481 	{ "chess",	GT_CHESS },	/* LSI Chess Terminal */
482 	{ "tty33",	GT_TTY33 },	/* 110 baud Model 33 TTY */
483 	{ "network",	GT_NETWORK },	/* ethernet port */
484 	{ "", 0 }
485 };
486 
487 char *
488 speedname (c)
489 char	c;
490 {
491 	struct speeds	*sp;
492 	static char	sbuf[32];
493 
494 	for (sp = speeds; sp->sp_table; sp++)
495 		if (sp->sp_table == c)
496 			break;
497 
498 	if (sp->sp_table)
499 		strcpy(sbuf, sp->sp_name);
500 	else
501 		strcpy(sbuf, "-");
502 
503 	if (strlen(sbuf) < 8)
504 		strcat(sbuf, "\t");
505 
506 	return (sbuf);
507 }
508 
509 char *
510 termname (port)
511 char	*port;
512 {
513 	register struct ttytype	*tp;
514 
515 	for (tp = ttytype; tp->tp_term[0]; tp++)
516 		if (strcmp(port, tp->tp_port) == 0)
517 			return (tp->tp_term);
518 
519 	if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1])
520 	{
521 		strcpy(tp->tp_port, port);
522 		strcpy(tp->tp_term, "unknown");
523 		(++tp)->tp_term[0] = '\0';
524 	}
525 
526 	return ("unknown");
527 }
528 
529 char
530 speedchar (speed)
531 char	*speed;
532 {
533 	register struct speeds	*sp;
534 
535 	for (sp = speeds; sp->sp_table; sp++)
536 		if (strcmp(sp->sp_name, speed) == 0)
537 			return (sp->sp_table);
538 	return ('\0');
539 }
540 
541 struct ttytype *
542 type (port)
543 char	*port;
544 {
545 	register struct ttytype	*tp;
546 
547 	for (tp = ttytype; tp->tp_term[0]; tp++)
548 		if (strcmp(tp->tp_port, port) == 0)
549 			return (tp);
550 
551 	if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1])
552 	{
553 		strcpy(tp->tp_port, port);
554 		strcpy(tp->tp_term, "unknown");
555 		return(tp);
556 	}
557 
558 	return((struct ttytype *)0);
559 }
560 
561 /* DELETE this for 4.2bsd */
562 
563 #include <errno.h>
564 
565 rename (from, to)
566 char	*from, *to;
567 {
568 	extern int	errno;
569 
570 	if (unlink(to) < 0)
571 		if (errno != ENOENT)
572 			return(-1);
573 	if (link(from, to) == 0)
574 		return (unlink(from));
575 	else
576 		return(-1);
577 }
578 
579