Files
Arquivotheca.SunOS-4.1.4/usr.etc/cron/crontab.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

448 lines
10 KiB
C

/* Copyright (c) 1984 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ifndef lint
static char sccsid[] = "@(#)crontab.c 1.1 94/10/31 SMI"; /* from S5R3 1.8 */
#endif
/**************************************************************************
*** C r o n t a b . c ***
**************************************************************************
date: 7/2/82
description: This program implements crontab (see cron(1)).
This program should be set-uid to root.
files:
/usr/lib/cron drwxr-xr-x root sys
/usr/lib/cron/cron.allow -rw-r--r-- root sys
/usr/lib/cron/cron.deny -rw-r--r-- root sys
**************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <pwd.h>
#include "cron.h"
#define TMPFILE "_cron" /* prefix for tmp file */
#define CRMODE 0400 /* mode for creating crontabs */
#define BADCREATE "can't create your crontab file in the crontab directory."
#define BADOPEN "can't open your crontab file"
#define BADREAD "error reading your crontab file"
#define BADUSAGE "proper usage is: \n crontab [file | -e [user] | -l [user] | -r [user] ]"
#define INVALIDUSER "you are not a valid user (no entry in /etc/passwd)."
#define UINVALIDUSER "the specified user is not a valid user (no entry in /etc/passwd)."
#define NOTALLOWED "you are not authorized to use cron. Sorry."
#define NOTROOT "you must be super-user to change or read another user's crontab file"
#define UNOTALLOWED "the specified user is not authorized to use cron."
#define EOLN "unexpected end of line."
#define UNEXPECT "unexpected character found in line."
#define OUTOFBOUND "number out of bounds."
extern int opterr, optind;
extern char *optarg, *xmalloc();
extern int errno;
extern char *errmsg();
int err,cursor,catch();
char *cf,*tnam,line[CTLINESIZE];
char edtemp[5+13+1];
main(argc,argv)
char **argv;
{
int c, eflag, rflag, lflag, errflg;
int ruid, euid;
char login[UNAMESIZE],*getuser();
extern char *getenv();
register char *pp;
register FILE *fp;
register FILE *tmpfp;
struct stat stbuf;
time_t omodtime;
char *editor;
char buf[BUFSIZ];
eflag = 0;
rflag = 0;
lflag = 0;
errflg = 0;
while ((c=getopt(argc, argv, "elr")) != EOF)
switch (c) {
case 'e':
if (lflag || rflag)
errflg++;
else
eflag++;
break;
case 'l':
if (eflag || rflag)
errflg++;
else
lflag++;
break;
case 'r':
if (eflag || lflag)
errflg++;
else
rflag++;
break;
case '?':
errflg++;
break;
}
argc -= optind;
argv += optind;
if (errflg || argc > 1)
crabort(BADUSAGE);
euid = geteuid();
ruid = getuid();
if ((eflag || lflag || rflag) && argc == 1) {
if (ruid != 0)
crabort(NOTROOT);
pp = *argv++;
argc--;
if (getpwnam(pp) == NULL)
crabort(UINVALIDUSER);
if (!allowed(pp,CRONALLOW,CRONDENY))
crabort(UNOTALLOWED);
} else {
pp = getuser(ruid);
if(pp == NULL)
crabort(INVALIDUSER);
if (!allowed(pp,CRONALLOW,CRONDENY))
crabort(NOTALLOWED);
}
strcpy(login,pp);
cf = xmalloc(strlen(CRONDIR)+strlen(login)+2);
strcat(strcat(strcpy(cf,CRONDIR),"/"),login);
if (rflag) {
unlink(cf);
sendmsg(DELETE,login);
exit(0);
}
if (lflag) {
if((fp = fopen(cf,"r")) == NULL)
crabortperror(BADOPEN);
while(fgets(line,CTLINESIZE,fp) != NULL) {
fputs(line,stdout);
if(ferror(stdout))
crabortperror("write error on standard output");
}
fclose(fp);
if (fflush(stdout) == EOF)
crabortperror("write error on standard output");
exit(0);
}
if (eflag) {
if((fp = fopen(cf,"r")) == NULL) {
if(errno != ENOENT)
crabortperror(BADOPEN);
}
/*
* Temporarily give up privileges.
*/
setreuid(-1, ruid);
(void)strcpy(edtemp, "/tmp/crontabXXXXXX");
(void)mktemp(edtemp);
if((tmpfp = fopen(edtemp,"w")) == NULL)
crabortperror("can't create temporary file");
if(fp != NULL) {
/*
* Copy user's crontab file to temporary file.
*/
while(fgets(line,CTLINESIZE,fp) != NULL) {
fputs(line,tmpfp);
if(ferror(tmpfp)) {
fclose(fp);
fclose(tmpfp);
crabortperror("write error on temporary file");
}
}
if (ferror(fp)) {
fclose(fp);
fclose(tmpfp);
crabortperror(BADREAD);
}
fclose(fp);
}
if(fclose(tmpfp) == EOF)
crabortperror("write error on temporary file");
if(stat(edtemp, &stbuf) < 0)
crabortperror("can't stat temporary file");
omodtime = stbuf.st_mtime;
editor = getenv("VISUAL");
if (editor == NULL)
editor = getenv("EDITOR");
if (editor == NULL)
editor = "vi";
(void)sprintf(buf, "%s %s", editor, edtemp);
sleep(1); /* To fix bug on line 205, where
the mod time can be same even though
file was changed, because time
resolution is 1 second. */
if (system(buf) == 0) {
/* sanity checks */
if((tmpfp = fopen(edtemp, "r")) == NULL)
crabortperror("can't open temporary file");
if(fstat(fileno(tmpfp), &stbuf) < 0)
crabortperror("can't stat temporary file");
if(stbuf.st_size == 0)
crabort("temporary file empty");
if(omodtime == stbuf.st_mtime) {
(void)unlink(edtemp);
fprintf(stderr,
"The crontab file was not changed.\n");
exit(0);
}
/*
* Reclaim privileges.
*/
setreuid(-1, euid);
copycron(tmpfp);
(void)unlink(edtemp);
} else {
/*
* Couldn't run editor.
*/
(void)unlink(edtemp);
exit(1);
}
} else {
if (argc==0)
copycron(stdin);
else {
if (access(argv[0],04) || (fp=fopen(argv[0],"r"))==NULL)
crabortperror(argv[0]);
copycron(fp);
}
}
sendmsg(ADD,login);
exit(0);
/* NOTREACHED */
}
/******************/
copycron(fp)
/******************/
FILE *fp;
{
FILE *tfp,*fdopen();
char pid[6],*strcat(),*strcpy();
int t;
sprintf(pid,"%-5d",getpid());
tnam=xmalloc(strlen(CRONDIR)+strlen(TMPFILE)+7);
strcat(strcat(strcat(strcpy(tnam,CRONDIR),"/"),TMPFILE),pid);
/* catch SIGINT, SIGHUP, SIGQUIT signals */
if (signal(SIGINT,catch) == SIG_IGN) signal(SIGINT,SIG_IGN);
if (signal(SIGHUP,catch) == SIG_IGN) signal(SIGHUP,SIG_IGN);
if (signal(SIGQUIT,catch) == SIG_IGN) signal(SIGQUIT,SIG_IGN);
if (signal(SIGTERM,catch) == SIG_IGN) signal(SIGTERM,SIG_IGN);
if ((t=creat(tnam,CRMODE))==-1) crabortperror(BADCREATE);
if ((tfp=fdopen(t,"w"))==NULL)
crabort(BADCREATE);
err=0; /* if errors found, err set to 1 */
while (fgets(line,CTLINESIZE,fp) != NULL) {
cursor=0;
while(line[cursor] == ' ' || line[cursor] == '\t')
cursor++;
if(line[cursor] == '#')
goto cont;
if (next_field(0,59)) continue;
if (next_field(0,23)) continue;
if (next_field(1,31)) continue;
if (next_field(1,12)) continue;
if (next_field(0,7)) continue;
if (line[++cursor] == '\0') {
cerror(EOLN);
continue;
}
cont:
if (fputs(line,tfp) == EOF)
crabortperror(BADCREATE);
}
if (ferror(fp)) {
fclose(fp);
/*
* Don't do an "fclose", as that may do a "write" which may
* fail, and cause the wrong "perror" error message to be
* printed.
*/
(void)close(fileno(tfp));
crabortperror(BADREAD);
}
fclose(fp);
if (fclose(tfp) == EOF)
crabortperror(BADCREATE);
if (!err) {
/* make file tfp the new crontab */
if (rename(tnam,cf)==-1)
crabortperror(BADCREATE);
} else
unlink(tnam);
tnam = NULL; /* file no longer exists */
}
/*****************/
next_field(lower,upper)
/*****************/
int lower,upper;
{
int num,num2;
while ((line[cursor]==' ') || (line[cursor]=='\t')) cursor++;
if (line[cursor] == '\0') {
cerror(EOLN);
return(1);
}
if (line[cursor] == '*') {
cursor++;
if ((line[cursor]!=' ') && (line[cursor]!='\t')) {
cerror(UNEXPECT);
return(1);
}
return(0);
}
while (TRUE) {
if (!isdigit(line[cursor])) {
cerror(UNEXPECT);
return(1);
}
num = 0;
do {
num = num*10 + (line[cursor]-'0');
} while (isdigit(line[++cursor]));
if ((num<lower) || (num>upper)) {
cerror(OUTOFBOUND);
return(1);
}
if (line[cursor]=='-') {
if (!isdigit(line[++cursor])) {
cerror(UNEXPECT);
return(1);
}
num2 = 0;
do {
num2 = num2*10 + (line[cursor]-'0');
} while (isdigit(line[++cursor]));
if ((num2<lower) || (num2>upper)) {
cerror(OUTOFBOUND);
return(1);
}
}
if ((line[cursor]==' ') || (line[cursor]=='\t')) break;
if (line[cursor]=='\0') {
cerror(EOLN);
return(1);
}
if (line[cursor++]!=',') {
cerror(UNEXPECT);
return(1);
}
}
return(0);
}
/**********/
cerror(msg)
/**********/
char *msg;
{
fprintf(stderr,"%scrontab: error on previous line; %s\n",line,msg);
err=1;
}
/**********/
catch()
/**********/
{
unlink(tnam);
exit(1);
}
/**********/
crabort(msg)
/**********/
char *msg;
{
int sverrno;
if (strcmp(edtemp, "") != 0) {
sverrno = errno;
(void)unlink(edtemp);
errno = sverrno;
}
if (tnam != NULL) {
sverrno = errno;
(void)unlink(tnam);
errno = sverrno;
}
fprintf(stderr,"crontab: %s\n",msg);
exit(1);
}
/****************/
crabortperror(msg)
/****************/
char *msg;
{
int sverrno;
if (strcmp(edtemp, "") != 0) {
sverrno = errno;
(void)unlink(edtemp);
errno = sverrno;
}
fprintf(stderr,"crontab: %s: %s\n", msg, errmsg(errno));
exit(1);
}
/***********/
sendmsg(action,fname)
/****************/
char action;
char *fname;
{
static int msgfd = -2;
struct message *pmsg;
register int i;
pmsg = &msgbuf;
if(msgfd == -2)
if((msgfd = open(FIFO,O_WRONLY|O_NDELAY)) < 0) {
if(errno == ENXIO || errno == ENOENT)
fprintf(stderr,"cron may not be running - call your system administrator\n");
else
perror("crontab: error in message queue open");
return;
}
pmsg->etype = CRON;
pmsg->action = action;
strncpy(pmsg->fname,fname,FLEN);
if((i = write(msgfd,pmsg,sizeof(struct message))) < 0)
perror("crontab: error in message send");
else if (i != sizeof(struct message))
fprintf(stderr,"crontab: error in message send: Premature EOF\n");
}