[net.sources] ULIMIT - set/get file size limit

paul@devon.UUCP (Paul Sutcliffe Jr.) (01/08/87)

With all the talk about ulimit lately, I've decided to share my "cure"
for the problem.  This program (aptly called ``ulimit'') will run
a command with any given file size limit.  Since it runs as setuid
root, ulimit is allowed to raise the maximum file size.  But fear
not, ulimit sets the process' user id back to that of the caller
before forking the command, so a security hole is not created.  For
complete instructions, see the man page.

The included makefile may require a few small changes.  Remove the
"-Dvoid=int" if your compiler supports the void type.  Set DESTDIR to
the directory you wish ulimit to reside in before typing "make install".
You must be the super-user to do the install.

This code has been compiled and run on IBM XENIX 1.0 and 2.0,
SCO XENIX V/286, Tandy XENIX 3.0, and UNIX SysVR2 on Sperry 5000's.
I have no idea if it will work (or is needed, for that matter) on
BSD Unix.

Save the part between the two "tear here" lines an run the resulting
file through the Bourne shell.  (e.g. sh ulimit.shar).

Comments welcome!

-paul

----------------------------- tear here -------------------------------
# To unbundle, sh this file
echo x - Makefile 1>&2
cat >Makefile <<'End of Makefile'
# Makefile for 'ulimit'
# Copyright (C) 1987 by Paul Sutcliffe, Jr.  (devon!paul)

CC	= cc -Dvoid=int
NROFF	= nroff
CFLAGS	= -s -O
DESTDIR	= /usr/local/bin
ROOTUSR	= root

ulimit:	ulimit.c
	$(CC) $(CFLAGS) -o ulimit ulimit.c

install: ulimit
	cp ulimit $(DESTDIR)
	chown $(ROOTUSR) $(DESTDIR)/ulimit
	chgrp bin $(DESTDIR)/ulimit
	chmod 4711 $(DESTDIR)/ulimit

man:	ulimit.1
	$(NROFF) -man ulimit.1

clean:
	rm -f ulimit.o core

clobber: clean
	rm -f ulimit

End of Makefile
echo x - ulimit.1 1>&2
cat >ulimit.1 <<'End of ulimit.1'
.tr ~
.TH ULIMIT 1 local
.SH NAME
ulimit~- get/set file size limit
.SH SYNTAX
.BR ulimit
.RI [~newlimit~command~[~args~...~]~]
.SH DESCRIPTION
.I Ulimit
with no arguments will display the current maximum file size for the
calling process (usually the shell).
.I Ulimit
with at least two arguments will set the maximum file size to
\fInewlimit\fR and then execute the \fIcommand\fR.
The \fInewlimit\fR is specified in units of blocks (i.e. 512 bytes).
Any additional arguments (if found) are passed through to the
\fIcommand\fR.
.SH EXAMPLE
ulimit 4096 cat file1 file2 >largefile
.PP
This will allow \fIlargefile\fR to be 2 Megabytes.
.SH SEE~ALSO
sh(1), ulimit(2)
.SH NOTES
The name conflicts with the Bourne shell builtin \fIulimit\fR.
.SH AUTHOR
Paul Sutcliffe, Jr.  (...!seismo!cbmvax!devon!paul)
End of ulimit.1
echo x - ulimit.c 1>&2
cat >ulimit.c <<'End of ulimit.c'
/*
 *	ulimit.c  -  get/set user filesize limits
 *
 *	Copyright (C) 1987 by Paul Sutcliffe, Jr.  (devon!paul)
 *
 *	Permission is hereby granted to copy, reproduce, redistribute or
 *	otherwise use this software as long as: there is no monetary
 *	profit gained specifically from the use or reproduction or this
 *	software, it is not sold, rented, traded or otherwise marketed, and
 *	this copyright notice is included prominently in any copy made.
 */

#ifndef lint
static char *sccsid = "@(#)ulimit.c	2.1  (devon)  1/7/86";
#endif

#include <sys/ulimit.h>

extern int getuid();
extern long ulimit();

main(argc, argv)
int argc;
char *argv[];
{
	char	*myname, *file;
	long	curlimit, newlimit;

	myname = argv[0];		/* program name */

	if (argc == 1) {	/* show current ulimit */
		if ((curlimit = ulimit(UL_GFILLIM, (long) 0)) < 0) {
			perror(myname);
			exit(1);
		}
		(void) printf("%ld\n", curlimit);

	} else if (argc >= 3) {		/* set new ulimit and run command */
		newlimit = atol((++argv)[0]);
		if (ulimit(UL_SFILLIM, newlimit) < 0) {
			perror(myname);
			exit(1);
		}
		(void) setuid(getuid());  /* run as real user, not root! */
		file = (++argv)[0];
		execvp(file, argv);
		perror(myname);		/* in case execvp fails */
		exit(1);

	} else	exit(2);
}
End of ulimit.c
----------------------------- tear here -------------------------------

-- 
Paul Sutcliffe, Jr.	 UUCP: {seismo,ihnp4,allegra,rutgers}!cbmvax!devon!paul
Devon Computer Services  COMPUSERVE: 76176,502
Allentown, Penna.	 Sarek: "Any message for your mother, Spock?"
+1 215 398 3776 	 Spock: "Yes. Tell her 'I feel fine.'"