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