X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/51631861ddb16afcfcf748cee26c14481549065e..b5d655f7532a546b54809da387f7467d128a756b:/gen/getttyent.c diff --git a/gen/getttyent.c b/gen/getttyent.c index 723077b..def6fa3 100644 --- a/gen/getttyent.c +++ b/gen/getttyent.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -53,12 +53,15 @@ * SUCH DAMAGE. */ +#include "xlocale_private.h" #include #include #include #include #include +#include +#include static char zapchar; static FILE *tf; @@ -70,22 +73,61 @@ getttynam(tty) register struct ttyent *t; setttyent(); - while (t = getttyent()) + while ((t = getttyent()) != NULL) if (!strcmp(tty, t->ty_name)) break; endttyent(); return (t); } +static char *skip(), *value(); + +/* + * 4372480: Support for sequences in the tty name. Expressions like [000-999] + * for decimal sequences and [0x0-0xf] for hexidecimal sequences causes a + * sequence of all combinations of names to be returned by getttyent(). + * + * There is also a slot=nn option, which will cause getttyent() to return + * non-existent ttyent structs until the slot number nn is reached. Note, slot + * numbers begin at 1. + */ +struct seq { + int first; + int count; + int index; + char fmt[NAME_MAX + 17]; +}; + +static char brapat[] = "\\[(.*)]"; +static regex_t brapreg; +static char decpat[] = "^([0-9]+)-([0-9]+)$"; +static regex_t decpreg; +static char hexpat[] = "^0x([0-9a-f]+)-0x([0-9a-f]+)$"; +static regex_t hexpreg; +static struct seq *seq = NULL; +static int slot; + struct ttyent * getttyent() { static struct ttyent tty; + static struct ttyent nonexistent = { + "\01", /* this shouldn't match anything */ + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; register int c; register char *p; #define MAXLINELENGTH 1024 static char *line = NULL; - static char *skip(), *value(); + locale_t loc = __current_locale(); + int newslot, hex; + long b, e; + regmatch_t match[3], save, bracket; if ( line == NULL ) { line = malloc(MAXLINELENGTH); @@ -95,6 +137,36 @@ getttyent() if (!tf && !setttyent()) return (NULL); + +restart: + if (slot < seq->first) { + /* + * the slot= option was set, and we are returning non-existent + * entries until we catch up. + */ + slot++; + return &nonexistent; + } + + if (seq->count > 0) { + /* + * generate the next tty name; the rest of the tty entries + * is the same. + */ + sprintf(tty.ty_name, seq->fmt, seq->index++); + slot++; + seq->count--; + return &tty; + } + + if (slot == seq->first) { + /* + * this was a regular entry with slot= + */ + slot++; + return &tty; + } + for (;;) { if (!fgets(p = line, MAXLINELENGTH, tf)) return (NULL); @@ -104,7 +176,7 @@ getttyent() ; continue; } - while (isspace(*p)) + while (isspace_l(*p, loc)) ++p; if (*p && *p != '#') break; @@ -127,8 +199,9 @@ getttyent() tty.ty_onerror = NULL; tty.ty_onoption = NULL; -#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1]) +#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace_l(p[sizeof(e) - 1], loc) #define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '=' + newslot = -1; for (; *p; p = skip(p)) { if (scmp(_TTYS_OFF)) tty.ty_status &= ~TTY_ON; @@ -142,7 +215,11 @@ getttyent() tty.ty_onerror = value(p); else if (vcmp(_TTYS_ONOPTION)) tty.ty_onoption = value(p); - else + else if (vcmp(_TTYS_SLOT)) { + char *slotstr = value(p); + if (slotstr) + newslot = atoi(slotstr); + } else break; } @@ -152,8 +229,64 @@ getttyent() tty.ty_comment = p; if (*p == 0) tty.ty_comment = 0; - if (p = index(p, '\n')) + if ((p = index(p, '\n')) != NULL) *p = '\0'; + + /* check if tty.tyname has a sequence */ + if (regexec(&brapreg, tty.ty_name, 3, match, 0) != 0) + goto out; + + /* + * save the range of the bracketed range, so we can find the strings + * before and after + */ + bracket = match[0]; + /* use REG_STARTEND to limit matching with the bracketed range */ + match[0] = save = match[1]; + if (regexec(&decpreg, tty.ty_name, 3, match, REG_STARTEND) == 0) { + /* a decimal range */ + b = strtol(tty.ty_name + match[1].rm_so, NULL, 10); + e = strtol(tty.ty_name + match[2].rm_so, NULL, 10); + hex = 0; + } else { + match[0] = save; + if (regexec(&hexpreg, tty.ty_name, 3, match, REG_STARTEND) == 0) { + /* a hexidecimal range */ + b = strtol(tty.ty_name + match[1].rm_so, NULL, 16); + e = strtol(tty.ty_name + match[2].rm_so, NULL, 16); + hex = 1; + } else + goto out; + } + if (b > e) /* skip */ + goto restart; + + /* seq->first is already less than slot, so just leave it */ + seq->count = e - b + 1; + seq->index = b; + /* + * The fmt string contains the characters before the bracket, the + * a format specifier (either decimal or hex) and any characters + * after the bracket. Note that the length of the lower range is + * use as a minimum digit length, with zero fill, so the format + * specifier will look something like %03d. + */ + sprintf(seq->fmt, "%.*s%%0%d%c%s", + (int)bracket.rm_so, tty.ty_name, + (int)(match[1].rm_eo - match[1].rm_so), + hex ? 'x' : 'd', + tty.ty_name + bracket.rm_eo); + +out: + if (newslot > slot) { + /* set up to skip until newslot */ + seq->first = newslot; + goto restart; + } + if (seq->count > 0) /* restart if we are doing a sequence */ + goto restart; + /* regular single value return */ + slot++; return (&tty); } @@ -209,10 +342,33 @@ int setttyent() { + /* initialize seq and the three regexp patterns */ + if (!seq) { + if (regcomp(&brapreg, brapat, REG_EXTENDED) != 0) + return 0; + if (regcomp(&decpreg, decpat, REG_EXTENDED) != 0) { + regfree(&brapreg); + return 0; + } + if (regcomp(&hexpreg, hexpat, REG_EXTENDED | REG_ICASE) != 0) { + regfree(&decpreg); + regfree(&brapreg); + return 0; + } + if ((seq = malloc(sizeof(struct seq))) == NULL) { + regfree(&hexpreg); + regfree(&decpreg); + regfree(&brapreg); + return 0; + } + } + seq->first = seq->count = 0; + slot = 1; + if (tf) { (void)rewind(tf); return (1); - } else if (tf = fopen(_PATH_TTYS, "r")) + } else if ((tf = fopen(_PATH_TTYS, "r")) != NULL) return (1); return (0); }