|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6898 (0x1af2)
Types: TextFile
Notes: UNIX file
Names: »Ncron.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/Ncron.c«
/*
* Cron. Execute commands stored in /usr/lib/crontab at preset times.
* It sets its uid and gid to those of daemon, if possible.
*/
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <ctype.h>
#include <pwd.h>
#define TRUE (0 == 0)
#define FALSE (0 != 0)
/*
* Time field types.
*/
#define MIN 0
#define HOUR 1
#define MDAY 2
#define MON 3
#define WDAY 4
/*
* (Finite) States in valid().
*/
#define START 0
#define INT 1
#define INTDASH 2
#define RANGE 3
#define STR 4
#define STRPLUS 5
#define ERR 6
#define END 7
#define GLOB ('*')
/*
* Tokens returned by gettoken(). Tokens are integers. EOF is also a token.
* INT, STR and GLOB above are also tokens.
*/
#define DASH ('-')
#define COMMA (',')
#define WS (' ')
#define PERCENT (-2)
#define NEWLINE (-3)
struct tm *tm;
long clock;
int tmfield[5];
FILE *f;
extern int errno;
int ugtokflag = FALSE;
int ugtoken;
int ufetflag = FALSE;
int ufetval;
char *tokbuf;
int buflen = 512;
char crontab[] = "/usr/lib/crontab";
char clog[] = "/usr/lib/cronlog";
main()
{
int n;
register FILE *logf;
sigsetup();
todaemon();
tokbuf = malloc(buflen);
chdir("/bin");
time(&clock);
tm = localtime(&clock);
alarm(61 - tm->tm_sec);
for (;;) {
/* Put the time values into tmfield[] for easy reference.
* localtime() gives tm_mon in the range 0-11, tm_wday, 0-6
* (0=sunday). These are adjusted for cron's syntax.
*/
tmfield[MIN] = tm->tm_min;
tmfield[HOUR] = tm->tm_hour;
tmfield[MDAY] = tm->tm_mday;
tmfield[MON] = tm->tm_mon + 1;
tmfield[WDAY] = tm->tm_wday;
if (tm->tm_min == 0) {
logf = fopen(clog, "a");
fputc(0x0A, logf);
fwrite(ctime(&clock), strlen(ctime(&clock)), 1, logf);
fputc(0x0A, logf);
fclose(logf);
}
if ((f = fopen(crontab, "r")) != NULL) {
while (tex() != EOF)
;
fclose(f);
}
while (wait(&n) != -1)
;
if (errno == ECHILD)
pause();
}
}
/*
* Test and Execute: tests a crontab entry against the time fields in `tm' to
* see if it should be executed, if so it executes. f is left pointing to the
* next entry (line). Returns EOF when encountered, something else otherwise.
*/
tex()
{
register int fieldnum;
for (fieldnum = MIN; fieldnum <= WDAY; ++fieldnum)
if (!valid(fieldnum))
return (skip_it());
return (do_it());
}
/*
* Valid(fieldnum) parses the next time field from the current line in crontab
* and checks whether tmfield[fieldnum] satisfies the constraints of that time
* field. Returns TRUE if so, FALSE if not. Leaves f at the next field.
* Detects syntax errors in the time fields.
*/
valid(fieldnum)
int fieldnum;
{
register int t;
register int ival;
register int state = START;
int ival2;
int tm_val = tmfield[fieldnum];
if (fieldnum == MIN) {
while ((t = gettoken()) == WS || t == NEWLINE)
;
ungettoken(t);
}
for (;;) {
t = gettoken();
switch (state) {
case START:
switch (t) {
case INT:
if (strlen(tokbuf) <= 2) {
ival = atoi(tokbuf);
state = INT;
}
else
state = ERR;
break;
case GLOB:
state = GLOB;
break;
case WS:
state = END;
break;
default:
state = ERR;
break;
}
break;
case INT:
if (t == COMMA || t == WS) {
if (ival == tm_val) {
while (t != WS)
t = gettoken();
return (TRUE);
}
state = (t == WS) ? END : START;
}
else if (t == DASH)
state = INTDASH;
else
state = ERR;
break;
case INTDASH:
if (t == INT && strlen(tokbuf) <= 2) {
ival2 = atoi(tokbuf);
state = RANGE;
}
else
state = ERR;
break;
case RANGE:
if (t == COMMA || t == WS) {
if (ival <= tm_val && tm_val <= ival2) {
while (t != WS)
t = gettoken();
return (TRUE);
}
state = (t == WS) ? END : START;
}
else
state = ERR;
break;
case GLOB:
if (t == COMMA || t == WS) {
while (t != WS)
t = gettoken();
return (TRUE);
}
else
state = ERR;
break;
} /* End switch on state */
if (state == END)
return (FALSE);
if (state == ERR) {
ungettoken(t);
ungettoken(skip_it());
return (FALSE);
}
}
}
ungettoken(t)
int t;
{
ugtokflag = TRUE;
ugtoken = t;
}
gettoken()
{
register int c;
register char *sp = tokbuf;
register char *mark;
int posn;
if (ugtokflag) {
ugtokflag = FALSE;
return (ugtoken);
}
switch (c = fetch()) {
case NEWLINE:
case EOF:
case PERCENT:
return (c);
case ' ':
case '\t':
while ((c = fetch()) == ' ' || c == '\t')
;
unfetch(c);
return (WS);
case '-':
return (DASH);
case ',':
return (COMMA);
case '*':
return (GLOB);
}
/*
* Case of INT. Place ascii digit string into tokbuf.
*/
if (isdigit(c)) {
*sp++ = c;
while (isdigit(c = fetch()))
*sp++ = c;
unfetch(c);
*sp = '\0';
return (INT);
}
/*
* The only remaining possibility is the token STR or STRPLUS.
*/
*sp++ = c;
mark = tokbuf + buflen - 2;
while ((c = fetch()) != EOF && c != NEWLINE && c != PERCENT) {
if (sp == mark) {
posn = sp - tokbuf;
tokbuf = realloc(tokbuf, (buflen += 128));
sp = tokbuf + posn;
mark = sp + buflen;
}
*sp++ = c;
}
*sp = '\0';
if (c == PERCENT)
return (STRPLUS);
unfetch(c);
return (STR);
}
unfetch(c)
int c;
{
ufetval = c;
ufetflag = TRUE;
}
fetch()
{
register int c;
register int c2;
if (ufetflag) {
ufetflag = FALSE;
return (ufetval);
}
for (;;)
switch (c = getc(f)) {
case '%':
return (PERCENT);
case '\n':
return (NEWLINE);
case '\\':
if ((c2 = getc(f)) == '%')
return ('%');
else if (c2 == '\n')
continue;
else {
ungetc(c2, f);
return ('\\');
}
default:
return (c);
}
}
skip_it()
{
register int t;
while ((t = gettoken()) != EOF && t != NEWLINE)
;
return (t);
}
do_it()
{
register int c;
register FILE *fp, *logf;
if ((c = gettoken()) != STR && c != STRPLUS) {
ungettoken(c);
return (skip_it());
}
if ((fp = popen(tokbuf, "w")) == NULL) {
fprintf(stderr, "Cron:\tCould not popen: %s\n\t\
errno = %d: %s.\n", tokbuf, errno, perror());
return (skip_it());
}
logf = fopen(clog, "a");
fwrite(tokbuf, strlen(tokbuf), 1, logf);
fputc(0x0A, logf);
fclose(logf);
if (c == STR) {
fclose(fp);
return (gettoken());
}
while ((c = fetch()) != NEWLINE && c != EOF)
if (c == PERCENT)
putc('\n', fp);
else
putc(c, fp);
putc('\n', fp);
fclose(fp);
return(c);
}
sigsetup()
{
int catchalarm();
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGALRM, catchalarm);
}
catchalarm()
{
signal(SIGALRM, catchalarm);
time(&clock);
tm = localtime(&clock);
alarm(61 - tm->tm_sec);
}
todaemon()
{
register struct passwd *pwp;
struct passwd *getpwnam();
pwp = getpwnam("daemon");
endpwent();
if (pwp == NULL)
return;
setgid(pwp->pw_gid);
setuid(pwp->pw_uid);
}