From ddcf8022362e214b7a5403ccda9b3d4626a816d6 Mon Sep 17 00:00:00 2001 From: "Andrey A. Chernov" Date: Mon, 21 Aug 1995 12:34:18 +0000 Subject: [PATCH] Upgrade to 2.9 --- libexec/atrun/LEGAL | 29 +++++ libexec/atrun/Makefile | 5 +- libexec/atrun/atrun.c | 172 +++++++++++++++++----------- libexec/atrun/gloadavg.c | 69 ++++++++++++ libexec/atrun/gloadavg.h | 29 +++++ usr.bin/at/LEGAL | 29 +++++ usr.bin/at/Makefile.inc | 2 +- usr.bin/at/at.c | 234 +++++++++++++++++++++++++++------------ usr.bin/at/at.h | 4 +- usr.bin/at/at.man | 8 +- usr.bin/at/panic.c | 9 +- usr.bin/at/panic.h | 4 +- usr.bin/at/parsetime.c | 32 +++--- usr.bin/at/parsetime.h | 4 +- usr.bin/at/perm.c | 6 +- usr.bin/at/perm.h | 4 +- usr.bin/at/privs.h | 40 ++++--- 17 files changed, 494 insertions(+), 186 deletions(-) create mode 100644 libexec/atrun/LEGAL create mode 100644 libexec/atrun/gloadavg.c create mode 100644 libexec/atrun/gloadavg.h create mode 100644 usr.bin/at/LEGAL diff --git a/libexec/atrun/LEGAL b/libexec/atrun/LEGAL new file mode 100644 index 000000000000..92b1b4983110 --- /dev/null +++ b/libexec/atrun/LEGAL @@ -0,0 +1,29 @@ +-----BEGIN PGP SIGNED MESSAGE----- + +Sorry for the long wait, but there still were a few things to +be ironed out in at, which I've finally done :-) + +The FreeBSD team does have my permission to use at, version 2.9, +under the BSD license. + +You'll find it on sunsite.unc.edu's Incoming, hopefully; the +md5 checksum is + +3ba2ca3c0e87e1a04feae2c6c1376b0d at-2.9.tgz + +Best regards + Thomas +- -- +Thomas Koenig, Thomas.Koenig@ciw.uni-karlsruhe.de, ig25@dkauni2.bitnet. +The joy of engineering is to find a straight line on a double +logarithmic diagram. + +-----BEGIN PGP SIGNATURE----- +Version: 2.6.2i + +iQCVAwUBMCjVrPBu+cbJcKCVAQFNiQP/dpWP57s/E8plVGUD3zfgOXDmKUvg8U7a +VwRzJrIMuSgnSJs0wkpvcomc3NLicipfX7hhWLh/xatPM2YbF7O5HZoNdvWvexD2 +1Y67zJ+0HFb1mPnSBOrS5RFiQAe3KqmGec6E14Rih/qNoFQZBVRFXZ4xxuwP+0Rs +e2U+TVTUz6A= +=TvyW +-----END PGP SIGNATURE----- diff --git a/libexec/atrun/Makefile b/libexec/atrun/Makefile index cb69fd16980d..96d415b6175c 100644 --- a/libexec/atrun/Makefile +++ b/libexec/atrun/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1 1994/01/05 01:02:56 nate Exp $ +# $Id: Makefile,v 1.3 1995/08/10 04:06:52 ache Exp $ MAINSRC= ${.CURDIR}/../../usr.bin/at @@ -6,13 +6,14 @@ MAINSRC= ${.CURDIR}/../../usr.bin/at PROG= atrun MAN8= atrun.8 +SRCS= atrun.c gloadavg.c BINDIR= $(ATLIB_DIR) MANSRC= . CLEANFILES += ${MAN8} MANDEPEND = ${MAN8} -CFLAGS+= -I$(MAINSRC) +CFLAGS+= -I$(MAINSRC) -I{$.CURDIR} ${MAN8}: atrun.man sed -e \ diff --git a/libexec/atrun/atrun.c b/libexec/atrun/atrun.c index 3ae9ee78decd..9bd7aca828d5 100644 --- a/libexec/atrun/atrun.c +++ b/libexec/atrun/atrun.c @@ -1,4 +1,4 @@ -/* +/* * atrun.c - run jobs queued by at; run with root privileges. * Copyright (C) 1993, 1994 Thomas Koenig * @@ -14,7 +14,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 @@ -42,17 +42,15 @@ #include #include #include -#ifndef __FreeBSD__ -#include -#else +#ifdef __FreeBSD__ #include +#else +#include #endif /* Local headers */ -#ifndef __FreeBSD__ #include "gloadavg.h" -#endif #define MAIN #include "privs.h" @@ -73,29 +71,19 @@ /* File scope variables */ static char *namep; -static char rcsid[] = "$Id: atrun.c,v 1.3 1995/04/12 19:21:43 ache Exp $"; +static char rcsid[] = "$Id: atrun.c,v 1.5 1995/08/10 04:06:53 ache Exp $"; static debug = 0; +void perr(const char *a); + /* Local functions */ -static void -perr(const char *a) -{ - if (debug) - { - perror(a); - } - else - syslog(LOG_ERR, "%s: %m", a); - - exit(EXIT_FAILURE); -} - static int write_string(int fd, const char* a) { return write(fd, a, strlen(a)); } +#undef DEBUG_FORK #ifdef DEBUG_FORK static pid_t myfork() @@ -124,10 +112,12 @@ run_file(const char *filename, uid_t uid, gid_t gid) char *mailname = NULL; FILE *stream; int send_mail = 0; - struct stat buf; + struct stat buf, lbuf; off_t size; struct passwd *pentry; int fflags; + long nuid; + long ngid; PRIV_START @@ -142,8 +132,8 @@ run_file(const char *filename, uid_t uid, gid_t gid) pid = fork(); if (pid == -1) perr("Cannot fork"); - - else if (pid > 0) + + else if (pid != 0) return; /* Let's see who we mail to. Hopefully, we can read it from @@ -156,7 +146,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) { syslog(LOG_ERR,"Userid %lu not found - aborting job %s", (unsigned long) uid, filename); - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } PRIV_START @@ -170,32 +160,63 @@ run_file(const char *filename, uid_t uid, gid_t gid) if ((fd_in = dup(fileno(stream))) <0) perr("Error duplicating input file descriptor"); + if (fstat(fd_in, &buf) == -1) + perr("Error in fstat of input file descriptor"); + + if (lstat(filename, &lbuf) == -1) + perr("Error in fstat of input file"); + + if (S_ISLNK(lbuf.st_mode)) { + syslog(LOG_ERR,"Symbolic link encountered in job %s - aborting", + filename); + exit(EXIT_FAILURE); + } + if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || + (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || + (lbuf.st_size!=buf.st_size)) { + syslog(LOG_ERR,"Somebody changed files from under us for job %s - " + "aborting",filename); + exit(EXIT_FAILURE); + } + if (buf.st_nlink > 1) { + syslog(LOG_ERR,"Someboy is trying to run a linked script for job %s", + filename); + exit(EXIT_FAILURE); + } 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) + if (fscanf(stream, "#!/bin/sh\n# atrun uid=%ld gid=%ld\n# mail %8s %d", + &nuid, &ngid, mailbuf, &send_mail) != 4) { - mailname = mailbuf; - pentry = getpwnam(mailname); - if (pentry == NULL || pentry->pw_uid != uid) { - syslog(LOG_ERR,"Userid %lu mismatch name %s - aborting job %s", - (unsigned long) uid, mailname, filename); - exit(EXIT_FAILURE); - } + syslog(LOG_ERR,"File %s is in wrong format - aborting", + filename); + exit(EXIT_FAILURE); } - else - { - mailname = pentry->pw_name; + if (mailbuf[0] == '-') { + syslog(LOG_ERR,"illegal mail name %s in %s",mailbuf,filename); + exit(EXIT_FAILURE); + } + mailname = mailbuf; + if (nuid != uid) { + syslog(LOG_ERR,"Job %s - userid %d does not match file uid %d", + filename, nuid, uid); + exit(EXIT_FAILURE); + } + if (ngid != gid) { + syslog(LOG_ERR,"Job %s - groupid %d does not match file gid %d", + filename, ngid, gid); + exit(EXIT_FAILURE); } fclose(stream); if (chdir(ATSPOOL_DIR) < 0) perr("Cannot chdir to " ATSPOOL_DIR); - + /* 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"); @@ -209,7 +230,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); - + pid = fork(); if (pid < 0) perr("Error in fork"); @@ -245,8 +266,9 @@ run_file(const char *filename, uid_t uid, gid_t gid) PRIV_START nice(tolower(queue) - 'a'); - - chdir(pentry->pw_dir); + + if (chdir(pentry->pw_dir)) + chdir("/"); if (initgroups(pentry->pw_name,pentry->pw_gid)) perr("Cannot delete saved userids"); @@ -258,7 +280,7 @@ run_file(const char *filename, uid_t uid, gid_t gid) perr("Cannot set user id"); if(execle("/bin/sh","sh",(char *) NULL, nenvp) != 0) - perr("Exec failed"); + perr("Exec failed for /bin/sh"); PRIV_END } @@ -277,7 +299,21 @@ run_file(const char *filename, uid_t uid, gid_t gid) unlink(filename); if ((buf.st_size != size) || send_mail) - { + { + PRIV_START + + if (chdir(pentry->pw_dir)) + chdir("/"); + + if (initgroups(pentry->pw_name,pentry->pw_gid)) + perr("Cannot delete saved userids"); + + if (setgid(gid) < 0) + perr("Cannot change group"); + + if (setuid(uid) < 0) + perr("Cannot set user id"); + #ifdef __FreeBSD__ execl(_PATH_SENDMAIL, "sendmail", "-F", "Atrun Service", "-odi", "-oem", @@ -285,13 +321,29 @@ run_file(const char *filename, uid_t uid, gid_t gid) #else execl(MAIL_CMD, MAIL_CMD, mailname, (char *) NULL); #endif - perr("Exec failed"); + perr("Exec failed for mail command"); + + PRIV_END } exit(EXIT_SUCCESS); } /* Global functions */ +/* Needed in gloadavg.c */ +void +perr(const char *a) +{ + if (debug) + { + perror(a); + } + else + syslog(LOG_ERR, "%s: %m", a); + + exit(EXIT_FAILURE); +} + int main(int argc, char *argv[]) { @@ -309,6 +361,7 @@ main(int argc, char *argv[]) struct dirent *dirent; struct stat buf; unsigned long ctm; + unsigned long jobno; char queue; time_t now, run_time; char batch_name[] = "Z2345678901234"; @@ -332,7 +385,7 @@ main(int argc, char *argv[]) { switch (c) { - case 'l': + case 'l': if (sscanf(optarg, "%lf", &load_avg) != 1) perr("garbled option -l"); if (load_avg <= 0.) @@ -375,31 +428,28 @@ main(int argc, char *argv[]) batch_uid = (uid_t) -1; batch_gid = (gid_t) -1; - while ((dirent = readdir(spool)) != NULL) - { + while ((dirent = readdir(spool)) != NULL) { if (stat(dirent->d_name,&buf) != 0) perr("Cannot stat in " ATJOB_DIR); /* We don't want directories */ - if (!S_ISREG(buf.st_mode)) + if (!S_ISREG(buf.st_mode)) continue; - if (sscanf(dirent->d_name,"%c%8lx",&queue,&ctm) != 2) + if (sscanf(dirent->d_name,"%c%5lx%8lx",&queue,&jobno,&ctm) != 3) continue; run_time = (time_t) ctm*60; - if ((S_IXUSR & buf.st_mode) && (run_time <=now)) - { - if (isupper(queue) && (strcmp(batch_name,dirent->d_name) > 0)) - { + if ((S_IXUSR & buf.st_mode) && (run_time <=now)) { + if (isupper(queue) && (strcmp(batch_name,dirent->d_name) > 0)) { run_batch = 1; strncpy(batch_name, dirent->d_name, sizeof(batch_name)); batch_uid = buf.st_uid; batch_gid = buf.st_gid; } - + /* The file is executable and old enough */ if (islower(queue)) @@ -412,18 +462,8 @@ main(int argc, char *argv[]) } /* run the single batch file, if any */ -#ifndef __FreeBSD__ - if (run_batch && (gloadavg() < load_avg)) { -#else - if (run_batch) { - double la; - - if (getloadavg(&la, 1) != 1) - perr("Error in getloadavg"); - if (la < load_avg) -#endif - run_file(batch_name, batch_uid, batch_gid); - } + if (run_batch && (gloadavg() < load_avg)) + run_file(batch_name, batch_uid, batch_gid); closelog(); exit(EXIT_SUCCESS); diff --git a/libexec/atrun/gloadavg.c b/libexec/atrun/gloadavg.c new file mode 100644 index 000000000000..6e996f078d58 --- /dev/null +++ b/libexec/atrun/gloadavg.c @@ -0,0 +1,69 @@ +/* + * gloadavg.c - get load average for Linux + * Copyright (C) 1993 Thomas Koenig + * + * 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(S) 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. + */ + +#ifndef __FreeBSD__ +#define _POSIX_SOURCE 1 + +/* System Headers */ + +#include +#else +#include +#endif + +/* Local headers */ + +#include "gloadavg.h" + +/* File scope variables */ + +static char rcsid[] = "$Id: gloadavg.c,v 1.2 1995/08/10 04:06:54 ache Exp $"; + +/* Global functions */ + +double +gloadavg(void) +/* return the current load average as a floating point number, or <0 for + * error + */ +{ + double result; +#ifndef __FreeBSD__ + FILE *fp; + + if((fp=fopen(PROC_DIR "loadavg","r")) == NULL) + result = -1.0; + else + { + if(fscanf(fp,"%lf",&result) != 1) + result = -1.0; + fclose(fp); + } +#else + if (getloadavg(&result, 1) != 1) + perr("Error in getloadavg"); +#endif + return result; +} diff --git a/libexec/atrun/gloadavg.h b/libexec/atrun/gloadavg.h new file mode 100644 index 000000000000..c7e2c2c7c8cc --- /dev/null +++ b/libexec/atrun/gloadavg.h @@ -0,0 +1,29 @@ +/* + * gloadavg.h - header for atrun(8) + * Copyright (C) 1993 Thomas Koenig + * + * 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(S) 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. + */ + +double gloadavg(void); +#if 0 +static char atrun_h_rcsid[] = "$Id: gloadavg.h,v 1.2 1995/08/10 04:06:55 ache Exp $"; +#endif diff --git a/usr.bin/at/LEGAL b/usr.bin/at/LEGAL new file mode 100644 index 000000000000..92b1b4983110 --- /dev/null +++ b/usr.bin/at/LEGAL @@ -0,0 +1,29 @@ +-----BEGIN PGP SIGNED MESSAGE----- + +Sorry for the long wait, but there still were a few things to +be ironed out in at, which I've finally done :-) + +The FreeBSD team does have my permission to use at, version 2.9, +under the BSD license. + +You'll find it on sunsite.unc.edu's Incoming, hopefully; the +md5 checksum is + +3ba2ca3c0e87e1a04feae2c6c1376b0d at-2.9.tgz + +Best regards + Thomas +- -- +Thomas Koenig, Thomas.Koenig@ciw.uni-karlsruhe.de, ig25@dkauni2.bitnet. +The joy of engineering is to find a straight line on a double +logarithmic diagram. + +-----BEGIN PGP SIGNATURE----- +Version: 2.6.2i + +iQCVAwUBMCjVrPBu+cbJcKCVAQFNiQP/dpWP57s/E8plVGUD3zfgOXDmKUvg8U7a +VwRzJrIMuSgnSJs0wkpvcomc3NLicipfX7hhWLh/xatPM2YbF7O5HZoNdvWvexD2 +1Y67zJ+0HFb1mPnSBOrS5RFiQAe3KqmGec6E14Rih/qNoFQZBVRFXZ4xxuwP+0Rs +e2U+TVTUz6A= +=TvyW +-----END PGP SIGNATURE----- diff --git a/usr.bin/at/Makefile.inc b/usr.bin/at/Makefile.inc index 765c9473d4dd..ec44e1f6a5a5 100644 --- a/usr.bin/at/Makefile.inc +++ b/usr.bin/at/Makefile.inc @@ -1,4 +1,4 @@ -VERSION= 2.7a +VERSION= 2.9 LOCKFILE = .lockfile ATSPOOL_DIR=/var/at/spool ATJOB_DIR=/var/at/jobs diff --git a/usr.bin/at/at.c b/usr.bin/at/at.c index d2e6e30efe5a..66655902c4fb 100644 --- a/usr.bin/at/at.c +++ b/usr.bin/at/at.c @@ -1,4 +1,4 @@ -/* +/* * at.c : Put file into atrun queue * Copyright (C) 1993, 1994 Thomas Koenig * @@ -17,7 +17,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 @@ -61,7 +61,7 @@ /* Macros */ -#ifndef ATJOB_DIR +#ifndef ATJOB_DIR #define ATJOB_DIR "/usr/spool/atjobs/" #endif @@ -78,9 +78,11 @@ #define SIZE 255 #define TIMESIZE 50 +enum { ATQ, ATRM, AT, BATCH, CAT }; /* what program we want to run */ + /* File scope variables */ -static char rcsid[] = "$Id: at.c,v 1.4 1995/04/27 19:27:41 ache Exp $"; +static char rcsid[] = "$Id: at.c,v 1.3 1995/08/08 15:24:51 ig25 Exp $"; char *no_export[] = { "TERM", "TERMCAP", "DISPLAY", "_" @@ -110,7 +112,7 @@ static void list_jobs(void); static void sigc(int signo) { -/* If the user presses ^C, remove the spool file and exit +/* If the user presses ^C, remove the spool file and exit */ if (fcreated) { @@ -149,22 +151,47 @@ static char *cwdname(void) if (getcwd(ptr, size-1) != NULL) return ptr; - + if (errno != ERANGE) perr("Cannot get directory"); - + free (ptr); size += SIZE; ptr = (char *) mymalloc(size); } } +static long +nextjob() +{ + long jobno; + FILE *fid; + + if ((fid = fopen(ATJOB_DIR ".SEQ", "r+")) != (FILE*)0) { + if (fscanf(fid, "%5lx", &jobno) == 1) { + rewind(fid); + jobno = (1+jobno) % 0xfffff; /* 2^20 jobs enough? */ + fprintf(fid, "%05lx\n", jobno); + } + else + jobno = EOF; + fclose(fid); + return jobno; + } + else if ((fid = fopen(ATJOB_DIR ".SEQ", "w")) != (FILE*)0) { + fprintf(fid, "%05lx\n", jobno = 1); + fclose(fid); + return 1; + } + return EOF; +} + static void writefile(time_t runtimer, char queue) { /* This does most of the work if at or batch are invoked for writing a job. */ - int i; + long jobno; char *ap, *ppos, *mailname; struct passwd *pass_entry; struct stat statbuf; @@ -175,7 +202,7 @@ writefile(time_t runtimer, char queue) int ch; mode_t cmask; struct flock lock; - + /* Install the signal handler for SIGINT; terminate after removing the * spool file if necessary */ @@ -213,25 +240,19 @@ writefile(time_t runtimer, char queue) fcntl(lockdes, F_SETLKW, &lock); alarm(0); - for(i=0; i= ATJOB_MX) - panic("Too many jobs already"); + for(ap=ppos; *ap != '\0'; ap ++) + if (*ap == ' ') + *ap = '0'; + + if (stat(atfile, &statbuf) != 0) + if (errno != ENOENT) + perr("Cannot access " ATJOB_DIR); /* Create the file. The x bit is only going to be set after it has * been completely written out, to make sure it is not executed in the @@ -240,7 +261,7 @@ writefile(time_t runtimer, char queue) */ cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); if ((fdes = creat(atfile, O_WRONLY)) == -1) - perr("Cannot create atjob file"); + perr("Cannot create atjob file"); if ((fd2 = dup(fdes)) <0) perr("Error in dup() of job file"); @@ -256,7 +277,7 @@ writefile(time_t runtimer, char queue) REDUCE_PRIV(DAEMON_UID, DAEMON_GID) - /* We've successfully created the file; let's set the flag so it + /* We've successfully created the file; let's set the flag so it * gets removed in case of an interrupt or error. */ fcreated = 1; @@ -278,10 +299,10 @@ writefile(time_t runtimer, char queue) if (mailname == NULL) mailname = getenv("LOGNAME"); - if ((mailname == NULL) || (mailname[0] == '\0') + if ((mailname == NULL) || (mailname[0] == '\0') || (strlen(mailname) > 8) || (getpwnam(mailname)==NULL)) { - pass_entry = getpwuid(getuid()); + pass_entry = getpwuid(real_uid); if (pass_entry != NULL) mailname = pass_entry->pw_name; } @@ -292,7 +313,8 @@ writefile(time_t runtimer, char queue) if (fpin == NULL) perr("Cannot open input file"); } - fprintf(fp, "#! /bin/sh\n# mail %8s %d\n", mailname, send_mail); + fprintf(fp, "#!/bin/sh\n# atrun uid=%ld gid=%ld\n# mail %8s %d\n", + (long) real_uid, (long) real_gid, mailname, send_mail); /* Write out the umask at the time of invocation */ @@ -317,7 +339,7 @@ writefile(time_t runtimer, char queue) for (i=0; id_name, &buf) != 0) perr("Cannot stat in " ATJOB_DIR); - + /* See it's a regular file and has its x bit turned on and * is the user's */ @@ -427,7 +459,7 @@ list_jobs() || !(S_IXUSR & buf.st_mode || atverify)) continue; - if(sscanf(dirent->d_name, "%c%8lx", &queue, &ctm)!=2) + if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3) continue; if (atqueue && (queue != atqueue)) @@ -442,42 +474,98 @@ list_jobs() } pw = getpwuid(buf.st_uid); - printf("%s\t%s\t%c%s\t%s\n", - timestr, - pw ? pw->pw_name : "???", - queue, - (S_IXUSR & buf.st_mode) ? "":"(done)", - dirent->d_name); + printf("%s\t%s\t%c%s\t%ld\n", + timestr, + pw ? pw->pw_name : "???", + queue, + (S_IXUSR & buf.st_mode) ? "":"(done)", + jobno); } PRIV_END } static void -delete_jobs(int argc, char **argv) +process_jobs(int argc, char **argv, int what) { /* Delete every argument (job - ID) given */ int i; struct stat buf; + DIR *spool; + struct dirent *dirent; + unsigned long ctm; + char queue; + long jobno; PRIV_START if (chdir(ATJOB_DIR) != 0) perr("Cannot change to " ATJOB_DIR); - for (i=optind; i < argc; i++) { - if (stat(argv[i], &buf) != 0) { - perr(argv[i]); - continue; - } - if ((buf.st_uid != real_uid) && !(real_uid == 0)) { - fprintf(stderr, "%s: Not owner\n", argv[i]); - continue; - } - if (unlink(argv[i]) != 0) - perr(argv[i]); - } + if ((spool = opendir(".")) == NULL) + perr("Cannot open " ATJOB_DIR); + PRIV_END + + /* Loop over every file in the directory + */ + while((dirent = readdir(spool)) != NULL) { + + PRIV_START + if (stat(dirent->d_name, &buf) != 0) + perr("Cannot stat in " ATJOB_DIR); + PRIV_END + + if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3) + continue; + + for (i=optind; i < argc; i++) { + if (atoi(argv[i]) == jobno) { + if ((buf.st_uid != real_uid) && !(real_uid == 0)) { + fprintf(stderr, "%s: Not owner\n", argv[i]); + exit(EXIT_FAILURE); + } + switch (what) { + case ATRM: + + PRIV_START + + if (unlink(dirent->d_name) != 0) + perr(dirent->d_name); + + PRIV_END + + break; + + case CAT: + { + FILE *fp; + int ch; + + PRIV_START + + fp = fopen(dirent->d_name,"r"); + + PRIV_END + + if (!fp) { + perr("Cannot open file"); + } + while((ch = getc(fp)) != EOF) { + putchar(ch); + } + } + break; + + default: + fprintf(stderr, + "Internal error, process_jobs = %d\n",what); + exit(EXIT_FAILURE); + break; + } + } + } + } } /* delete_jobs */ /* Global functions */ @@ -502,9 +590,9 @@ main(int argc, char **argv) char queue_set = 0; char *pgm; - enum { ATQ, ATRM, AT, BATCH }; /* what program we want to run */ + enum { ATQ, ATRM, AT, BATCH, CAT }; /* what program we want to run */ int program = AT; /* our default program */ - char *options = "q:f:mvldbV"; /* default options for at */ + char *options = "q:f:mvldbVc"; /* default options for at */ int disp_version = 0; time_t timer; @@ -550,7 +638,7 @@ main(int argc, char **argv) case 'f': atinput = optarg; break; - + case 'q': /* specify queue */ if (strlen(optarg) > 1) usage(); @@ -590,6 +678,11 @@ main(int argc, char **argv) disp_version = 1; break; + case 'c': + program = CAT; + options = ""; + break; + default: usage(); break; @@ -620,7 +713,12 @@ main(int argc, char **argv) REDUCE_PRIV(DAEMON_UID, DAEMON_GID) - delete_jobs(argc, argv); + process_jobs(argc, argv, ATRM); + break; + + case CAT: + + process_jobs(argc, argv, CAT); break; case AT: @@ -643,7 +741,7 @@ main(int argc, char **argv) timer = parsetime(argc, argv); else timer = time(NULL); - + if (atverify) { struct tm *tm = localtime(&timer); diff --git a/usr.bin/at/at.h b/usr.bin/at/at.h index 4a5a5e5a821a..40a5a6f298f9 100644 --- a/usr.bin/at/at.h +++ b/usr.bin/at/at.h @@ -1,4 +1,4 @@ -/* +/* * at.h - header for at(1) * Copyright (C) 1993 Thomas Koenig * @@ -14,7 +14,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 diff --git a/usr.bin/at/at.man b/usr.bin/at/at.man index d279ff86d084..d30a13845287 100644 --- a/usr.bin/at/at.man +++ b/usr.bin/at/at.man @@ -1,4 +1,4 @@ -.\" $Id: at.man,v 1.1 1995/04/12 02:42:31 ache Exp $ +.\" $Id: at.man,v 1.2 1995/06/24 17:15:55 joerg Exp $ .Dd April 12, 1995 .Dt "AT" 1 .Os "FreeBSD 2.1" @@ -13,6 +13,10 @@ .Op Fl mldbv .Ar time .Pp +.Nm at +.Op Fl V +.Fl c Ar job Op Ar job ... +.Pp .Nm atq .Op Fl V .Op Fl q Ar queue @@ -215,6 +219,8 @@ For .Nm atq , shows completed but not yet deleted jobs in the queue; otherwise shows the time the job will be executed. +.It Fl c +Cats the jobs listed on the command line to standart output. .Sh FILES .Bl -tag -width _ATJOB_DIR/_LOCKFILE -compact .It Pa _ATJOB_DIR diff --git a/usr.bin/at/panic.c b/usr.bin/at/panic.c index 9d21e096b85c..c171b5de399e 100644 --- a/usr.bin/at/panic.c +++ b/usr.bin/at/panic.c @@ -1,4 +1,4 @@ -/* +/* * panic.c - terminate fast in case of error * Copyright (C) 1993 Thomas Koenig * @@ -14,7 +14,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 @@ -37,7 +37,7 @@ /* File scope variables */ -static char rcsid[] = "$Id: panic.c,v 1.2 1995/04/12 02:42:32 ache Exp $"; +static char rcsid[] = "$Id: panic.c,v 1.1 1995/05/24 15:07:32 ig25 Exp $"; /* External variables */ @@ -73,8 +73,9 @@ usage(void) /* Print usage and exit. */ fprintf(stderr, "Usage: at [-V] [-q x] [-f file] [-m] time\n" + " at [-V] -c job [job ...]\n" " atq [-V] [-q x] [-v]\n" - " atrm [-V] [-q x] job ...\n" + " atrm [-V] job [job ...]\n" " batch [-V] [-f file] [-m]\n"); exit(EXIT_FAILURE); } diff --git a/usr.bin/at/panic.h b/usr.bin/at/panic.h index 61728951d864..a809b8a20999 100644 --- a/usr.bin/at/panic.h +++ b/usr.bin/at/panic.h @@ -1,4 +1,4 @@ -/* +/* * panic.h - header for at(1) * Copyright (C) 1993 Thomas Koenig * @@ -14,7 +14,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 diff --git a/usr.bin/at/parsetime.c b/usr.bin/at/parsetime.c index 88cc5edf2206..a54e7f0aed44 100644 --- a/usr.bin/at/parsetime.c +++ b/usr.bin/at/parsetime.c @@ -1,4 +1,4 @@ -/* +/* * parsetime.c - parse time for at(1) * Copyright (C) 1993, 1994 Thomas Koenig * @@ -17,7 +17,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 @@ -56,7 +56,7 @@ /* Structures and unions */ -enum tok { /* symbols */ +enum { /* symbols */ MIDNIGHT, NOON, TEATIME, PM, AM, TOMORROW, TODAY, NOW, MINUTES, HOURS, DAYS, WEEKS, @@ -69,8 +69,8 @@ enum tok { /* symbols */ /* parse translation table - table driven parsers can be your FRIEND! */ struct { - const char *name; /* token name */ - enum tok value; /* token id */ + char *name; /* token name */ + int value; /* token id */ int plural; /* is this plural? */ } Specials[] = { { "midnight", MIDNIGHT,0 }, /* 00:00:00 of today or tomorrow */ @@ -127,18 +127,18 @@ static int need; /* scanner - need to advance to next argument */ static char *sc_token; /* scanner - token buffer */ static size_t sc_len; /* scanner - lenght of token buffer */ -static enum tok sc_tokid; /* scanner - token id */ +static int sc_tokid; /* scanner - token id */ static int sc_tokplur; /* scanner - is token plural? */ -static char rcsid[] = "$Id: parsetime.c,v 1.4 1995/05/30 06:29:25 rgrimes Exp $"; +static char rcsid[] = "$Id: parsetime.c,v 1.1 1995/05/24 15:07:32 ig25 Exp $"; /* Local functions */ /* * parse a token, checking if it's something special to us */ -static enum tok -parse_token(const char *arg) +static int +parse_token(char *arg) { int i; @@ -163,8 +163,8 @@ init_scanner(int argc, char **argv) scc = argc; need = 1; sc_len = 1; - while (--argc > 0) - sc_len += strlen(*++argv); + while (argc-- > 0) + sc_len += strlen(*argv++); sc_token = (char *) mymalloc(sc_len); } /* init_scanner */ @@ -172,7 +172,7 @@ init_scanner(int argc, char **argv) /* * token() fetches a token from the input stream */ -static enum tok +static int token() { int idx; @@ -246,11 +246,11 @@ plonk(int tok) } /* plonk */ -/* +/* * expect() gets a token and dies most horribly if it's not the token we want */ static void -expect(enum tok desired) +expect(int desired) { if (token() != desired) plonk(sc_tokid); /* and we die here... */ @@ -417,7 +417,7 @@ assign_date(struct tm *tm, long mday, long mon, long year) } /* assign_date */ -/* +/* * month() picks apart a month specification * * /[ NUMBER [NUMBER]] \ @@ -489,7 +489,7 @@ month(struct tm *tm) token(); if (sc_tokid == SLASH || sc_tokid == DOT) { - enum tok sep; + int sep; sep = sc_tokid; expect(NUMBER); diff --git a/usr.bin/at/parsetime.h b/usr.bin/at/parsetime.h index 6bf3dfcf598e..30c3f207aa3d 100644 --- a/usr.bin/at/parsetime.h +++ b/usr.bin/at/parsetime.h @@ -1,4 +1,4 @@ -/* +/* * at.h - header for at(1) * Copyright (C) 1993 Thomas Koenig * @@ -14,7 +14,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 diff --git a/usr.bin/at/perm.c b/usr.bin/at/perm.c index 078af59269a8..7577ac0d8f55 100644 --- a/usr.bin/at/perm.c +++ b/usr.bin/at/perm.c @@ -1,4 +1,4 @@ -/* +/* * perm.c - check user permission for at(1) * Copyright (C) 1994 Thomas Koenig * @@ -14,7 +14,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 @@ -48,7 +48,7 @@ /* File scope variables */ -static char rcsid[] = "$Id: perm.c,v 1.1 1995/04/12 02:42:37 ache Exp $"; +static char rcsid[] = "$Id: perm.c,v 1.1 1995/05/24 15:07:32 ig25 Exp $"; /* Function declarations */ diff --git a/usr.bin/at/perm.h b/usr.bin/at/perm.h index b7e02c85c0b5..0a12a90614e2 100644 --- a/usr.bin/at/perm.h +++ b/usr.bin/at/perm.h @@ -1,4 +1,4 @@ -/* +/* * perm.h - header for at(1) * Copyright (C) 1994 Thomas Koenig * @@ -14,7 +14,7 @@ * 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, + * IN NO EVENT SHALL THE AUTHOR(S) 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 diff --git a/usr.bin/at/privs.h b/usr.bin/at/privs.h index f85206618359..2108efb84d73 100644 --- a/usr.bin/at/privs.h +++ b/usr.bin/at/privs.h @@ -1,20 +1,26 @@ -/* - * privs.h - header for privileged operations +/* + * privs.h - header for privileged operations * Copyright (C) 1993 Thomas Koenig * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * 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 program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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(S) 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. */ #ifndef _PRIVS_H @@ -62,7 +68,7 @@ extern #endif uid_t real_uid, effective_uid; -#ifndef MAIN +#ifndef MAIN extern #endif gid_t real_gid, effective_gid; @@ -81,8 +87,8 @@ gid_t real_gid, effective_gid; effective_uid = geteuid(); \ real_gid = (b); \ effective_gid = getegid(); \ - setreuid(effective_uid, real_uid); \ setregid(effective_gid, real_gid); \ + setreuid(effective_uid, real_uid); \ } #define PRIV_START {\ @@ -90,8 +96,8 @@ gid_t real_gid, effective_gid; setregid(real_gid, effective_gid); #define PRIV_END \ - setreuid(effective_uid, real_uid); \ setregid(effective_gid, real_gid); \ + setreuid(effective_uid, real_uid); \ } #define REDUCE_PRIV(a,b) {\