xref: /csrg-svn/old/configttys/configttys.c (revision 12566)
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.3 Berkeley 05/19/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", "login", "speed\t", "terminal type");
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 		if (exists(etc_conf))
310 			return (0);	/* hope user has it together! */
311 		perror(etc_ttys);
312 		quit(1);
313 	}
314 
315 	lineno = 0;
316 	ty = ttys;
317 	while (fgets(buf, sizeof buf, tyf))
318 	{
319 		lineno++;
320 		if (sscanf(buf, "%c%c%s",
321 			&ty->ty_active, &ty->ty_speed, ty->ty_port) == 3)
322 			ty++;
323 		else
324 		{
325 			error++;
326 			fprintf(stderr, "bad line %d in %s: %s",
327 				lineno, etc_ttys, buf);
328 		}
329 	}
330 	fclose(tyf);
331 	ty->ty_active = '\0';
332 	return(error);
333 }
334 
335 writettys()
336 {
337 	int	rtn = 0;
338 	char	temp[1024];
339 	FILE	*tyf, *tpf;
340 	register struct ttys	*ty;
341 
342 	sprintf(temp, "%s.tmp", etc_ttys);
343 	if ((tyf = fopen(temp, "w")) == NULL)
344 	{
345 		perror(temp);
346 		quit(1);
347 	}
348 
349 	for (ty = ttys; ty->ty_active; ty++)
350 		fprintf(tyf, "%c%c%s\n",
351 			ty->ty_active, ty->ty_speed, ty->ty_port);
352 	fclose(tyf);
353 
354 	if (rename(temp, etc_ttys) != 0)
355 	{
356 		fprintf(stderr, "Can't rename %s\n", temp);
357 		rtn = 1;
358 	}
359 
360 	sprintf(temp, "%s.tmp", etc_ttytype);
361 	if ((tpf = fopen(temp, "w")) == NULL)
362 	{
363 		perror(temp);
364 		quit(1);
365 	}
366 
367 	for (ty = ttys; ty->ty_active; ty++)	/* same ports! */
368 		fprintf(tpf, "%s %s\n",
369 			type(ty->ty_port)->tp_term, ty->ty_port);
370 	fclose(tpf);
371 
372 	if (rename(temp, etc_ttytype) != 0)
373 	{
374 		fprintf(stderr, "Can't rename %s\n", temp);
375 		rtn = 1;
376 	}
377 
378 	return (rtn);
379 }
380 
381 
382 edit()
383 {
384 	/*
385 	 * invoke editor
386 	 */
387 	int	child;
388 	int	status;
389 
390 	if ((child = fork()) == 0)
391 	{
392 		execl("/usr/ucb/vi", "vi", etc_conf, 0);
393 		execl("/bin/ed", "ed", etc_conf, 0);
394 		exit(1);
395 	}
396 
397 	if (child < 0)
398 	{
399 		perror("can't fork editor");
400 		quit(1);
401 	}
402 
403 	/*
404 	 * wait for editor
405 	 */
406 	while (wait(&status) >= 0)
407 		;
408 
409 	return (status);
410 }
411 
412 
413 quit (n)
414 int	n;
415 {
416 	unlink (lockfile);
417 	if (n > 1)
418 	{
419 		signal (n, SIG_DFL);
420 		kill (getpid(), n);
421 	}
422 	exit (n);
423 }
424 
425 getlockfile ()
426 {
427 	char	*p;
428 	char	locktmp[64];
429 	int	fd;
430 
431 	strcpy(locktmp, lockfile);
432 	if (p = rindex(locktmp, '/'))
433 		p++;
434 	else
435 		p = locktmp;
436 	strcpy(p, "confttysXXXXXX");
437 	mktemp(locktmp);
438 
439 	if ((fd = creat(locktmp, 0600)) < 0)
440 	{
441 		perror(locktmp);
442 		exit(1);
443 	}
444 
445 	if (link(locktmp, lockfile) < 0)
446 	{
447 		perror(lockfile);
448 		unlink(locktmp);
449 		exit(1);
450 	}
451 
452 	signal(SIGINT,	quit);
453 	signal(SIGQUIT,	quit);
454 
455 	unlink(locktmp);
456 	return(0);
457 }
458 
459 struct speeds {
460 	char	*sp_name;	/* human readable name */
461 	char	sp_table;	/* getty table name */
462 } speeds[] = {
463 	{ "dialup",	GT_DIALUP },	/* normal dialup rotation */
464 	{ "selector",	GT_SELECTOR },	/* port selector pseudo-table autobaud*/
465 	{ "b110",	GT_B110 },	/* 110 baud */
466 	{ "b134",	GT_B134 },	/* 134.5 baud selectric */
467 	{ "b150",	GT_B150 },	/* 150 baud */
468 	{ "b300",	GT_B300 },	/* 300 baud */
469 	{ "b600",	GT_B600 },	/* 600 baud */
470 	{ "b1200",	GT_B1200 },	/* 1200 baud */
471 	{ "b2400",	GT_B2400 },	/* 2400 baud */
472 	{ "b4800",	GT_B4800 },	/* 4800 baud */
473 	{ "b9600",	GT_B9600 },	/* 9600 baud */
474 	{ "dw2console",	GT_DW2CONSOLE },/* Decwriter Console - 300 baud */
475 	{ "fastdialup",	GT_FASTDIALUP },/* 1200-300 baud rotation for dialup */
476 	{ "fastdialup1",GT_FASTDIALUP1},/* 300-1200  "     "       "     "    */
477 	{ "crt_hcpy",	GT_CRT_HCPY },	/* 9600-300 CRT + hardcopy rotation */
478 	{ "hcpy_crt",	GT_HCPY_CRT },	/* 300-9600  "      "        "      */
479 	{ "plugboard",	GT_PLUGBOARD },	/* 9600-300-1200 rotation */
480 	{ "plugboard1",	GT_PLUGBOARD2 },/* 300-1200-9600 rotation */
481 	{ "plugboard2",	GT_PLUGBOARD2 },/* 1200-9600-300 rotation */
482 	{ "interdata",	GT_INTERDATA },	/* Interdata Console */
483 	{ "chess",	GT_CHESS },	/* LSI Chess Terminal */
484 	{ "tty33",	GT_TTY33 },	/* 110 baud Model 33 TTY */
485 	{ "network",	GT_NETWORK },	/* ethernet port */
486 	{ "", 0 }
487 };
488 
489 char *
490 speedname (c)
491 char	c;
492 {
493 	struct speeds	*sp;
494 	static char	sbuf[32];
495 
496 	for (sp = speeds; sp->sp_table; sp++)
497 		if (sp->sp_table == c)
498 			break;
499 
500 	if (sp->sp_table)
501 		strcpy(sbuf, sp->sp_name);
502 	else
503 		strcpy(sbuf, "-");
504 
505 	if (strlen(sbuf) < 8)
506 		strcat(sbuf, "\t");
507 
508 	return (sbuf);
509 }
510 
511 char *
512 termname (port)
513 char	*port;
514 {
515 	register struct ttytype	*tp;
516 
517 	for (tp = ttytype; tp->tp_term[0]; tp++)
518 		if (strcmp(port, tp->tp_port) == 0)
519 			return (tp->tp_term);
520 
521 	if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1])
522 	{
523 		strcpy(tp->tp_port, port);
524 		strcpy(tp->tp_term, "unknown");
525 		(++tp)->tp_term[0] = '\0';
526 	}
527 
528 	return ("unknown");
529 }
530 
531 char
532 speedchar (speed)
533 char	*speed;
534 {
535 	register struct speeds	*sp;
536 
537 	for (sp = speeds; sp->sp_table; sp++)
538 		if (strcmp(sp->sp_name, speed) == 0)
539 			return (sp->sp_table);
540 	return ('\0');
541 }
542 
543 struct ttytype *
544 type (port)
545 char	*port;
546 {
547 	register struct ttytype	*tp;
548 
549 	for (tp = ttytype; tp->tp_term[0]; tp++)
550 		if (strcmp(tp->tp_port, port) == 0)
551 			return (tp);
552 
553 	if (tp < &ttytype[(sizeof ttytype / sizeof (struct ttytype)) -1])
554 	{
555 		strcpy(tp->tp_port, port);
556 		strcpy(tp->tp_term, "unknown");
557 		return(tp);
558 	}
559 
560 	return((struct ttytype *)0);
561 }
562