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