X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/59e0d9fe772464b93d835d2a2964457702469a43..aa54d2fad3d9038b43475aa93c76795c5141a993:/gen/getttyent.c diff --git a/gen/getttyent.c b/gen/getttyent.c index 21f5096..50acdd1 100644 --- a/gen/getttyent.c +++ b/gen/getttyent.c @@ -1,10 +1,8 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -55,12 +53,18 @@ * SUCH DAMAGE. */ +#include "xlocale_private.h" #include #include #include #include #include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" static char zapchar; static FILE *tf; @@ -72,22 +76,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 const char *brapat = "\\[(.*)]"; +static regex_t brapreg; +static const char *decpat = "^([0-9]+)-([0-9]+)$"; +static regex_t decpreg; +static const 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() +getttyent(void) { static struct ttyent tty; + static const 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); @@ -97,6 +140,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 (struct ttyent *)&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); @@ -106,7 +179,7 @@ getttyent() ; continue; } - while (isspace(*p)) + while (isspace_l(*p, loc)) ++p; if (*p && *p != '#') break; @@ -129,8 +202,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; @@ -144,7 +218,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; } @@ -154,8 +232,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 = (int)(e - b + 1); + seq->index = (int)(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); } @@ -211,10 +345,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); } @@ -231,3 +388,5 @@ endttyent() } return (1); } +#pragma clang diagnostic pop +