]> git.saurik.com Git - apple/libc.git/blame - gen/getttyent.c
Libc-1244.1.7.tar.gz
[apple/libc.git] / gen / getttyent.c
CommitLineData
e9ce8d39 1/*
224c7076 2 * Copyright (c) 1999, 2005 Apple Computer, Inc. All rights reserved.
e9ce8d39
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
734aad71
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
e9ce8d39
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
734aad71
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
e9ce8d39
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * Copyright (c) 1989, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 */
55
3d9156a7 56#include "xlocale_private.h"
e9ce8d39
A
57
58#include <ttyent.h>
59#include <stdio.h>
60#include <ctype.h>
61#include <string.h>
5b2abdfb 62#include <stdlib.h>
224c7076
A
63#include <regex.h>
64#include <limits.h>
e9ce8d39
A
65
66static char zapchar;
67static FILE *tf;
68
69struct ttyent *
70getttynam(tty)
71 const char *tty;
72{
73 register struct ttyent *t;
74
75 setttyent();
224c7076 76 while ((t = getttyent()) != NULL)
e9ce8d39
A
77 if (!strcmp(tty, t->ty_name))
78 break;
79 endttyent();
80 return (t);
81}
82
3d9156a7
A
83static char *skip(), *value();
84
224c7076
A
85/*
86 * 4372480: Support for sequences in the tty name. Expressions like [000-999]
87 * for decimal sequences and [0x0-0xf] for hexidecimal sequences causes a
88 * sequence of all combinations of names to be returned by getttyent().
89 *
90 * There is also a slot=nn option, which will cause getttyent() to return
91 * non-existent ttyent structs until the slot number nn is reached. Note, slot
92 * numbers begin at 1.
93 */
94struct seq {
95 int first;
96 int count;
97 int index;
98 char fmt[NAME_MAX + 17];
99};
100
6465356a 101static const char *brapat = "\\[(.*)]";
224c7076 102static regex_t brapreg;
6465356a 103static const char *decpat = "^([0-9]+)-([0-9]+)$";
224c7076 104static regex_t decpreg;
6465356a 105static const char *hexpat = "^0x([0-9a-f]+)-0x([0-9a-f]+)$";
224c7076
A
106static regex_t hexpreg;
107static struct seq *seq = NULL;
108static int slot;
109
e9ce8d39 110struct ttyent *
6465356a 111getttyent(void)
e9ce8d39
A
112{
113 static struct ttyent tty;
6465356a 114 static const struct ttyent nonexistent = {
224c7076
A
115 "\01", /* this shouldn't match anything */
116 NULL,
117 NULL,
118 0,
119 NULL,
120 NULL,
121 NULL
122 };
e9ce8d39
A
123 register int c;
124 register char *p;
125#define MAXLINELENGTH 1024
5b2abdfb 126 static char *line = NULL;
3d9156a7 127 locale_t loc = __current_locale();
224c7076
A
128 int newslot, hex;
129 long b, e;
130 regmatch_t match[3], save, bracket;
e9ce8d39 131
5b2abdfb
A
132 if ( line == NULL ) {
133 line = malloc(MAXLINELENGTH);
134 if( line == NULL )
135 return NULL;
136 }
137
e9ce8d39
A
138 if (!tf && !setttyent())
139 return (NULL);
224c7076
A
140
141restart:
142 if (slot < seq->first) {
143 /*
144 * the slot= option was set, and we are returning non-existent
145 * entries until we catch up.
146 */
147 slot++;
6465356a 148 return (struct ttyent *)&nonexistent;
224c7076
A
149 }
150
151 if (seq->count > 0) {
152 /*
153 * generate the next tty name; the rest of the tty entries
154 * is the same.
155 */
156 sprintf(tty.ty_name, seq->fmt, seq->index++);
157 slot++;
158 seq->count--;
159 return &tty;
160 }
161
162 if (slot == seq->first) {
163 /*
164 * this was a regular entry with slot=
165 */
166 slot++;
167 return &tty;
168 }
169
e9ce8d39 170 for (;;) {
5b2abdfb 171 if (!fgets(p = line, MAXLINELENGTH, tf))
e9ce8d39
A
172 return (NULL);
173 /* skip lines that are too big */
174 if (!index(p, '\n')) {
175 while ((c = getc(tf)) != '\n' && c != EOF)
176 ;
177 continue;
178 }
3d9156a7 179 while (isspace_l(*p, loc))
e9ce8d39
A
180 ++p;
181 if (*p && *p != '#')
182 break;
183 }
184
185 zapchar = 0;
186 tty.ty_name = p;
187 p = skip(p);
188 if (!*(tty.ty_getty = p))
189 tty.ty_getty = tty.ty_type = NULL;
190 else {
191 p = skip(p);
192 if (!*(tty.ty_type = p))
193 tty.ty_type = NULL;
194 else
195 p = skip(p);
196 }
197 tty.ty_status = 0;
198 tty.ty_window = NULL;
199 tty.ty_onerror = NULL;
200 tty.ty_onoption = NULL;
201
3d9156a7 202#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace_l(p[sizeof(e) - 1], loc)
e9ce8d39 203#define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
224c7076 204 newslot = -1;
e9ce8d39
A
205 for (; *p; p = skip(p)) {
206 if (scmp(_TTYS_OFF))
207 tty.ty_status &= ~TTY_ON;
208 else if (scmp(_TTYS_ON))
209 tty.ty_status |= TTY_ON;
210 else if (scmp(_TTYS_SECURE))
211 tty.ty_status |= TTY_SECURE;
212 else if (vcmp(_TTYS_WINDOW))
213 tty.ty_window = value(p);
214 else if (vcmp(_TTYS_ONERROR))
215 tty.ty_onerror = value(p);
216 else if (vcmp(_TTYS_ONOPTION))
217 tty.ty_onoption = value(p);
224c7076
A
218 else if (vcmp(_TTYS_SLOT)) {
219 char *slotstr = value(p);
220 if (slotstr)
221 newslot = atoi(slotstr);
222 } else
e9ce8d39
A
223 break;
224 }
225
226 if (zapchar == '#' || *p == '#')
227 while ((c = *++p) == ' ' || c == '\t')
228 ;
229 tty.ty_comment = p;
230 if (*p == 0)
231 tty.ty_comment = 0;
224c7076 232 if ((p = index(p, '\n')) != NULL)
e9ce8d39 233 *p = '\0';
224c7076
A
234
235 /* check if tty.tyname has a sequence */
236 if (regexec(&brapreg, tty.ty_name, 3, match, 0) != 0)
237 goto out;
238
239 /*
240 * save the range of the bracketed range, so we can find the strings
241 * before and after
242 */
243 bracket = match[0];
244 /* use REG_STARTEND to limit matching with the bracketed range */
245 match[0] = save = match[1];
246 if (regexec(&decpreg, tty.ty_name, 3, match, REG_STARTEND) == 0) {
247 /* a decimal range */
248 b = strtol(tty.ty_name + match[1].rm_so, NULL, 10);
249 e = strtol(tty.ty_name + match[2].rm_so, NULL, 10);
250 hex = 0;
251 } else {
252 match[0] = save;
253 if (regexec(&hexpreg, tty.ty_name, 3, match, REG_STARTEND) == 0) {
254 /* a hexidecimal range */
255 b = strtol(tty.ty_name + match[1].rm_so, NULL, 16);
256 e = strtol(tty.ty_name + match[2].rm_so, NULL, 16);
257 hex = 1;
258 } else
259 goto out;
260 }
261 if (b > e) /* skip */
262 goto restart;
263
264 /* seq->first is already less than slot, so just leave it */
b061a43b
A
265 seq->count = (int)(e - b + 1);
266 seq->index = (int)(b);
224c7076
A
267 /*
268 * The fmt string contains the characters before the bracket, the
269 * a format specifier (either decimal or hex) and any characters
270 * after the bracket. Note that the length of the lower range is
271 * use as a minimum digit length, with zero fill, so the format
272 * specifier will look something like %03d.
273 */
274 sprintf(seq->fmt, "%.*s%%0%d%c%s",
275 (int)bracket.rm_so, tty.ty_name,
276 (int)(match[1].rm_eo - match[1].rm_so),
277 hex ? 'x' : 'd',
278 tty.ty_name + bracket.rm_eo);
279
280out:
281 if (newslot > slot) {
282 /* set up to skip until newslot */
283 seq->first = newslot;
284 goto restart;
285 }
286 if (seq->count > 0) /* restart if we are doing a sequence */
287 goto restart;
288 /* regular single value return */
289 slot++;
e9ce8d39
A
290 return (&tty);
291}
292
293#define QUOTED 1
294
295/*
296 * Skip over the current field, removing quotes, and return a pointer to
297 * the next field.
298 */
299static char *
300skip(p)
301 register char *p;
302{
303 register char *t;
304 register int c, q;
305
306 for (q = 0, t = p; (c = *p) != '\0'; p++) {
307 if (c == '"') {
308 q ^= QUOTED; /* obscure, but nice */
309 continue;
310 }
311 if (q == QUOTED && *p == '\\' && *(p+1) == '"')
312 p++;
313 *t++ = *p;
314 if (q == QUOTED)
315 continue;
316 if (c == '#') {
317 zapchar = c;
318 *p = 0;
319 break;
320 }
321 if (c == '\t' || c == ' ' || c == '\n') {
322 zapchar = c;
323 *p++ = 0;
324 while ((c = *p) == '\t' || c == ' ' || c == '\n')
325 p++;
326 break;
327 }
328 }
329 *--t = '\0';
330 return (p);
331}
332
333static char *
334value(p)
335 register char *p;
336{
337
338 return ((p = index(p, '=')) ? ++p : NULL);
339}
340
341int
342setttyent()
343{
344
224c7076
A
345 /* initialize seq and the three regexp patterns */
346 if (!seq) {
347 if (regcomp(&brapreg, brapat, REG_EXTENDED) != 0)
348 return 0;
349 if (regcomp(&decpreg, decpat, REG_EXTENDED) != 0) {
350 regfree(&brapreg);
351 return 0;
352 }
353 if (regcomp(&hexpreg, hexpat, REG_EXTENDED | REG_ICASE) != 0) {
354 regfree(&decpreg);
355 regfree(&brapreg);
356 return 0;
357 }
358 if ((seq = malloc(sizeof(struct seq))) == NULL) {
359 regfree(&hexpreg);
360 regfree(&decpreg);
361 regfree(&brapreg);
362 return 0;
363 }
364 }
365 seq->first = seq->count = 0;
366 slot = 1;
367
e9ce8d39
A
368 if (tf) {
369 (void)rewind(tf);
370 return (1);
224c7076 371 } else if ((tf = fopen(_PATH_TTYS, "r")) != NULL)
e9ce8d39
A
372 return (1);
373 return (0);
374}
375
376int
377endttyent()
378{
379 int rval;
380
381 if (tf) {
382 rval = !(fclose(tf) == EOF);
383 tf = NULL;
384 return (rval);
385 }
386 return (1);
387}