home *** CD-ROM | disk | FTP | other *** search
- Subject: v20i007: Allow users to automatically run scripts at boot time
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: sgrimm@sun.com (Steven Grimm)
- Posting-number: Volume 20, Issue 7
- Archive-name: rc.user
-
- This utility package allows users to run shell scripts automatically
- at system boot time. This is useful for everything from restarting
- servers (in fact, I developed it for use with the superserver program
- appearing here not too long ago) to sending mail notification of
- system reboots. The user interface is similar to Sun's crontab.
-
- ---
- Steven Grimm koreth@ssyx.ucsc.edu
- Division of Social Sciences uunet!ucbvax!ucscc!ssyx!koreth
- University of California, Santa Cruz "Pithy quotes are for losers."
-
- #!/bin/sh
- # shar: Shell Archiver (v1.22)
- #
- # Run the following text with /bin/sh to create:
- # Makefile
- # rc.users
- # rcuser.1
- # rcuser.c
- #
- sed 's/^X//' << 'SHAR_EOF' > Makefile &&
- X#
- X# rcuser
- X#
- X# Installation:
- X#
- X# Edit this Makefile and rcuser.c to suit your site.
- X# Run "make install" as root.
- X# Then edit your /etc/rc.local (or other startup script) so that
- X# /etc/rc.users is run at boot time. Usually you will want it to
- X# be run fairly late in the boot process, in case users want to
- X# talk to other system daemons, etc. (This could be done by make
- X# install, but it's probably best not to go tweaking peoples'
- X# rc files...)
- X#
- X
- XCFLAGS = -O -s
- XBINDIR = /usr/local
- X
- X# Change this if you want the rc files to be somewhere other than
- X# /usr/lib/rc.
- XRCDIR = /usr/lib/rc
- X
- Xrcuser: rcuser.c
- X $(CC) -DRCDIR=\"$(RCDIR)/\" $(CFLAGS) rcuser.c -o $@
- X
- Xinstall: rcuser
- X install -m 4711 rcuser $(BINDIR)
- X install -c -m 644 rc.users /etc
- X -mkdir $(RCDIR)
- X chmod 755 $(RCDIR)
- X @echo "Remember to edit /etc/rc.local to run /etc/rc.users"
- X
- Xclean:
- X -/bin/rm -f core rcuser *.o
- SHAR_EOF
- chmod 0600 Makefile || echo "restore of Makefile fails"
- sed 's/^X//' << 'SHAR_EOF' > rc.users &&
- X#!/bin/sh
- X# Run all the user scripts in /usr/lib/rc.
- X
- Xcd /usr/lib/rc
- X
- Xexport USER
- X
- Xfor USER in *
- Xdo
- X(
- X /bin/su -f $USER -c "/bin/sh $USER" >/tmp/#rc.$USER 2>&1 </dev/null
- X if test -s /tmp/#rc.$USER; then
- X (echo "Output from your startup file at `date`"; echo "";
- X cat /tmp/#rc.$USER) | mail $USER
- X fi
- X /bin/rm /tmp/#rc.$USER
- X) &
- Xdone
- SHAR_EOF
- chmod 0600 rc.users || echo "restore of rc.users fails"
- sed 's/^X//' << 'SHAR_EOF' > rcuser.1 &&
- X.TH RCUSER 1 "29 March 1988" "Koreth's Nifty Utilities"
- X.SH NAME
- Xrcuser \- manipulate user system startup files
- X.SH SYNOPSIS
- X\fBrcuser\fR [\fB\-e\fR|\fB\-l\fR|\fB\-d\fR|\fB\-t\fR [\fIusername\fR]]
- X.SH DESCRIPTION
- X\fIRcuser\fR allows users to maintain shell scripts which are executed at
- Xsystem startup time. Users' startup scripts are stored in a system directory
- X(\fI/usr/lib/rc\fR by default), in filenames matching the usernames of their
- Xowners. Startup files are executed by
- X.IR sh (1).
- X.LP
- XAny output from the users' scripts are mailed to them.
- X.LP
- XThe superuser may specify a username on the command line; that user's file
- Xwill be manipulated. If no username is specified or \fIrcuser\fR is not
- Xinvoked by the superuser, the current user's login name is used.
- X.SH OPTIONS
- X.IP \-e
- XEdit a startup file. The environment variable VISUAL is used if it exists;
- Xotherwise a default editor
- X.RI ( vi (1))
- Xis used. If a startup file
- Xdoes not exist, it is created by \fIrcuser\fR before the editor is invoked.
- X.IP \-l
- XList a startup file. The startup file is copied to standard output, using
- X.IR cat (1).
- XThis is the default action if no flags are specified on the command line.
- X.IP \-d
- XDelete a startup file.
- X.IP \-t
- XTest a startup file. The file is executed the same way it would be at
- Xsystem startup time. If it doesn't exit fairly quickly and without
- Xproducing output, something is probably wrong. Note that startup files
- Xare run with minimal environment strings; this environment is duplicated
- Xby \fIrcuser\fR.
- X.SH FILES
- X.IP /usr/lib/rc
- XUser startup directory
- X.IP /etc/rc.local
- XSystem startup script
- X.IP /etc/rc.users
- XRuns user startup scripts
- X.SH "SEE ALSO"
- Xcat(1), vi(1)
- X.SH AUTHOR
- XSteven Grimm, koreth@ssyx.ucsc.edu
- SHAR_EOF
- chmod 0600 rcuser.1 || echo "restore of rcuser.1 fails"
- sed 's/^X//' << 'SHAR_EOF' > rcuser.c &&
- X/*
- X** rcuser -- allow users to perform functions at startup time
- X**
- X** by Steven Grimm, koreth@ssyx.ucsc.edu
- X** 3-29-89
- X*/
- X
- X/* Default editor, if VISUAL environment variable isn't set */
- X#define VISUAL "/usr/ucb/vi"
- X
- X/* Command to display a file */
- X#define DISPLAY "/bin/cat"
- X
- X/*
- X** Command shell to test scripts with. This should be the same
- X** shell that's invoked for user scripts in rc.users.
- X*/
- X#define SHELL "/bin/sh"
- X
- X#include <pwd.h>
- X#include <stdio.h>
- X#include <errno.h>
- X#include <sys/file.h>
- X#include <sys/param.h>
- X
- X/* The username and id that we're working on behalf of. */
- Xchar *username;
- Xint uid;
- Xstruct passwd *pent;
- X
- Xchar *malloc();
- X
- X/*
- X** Get a user's uid and, if necessary, name
- X*/
- Xgetuser(name)
- Xchar *name;
- X{
- X if (name == NULL)
- X {
- X uid = getuid();
- X pent = getpwuid(uid);
- X if (pent != NULL)
- X username = pent->pw_name;
- X }
- X else
- X {
- X username = name;
- X pent = getpwnam(name);
- X if (pent != NULL)
- X uid = pent->pw_uid;
- X }
- X}
- X
- X/*
- X** Print an error and exit.
- X*/
- Xpanic(err)
- Xchar *err;
- X{
- X perror(err);
- X exit(-1);
- X}
- X
- X/*
- X** Print usage and exit.
- X*/
- Xusage(name)
- Xchar *name;
- X{
- X fprintf(stderr,"Usage: %s [-l|-e|-d] [user]\n", name);
- X fprintf(stderr,"\t-l - show startup script\n");
- X fprintf(stderr,"\t-e - edit startup script\n");
- X fprintf(stderr,"\t-d - delete startup script\n");
- X fprintf(stderr,"\t-t - test startup script\n");
- X fprintf(stderr,"\n\tusername may only be specified by superuser\n");
- X exit(-1);
- X}
- X
- X/*
- X** Create a file, owned by the appropriate user.
- X*/
- Xcreate(file, uid)
- Xchar *file;
- Xint uid;
- X{
- X int fd;
- X
- X fd = open(file, O_WRONLY|O_CREAT, 0600);
- X if (fd == -1)
- X panic(file);
- X
- X close(fd);
- X
- X/* fchown() is a BSDism */
- X chown(file, uid, -1);
- X}
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X char function, filename[MAXPATHLEN], *editor, *getenv();
- X
- X if (argc < 2)
- X {
- X getuser(NULL);
- X function = 'l';
- X } else
- X if (argv[1][0] != '-')
- X usage(argv[0]);
- X else
- X switch(argv[1][1]) {
- X case 'l':
- X case 'e':
- X case 'd':
- X case 't':
- X function = argv[1][1];
- X break;
- X default:
- X usage(argv[0]);
- X }
- X
- X/* If a username is given on the command line, and we are superuser, use it. */
- X if (argc == 3 && getuid() == 0)
- X getuser(argv[2]);
- X else
- X getuser(NULL);
- X
- X/* Construct the name of the appropriate user's startup file. */
- X strcpy(filename, RCDIR);
- X strncat(filename, username, sizeof(filename)-sizeof(RCDIR)-1);
- X
- X/* Now, if the function requires it, create the file if it doesn't exist. */
- X if (function == 'e' && access(filename, F_OK) == -1)
- X if (errno == ENOENT)
- X create(filename, uid);
- X else
- X panic(filename);
- X
- X/* Delete the file if necessary/possible. */
- X if (function == 'd')
- X if (unlink(filename) == -1)
- X panic(filename);
- X
- X/* That's all we need to be root for, so change our uid to something secure. */
- X setreuid(uid, uid);
- X
- X/* Now edit or show the file, as appropriate. */
- X if (function == 'l')
- X execl(DISPLAY, DISPLAY, filename, NULL);
- X if (function == 'e')
- X {
- X if ((editor = getenv("VISUAL")) == NULL)
- X editor = VISUAL;
- X execl(editor, editor, filename, NULL);
- X }
- X if (function == 't')
- X {
- X/* Duplicate the minimal environment under which the scripts are run */
- X char *env[5];
- X
- X env[4] = NULL;
- X env[3] = malloc(strlen(pent->pw_name)+6);
- X sprintf(env[3], "USER=%s", pent->pw_name);
- X env[2] = malloc(strlen(pent->pw_shell)+7);
- X sprintf(env[2], "SHELL=%s", pent->pw_shell);
- X env[1] = malloc(strlen(RCDIR)+4);
- X sprintf(env[1], "PWD=%s", RCDIR);
- X env[1][strlen(RCDIR)+3] = '\0'; /* lop off trailing / */
- X env[0] = malloc(strlen(pent->pw_dir)+6);
- X sprintf(env[0], "HOME=%s", pent->pw_dir);
- X
- X execle(SHELL, SHELL, filename, NULL, env);
- X }
- X exit(0);
- X}
- X
- SHAR_EOF
- chmod 0600 rcuser.c || echo "restore of rcuser.c fails"
- exit 0
-
-