home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i049: Add ksh-style 'ulimit' to 4.2BSD /bin/sh (sh.ulimit)
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: seismo!gatech!emory!arnold (Arnold D. Robbins {EUCC})
- Mod.sources: Volume 6, Issue 49
- Archive-name: sh.ulimit
-
- The 4.2 BSD sh does not have any functional equivalent of the csh's 'limit'
- built-in command. Below are some patches that provide the "ulimit" builtin,
- basically compatible with that implemented in the ksh, which understands the
- various BSD resource limits, as well as those available in System V. (Actually,
- it is a little different in the output format; but at the time I wrote the code,
- I only had ksh doc to go by, and not the ksh to test against. Oh well. 95% now
- is better than 100% in two weeks.)
-
- *** WARNING: This code has only been minimally tested in the BSD sh!!! ***
- It is however, very straightforward, and shouldn't give you too many problems.
- I pulled it out of the work I've been doing on the System V Release 2 shell.
- (That work is still in progress, and maybe once things settle down with 4.3,
- I'll be able to get back to it and post something.) It should be adaptable
- to System V shells currently running under 4.2, such as the one in Doug
- Gwyn's S5 emulation, and/or the Sun 3.0 shell (if you have source). Sun is
- welcome to pick this up and add it in, as it is mostly based on Doug's code,
- which is public domain.
-
- This posting was motivated by some discussion a while back in net.unix and
- net.unix-wizards. I hope it meets a need. (As for those who want job control
- for the shell, see the nine part sh posting in volume 1 of mod.sources that I
- did last summer. Several parts of that were diffs to the BSD sh, as well as
- the S5R2 sh. I am working on that some more too.)
-
- Enjoy,
- Arnold Robbins
- CSNET: arnold@emory BITNET: arnold@emoryu1
- ARPA: arnold%emory.csnet@csnet-relay.arpa
- UUCP: { akgua, decvax, gatech, sb1, sb6, sunatl }!emory!arnold
- -------------------------------------------------------------------------
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # sh.patch
- # ulimit.c
- # This archive created: Mon Jun 30 16:14:11 1986
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'sh.patch'" '(6246 characters)'
- if test -f 'sh.patch'
- then
- echo shar: will not over-write existing file "'sh.patch'"
- else
- cat << \SHAR_EOF > 'sh.patch'
- *** /usr/src/bin/sh/Makefile Fri Jul 1 06:48:58 1983
- --- Makefile Mon Jun 30 15:47:27 1986
- ***************
- *** 19,24
- sh: xec.o service.o error.o io.o
- sh: print.o macro.o expand.o
- sh: ctype.o msg.o
- blok.o: brkincr.h
- fault.o: brkincr.h
- main.o: brkincr.h
-
- --- 19,25 -----
- sh: xec.o service.o error.o io.o
- sh: print.o macro.o expand.o
- sh: ctype.o msg.o
- + sh: ulimit.o
- blok.o: brkincr.h
- fault.o: brkincr.h
- main.o: brkincr.h
- *** /usr/src/bin/sh/defs.h Sat Jun 11 02:38:06 1983
- --- defs.h Mon Jun 30 15:44:51 1986
- ***************
- *** 54,59
- #define SYSREAD 17
- #define SYSTST 18
- #define SYSUMASK 19
-
- /* used for input and output of shell */
- #define INIO 10
-
- --- 54,60 -----
- #define SYSREAD 17
- #define SYSTST 18
- #define SYSUMASK 19
- + #define SYSULIMIT 20
-
- /* used for input and output of shell */
- #define INIO 10
- ***************
- *** 264,269
- MSG badopt;
- MSG badparam;
- MSG badsub;
- MSG nospace;
- MSG notfound;
- MSG badtrap;
-
- --- 265,271 -----
- MSG badopt;
- MSG badparam;
- MSG badsub;
- + MSG badulimit;
- MSG nospace;
- MSG notfound;
- MSG badtrap;
- *** /usr/src/bin/sh/msg.c Thu Aug 11 23:21:53 1983
- --- msg.c Mon Jun 30 15:45:24 1986
- ***************
- *** 26,31
- MSG badnum = "bad number";
- MSG badparam = "parameter not set";
- MSG badsub = "bad substitution";
- MSG badcreate = "cannot create";
- MSG illegal = "illegal io";
- MSG restricted = "restricted";
-
- --- 26,32 -----
- MSG badnum = "bad number";
- MSG badparam = "parameter not set";
- MSG badsub = "bad substitution";
- + MSG badulimit = "bad ulimit";
- MSG badcreate = "cannot create";
- MSG illegal = "illegal io";
- MSG restricted = "restricted";
- ***************
- *** 135,139
- {"exec", SYSEXEC},
- {"times", SYSTIMES},
- {"umask", SYSUMASK},
- {0, 0},
- };
-
- --- 136,141 -----
- {"exec", SYSEXEC},
- {"times", SYSTIMES},
- {"umask", SYSUMASK},
- + {"ulimit", SYSULIMIT},
- {0, 0},
- };
- *** /usr/src/bin/sh/xec.c Thu Aug 11 23:21:56 1983
- --- xec.c Mon Jun 30 16:07:08 1986
- ***************
- *** 222,227
- }
- break;
-
- default:
- internal=builtin(argn,com);
-
-
- --- 222,305 -----
- }
- break;
-
- + case SYSULIMIT:
- + {
- + long int i;
- + long ulimit();
- + int command = 2;
- +
- + if (*a1 == '-')
- + {
- + switch(*(a1+1)) {
- + case 'f':
- + command = 2;
- + break;
- +
- + #ifdef rt
- + case 'p':
- + command = 5;
- + break;
- +
- + #endif
- + case 'c':
- + command = 7;
- + break;
- +
- + case 'd':
- + command = 9;
- + break;
- +
- + case 'm':
- + command = 11;
- + break;
- +
- + case 't':
- + command = 13;
- + break;
- +
- + default:
- + error(badopt);
- + }
- + a1 = com[2];
- + }
- + if (a1)
- + {
- + int c;
- +
- + i = 0;
- + while ((c = *a1++) >= '0' && c <= '9')
- + {
- + i = (i * 10) + (long)(c - '0');
- + if (i < 0)
- + error(badulimit);
- + }
- + if (c || i < 0)
- + error(badulimit);
- + }
- + else
- + {
- + i = -1;
- + command--;
- + }
- +
- + if ((i = ulimit(command,i)) < 0)
- + error(badulimit);
- +
- + switch (command) {
- + case 1:
- + #ifdef rt
- + case 4:
- + #endif
- + case 6:
- + case 8:
- + case 10:
- + case 12:
- + prl(i);
- + prc(NL);
- + }
- + break;
- + }
- +
- default:
- internal=builtin(argn,com);
-
- ***************
- *** 422,425
- FI
- execute(cmd(NL, NLFLG|MTFLG),0);
- pop();
- }
-
- --- 500,532 -----
- FI
- execute(cmd(NL, NLFLG|MTFLG),0);
- pop();
- + }
- +
- + /*
- + * standard itos expects 16 bit ints, so write a prl() routine
- + */
- +
- + static int prl (n)
- + register long n;
- + {
- + register int i, j;
- + char buf[12], c;
- +
- + buf[0] = '0';
- + buf[1] = buf[11] = 0;
- + for (i = 0; n && i < 11; i++)
- + {
- + buf[i] = n % 10 + '0';
- + n /= 10;
- + }
- + buf[i] = 0;
- +
- + for (j = --i, i = 0; i < j ; i++, j--)
- + {
- + c = buf[j];
- + buf[j] = buf[i];
- + buf[i] = c;
- + }
- +
- + prs(buf);
- }
- *** /usr/man/man1/sh.1 Thu Jul 28 17:52:12 1983
- --- sh.1 Mon Jun 30 15:44:06 1986
- ***************
- *** 1,6
- .TH SH 1 "7 February 1983"
- .SH NAME
- ! 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
- .SH SYNOPSIS
- .B sh
- [
-
- --- 1,6 -----
- .TH SH 1 "7 February 1983"
- .SH NAME
- ! 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
- .SH SYNOPSIS
- .B sh
- [
- ***************
- *** 762,767
- .IR sigvec (2).
- .I Trap
- with no arguments prints a list of commands associated with each signal number.
- .TP
- \fBumask \fR[ \fInnn\fR ]
- The user file creation mask is set to the octal value
-
- --- 762,813 -----
- .IR sigvec (2).
- .I Trap
- with no arguments prints a list of commands associated with each signal number.
- + .TP
- + \fBulimit\fP \*(OK \fB\-cdfmpt\fP \*(CK \*(OK \f2n\^\fP \*(CK
- + imposes a size limit of
- + .IR n\^ .
- + .RS
- + .TP
- + .B \-c
- + imposes a size limit of
- + .I n\^
- + blocks on the size of core dumps.
- + .TP
- + .B \-d
- + imposes a size limit of
- + .I n\^
- + blocks on the size of the data area.
- + .TP
- + .B \-f
- + imposes a size limit of
- + .I n
- + blocks on files written by child processes (files of any size may be read).
- + .TP
- + .B \-m
- + imposes a soft limit of
- + .I n\^
- + blocks on the size of physical memory.
- + .TP
- + .B \-p
- + changes the pipe size to
- + .I n
- + (\s-1UNIX\s+1/\s-1RT\s+1 only).
- + .TP
- + .B \-t
- + imposes a time limit of
- + .I n\^
- + seconds to be used by each process.
- + .PP
- + If no option is given,
- + .B \-f
- + is assumed.
- + If
- + .I n\^
- + is not given, the current limit is printed.
- + (As far as
- + .B ulimit
- + is concerned, a block is 512 bytes.)
- + .RE
- .TP
- \fBumask \fR[ \fInnn\fR ]
- The user file creation mask is set to the octal value
- SHAR_EOF
- fi # end of overwriting check
- echo shar: extracting "'ulimit.c'" '(2911 characters)'
- if test -f 'ulimit.c'
- then
- echo shar: will not over-write existing file "'ulimit.c'"
- else
- cat << \SHAR_EOF > 'ulimit.c'
- #ifndef lint
- static char RCSid[] = "$Header: ulimit.c,v 1.4 85/12/09 13:02:22 arnold Exp $";
- #endif
-
- /*
- * $Log: ulimit.c,v $
- * Revision 1.4 85/12/09 13:02:22 arnold
- * changed the declaration of limit to keep lint happy
- *
- * Revision 1.3 85/12/03 16:18:42 arnold
- * Fixed original code to use symbolic constants from the header files
- * Added many more commands for use with the ksh style ulimit command,
- * for the BSD limits.
- *
- * Revision 1.2 85/11/18 10:04:46 arnold
- * Updated from bare S5R2 to my first release
- *
- * Revision 1.1 85/11/15 12:19:05 arnold
- * Initial revision
- *
- *
- */
-
- /*
- ulimit -- system call emulation for Bourne shell on 4.2BSD
-
- last edit: 22-Aug-1983 D A Gwyn
- */
-
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <errno.h>
-
- extern int getrlimit(), setrlimit();
- extern int errno;
-
- #define BLOCK 512L /* all these things are done in "blocks" */
-
- long
- ulimit (cmd, newlimit)
- int cmd; /* subcommand */
- long newlimit; /* desired new limit */
- {
- struct rlimit limit; /* data being gotten/set */
-
- switch (cmd) {
- case 1: /* get file size limit */
- if (getrlimit (RLIMIT_FSIZE, &limit) != 0 )
- return -1L; /* errno is already set */
- return limit.rlim_max / BLOCK;
-
- case 2: /* set file size limit */
- limit.rlim_cur = limit.rlim_max = newlimit * BLOCK;
- return setrlimit (RLIMIT_FSIZE, &limit);
-
- case 3: /* get maximum break value */
- if (getrlimit (RLIMIT_DATA, &limit) != 0)
- return -1L; /* errno is already set */
- return limit.rlim_max;
-
- case 6: /* get core file size limit */
- if (getrlimit (RLIMIT_CORE, &limit) != 0)
- return -1L; /* errno already set */
- return limit.rlim_max / BLOCK;
-
- case 7: /* set core file size limit */
- limit.rlim_cur = limit.rlim_max = newlimit * BLOCK;
- return setrlimit (RLIMIT_CORE, &limit);
-
- case 8: /* get data segment size limit */
- if (getrlimit (RLIMIT_DATA, &limit) != 0)
- return -1L; /* errno already set */
- return limit.rlim_max / BLOCK;
-
- case 9: /* set data segment size limit */
- limit.rlim_cur = limit.rlim_max = newlimit * BLOCK;
- return setrlimit (RLIMIT_DATA, &limit);
-
- case 10: /* get physical memory limit */
- if (getrlimit (RLIMIT_RSS, &limit) != 0)
- return -1L; /* errno already set */
- return limit.rlim_max / BLOCK;
-
- case 11: /* set physical memory limit */
- limit.rlim_cur = newlimit * BLOCK;
- return setrlimit (RLIMIT_RSS, &limit);
-
- case 12: /* get cpu time limit */
- if (getrlimit (RLIMIT_CPU, &limit) != 0)
- return -1L; /* errno already set */
- return limit.rlim_max / 1000L; /* system uses milliseconds */
-
- case 13: /* set cpu time limit */
- limit.rlim_cur = limit.rlim_max = newlimit * 1000L;
- return setrlimit (RLIMIT_CPU, &limit);
-
- case 4:
- case 5:
- /* These two are for getting and setting the pipe */
- /* size under UNIX/RT -- not applicable here */
- /* so fall thru and complain */
- default:
- errno = EINVAL;
- return -1L;
- }
- }
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-