summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authornate <nate@FreeBSD.org>1994-01-05 01:03:02 +0000
committernate <nate@FreeBSD.org>1994-01-05 01:03:02 +0000
commit69dc0f6e65519fe5cd67e46a69547f906b9d2d4e (patch)
tree9433ae72489b5cbc42ae8a30e2ffe21c3fce3b33 /libexec
parente89a0b36ded5f6ce24d4d4e94bcd21308c9002e3 (diff)
downloadFreeBSD-src-69dc0f6e65519fe5cd67e46a69547f906b9d2d4e.zip
FreeBSD-src-69dc0f6e65519fe5cd67e46a69547f906b9d2d4e.tar.gz
Added the Linux atrun command as hacked by Chris Demetriou for NetBSD.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/atrun/Makefile13
-rw-r--r--libexec/atrun/atrun.877
-rw-r--r--libexec/atrun/atrun.c327
-rw-r--r--libexec/atrun/atrun.h33
4 files changed, 450 insertions, 0 deletions
diff --git a/libexec/atrun/Makefile b/libexec/atrun/Makefile
new file mode 100644
index 0000000..27b8ea3
--- /dev/null
+++ b/libexec/atrun/Makefile
@@ -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>
diff --git a/libexec/atrun/atrun.8 b/libexec/atrun/atrun.8
new file mode 100644
index 0000000..957eacc
--- /dev/null
+++ b/libexec/atrun/atrun.8
@@ -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.
diff --git a/libexec/atrun/atrun.c b/libexec/atrun/atrun.c
new file mode 100644
index 0000000..3b84ec9
--- /dev/null
+++ b/libexec/atrun/atrun.c
@@ -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);
+}
diff --git a/libexec/atrun/atrun.h b/libexec/atrun/atrun.h
new file mode 100644
index 0000000..be0588a
--- /dev/null
+++ b/libexec/atrun/atrun.h
@@ -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
OpenPOWER on IntegriCloud