home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume6 / sh.ulimit < prev    next >
Text File  |  1986-11-30  |  12KB  |  478 lines

  1. Subject: v06i049:  Add ksh-style 'ulimit' to 4.2BSD /bin/sh (sh.ulimit)
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: seismo!gatech!emory!arnold (Arnold D. Robbins {EUCC})
  6. Mod.sources: Volume 6, Issue 49
  7. Archive-name: sh.ulimit
  8.  
  9. The 4.2 BSD sh does not have any functional equivalent of the csh's 'limit'
  10. built-in command. Below are some patches that provide the "ulimit" builtin,
  11. basically compatible with that implemented in the ksh, which understands the
  12. various BSD resource limits, as well as those available in System V. (Actually,
  13. it is a little different in the output format; but at the time I wrote the code,
  14. I only had ksh doc to go by, and not the ksh to test against. Oh well. 95% now
  15. is better than 100% in two weeks.)
  16.  
  17. *** WARNING: This code has only been minimally tested in the BSD sh!!! ***
  18. It is however, very straightforward, and shouldn't give you too many problems.
  19. I pulled it out of the work I've been doing on the System V Release 2 shell.
  20. (That work is still in progress, and maybe once things settle down with 4.3,
  21. I'll be able to get back to it and post something.) It should be adaptable
  22. to System V shells currently running under 4.2, such as the one in Doug
  23. Gwyn's S5 emulation, and/or the Sun 3.0 shell (if you have source). Sun is
  24. welcome to pick this up and add it in, as it is mostly based on Doug's code,
  25. which is public domain.
  26.  
  27. This posting was motivated by some discussion a while back in net.unix and
  28. net.unix-wizards. I hope it meets a need. (As for those who want job control
  29. for the shell, see the nine part sh posting in volume 1 of mod.sources that I
  30. did last summer. Several parts of that were diffs to the BSD sh, as well as
  31. the S5R2 sh. I am working on that some more too.)
  32.  
  33. Enjoy,
  34.     Arnold Robbins
  35.     CSNET:    arnold@emory    BITNET:    arnold@emoryu1
  36.     ARPA:    arnold%emory.csnet@csnet-relay.arpa
  37.     UUCP:    { akgua, decvax, gatech, sb1, sb6, sunatl }!emory!arnold
  38. -------------------------------------------------------------------------
  39. #! /bin/sh
  40. # This is a shell archive, meaning:
  41. # 1. Remove everything above the #! /bin/sh line.
  42. # 2. Save the resulting text in a file.
  43. # 3. Execute the file with /bin/sh (not csh) to create the files:
  44. #    sh.patch
  45. #    ulimit.c
  46. # This archive created: Mon Jun 30 16:14:11 1986
  47. export PATH; PATH=/bin:$PATH
  48. echo shar: extracting "'sh.patch'" '(6246 characters)'
  49. if test -f 'sh.patch'
  50. then
  51.     echo shar: will not over-write existing file "'sh.patch'"
  52. else
  53. cat << \SHAR_EOF > 'sh.patch'
  54. *** /usr/src/bin/sh/Makefile    Fri Jul  1 06:48:58 1983
  55. --- Makefile    Mon Jun 30 15:47:27 1986
  56. ***************
  57. *** 19,24
  58.   sh:    xec.o service.o error.o io.o
  59.   sh:    print.o macro.o expand.o
  60.   sh:    ctype.o msg.o
  61.   blok.o:        brkincr.h
  62.   fault.o:    brkincr.h
  63.   main.o:        brkincr.h
  64.  
  65. --- 19,25 -----
  66.   sh:    xec.o service.o error.o io.o
  67.   sh:    print.o macro.o expand.o
  68.   sh:    ctype.o msg.o
  69. + sh:    ulimit.o
  70.   blok.o:        brkincr.h
  71.   fault.o:    brkincr.h
  72.   main.o:        brkincr.h
  73. *** /usr/src/bin/sh/defs.h    Sat Jun 11 02:38:06 1983
  74. --- defs.h    Mon Jun 30 15:44:51 1986
  75. ***************
  76. *** 54,59
  77.   #define SYSREAD 17
  78.   #define SYSTST    18
  79.   #define    SYSUMASK    19
  80.   
  81.   /* used for input and output of shell */
  82.   #define INIO 10
  83.  
  84. --- 54,60 -----
  85.   #define SYSREAD 17
  86.   #define SYSTST    18
  87.   #define    SYSUMASK    19
  88. + #define SYSULIMIT    20
  89.   
  90.   /* used for input and output of shell */
  91.   #define INIO 10
  92. ***************
  93. *** 264,269
  94.   MSG        badopt;
  95.   MSG        badparam;
  96.   MSG        badsub;
  97.   MSG        nospace;
  98.   MSG        notfound;
  99.   MSG        badtrap;
  100.  
  101. --- 265,271 -----
  102.   MSG        badopt;
  103.   MSG        badparam;
  104.   MSG        badsub;
  105. + MSG        badulimit;
  106.   MSG        nospace;
  107.   MSG        notfound;
  108.   MSG        badtrap;
  109. *** /usr/src/bin/sh/msg.c    Thu Aug 11 23:21:53 1983
  110. --- msg.c    Mon Jun 30 15:45:24 1986
  111. ***************
  112. *** 26,31
  113.   MSG    badnum        = "bad number";
  114.   MSG    badparam    = "parameter not set";
  115.   MSG    badsub        = "bad substitution";
  116.   MSG    badcreate    = "cannot create";
  117.   MSG    illegal        = "illegal io";
  118.   MSG    restricted    = "restricted";
  119.  
  120. --- 26,32 -----
  121.   MSG    badnum        = "bad number";
  122.   MSG    badparam    = "parameter not set";
  123.   MSG    badsub        = "bad substitution";
  124. + MSG badulimit    = "bad ulimit";
  125.   MSG    badcreate    = "cannot create";
  126.   MSG    illegal        = "illegal io";
  127.   MSG    restricted    = "restricted";
  128. ***************
  129. *** 135,139
  130.           {"exec",    SYSEXEC},
  131.           {"times",    SYSTIMES},
  132.           {"umask",    SYSUMASK},
  133.           {0,    0},
  134.   };
  135.  
  136. --- 136,141 -----
  137.           {"exec",    SYSEXEC},
  138.           {"times",    SYSTIMES},
  139.           {"umask",    SYSUMASK},
  140. +         {"ulimit",    SYSULIMIT},
  141.           {0,    0},
  142.   };
  143. *** /usr/src/bin/sh/xec.c    Thu Aug 11 23:21:56 1983
  144. --- xec.c    Mon Jun 30 16:07:08 1986
  145. ***************
  146. *** 222,227
  147.                                           }
  148.                                           break;
  149.       
  150.                   default:
  151.                       internal=builtin(argn,com);
  152.       
  153.  
  154. --- 222,305 -----
  155.                                           }
  156.                                           break;
  157.       
  158. +                     case SYSULIMIT:    
  159. +                     {    
  160. +                         long int i;    
  161. +                         long ulimit();    
  162. +                         int command = 2;    
  163. +         
  164. +                         if (*a1 == '-')    
  165. +                         {
  166. +                             switch(*(a1+1))    {    
  167. +                             case 'f':    
  168. +                                 command = 2;    
  169. +                                 break;    
  170. +         
  171. + #ifdef rt    
  172. +                             case 'p':    
  173. +                                 command = 5;    
  174. +                                 break;    
  175. +         
  176. + #endif    
  177. +                             case 'c':
  178. +                                 command = 7;
  179. +                                 break;
  180. +                             case 'd':
  181. +                                 command = 9;
  182. +                                 break;
  183. +                             case 'm':
  184. +                                 command = 11;
  185. +                                 break;
  186. +                             case 't':
  187. +                                 command = 13;
  188. +                                 break;
  189. +                             default:    
  190. +                                 error(badopt);    
  191. +                             }    
  192. +                             a1 = com[2];    
  193. +                         }    
  194. +                         if (a1)    
  195. +                         {    
  196. +                             int c;    
  197. +                             i = 0;    
  198. +                             while ((c = *a1++) >= '0' && c <= '9')    
  199. +                             {    
  200. +                                 i = (i * 10) + (long)(c - '0');    
  201. +                                 if (i < 0)    
  202. +                                     error(badulimit);    
  203. +                             }    
  204. +                             if (c || i < 0)    
  205. +                                     error(badulimit);    
  206. +                         }    
  207. +                         else    
  208. +                         {    
  209. +                             i = -1;    
  210. +                             command--;    
  211. +                         }    
  212. +                                     
  213. +                         if ((i = ulimit(command,i)) < 0)    
  214. +                                 error(badulimit);    
  215. +         
  216. +                         switch (command) {    
  217. +                         case 1:
  218. + #ifdef rt
  219. +                         case 4:
  220. + #endif
  221. +                         case 6:
  222. +                         case 8:
  223. +                         case 10:
  224. +                         case 12:
  225. +                             prl(i);    
  226. +                             prc(NL);    
  227. +                         }    
  228. +                         break;    
  229. +                     }                
  230.                   default:
  231.                       internal=builtin(argn,com);
  232.       
  233. ***************
  234. *** 422,425
  235.       FI
  236.       execute(cmd(NL, NLFLG|MTFLG),0);
  237.       pop();
  238.   }
  239.  
  240. --- 500,532 -----
  241.       FI
  242.       execute(cmd(NL, NLFLG|MTFLG),0);
  243.       pop();
  244. + }
  245. + /*
  246. +  * standard itos expects 16 bit ints, so write a prl() routine
  247. +  */
  248. + static int prl (n)
  249. + register long n;
  250. + {
  251. +     register int i, j;
  252. +     char buf[12], c;
  253. +     buf[0] = '0';
  254. +     buf[1] = buf[11] = 0;
  255. +     for (i = 0; n && i < 11; i++)
  256. +     {
  257. +         buf[i] = n % 10 + '0';
  258. +         n /= 10;
  259. +     }
  260. +     buf[i] = 0;
  261. +     for (j = --i, i = 0; i < j ; i++, j--)
  262. +     {
  263. +         c = buf[j];
  264. +         buf[j] = buf[i];
  265. +         buf[i] = c;
  266. +     }
  267. +     prs(buf);
  268.   }
  269. *** /usr/man/man1/sh.1    Thu Jul 28 17:52:12 1983
  270. --- sh.1    Mon Jun 30 15:44:06 1986
  271. ***************
  272. *** 1,6
  273.   .TH SH 1 "7 February 1983"
  274.   .SH NAME
  275. ! sh, for, case, if, while, \fB:\fP, \fB.\fP, break, continue, cd, eval, exec, exit, export, login, read, readonly, set, shift, times, trap, umask, wait \- command language
  276.   .SH SYNOPSIS
  277.   .B sh
  278.   [
  279.  
  280. --- 1,6 -----
  281.   .TH SH 1 "7 February 1983"
  282.   .SH NAME
  283. ! sh, for, case, if, while, \fB:\fP, \fB.\fP, break, continue, cd, eval, exec, exit, export, login, read, readonly, set, shift, times, trap, ulimit, umask, wait \- command language
  284.   .SH SYNOPSIS
  285.   .B sh
  286.   [
  287. ***************
  288. *** 762,767
  289.   .IR sigvec (2).
  290.   .I Trap
  291.   with no arguments prints a list of commands associated with each signal number.
  292.   .TP
  293.   \fBumask \fR[ \fInnn\fR ]
  294.   The user file creation mask is set to the octal value
  295.  
  296. --- 762,813 -----
  297.   .IR sigvec (2).
  298.   .I Trap
  299.   with no arguments prints a list of commands associated with each signal number.
  300. + .TP
  301. + \fBulimit\fP \*(OK \fB\-cdfmpt\fP \*(CK \*(OK \f2n\^\fP \*(CK
  302. + imposes a size limit of
  303. + .IR n\^ .
  304. + .RS
  305. + .TP
  306. + .B \-c
  307. + imposes a size limit of
  308. + .I n\^
  309. + blocks on the size of core dumps.
  310. + .TP
  311. + .B \-d
  312. + imposes a size limit of
  313. + .I n\^
  314. + blocks on the size of the data area.
  315. + .TP
  316. + .B \-f
  317. + imposes a size limit of 
  318. + .I n
  319. + blocks on files written by child processes (files of any size may be read).
  320. + .TP
  321. + .B \-m
  322. + imposes a soft limit of
  323. + .I n\^
  324. + blocks on the size of physical memory.
  325. + .TP
  326. + .B \-p
  327. + changes the pipe size to
  328. + .I n
  329. + (\s-1UNIX\s+1/\s-1RT\s+1 only).
  330. + .TP
  331. + .B \-t
  332. + imposes a time limit of
  333. + .I n\^
  334. + seconds to be used by each process.
  335. + .PP
  336. + If no option is given,
  337. + .B \-f
  338. + is assumed.
  339. + If
  340. + .I n\^
  341. + is not given, the current limit is printed.
  342. + (As far as
  343. + .B ulimit
  344. + is concerned, a block is 512 bytes.)
  345. + .RE
  346.   .TP
  347.   \fBumask \fR[ \fInnn\fR ]
  348.   The user file creation mask is set to the octal value
  349. SHAR_EOF
  350. fi # end of overwriting check
  351. echo shar: extracting "'ulimit.c'" '(2911 characters)'
  352. if test -f 'ulimit.c'
  353. then
  354.     echo shar: will not over-write existing file "'ulimit.c'"
  355. else
  356. cat << \SHAR_EOF > 'ulimit.c'
  357. #ifndef lint
  358. static char RCSid[] = "$Header: ulimit.c,v 1.4 85/12/09 13:02:22 arnold Exp $";
  359. #endif
  360.  
  361. /*
  362.  * $Log:    ulimit.c,v $
  363.  * Revision 1.4  85/12/09  13:02:22  arnold
  364.  * changed the declaration of limit to keep lint happy
  365.  * 
  366.  * Revision 1.3  85/12/03  16:18:42  arnold
  367.  * Fixed original code to use symbolic constants from the header files
  368.  * Added many more commands for use with the ksh style ulimit command,
  369.  * for the BSD limits.
  370.  * 
  371.  * Revision 1.2  85/11/18  10:04:46  arnold
  372.  * Updated from bare S5R2 to my first release
  373.  * 
  374.  * Revision 1.1  85/11/15  12:19:05  arnold
  375.  * Initial revision
  376.  * 
  377.  * 
  378.  */
  379.  
  380. /*
  381.     ulimit -- system call emulation for Bourne shell on 4.2BSD
  382.  
  383.     last edit:    22-Aug-1983    D A Gwyn
  384. */
  385.  
  386. #include    <sys/time.h>
  387. #include    <sys/resource.h>
  388. #include    <errno.h>
  389.  
  390. extern int    getrlimit(), setrlimit();
  391. extern int    errno;
  392.  
  393. #define BLOCK    512L    /* all these things are done in "blocks" */
  394.  
  395. long
  396. ulimit (cmd, newlimit)
  397. int    cmd;            /* subcommand */
  398. long    newlimit;        /* desired new limit */
  399. {
  400.     struct rlimit limit;    /* data being gotten/set */
  401.  
  402.     switch (cmd) {
  403.     case 1:             /* get file size limit */
  404.         if (getrlimit (RLIMIT_FSIZE, &limit) != 0 )
  405.             return -1L;    /* errno is already set */
  406.         return limit.rlim_max / BLOCK;
  407.  
  408.     case 2:             /* set file size limit */
  409.         limit.rlim_cur = limit.rlim_max = newlimit * BLOCK;
  410.         return setrlimit (RLIMIT_FSIZE, &limit);
  411.  
  412.     case 3:             /* get maximum break value */
  413.         if (getrlimit (RLIMIT_DATA, &limit) != 0)
  414.             return -1L;    /* errno is already set */
  415.         return limit.rlim_max;
  416.  
  417.     case 6:        /* get core file size limit */
  418.         if (getrlimit (RLIMIT_CORE, &limit) != 0)
  419.             return -1L;    /* errno already set */
  420.         return limit.rlim_max / BLOCK;
  421.  
  422.     case 7:        /* set core file size limit */
  423.         limit.rlim_cur = limit.rlim_max = newlimit * BLOCK;
  424.         return setrlimit (RLIMIT_CORE, &limit);
  425.  
  426.     case 8:        /* get data segment size limit */
  427.         if (getrlimit (RLIMIT_DATA, &limit) != 0)
  428.             return -1L;    /* errno already set */
  429.         return limit.rlim_max / BLOCK;
  430.  
  431.     case 9:        /* set data segment size limit */
  432.         limit.rlim_cur = limit.rlim_max = newlimit * BLOCK;
  433.         return setrlimit (RLIMIT_DATA, &limit);
  434.  
  435.     case 10:    /* get physical memory limit */
  436.         if (getrlimit (RLIMIT_RSS, &limit) != 0)
  437.             return -1L;    /* errno already set */
  438.         return limit.rlim_max / BLOCK;
  439.  
  440.     case 11:    /* set physical memory limit */
  441.         limit.rlim_cur = newlimit * BLOCK;
  442.         return setrlimit (RLIMIT_RSS, &limit);
  443.  
  444.     case 12:    /* get cpu time limit */
  445.         if (getrlimit (RLIMIT_CPU, &limit) != 0)
  446.             return -1L;    /* errno already set */
  447.         return limit.rlim_max / 1000L;    /* system uses milliseconds */
  448.  
  449.     case 13:    /* set cpu time limit */
  450.         limit.rlim_cur = limit.rlim_max = newlimit * 1000L;
  451.         return setrlimit (RLIMIT_CPU, &limit);
  452.  
  453.     case 4:
  454.     case 5:
  455.         /* These two are for getting and setting the pipe */
  456.         /* size under UNIX/RT -- not applicable here */
  457.         /* so fall thru and complain */
  458.     default:
  459.         errno = EINVAL;
  460.         return -1L;
  461.     }
  462. }
  463. SHAR_EOF
  464. fi # end of overwriting check
  465. #    End of shell archive
  466. exit 0
  467.