Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP Path: utzoo!watmath!clyde!cbosgd!gatech!seismo!ut-sally!std-unix From: std-unix@ut-sally.UUCP (Moderator, John Quarterman) Newsgroups: mod.std.unix Subject: Re: limits Message-ID: <3624@ut-sally.UUCP> Date: Fri, 22-Nov-85 12:21:39 EST Article-I.D.: ut-sally.3624 Posted: Fri Nov 22 12:21:39 1985 Date-Received: Sun, 24-Nov-85 05:30:54 EST References: <3575@ut-sally.UUCP> <3598@ut-sally.UUCP> Organization: IEEE/P1003 Portable Operating System Environment Committee Lines: 318 Approved: jsq@ut-sally.UUCP Date: Fri, 22 Nov 85 04:15:24 est From: seismo!hadron!jsdy (Joseph S. D. Yao) One person suggested that having separate and /etc/limits files might lead to inconsistency. True. But it was a deliberate (and, i apologise, unspoken) design decision that reading limits.h implied knowing too much about the machine -- such as how long are longs, what byte order are ints vs longs vs ... (not to mention floats, which I completely ignore below, and which I shouldn't!), and so forth. Reading a separate file gives me the freedom to read an n-ary list of ints, formatted God Alone knows how, which I can convert at my leisure to whatever I want. Nevertheless, we aim to please, and I made the minor mods to limits.c to make limits2.c, designed to read a single int or long int from a define line. As I said, I completely ignored floats, which in a working program is unforgivable. But the person who wants to read in floats may send me (readable!) code to do so PORTABLY. The following is a compressed context diff. *** limits.c Sat Nov 16 15:08:15 1985 --- limits2.c Fri Nov 22 00:00:00 1985 *************** *** 66,73 ** void endlimits() ! ** static int getnum(str) ** ** Declared: ! ** static char limfile[] = "/etc/limits" ! ** static char *curlimfile = limfile ! ** static FILE *limf = (FILE *) NULL ** --- 66,75 ----- ** void endlimits() ! ** static int getnum(str, buf, n) ! ** static int getnbits() ** ** Declared: ! ** static char defn[] = "#define" ! ** static char limfile[] = "/etc/limits" ! ** static char *curlimfile = limfile ! ** static FILE *limf = (FILE *) NULL ** *************** *** 136,138 #define NL '\n' ! #define COMMENT '#' #define COMMA ',' --- 138,141 ----- #define NL '\n' ! #define COMM1 '/' ! #define COMM2 '*' #define COMMA ',' *************** *** 141,145 ! static char limfile[] = "/etc/limits"; ! static char *curlimfile = limfile; ! static FILE *limf = (FILE *) NULL; --- 144,158 ----- + #ifdef EBUG + #define WDPLG 2 + # else + #define WDPLG (sizeof(long int)/sizeof(int)) + #endif EBUG + + typedef char byte; /* Very small signed value */ + + static char defn[] = "#define"; ! static char limfile[] = "/etc/limits"; ! static char *curlimfile = limfile; ! static FILE *limf = (FILE *) NULL; *************** *** 200,201 register int n; bool been_here; --- 212,214 ----- register int n; + register int defnlen = strlen(defn); bool been_here; *************** *** 204,205 off_t current; extern char *index(); --- 213,219 ----- off_t current; + int getnum(); extern char *index(); *************** *** 225,240 if (new_line && ! /* and not a comment line */ ! *cp != COMMENT && ! /* and not a continuation line */ ! !isspace(*cp) && ! /* and the limit name is first */ ! strneq(cp, name, n) && ! /* followed by white space */ ! isspace(cp[n])) ! break; /* go handle it. */ /* Check whether a NL terminated the read. */ --- 243,259 ----- if (new_line && ! /* and starts with "#define" */ ! strneq(cp, defn, defnlen)) { + /* Skip over defn */ + cp += defnlen; + while (isspace(*cp)) + ++cp; + + /* If the limit name is first */ + if (strneq(cp, name, n) && + /* followed by white space */ + isspace(cp[n])) + break; /* go handle it. */ + } + /* Check whether a NL terminated the read. */ *************** *** 269,334 cp += n + 1; - n = 0; - /* Check whether a NL terminated the read. */ - new_line = (index(cp, NL) != (char *) NULL); /* ! ** Our value may be preceded by whitespace, and is ended ! ** by a comma or whitespace or comment or EOL. */ for ever { ! /* Skip any initial white space. */ ! while (isspace(*cp)) ++cp; ! ! /* Check whether line is done. */ ! if (*cp == COMMENT || *cp == NUL) { ! /* Save current position */ ! current = ftell(limf); ! /* Get new line. */ ! cp = fgets(inbuf, sizeof(inbuf), limf); ! /* If EOF, do it over again at loc 0. */ ! if (cp == (char *) NULL) { ! (void) fseek(limf, (off_t) 0L, 0); ! current = (off_t) 0L; ! cp = fgets(inbuf, sizeof(inbuf), limf); ! /* There has to be data here. */ ! if (cp == (char *) NULL) { ! /* "never happen" */ ! break; ! } ! } ! ! /* ! ** If new line is start of line but no white ! ** space, go back to start of line and return. ! */ ! if (!new_line || !isspace(*cp)) { ! (void) fseek(limf, current, 0); ! break; ! } ! ! /* Check whether a NL terminated the read. */ ! new_line = (index(cp, NL) != (char *) NULL); ! ! continue; ! } ! ! /* If it can fit, store the present value. */ ! if (n < length) ! buf[n] = getnum(cp); ! ! /* Count another value. */ ! ++n; ! ! /* ! ** We want to break but not skip on space, COMMENT, and ! ** NUL. We want to skip and break on COMMA. We want ! ** just to skip over everything else. ! */ ! while (!isspace(*cp) && *cp != COMMENT && *cp != NUL && ! *cp++ != COMMA); } ! /* Return the number of values found. */ ! return(n); } --- 288,312 ----- cp += n + 1; /* ! ** Our value may be preceded by whitespace, or a comment. */ for ever { ! if (isspace(*cp)) ++cp; ! else if (*cp == COMM1 && cp[1] == COMM2) { ! cp += 2; ! while (*cp != NUL) { ! if (*cp++ != COMM2) ! continue; ! if (*cp == COMM1) { ! ++cp; ! break; ! } ! } ! } else ! break; } ! /* Return the size (number of ints) of values found. */ ! return(getnum(cp, buf, length)); } *************** *** 351,361 ** used because it doesn't allow different bases, and for the ! ** sake of consistency. */ ! static int getnum(str) ! register char *str; { register int base = 10; ! register int i = 0, digit; ! register int sign = 1; while (isspace(*str) || *str == PLUS || *str == MINUS) { --- 329,351 ----- ** used because it doesn't allow different bases, and for the ! ** sake of consistency. Postfix 'L' or 'l' indicates long. ! ** ! ** As long as we're reading in only one (variably sized) value, ! ** we'll also take on the task of storing it. */ ! static int getnum(str, buf, n) ! register char *str; /* String containing number */ ! int *buf; /* Address of int storage array */ ! int n; /* Length of storage array */ { register int base = 10; ! register int j, digit; ! register long int i = 0; ! byte sign = 1; ! bool is_long = FALSE; ! static int nbits = 0; + /* If no room to store, don't bother. */ + if (n <= 0) + return(0); + while (isspace(*str) || *str == PLUS || *str == MINUS) { *************** *** 430,432 break; default: break; --- 420,427 ----- break; + case 'L': /* Not a digit -- "long" indicator. */ + case 'l': + is_long = TRUE; + break; + default: break; *************** *** 442,445 if (sign < 0) ! return(-i); ! return(i); } --- 433,470 ----- if (sign < 0) ! i = -i; ! ! buf[0] = i; ! ! if (!is_long) /* Value wasn't really long. */ ! return(1); ! ! if (nbits == 0) /* Figure out #bits/int */ ! nbits = getnbits(); ! ! if (n > WDPLG) /* Return only long, at most. */ ! n = WDPLG; ! ! for (j = 1; j < n; j++) { ! i >>= nbits; ! *++buf = i; ! } ! ! return(n); ! } ! ! static int getnbits() ! { ! register int i, n; ! ! #ifdef EBUG ! return(16); ! #endif EBUG ! n = 0; ! for (i = 1; i != 0; i <<= 1) ! ++n; ! return(n); } Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP} Volume-Number: Volume 3, Number 34