home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / std_unix / mod.std.unix.v3 / text0023.txt < prev    next >
Encoding:
Text File  |  1987-06-30  |  10.9 KB  |  468 lines

  1. [ Everybody talks about it, but this one did something about it.  -mod ]
  2.  
  3. Date: Sat, 16 Nov 85 15:11:46 est
  4. From: seismo!hadron!jsdy (Joseph S. D. Yao)
  5.  
  6. Reading in limits on a per-machine basis is a good idea.
  7. However, the idea of reading in a struct or using a numerical
  8. ID for limits both constrain expandability.  I also have
  9. problems with reading directly from limits.h.  Let's do it
  10. from a file like /etc/limits.
  11.  
  12. By the way -- one person said that define'd limits were needed
  13. for #if expressions in code.  What about if () expressions?  The
  14. only case in which the former couldn't be handled by the latter is
  15. in the case that you are really squeezed for core.  ("main memory"
  16. to all you young whippersnappers.)
  17.  
  18. /* #include <local.h> */
  19.  
  20. /*********************************************************************\
  21. **
  22. ** limits -- read limits from the limits file.
  23. **
  24. ** Copyright and disclaimers:
  25. **    This code is Copyright (c) 1985 by one or more of:
  26. **        The author named below;
  27. **        The author's institution named below;
  28. **        (No institution paid for this code, so that's it).
  29. **    Permission is hereby granted to use or copy this code, in
  30. **    whole or in part, only under the conditions that this copyright
  31. **    notice (including other portions of this header comment and
  32. **    code herein referenced) are retained with all parts of this
  33. **    code; that all changes or corrections to this code be fully
  34. **    annotated in the code and notification of such be sent to
  35. **    the author and authors institution; and that this code not
  36. **    specifically be used for profit (although it may be included
  37. **    to enhance a larger work which would otherwise have still
  38. **    been used for profit).
  39. **
  40. ** Syntax:
  41. **    setlimits(filename)
  42. **      char *filename;
  43. **    getlimit(name, buf, length)
  44. **      char *name;    int buf[], length;
  45. **    endlimits()
  46. **
  47. ** Description:
  48. **    This is an implementation of the suggested code to read the
  49. **    per-machine limits from a limits file.  It assumes a file of
  50. **    the format:
  51. **        limit-name    limit-value[, limit_value ... ]
  52. **    e.g.:
  53. **        char_bit    8
  54. **        char_min    -128
  55. **        char_max    128
  56. **    etc.  Lines that start with '#' are assumed to be comment
  57. **    lines.  Lines that start with white space are assumed to
  58. **    be continuation lines.
  59. **
  60. **    Setlimits() returns SUCCESS if the file whose name is passed
  61. **    is readable, FAILURE if not.  On a SUCCESS return, the file is
  62. **    set but not opened.  A NULL argument returns to the original
  63. **    file name.  Getlimit() returns FAILURE if no value, otherwise
  64. **    the number of values available.  (May be > length.)
  65. **    Endlimits() closes the limits file, if open.  No value is
  66. **    returned.
  67. **
  68. #ifdef    SCCS
  69. ** Last modifed %G% %U%.  Last retrieved %H% %T%.
  70. #endif    SCCS
  71. **
  72. ** Author:
  73. **    Joseph S. D. Yao
  74. **    Engineering and Information Sciences Division
  75. **    Hadron, Inc.
  76. **    9990 Lee Highway
  77. **    Fairfax VA   22030
  78. **    (703) 359-6163
  79. **
  80. ** Routines:
  81. **    int setlimits(filename)
  82. **    int getlimit(name, buf, length)
  83. **    void endlimits()
  84. **    static int getnum(str)
  85. **
  86. ** Declared:
  87. **    static char limfile[] = "/etc/limits"
  88. **    static char *curlimfile = limfile
  89. **    static FILE *limf = (FILE *) NULL
  90. **
  91. \*********************************************************************/
  92.  
  93. #ifndef    lint
  94. # ifdef SCCS
  95.   static char SCCS_id[] = "%W%";
  96. #  else
  97.   static char RCS_id[] =
  98.     "@(#)$Header:$";
  99. # endif    SCCS
  100. #endif    lint
  101.  
  102. #include <stdio.h>
  103. #include <ctype.h>
  104. #ifdef    limits
  105. # include <limits.h>
  106. #endif    limits
  107. #include <sys/types.h>
  108.  
  109. /* #include "std.h" */
  110. #define TRUE    1
  111. #define FALSE    0
  112.  
  113. #define SUCCESS    0
  114. #define FAILURE    (-1)
  115.  
  116. #define NUL    '\0'
  117.  
  118. #define STDIN    0
  119. #define STDOUT    1
  120. #define STDERR    2
  121.  
  122. #define ROPEN    0
  123. #define WOPEN    1
  124. #define RWOPEN    2
  125. #define XOPEN    3
  126. #define RXOPEN    4
  127. #define WXOPEN    5
  128. #define RWXOPEN    6
  129.  
  130. #define READ    "r"
  131. #define WRITE    "w"
  132. #define APPEND    "a"
  133. #define WREAD    "r+"
  134. #define RWRITE    "w+"
  135. #define RAPPEND    "a+"
  136.  
  137. #define F_ACC    00
  138. #define X_ACC    01
  139. #define W_ACC    02
  140. #define R_ACC    04
  141.  
  142. #define ever        (;;)
  143. #define until(x)    while (!(x))
  144. #define unless(x)    if (!(x))
  145.  
  146. #define streq(a,b)    (strcmp(a, b) == 0)
  147. #define strneq(a,b,n)    (strncmp(a, b, n) == 0)
  148.  
  149. typedef char bool;    /* Smallest data object */
  150. typedef int boolean;    /* Function argument and return. */
  151. /**/
  152.  
  153. #define NL    '\n'
  154. #define COMMENT    '#'
  155. #define COMMA    ','
  156. #define PLUS    '+'
  157. #define MINUS    '-'
  158.  
  159. static char limfile[] = "/etc/limits";
  160. static char *curlimfile = limfile;
  161.  
  162. static FILE *limf = (FILE *) NULL;
  163.  
  164. /*
  165. ** Setlimits() returns SUCCESS if the file whose name is passed
  166. ** is readable, FAILURE if not.  On a SUCCESS return, the file is
  167. ** set but not opened.  A NULL argument returns to the original
  168. ** file name, whether or not the original file is readable.
  169. ** Note that a non-NULL filename must not disappear (e.g., be
  170. ** reclaimed on the stack, free'd, or written over) before it
  171. ** is opened in getlimit()!
  172. */
  173. int setlimits(filename)
  174.   char *filename;    /* NULL or the name of the new limits file. */
  175. {
  176.     void endlimits();
  177.  
  178.     /* If name is NULL, go to the original. */
  179.     if (filename == (char *) NULL) {
  180.         if (limf != NULL)
  181.             endlimits();
  182.         curlimfile = limfile;
  183.         return(SUCCESS);
  184.     }
  185.  
  186.     /* If new file can't be read, forget it. */
  187.     if (access(filename, R_ACC) < 0)
  188.         return(FAILURE);
  189.  
  190.     /* Close old open file. */
  191.     if (limf != NULL)
  192.         endlimits();
  193.     /* And use new one. */
  194.     curlimfile = filename;
  195.     return(SUCCESS);
  196. }
  197.  
  198. /*
  199. ** Getlimit() returns FAILURE if no value, otherwise the number
  200. ** of values available.  The number of values may be > 'length';
  201. ** but the number stored into buf[] will never be.
  202. ** Note that the result is always returned as a number of integers.
  203. ** It is up to the calling program to put them together into longs,
  204. ** complexes, etc. or decompose them into chars, bitfields, or
  205. ** whatever.
  206. **
  207. ** The search starts from wherever it left off, which improves
  208. ** performance if names are called in order from the file.
  209. ** (Say, alphabetical order.)
  210. */
  211. int getlimit(name, buf, length)
  212.   char *name;    /* Name of the limit wanted. */
  213.   int buf[];    /* Pointer to the array of int's for these values. */
  214.   int length;
  215. {
  216.     register char *cp;
  217.     register int n;
  218.     bool been_here;
  219.     bool new_line;
  220.     char inbuf[BUFSIZ];
  221.     off_t current;
  222.     extern char *index();
  223.  
  224.     /* If not open, open it. */
  225.     if (limf == (FILE *) NULL)
  226.         limf = fopen(curlimfile, READ);
  227.  
  228.     /* If still not open, kick it in. */
  229.     if (limf == (FILE *) NULL)
  230.         return(FAILURE);
  231.  
  232.     n = strlen(name);
  233.     /* Find where we currently are in the file. */
  234.     current = ftell(limf);
  235.     /* Initialise boolean values. */
  236.     new_line = TRUE;
  237.     been_here = FALSE;
  238.  
  239.     /* Search, starting wherever we left off. */
  240.     for ever {
  241.         /* Get a line from the file */
  242.         cp = fgets(inbuf, sizeof(inbuf), limf);
  243.         if (cp != (char *) NULL) {
  244.  
  245.             /* If gotten, test: if start of line */
  246.             if (new_line &&
  247.                 /* and not a comment line */
  248.                 *cp != COMMENT &&
  249.                 /* and not a continuation line */
  250.                 !isspace(*cp) &&
  251.                 /* and the limit name is first */
  252.                 strneq(cp, name, n) &&
  253.                 /* followed by white space */
  254.                 isspace(cp[n]))
  255.                 break;    /* go handle it. */
  256.  
  257.             /* Check whether a NL terminated the read. */
  258.             new_line = (index(cp, NL) != (char *) NULL);
  259.         } else {
  260.             /* If not gotten, re-cycle. */
  261.  
  262.             /*
  263.             ** Make sure the file doesn't get changed
  264.             ** and cause an infinite loop here.
  265.             */
  266.             if (been_here)
  267.                 return(FAILURE);
  268.             been_here = TRUE;
  269.  
  270.             /* Go back. */
  271.             (void) fseek(limf, (off_t) 0L, 0);
  272.             /* Well this starts a new line, no? */
  273.             new_line = TRUE;
  274.         }
  275.  
  276.         /* If we're where we started, we failed. */
  277.         if (current == ftell(limf))
  278.             return(FAILURE);
  279.     }
  280.  
  281.     /*
  282.     ** We only get here if we have a line in inbuf (or the start
  283.     ** of one) that contains the limit name.  Skip over it and
  284.     ** start passing values.
  285.     */
  286.     cp += n + 1;
  287.     n = 0;
  288.     /* Check whether a NL terminated the read. */
  289.     new_line = (index(cp, NL) != (char *) NULL);
  290.  
  291.     /*
  292.     ** Our value may be preceded by whitespace, and is ended
  293.     ** by a comma or whitespace or comment or EOL.
  294.     */
  295.     for ever {
  296.         /* Skip any initial white space. */
  297.         while (isspace(*cp))
  298.             ++cp;
  299.  
  300.         /* Check whether line is done. */
  301.         if (*cp == COMMENT || *cp == NUL) {
  302.             /* Save current position */
  303.             current = ftell(limf);
  304.             /* Get new line. */
  305.             cp = fgets(inbuf, sizeof(inbuf), limf);
  306.             /* If EOF, do it over again at loc 0. */
  307.             if (cp == (char *) NULL) {
  308.                 (void) fseek(limf, (off_t) 0L, 0);
  309.                 current = (off_t) 0L;
  310.                 cp = fgets(inbuf, sizeof(inbuf), limf);
  311.                 /* There has to be data here. */
  312.                 if (cp == (char *) NULL) {
  313.                     /* "never happen" */
  314.                     break;
  315.                 }
  316.             }
  317.  
  318.             /*
  319.             ** If new line is start of line but no white
  320.             ** space, go back to start of line and return.
  321.             */
  322.             if (!new_line || !isspace(*cp)) {
  323.                 (void) fseek(limf, current, 0);
  324.                 break;
  325.             }
  326.  
  327.             /* Check whether a NL terminated the read. */
  328.             new_line = (index(cp, NL) != (char *) NULL);
  329.  
  330.             continue;
  331.         }
  332.  
  333.         /* If it can fit, store the present value. */
  334.         if (n < length)
  335.             buf[n] = getnum(cp);
  336.  
  337.         /* Count another value. */
  338.         ++n;
  339.  
  340.         /*
  341.         ** We want to break but not skip on space, COMMENT, and
  342.         ** NUL.  We want to skip and break on COMMA.  We want
  343.         ** just to skip over everything else.
  344.         */
  345.         while (!isspace(*cp) && *cp != COMMENT && *cp != NUL &&
  346.                *cp++ != COMMA);
  347.     }
  348.  
  349.     /* Return the number of values found. */
  350.     return(n);
  351. }
  352.  
  353. /*
  354. ** Endlimits() closes the limits file, if open.  No value is
  355. ** returned.
  356. */
  357. void endlimits()
  358. {
  359.     if (limf != (FILE *) NULL) {
  360.         (void) fclose(limf);
  361.         limf = (FILE *) NULL;
  362.     }
  363. }
  364.  
  365. /*
  366. ** This routine converts strings to numbers of base specified
  367. ** by 0x or 0 or no prefix.  Signs are allowed.  Atoi() isn't
  368. ** used because it doesn't allow different bases, and for the
  369. ** sake of consistency.
  370. */
  371. static int getnum(str)
  372.   register char *str;
  373. {
  374.     register int base = 10;
  375.     register int i = 0, digit;
  376.     register int sign = 1;
  377.  
  378.     while (isspace(*str) || *str == PLUS || *str == MINUS) {
  379.         if (*str == MINUS)
  380.             sign = -sign;
  381.         ++str;
  382.     }
  383.  
  384.     if (*str == '0') {
  385.         ++str;
  386.         if (*str == 'x') {
  387.             ++str;
  388.             base = 16;
  389.         } else
  390.             base = 8;
  391.     }
  392.  
  393.     /*
  394.     ** As opposed to code that assumes contiguous digits and
  395.     ** letters, the following will work even for (*shudder*)
  396.     ** EBCDIC.  Heck, it'll work for TTS and Baudot!
  397.     */
  398.     for ever {
  399.         digit = -1;
  400.         switch (*str++) {
  401.           case '0':    digit = 0; break;
  402.           case '1':    digit = 1; break;
  403.           case '2':    digit = 2; break;
  404.           case '3':    digit = 3; break;
  405.           case '4':    digit = 4; break;
  406.           case '5':    digit = 5; break;
  407.           case '6':    digit = 6; break;
  408.           case '7':    digit = 7; break;
  409.  
  410.           case '8':    if (base > 8) digit = 8; break;
  411.           case '9':    if (base > 9) digit = 9; break;
  412.  
  413.           case 'A':
  414.           case 'a':
  415.             if (base > 10)
  416.                 digit = 10;
  417.             break;
  418.  
  419.           case 'B':
  420.           case 'b':
  421.             if (base > 11)
  422.                 digit = 11;
  423.             break;
  424.  
  425.           case 'C':
  426.           case 'c':
  427.             if (base > 12)
  428.                 digit = 12;
  429.             break;
  430.  
  431.           case 'D':
  432.           case 'd':
  433.             if (base > 13)
  434.                 digit = 13;
  435.             break;
  436.  
  437.           case 'E':
  438.           case 'e':
  439.             if (base > 14)
  440.                 digit = 14;
  441.             break;
  442.  
  443.           case 'F':
  444.           case 'f':
  445.             if (base > 15)
  446.                 digit = 15;
  447.             break;
  448.  
  449.           default:    break;
  450.         }
  451.  
  452.         if (digit < 0)
  453.             break;
  454.  
  455.         i *= base;
  456.         i += digit;
  457.     }
  458.  
  459.     if (sign < 0)
  460.         return(-i);
  461.     return(i);
  462. }
  463.  
  464.     Joe Yao        hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}
  465.  
  466. Volume-Number: Volume 3, Number 24
  467.  
  468.