xref: /openbsd/sbin/ttyflags/ttyflags.c (revision d7259957)
1*d7259957Scheloha /*	$OpenBSD: ttyflags.c,v 1.17 2022/12/04 23:50:47 cheloha Exp $	*/
2f3bae140Sderaadt /*	$NetBSD: ttyflags.c,v 1.8 1996/04/09 05:20:30 cgd Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
546f3f978Sderaadt  * Copyright (c) 1996 Theo de Raadt
6df930be7Sderaadt  * Copyright (c) 1994 Christopher G. Demetriou
7df930be7Sderaadt  * All rights reserved.
8df930be7Sderaadt  *
9df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
10df930be7Sderaadt  * modification, are permitted provided that the following conditions
11df930be7Sderaadt  * are met:
12df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
13df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
14df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
15df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
16df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
17df930be7Sderaadt  * 3. All advertising materials mentioning features or use of this software
18df930be7Sderaadt  *    must display the following acknowledgement:
19df930be7Sderaadt  *      This product includes software developed by Christopher G. Demetriou.
20df930be7Sderaadt  * 4. The name of the author may not be used to endorse or promote products
21df930be7Sderaadt  *    derived from this software without specific prior written permission
22df930be7Sderaadt  *
23df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24df930be7Sderaadt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25df930be7Sderaadt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26df930be7Sderaadt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27df930be7Sderaadt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28df930be7Sderaadt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29df930be7Sderaadt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30df930be7Sderaadt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31df930be7Sderaadt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32df930be7Sderaadt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33df930be7Sderaadt  */
34df930be7Sderaadt 
35df930be7Sderaadt #include <sys/types.h>
36df930be7Sderaadt #include <sys/ioctl.h>
37df930be7Sderaadt 
38df930be7Sderaadt #include <err.h>
39df930be7Sderaadt #include <errno.h>
40df930be7Sderaadt #include <fcntl.h>
41df930be7Sderaadt #include <limits.h>
42df930be7Sderaadt #include <paths.h>
43df930be7Sderaadt #include <stdio.h>
44df930be7Sderaadt #include <stdlib.h>
45f3bae140Sderaadt #include <string.h>
46df930be7Sderaadt #include <ttyent.h>
47df930be7Sderaadt #include <unistd.h>
48df930be7Sderaadt 
49c72b5b24Smillert int all(int);
50c72b5b24Smillert int ttys(char **, int);
51c72b5b24Smillert int ttyflags(struct ttyent *, int);
52c72b5b24Smillert void usage(void);
53df930be7Sderaadt 
54df930be7Sderaadt int nflag, vflag;
55df930be7Sderaadt 
56df930be7Sderaadt /*
57df930be7Sderaadt  * Ttyflags sets the device-specific tty flags, based on the contents
58df930be7Sderaadt  * of /etc/ttys.  It can either set all of the ttys' flags, or set
59df930be7Sderaadt  * the flags of the ttys specified on the command line.
60df930be7Sderaadt  */
61df930be7Sderaadt int
main(int argc,char * argv[])62bc52e260Sderaadt main(int argc, char *argv[])
63df930be7Sderaadt {
6446f3f978Sderaadt 	int aflag, ch, rval, pflag = 0;
65df930be7Sderaadt 
66df930be7Sderaadt 	aflag = nflag = vflag = 0;
6772799b18Smillert 	while ((ch = getopt(argc, argv, "panv")) != -1)
68df930be7Sderaadt 		switch (ch) {
69df930be7Sderaadt 		case 'a':
70df930be7Sderaadt 			aflag = 1;
71df930be7Sderaadt 			break;
72df930be7Sderaadt 		case 'n':		/* undocumented */
73df930be7Sderaadt 			nflag = 1;
74df930be7Sderaadt 			break;
7546f3f978Sderaadt 		case 'p':
7646f3f978Sderaadt 			pflag = 1;
7746f3f978Sderaadt 			break;
78df930be7Sderaadt 		case 'v':
79df930be7Sderaadt 			vflag = 1;
80df930be7Sderaadt 			break;
81df930be7Sderaadt 		default:
82df930be7Sderaadt 			usage();
83df930be7Sderaadt 		}
84df930be7Sderaadt 	argc -= optind;
85df930be7Sderaadt 	argv += optind;
86df930be7Sderaadt 
87df930be7Sderaadt 	if (aflag && argc != 0)
88df930be7Sderaadt 		usage();
89df930be7Sderaadt 
90df930be7Sderaadt 	if (setttyent() == 0)
91df930be7Sderaadt 		err(1, "setttyent");
92df930be7Sderaadt 
93df930be7Sderaadt 	if (aflag)
9446f3f978Sderaadt 		rval = all(pflag);
95df930be7Sderaadt 	else
9646f3f978Sderaadt 		rval = ttys(argv, pflag);
97df930be7Sderaadt 
98df930be7Sderaadt 	if (endttyent() == 0)
99df930be7Sderaadt 		warn("endttyent");
100df930be7Sderaadt 
101df930be7Sderaadt 	exit(rval);
102df930be7Sderaadt }
103df930be7Sderaadt 
104df930be7Sderaadt /*
105df930be7Sderaadt  * Change all /etc/ttys entries' flags.
106df930be7Sderaadt  */
107df930be7Sderaadt int
all(int print)108bc52e260Sderaadt all(int print)
109df930be7Sderaadt {
110df930be7Sderaadt 	struct ttyent *tep;
111df930be7Sderaadt 	int rval;
112df930be7Sderaadt 
113df930be7Sderaadt 	rval = 0;
114dec45198Sderaadt 	for (tep = getttyent(); tep != NULL; tep = getttyent()) {
115dec45198Sderaadt 		/* pseudo-tty ignore TIOCSFLAGS, so don't bother */
1169cf8b525Sotto 		if (tep->ty_type == NULL ||
1179cf8b525Sotto 		    strcmp(tep->ty_type, "network") == 0)
118dec45198Sderaadt 			continue;
11946f3f978Sderaadt 		if (ttyflags(tep, print))
120df930be7Sderaadt 			rval = 1;
121dec45198Sderaadt 	}
122df930be7Sderaadt 	return (rval);
123df930be7Sderaadt }
124df930be7Sderaadt 
125df930be7Sderaadt /*
126df930be7Sderaadt  * Change the specified ttys' flags.
127df930be7Sderaadt  */
128df930be7Sderaadt int
ttys(char ** ttylist,int print)129bc52e260Sderaadt ttys(char **ttylist, int print)
130df930be7Sderaadt {
131df930be7Sderaadt 	struct ttyent *tep;
132df930be7Sderaadt 	int rval;
133df930be7Sderaadt 
134df930be7Sderaadt 	rval = 0;
135df930be7Sderaadt 	for (; *ttylist != NULL; ttylist++) {
136df930be7Sderaadt 		tep = getttynam(*ttylist);
137df930be7Sderaadt 		if (tep == NULL) {
138df930be7Sderaadt 			warnx("couldn't find an entry in %s for \"%s\"",
139df930be7Sderaadt 			    _PATH_TTYS, *ttylist);
140df930be7Sderaadt 			rval = 1;
141df930be7Sderaadt 			continue;
142df930be7Sderaadt 		}
143df930be7Sderaadt 
14446f3f978Sderaadt 		if (ttyflags(tep, print))
145df930be7Sderaadt 			rval = 1;
146df930be7Sderaadt 	}
147df930be7Sderaadt 	return (rval);
148df930be7Sderaadt }
149df930be7Sderaadt 
150f3bae140Sderaadt 
151df930be7Sderaadt /*
152f3bae140Sderaadt  * Actually do the work; find out what the new flags value should be,
153df930be7Sderaadt  * open the device, and change the flags.
154df930be7Sderaadt  */
155df930be7Sderaadt int
ttyflags(struct ttyent * tep,int print)156bc52e260Sderaadt ttyflags(struct ttyent *tep, int print)
157df930be7Sderaadt {
158c1e8532bStholo 	int fd, flags = 0, rval = 0, st, sep = 0;
159df930be7Sderaadt 	char path[PATH_MAX];
160c1e8532bStholo 	char strflags[256];
161c1e8532bStholo 
162c1e8532bStholo 	st = tep->ty_status;
163c1e8532bStholo 	strflags[0] = '\0';
164df930be7Sderaadt 
165c8b72154Stholo 	/* Find the full device path name. */
166c8b72154Stholo 	(void)snprintf(path, sizeof path, "%s%s", _PATH_DEV, tep->ty_name);
167c8b72154Stholo 
16846f3f978Sderaadt 	if (print == 0) {
169df930be7Sderaadt 		/* Convert ttyent.h flags into ioctl flags. */
170f3bae140Sderaadt 		if (st & TTY_LOCAL) {
171df930be7Sderaadt 			flags |= TIOCFLAG_CLOCAL;
172df6be55dSderaadt 			(void)strlcat(strflags, "local", sizeof strflags);
173f3bae140Sderaadt 			sep++;
174f3bae140Sderaadt 		}
175f3bae140Sderaadt 		if (st & TTY_RTSCTS) {
176df930be7Sderaadt 			flags |= TIOCFLAG_CRTSCTS;
177f3bae140Sderaadt 			if (sep++)
178df6be55dSderaadt 				(void)strlcat(strflags, "|", sizeof strflags);
179df6be55dSderaadt 			(void)strlcat(strflags, "rtscts", sizeof strflags);
180f3bae140Sderaadt 		}
181f3bae140Sderaadt 		if (st & TTY_SOFTCAR) {
182df930be7Sderaadt 			flags |= TIOCFLAG_SOFTCAR;
183f3bae140Sderaadt 			if (sep++)
184df6be55dSderaadt 				(void)strlcat(strflags, "|", sizeof strflags);
185df6be55dSderaadt 			(void)strlcat(strflags, "softcar", sizeof strflags);
186f3bae140Sderaadt 		}
187f3bae140Sderaadt 		if (st & TTY_MDMBUF) {
188df930be7Sderaadt 			flags |= TIOCFLAG_MDMBUF;
189f3bae140Sderaadt 			if (sep++)
190df6be55dSderaadt 				(void)strlcat(strflags, "|", sizeof strflags);
191df6be55dSderaadt 			(void)strlcat(strflags, "mdmbuf", sizeof strflags);
192f3bae140Sderaadt 		}
19346f3f978Sderaadt 		if (vflag)
19446f3f978Sderaadt 			printf("%s setting flags to: %s\n", path, strflags);
19546f3f978Sderaadt 	}
196df930be7Sderaadt 
197df930be7Sderaadt 	if (nflag)
198df930be7Sderaadt 		return (0);
199df930be7Sderaadt 
200df930be7Sderaadt 	/* Open the device NON-BLOCKING, set the flags, and close it. */
201b7041c07Sderaadt 	if ((fd = open(path, O_RDONLY | O_NONBLOCK)) == -1) {
202df930be7Sderaadt 		if (!(errno == ENXIO ||
203df930be7Sderaadt 		      (errno == ENOENT && (st & TTY_ON) == 0)))
204df930be7Sderaadt 			rval = 1;
20546f3f978Sderaadt 		if (vflag)
206df930be7Sderaadt 			warn("open %s", path);
207df930be7Sderaadt 		return (rval);
208df930be7Sderaadt 	}
20946f3f978Sderaadt 	if (print == 0) {
210df930be7Sderaadt 		if (ioctl(fd, TIOCSFLAGS, &flags) == -1)
211df930be7Sderaadt 			if (errno != ENOTTY || vflag) {
212df930be7Sderaadt 				warn("TIOCSFLAGS on %s", path);
213df930be7Sderaadt 				rval = (errno != ENOTTY);
214df930be7Sderaadt 			}
21546f3f978Sderaadt 	} else {
21646f3f978Sderaadt 		if (ioctl(fd, TIOCGFLAGS, &flags) == -1)
21746f3f978Sderaadt 			if (errno != ENOTTY || vflag) {
218c8b72154Stholo 				warn("TIOCGFLAGS on %s", path);
21946f3f978Sderaadt 				rval = (errno != ENOTTY);
22046f3f978Sderaadt 			}
22146f3f978Sderaadt 		if (flags & TIOCFLAG_CLOCAL) {
222df6be55dSderaadt 			(void)strlcat(strflags, "local", sizeof strflags);
22346f3f978Sderaadt 			sep++;
22446f3f978Sderaadt 		}
22546f3f978Sderaadt 		if (flags & TIOCFLAG_CRTSCTS) {
22646f3f978Sderaadt 			if (sep++)
227df6be55dSderaadt 				(void)strlcat(strflags, "|", sizeof strflags);
228df6be55dSderaadt 			(void)strlcat(strflags, "rtscts", sizeof strflags);
22946f3f978Sderaadt 		}
23046f3f978Sderaadt 		if (flags & TIOCFLAG_SOFTCAR) {
23146f3f978Sderaadt 			if (sep++)
232df6be55dSderaadt 				(void)strlcat(strflags, "|", sizeof strflags);
233df6be55dSderaadt 			(void)strlcat(strflags, "softcar", sizeof strflags);
23446f3f978Sderaadt 		}
23546f3f978Sderaadt 		if (flags & TIOCFLAG_MDMBUF) {
23646f3f978Sderaadt 			if (sep++)
237df6be55dSderaadt 				(void)strlcat(strflags, "|", sizeof strflags);
238df6be55dSderaadt 			(void)strlcat(strflags, "mdmbuf", sizeof strflags);
23946f3f978Sderaadt 		}
24046f3f978Sderaadt 		printf("%s flags are: %s\n", path, strflags);
24146f3f978Sderaadt 	}
242df930be7Sderaadt 	if (close(fd) == -1) {
243df930be7Sderaadt 		warn("close %s", path);
244df930be7Sderaadt 		return (1);
245df930be7Sderaadt 	}
246df930be7Sderaadt 	return (rval);
247df930be7Sderaadt }
248df930be7Sderaadt 
249df930be7Sderaadt /*
250df930be7Sderaadt  * Print usage information when a bogus set of arguments is given.
251df930be7Sderaadt  */
252df930be7Sderaadt void
usage(void)253bc52e260Sderaadt usage(void)
254df930be7Sderaadt {
2551410e271Sjmc 	(void)fprintf(stderr, "usage: ttyflags [-pv] [-a | tty ...]\n");
256df930be7Sderaadt 	exit(1);
257df930be7Sderaadt }
258