Remove some unnecessary inclusions of <sys/cdefs.h> across the tree.
[dragonfly.git] / lib / libc / gen / getttyent.c
1 /*
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $FreeBSD: src/lib/libc/gen/getttyent.c,v 1.13 2005/07/25 17:57:15 mdodd Exp $
34  *
35  * @(#)getttyent.c      8.1 (Berkeley) 6/4/93
36  */
37
38 #include <ttyent.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <string.h>
43 #include <dirent.h>
44 #include <paths.h>
45
46 static char zapchar;
47 static FILE *tf;
48 static int maxpts = -1;
49 static int curpts = 0;
50 static size_t lbsize;
51 static char *line;
52
53 #define PTS     "pts/"
54 #define MALLOCCHUNK     100
55
56 static char *skip (char *);
57 static char *value (char *);
58
59 struct ttyent *
60 getttynam(const char *tty)
61 {
62         struct ttyent *t;
63
64         if (strncmp(tty, "/dev/", 5) == 0)
65                 tty += 5;
66         setttyent();
67         while ( (t = getttyent()) )
68                 if (!strcmp(tty, t->ty_name))
69                         break;
70         endttyent();
71         return (t);
72 }
73
74 struct ttyent *
75 getttyent(void)
76 {
77         static struct ttyent tty;
78         static char devpts_name[] = "pts/9999999999";
79         char *p;
80         int c;
81         size_t i;
82
83         if (!tf && !setttyent())
84                 return (NULL);
85         for (;;) {
86                 if (!fgets(p = line, lbsize, tf)) {
87                         if (curpts <= maxpts) {
88                                 sprintf(devpts_name, "pts/%d", curpts++);
89                                 tty.ty_name = devpts_name;
90                                 tty.ty_getty = NULL;
91                                 tty.ty_type = NULL;
92                                 tty.ty_status = TTY_NETWORK;
93                                 tty.ty_window = NULL;
94                                 tty.ty_comment = NULL;
95                                 tty.ty_group = _TTYS_NOGROUP;
96                                 return (&tty);
97                         }
98                         return (NULL);
99                 }
100                 /* extend buffer if line was too big, and retry */
101                 while (!index(p, '\n') && !feof(tf)) {
102                         i = strlen(p);
103                         lbsize += MALLOCCHUNK;
104                         if ((p = realloc(line, lbsize)) == NULL) {
105                                 endttyent();
106                                 return (NULL);
107                         }
108                         line = p;
109                         if (!fgets(&line[i], lbsize - i, tf))
110                                 return (NULL);
111                 }
112                 while (isspace((unsigned char)*p))
113                         ++p;
114                 if (*p && *p != '#')
115                         break;
116         }
117
118 #define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace((unsigned char)p[sizeof(e) - 1])
119 #define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
120
121         zapchar = 0;
122         tty.ty_name = p;
123         tty.ty_status = 0;
124         tty.ty_window = NULL;
125         tty.ty_group  = _TTYS_NOGROUP;
126
127         p = skip(p);
128         if (!*(tty.ty_getty = p))
129                 tty.ty_getty = tty.ty_type = NULL;
130         else {
131                 p = skip(p);
132                 if (!*(tty.ty_type = p))
133                         tty.ty_type = NULL;
134                 else {
135                         /* compatibility kludge: handle network/dialup specially */
136                         if (scmp(_TTYS_DIALUP))
137                                 tty.ty_status |= TTY_DIALUP;
138                         else if (scmp(_TTYS_NETWORK))
139                                 tty.ty_status |= TTY_NETWORK;
140                         p = skip(p);
141                 }
142         }
143
144         for (; *p; p = skip(p)) {
145                 if (scmp(_TTYS_OFF))
146                         tty.ty_status &= ~TTY_ON;
147                 else if (scmp(_TTYS_ON))
148                         tty.ty_status |= TTY_ON;
149                 else if (scmp(_TTYS_SECURE))
150                         tty.ty_status |= TTY_SECURE;
151                 else if (scmp(_TTYS_INSECURE))
152                         tty.ty_status &= ~TTY_SECURE;
153                 else if (scmp(_TTYS_DIALUP))
154                         tty.ty_status |= TTY_DIALUP;
155                 else if (scmp(_TTYS_NETWORK))
156                         tty.ty_status |= TTY_NETWORK;
157                 else if (vcmp(_TTYS_WINDOW))
158                         tty.ty_window = value(p);
159                 else if (vcmp(_TTYS_GROUP))
160                         tty.ty_group = value(p);
161                 else
162                         break;
163         }
164
165         if (zapchar == '#' || *p == '#')
166                 while ((c = *++p) == ' ' || c == '\t')
167                         ;
168         tty.ty_comment = p;
169         if (*p == 0)
170                 tty.ty_comment = 0;
171         if ( (p = index(p, '\n')) )
172                 *p = '\0';
173         return (&tty);
174 }
175
176 #define QUOTED  1
177
178 /*
179  * Skip over the current field, removing quotes, and return a pointer to
180  * the next field.
181  */
182 static char *
183 skip(char *p)
184 {
185         char *t;
186         int c, q;
187
188         for (q = 0, t = p; (c = *p) != '\0'; p++) {
189                 if (c == '"') {
190                         q ^= QUOTED;    /* obscure, but nice */
191                         continue;
192                 }
193                 if (q == QUOTED && *p == '\\' && *(p+1) == '"')
194                         p++;
195                 *t++ = *p;
196                 if (q == QUOTED)
197                         continue;
198                 if (c == '#') {
199                         zapchar = c;
200                         *p = 0;
201                         break;
202                 }
203                 if (c == '\t' || c == ' ' || c == '\n') {
204                         zapchar = c;
205                         *p++ = 0;
206                         while ((c = *p) == '\t' || c == ' ' || c == '\n')
207                                 p++;
208                         break;
209                 }
210         }
211         *--t = '\0';
212         return (p);
213 }
214
215 static char *
216 value(char *p)
217 {
218
219         return ((p = index(p, '=')) ? ++p : NULL);
220 }
221
222 int
223 setttyent(void)
224 {
225         DIR *devpts_dir;
226         struct dirent *dp;
227         int unit;
228
229         if (line == NULL) {
230                 if ((line = malloc(MALLOCCHUNK)) == NULL)
231                         return (0);
232                 lbsize = MALLOCCHUNK;
233         }
234         devpts_dir = opendir(_PATH_DEV PTS);
235         if (devpts_dir) {
236                 maxpts = -1;
237                 while ((dp = readdir(devpts_dir))) {
238                         if (strcmp(dp->d_name, ".") == 0 ||
239                             strcmp(dp->d_name, "..") == 0)
240                                 continue;
241
242                         unit = (int)strtol(dp->d_name, NULL, 10);
243
244                         if (unit > maxpts) {
245                                 maxpts = unit;
246                                 curpts = 0;
247                         }
248                 }
249                 closedir(devpts_dir);
250         }
251         if (tf) {
252                 rewind(tf);
253                 return (1);
254         } else if ( (tf = fopen(_PATH_TTYS, "r")) )
255                 return (1);
256         return (0);
257 }
258
259 int
260 endttyent(void)
261 {
262         int rval;
263
264         maxpts = -1;
265         /*
266          * NB: Don't free `line' because getttynam()
267          * may still be referencing it
268          */
269         if (tf) {
270                 rval = (fclose(tf) != EOF);
271                 tf = NULL;
272                 return (rval);
273         }
274         return (1);
275 }
276
277 static int
278 isttystat(const char *tty, int flag)
279 {
280         struct ttyent *t;
281
282         return ((t = getttynam(tty)) == NULL) ? 0 : !!(t->ty_status & flag);
283 }
284
285
286 int
287 isdialuptty(const char *tty)
288 {
289
290         return isttystat(tty, TTY_DIALUP);
291 }
292
293 int
294 isnettty(const char *tty)
295 {
296
297         return isttystat(tty, TTY_NETWORK);
298 }