xref: /openbsd/sbin/ttyflags/ttyflags.c (revision db3296cf)
1 /*	$OpenBSD: ttyflags.c,v 1.10 2002/07/03 22:32:34 deraadt 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 #ifndef lint
36 char copyright[] =
37 "@(#) Copyright (c) 1994 Christopher G. Demetriou\n\
38 	All rights reserved.\n";
39 #endif /* not lint */
40 
41 #ifndef lint
42 static char rcsid[] = "$OpenBSD: ttyflags.c,v 1.10 2002/07/03 22:32:34 deraadt Exp $";
43 #endif /* not lint */
44 
45 #include <sys/types.h>
46 #include <sys/cdefs.h>
47 #include <sys/ioctl.h>
48 
49 #include <err.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <limits.h>
53 #include <paths.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <ttyent.h>
58 #include <unistd.h>
59 
60 int all(int);
61 int ttys(char **, int);
62 int ttyflags(struct ttyent *, int);
63 void usage(void);
64 
65 int nflag, vflag;
66 
67 /*
68  * Ttyflags sets the device-specific tty flags, based on the contents
69  * of /etc/ttys.  It can either set all of the ttys' flags, or set
70  * the flags of the ttys specified on the command line.
71  */
72 int
73 main(int argc, char *argv[])
74 {
75 	int aflag, ch, rval, pflag = 0;
76 
77 	aflag = nflag = vflag = 0;
78 	while ((ch = getopt(argc, argv, "panv")) != -1)
79 		switch (ch) {
80 		case 'a':
81 			aflag = 1;
82 			break;
83 		case 'n':		/* undocumented */
84 			nflag = 1;
85 			break;
86 		case 'p':
87 			pflag = 1;
88 			break;
89 		case 'v':
90 			vflag = 1;
91 			break;
92 		case '?':
93 		default:
94 			usage();
95 		}
96 	argc -= optind;
97 	argv += optind;
98 
99 	if (aflag && argc != 0)
100 		usage();
101 
102 	if (setttyent() == 0)
103 		err(1, "setttyent");
104 
105 	if (aflag)
106 		rval = all(pflag);
107 	else
108 		rval = ttys(argv, pflag);
109 
110 	if (endttyent() == 0)
111 		warn("endttyent");
112 
113 	exit(rval);
114 }
115 
116 /*
117  * Change all /etc/ttys entries' flags.
118  */
119 int
120 all(int print)
121 {
122 	struct ttyent *tep;
123 	int rval;
124 
125 	rval = 0;
126 	for (tep = getttyent(); tep != NULL; tep = getttyent())
127 		if (ttyflags(tep, print))
128 			rval = 1;
129 	return (rval);
130 }
131 
132 /*
133  * Change the specified ttys' flags.
134  */
135 int
136 ttys(char **ttylist, int print)
137 {
138 	struct ttyent *tep;
139 	int rval;
140 
141 	rval = 0;
142 	for (; *ttylist != NULL; ttylist++) {
143 		tep = getttynam(*ttylist);
144 		if (tep == NULL) {
145 			warnx("couldn't find an entry in %s for \"%s\"",
146 			    _PATH_TTYS, *ttylist);
147 			rval = 1;
148 			continue;
149 		}
150 
151 		if (ttyflags(tep, print))
152 			rval = 1;
153 	}
154 	return (rval);
155 }
156 
157 
158 /*
159  * Actually do the work; find out what the new flags value should be,
160  * open the device, and change the flags.
161  */
162 int
163 ttyflags(struct ttyent *tep, int print)
164 {
165 	int fd, flags = 0, rval = 0, st, sep = 0;
166 	char path[PATH_MAX];
167 	char strflags[256];
168 
169 	st = tep->ty_status;
170 	strflags[0] = '\0';
171 
172 	/* Find the full device path name. */
173 	(void)snprintf(path, sizeof path, "%s%s", _PATH_DEV, tep->ty_name);
174 
175 	if (print == 0) {
176 		/* Convert ttyent.h flags into ioctl flags. */
177 		if (st & TTY_LOCAL) {
178 			flags |= TIOCFLAG_CLOCAL;
179 			(void)strlcat(strflags, "local", sizeof strflags);
180 			sep++;
181 		}
182 		if (st & TTY_RTSCTS) {
183 			flags |= TIOCFLAG_CRTSCTS;
184 			if (sep++)
185 				(void)strlcat(strflags, "|", sizeof strflags);
186 			(void)strlcat(strflags, "rtscts", sizeof strflags);
187 		}
188 		if (st & TTY_SOFTCAR) {
189 			flags |= TIOCFLAG_SOFTCAR;
190 			if (sep++)
191 				(void)strlcat(strflags, "|", sizeof strflags);
192 			(void)strlcat(strflags, "softcar", sizeof strflags);
193 		}
194 		if (st & TTY_MDMBUF) {
195 			flags |= TIOCFLAG_MDMBUF;
196 			if (sep++)
197 				(void)strlcat(strflags, "|", sizeof strflags);
198 			(void)strlcat(strflags, "mdmbuf", sizeof strflags);
199 		}
200 		if (vflag)
201 			printf("%s setting flags to: %s\n", path, strflags);
202 	}
203 
204 	if (nflag)
205 		return (0);
206 
207 	/* Open the device NON-BLOCKING, set the flags, and close it. */
208 	if ((fd = open(path, O_RDONLY | O_NONBLOCK, 0)) == -1) {
209 		if (!(errno == ENXIO ||
210 		      (errno == ENOENT && (st & TTY_ON) == 0)))
211 			rval = 1;
212 		if (vflag)
213 			warn("open %s", path);
214 		return (rval);
215 	}
216 	if (print == 0) {
217 		if (ioctl(fd, TIOCSFLAGS, &flags) == -1)
218 			if (errno != ENOTTY || vflag) {
219 				warn("TIOCSFLAGS on %s", path);
220 				rval = (errno != ENOTTY);
221 			}
222 	} else {
223 		if (ioctl(fd, TIOCGFLAGS, &flags) == -1)
224 			if (errno != ENOTTY || vflag) {
225 				warn("TIOCGFLAGS on %s", path);
226 				rval = (errno != ENOTTY);
227 			}
228 		if (flags & TIOCFLAG_CLOCAL) {
229 			(void)strlcat(strflags, "local", sizeof strflags);
230 			sep++;
231 		}
232 		if (flags & TIOCFLAG_CRTSCTS) {
233 			if (sep++)
234 				(void)strlcat(strflags, "|", sizeof strflags);
235 			(void)strlcat(strflags, "rtscts", sizeof strflags);
236 		}
237 		if (flags & TIOCFLAG_SOFTCAR) {
238 			if (sep++)
239 				(void)strlcat(strflags, "|", sizeof strflags);
240 			(void)strlcat(strflags, "softcar", sizeof strflags);
241 		}
242 		if (flags & TIOCFLAG_MDMBUF) {
243 			if (sep++)
244 				(void)strlcat(strflags, "|", sizeof strflags);
245 			(void)strlcat(strflags, "mdmbuf", sizeof strflags);
246 		}
247 		printf("%s flags are: %s\n", path, strflags);
248 	}
249 	if (close(fd) == -1) {
250 		warn("close %s", path);
251 		return (1);
252 	}
253 	return (rval);
254 }
255 
256 /*
257  * Print usage information when a bogus set of arguments is given.
258  */
259 void
260 usage(void)
261 {
262 	(void)fprintf(stderr, "usage: ttyflags [-v] [-p] [-a | tty ... ]\n");
263 	exit(1);
264 }
265