Added the Linux atrun command as hacked by Chris Demetriou for NetBSD.

This commit is contained in:
nate 1994-01-05 01:03:02 +00:00
parent e89a0b36de
commit 69dc0f6e65
4 changed files with 450 additions and 0 deletions

13
libexec/atrun/Makefile Normal file
View File

@ -0,0 +1,13 @@
# $Id: Makefile,v 1.2 1993/12/05 12:26:10 cgd Exp $
PROG= atrun
MAN8= atrun.8
BINDIR= /usr/libexec
BINOWN= root
CFLAGS+= -I${.CURDIR}/../../usr.bin/at
LDADD+= -lutil
DPADD+= ${LIBUTIL}
.include <bsd.prog.mk>

77
libexec/atrun/atrun.8 Normal file
View File

@ -0,0 +1,77 @@
.\"
.\" Copyright (c) 1993 Christopher G. Demetriou
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Christopher G. Demetriou.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software withough specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: atrun.8,v 1.1 1993/12/05 11:36:29 cgd Exp $
.\"
.Dd December 5, 1993
.Dt ATRUN 8
.Os NetBSD 0.9a
.Sh NAME
.Nm atrun
.Nd run jobs queued for later execution
.\"
.Sh SYOPSIS
.Nm atrun
.Sh DESCRIPTION
The
.Nm atrun
utility runs commands queued by
.Xr at 1 .
It is usually invoked by
.Xr crond 8
every ten minutes.
.Sh FILES
.Bl -tag -width /var/at/lockfile -compact
.It Pa /var/at/jobs
Directory containing job files
.It Pa /var/at/spool
Directory containing output spool files
.It Pa /var/at/lockfile
Job-creation lock file.
.El
.Sh SEE ALSO
.Xr crond 8 ,
.Xr at 1
.Sh AUTHOR
.Bl -tag
Thomas Koenig, ig25@rz.uni-karlsruhe.de
.El
.Sh BUGS
The functionality of
.Nm atrun
should arguaby be merged into
.Xr crond 8 .
.Sh CAVEATS
Since the default configuration causes
.Nm atrun
to be invoked every ten minutes,
commands queued by
.Xr at 1
may end up being executed up to nine minutes
later than would be otherwise expected.

327
libexec/atrun/atrun.c Normal file
View File

@ -0,0 +1,327 @@
/*
* atrun.c - run jobs queued by at; run with root privileges.
* Copyright (c) 1993 by Thomas Koenig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author(s) may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* System Headers */
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <syslog.h>
#include <paths.h>
/* Local headers */
#define MAIN
#include "privs.h"
#include "pathnames.h"
#include "atrun.h"
/* File scope variables */
static char *namep;
static char rcsid[] = "$Id: atrun.c,v 1.1 1993/12/05 11:36:38 cgd Exp $";
/* Local functions */
static void
perr(a)
const char *a;
{
syslog(LOG_ERR, "%s: %m", a);
exit(EXIT_FAILURE);
}
static int
write_string(fd, a)
int fd;
const char *a;
{
return write(fd, a, strlen(a));
}
static void
run_file(filename, uid, gid)
const char *filename;
uid_t uid;
gid_t gid;
{
/*
* Run a file by by spawning off a process which redirects I/O,
* spawns a subshell, then waits for it to complete and spawns another
* process to send mail to the user.
*/
pid_t pid;
int fd_out, fd_in;
int queue;
char mailbuf[9];
char *mailname = NULL;
FILE *stream;
int send_mail = 0;
struct stat buf;
off_t size;
struct passwd *pentry;
int fflags;
pid = fork();
if (pid == -1)
perr("Cannot fork");
else if (pid > 0)
return;
/*
* Let's see who we mail to. Hopefully, we can read it from the
* command file; if not, send it to the owner, or, failing that, to
* root.
*/
PRIV_START
stream = fopen(filename, "r");
PRIV_END
if (stream == NULL)
perr("Cannot open input file");
if ((fd_in = dup(fileno(stream))) < 0)
perr("Error duplicating input file descriptor");
if ((fflags = fcntl(fd_in, F_GETFD)) < 0)
perr("Error in fcntl");
fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC);
if (fscanf(stream, "#! /bin/sh\n# mail %8s %d", mailbuf, &send_mail) == 2) {
mailname = mailbuf;
} else {
pentry = getpwuid(uid);
if (pentry == NULL)
mailname = "root";
else
mailname = pentry->pw_name;
}
fclose(stream);
if (chdir(_PATH_ATSPOOL) < 0)
perr("Cannot chdir to " _PATH_ATSPOOL);
/*
* Create a file to hold the output of the job we are about to
* run. Write the mail header.
*/
if ((fd_out = open(filename,
O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0)
perr("Cannot create output file");
write_string(fd_out, "Subject: Output from your job ");
write_string(fd_out, filename);
write_string(fd_out, "\n\n");
fstat(fd_out, &buf);
size = buf.st_size;
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
pid = fork();
if (pid < 0)
perr("Error in fork");
else if (pid == 0) {
char *nul = NULL;
char **nenvp = &nul;
/*
* Set up things for the child; we want standard input from
* the input file, and standard output and error sent to
* our output file.
*/
if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0)
perr("Error in lseek");
if (dup(fd_in) != STDIN_FILENO)
perr("Error in I/O redirection");
if (dup(fd_out) != STDOUT_FILENO)
perr("Error in I/O redirection");
if (dup(fd_out) != STDERR_FILENO)
perr("Error in I/O redirection");
close(fd_in);
close(fd_out);
if (chdir(_PATH_ATJOBS) < 0)
perr("Cannot chdir to " _PATH_ATJOBS);
queue = *filename;
PRIV_START
if (queue > 'b')
nice(queue - 'b');
if (setgid(gid) < 0)
perr("Cannot change group");
if (setuid(uid) < 0)
perr("Cannot set user id");
chdir("/");
if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0)
perr("Exec failed");
PRIV_END
}
/* We're the parent. Let's wait. */
close(fd_in);
close(fd_out);
waitpid(pid, (int *) NULL, 0);
stat(filename, &buf);
if ((buf.st_size != size) || send_mail) {
/* Fork off a child for sending mail */
pid = fork();
if (pid < 0)
perr("Fork failed");
else if (pid == 0) {
if (open(filename, O_RDONLY) != STDIN_FILENO)
perr("Cannot reopen output file");
execl(_PATH_SENDMAIL, _PATH_SENDMAIL, mailname,
(char *) NULL);
perr("Exec failed");
}
waitpid(pid, (int *) NULL, 0);
}
unlink(filename);
exit(EXIT_SUCCESS);
}
/* Global functions */
int
main(argc, argv)
int argc;
char *argv[];
{
/*
* Browse through _PATH_ATJOBS, checking all the jobfiles wether
* they should be executed and or deleted. The queue is coded into
* the first byte of the job filename, the date (in minutes since
* Eon) as a hex number in the following eight bytes, followed by
* a dot and a serial number. A file which has not been executed
* yet is denoted by its execute - bit set. For those files which
* are to be executed, run_file() is called, which forks off a
* child which takes care of I/O redirection, forks off another
* child for execution and yet another one, optionally, for sending
* mail. Files which already have run are removed during the
* next invocation.
*/
DIR *spool;
struct dirent *dirent;
struct stat buf;
int older;
unsigned long ctm;
char queue;
/*
* We don't need root privileges all the time; running under uid
* and gid daemon is fine.
*/
RELINQUISH_PRIVS_ROOT(0) /* it's setuid root */
openlog("atrun", LOG_PID, LOG_CRON);
namep = argv[0];
if (chdir(_PATH_ATJOBS) != 0)
perr("Cannot change to " _PATH_ATJOBS);
/*
* Main loop. Open spool directory for reading and look over all
* the files in there. If the filename indicates that the job
* should be run and the x bit is set, fork off a child which sets
* its user and group id to that of the files and exec a /bin/sh
* which executes the shell script. Unlink older files if they
* should no longer be run. For deletion, their r bit has to be
* turned on.
*/
if ((spool = opendir(".")) == NULL)
perr("Cannot read " _PATH_ATJOBS);
while ((dirent = readdir(spool)) != NULL) {
double la;
if (stat(dirent->d_name, &buf) != 0)
perr("Cannot stat in " _PATH_ATJOBS);
/* We don't want directories */
if (!S_ISREG(buf.st_mode))
continue;
if (sscanf(dirent->d_name, "%c%8lx", &queue, &ctm) != 2)
continue;
if ((queue == 'b') && ((getloadavg(&la, 1) != 1) ||
(la > ATRUN_MAXLOAD)))
continue;
older = (time_t) ctm *60 <= time(NULL);
/* The file is executable and old enough */
if (older && (S_IXUSR & buf.st_mode)) {
/*
* Now we know we want to run the file, we can turn
* off the execute bit
*/
PRIV_START
if (chmod(dirent->d_name, S_IRUSR) != 0)
perr("Cannot change file permissions");
PRIV_END
run_file(dirent->d_name, buf.st_uid, buf.st_gid);
}
/* Delete older files */
if (older && !(S_IXUSR & buf.st_mode) &&
(S_IRUSR & buf.st_mode))
unlink(dirent->d_name);
}
closelog();
exit(EXIT_SUCCESS);
}

33
libexec/atrun/atrun.h Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 1993 Christopher G. Demetriou
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: atrun.h,v 1.1 1993/12/05 11:36:45 cgd Exp $
*/
#define ATRUN_MAXLOAD 1.5