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