home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (c) 1991 -- Kyle A. York
- copy / use / modify at will -- see CRON.DOC for details
- */
-
- #include <dir.h>
- #include <stdio.h>
- #include <string.h>
- #include <time.h>
- #include <process.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <io.h>
- #include <tvapi.h>
- #include <ctype.h>
- #include <sys\stat.h>
- #include <alloc.h>
- #include "pif.h"
- #include "getopt.h"
-
- extern int directvideo=0; /* use BIOS calls for writes */
- unsigned _stklen=2048; /* use a 2K stack (not default 4K) */
-
- char *buffer, /* buffer for CRONTAB file. set once at start */
- crontabname[MAXPATH], /* full path to 'crontab' */
- cronlogname[MAXPATH], /* full path to 'cron.log'*/
- crontemplate[MAXPATH]; /* full path to template ".dvp" file */
- int bufsize; /* size of input buffer */
- time_t now; /* current time */
- /*
- this function seems to be missing from the DVGLUE library.
- it pops-up an error window & displays the message. then it waits
- for ESCAPE or a mouse button to be pressed before returning
- */
- void DVError(char *fmt, ...)
- {
- struct REGPACK regs;
- OBJECT mytask;
- char errmsg[256],
- *tmp=errmsg;
- va_list ap;
- int rows=1;
-
- va_start(ap, fmt);
- vsprintf(errmsg, fmt, ap);
- va_end(ap);
-
- while (*tmp) /* count # of rows used */
- if (*(tmp++) == '\n') /* by message */
- rows++;
- mytask=TVmytask();
- regs.r_bx=0x4000 + 0x2000 + strlen(errmsg);
- regs.r_es=FP_SEG(errmsg);
- regs.r_di=FP_OFF(errmsg);
- regs.r_cx=0x5000 | rows;
- regs.r_dx=FP_SEG(mytask);
- regs.r_ax=0x101f;
- intr(0x15, ®s);
- }
-
- /*
- write info to log file
- (1) open logfile
- (2) write info with timestamp
- (3) close file
- */
- void cronlog(char *fmt, ...)
- {
- FILE *logfile;
- char logstr[256];
- va_list ap;
-
- if (!*cronlogname)
- return;
- va_start(ap, fmt);
- vsprintf(logstr, fmt, ap);
- va_end(ap);
- logfile=fopen(cronlogname, "at");
- printf("%24.24s: %s\n", ctime(&now), logstr);
- if (logfile) {
- fprintf(logfile, "%24.24s: %s\n", ctime(&now), logstr);
- fclose(logfile);
- } else
- fprintf(stderr, "cannot open logfile {%s}\n", cronlogname);
- }
-
- /*
- read the CRON file if necessary
- 1st call : open 'crontab'
- successive calls : check file time with last read, if updated, reread
- note: crontab is open FOR THE DURATION OF THE PROGRAM. it is NEVER closed
- */
- void ReadCronFile(void)
- {
- struct ftime new; /* file time now */
- static struct ftime old; /* last file time */
- static int handle=-1;
- int bytesread;
-
- if (handle < 0) {
- old.ft_day=0; /* force new read */
- handle=open(crontabname, /* name of file */
- O_RDONLY | O_TEXT | O_CREAT, /* used to open normal file */
- S_IREAD | S_IWRITE); /* used if file created */
- if (handle < 0) { /* if un-openable, abort */
- DVError("unable to open crontab file");
- exit(1);
- } else
- cronlog("{%s} opened successfully", crontabname);
- }
- getftime(handle, &new); /* get timestamp on file */
- if (memcmp(&new, &old, sizeof(new))) { /* if unequal, re-read file */
- old=new; /* update last read */
- cronlog("CRONTAB core updated");
- lseek(handle, 0, SEEK_SET); /* rewind file */
- bytesread=read(handle, buffer, min(bufsize, filelength(handle)));
- buffer[bytesread]=0;
- if (filelength(handle) >= bufsize)
- cronlog("crontab file overflowed buffer. truncated.");
- }
- }
-
- /*
- skip string ptr over spaces & tabs
- cannot use isspace() as it also skips c/r, l/f, f/f and some others
- */
- void SkipSpace(char **spc)
- {
- while ((**spc == ' ') || (**spc == 9))
- (*spc)++;
- }
-
- /*
- skip string ptr over a signed integer
- */
- void SkipNum(char **spc)
- {
- SkipSpace(spc);
- if (**spc == '-')
- (*spc)++;
- while (isdigit(**spc))
- (*spc)++;
- }
-
- /*
- skip string ptr until a space is found
- */
- void SkipNonSpc(char **spc)
- {
- while (**spc && !isspace(**spc))
- (*spc)++;
- }
-
- /*
- given a number list
- eg: 1-9,10,12-14
- check that a number is included in the list
- */
- int IsNumInList(char *s, int num)
- {
- int lo, hi;
- char *list=s;
-
- SkipSpace(&list);
- if (*list == '*')
- return(TRUE);
- while (isdigit(*list)) {
- lo=atoi(list);
- SkipNum(&list);
- if (lo == num)
- return(TRUE);
- else if (*list == '-') {
- list++;
- if (!isdigit(*list))
- return(FALSE);
- hi=atoi(list);
- SkipNum(&list);
- if ((lo <= num) && (num <= hi))
- return(TRUE);
- }
- if (*list == ',')
- list++;
- }
- return(FALSE);
- }
-
- /*
- call IsNumInList(), then skip field
- */
- int CheckNumInList(char **s, int num)
- {
- int tmp;
-
- tmp=IsNumInList(*s, num);
- SkipNonSpc(s);
- SkipSpace(s);
- return(tmp);
- }
-
- /*
- begin a new task
- assume preceding flags are checked
- this does the extension parsing for how-to-execute
- */
- int SpawnPif(char *name, char *parms, int minmem, int maxmem,
- int maxexp, int hiddenflag, int backflag)
- {
- int handle,
- size,
- t;
- DVPtype pif;
- OBJECT obj;
- char ext[MAXEXT],
- tmp[128];
-
- fnsplit(name, NULL, NULL, NULL, ext);
-
- t=(stricmp(ext, ".dvp") == 0);
- handle=open(t ? name : crontemplate, O_BINARY | O_RDONLY);
- if (handle < 0) {
- cronlog("cannot open: %s", t ? name : crontemplate);
- return(-1);
- }
- size=read(handle, &pif, sizeof(pif));
- close(handle);
- if (minmem >= 0)
- pif.minmem=minmem;
- if (maxmem >= 0)
- pif.maxmem=maxmem;
- if (maxexp >= 0)
- pif.maxexpanded=maxexp;
- if (backflag >= 0)
- pif.flags4 |= 0x10;
- if (!stricmp(ext, ".com") || !stricmp(ext, ".exe")) {
- strcpy(pif.path, name);
- pif.autocloseonexit=1;
- }
- if (!stricmp(ext, ".bat")) {
- strcpy(tmp, name);
- strcat(tmp, " ");
- strcat(tmp, parms);
- } else
- strcpy(tmp, parms);
- if (strlen(tmp) > 63) {
- cronlog("parameter string > 63 chars {%s} {%s}", name, parms);
- return(-1);
- }
- strcpy(pif.parameters, tmp);
- pif.flags2=0x20 | (*tmp ? 0x40 : 0x00);
- obj=DVapp_start(&pif, size);
- if (obj && hiddenflag)
- TVapp_hide(obj);
- if (obj)
- cronlog("%s spawned as %08lx", name, obj);
- else
- cronlog("%s <<SPAWN FAILED>>", name);
- return(0);
- }
-
- /*
- replace all occurences of rep in str with 2-digit val
- */
- void Replace(char *str, char *rep, int val)
- {
- char *ptr, tmp[3];
-
- do {
- ptr=strstr(str, rep);
- if (ptr) {
- sprintf(tmp, "%02d", val);
- memcpy(ptr, tmp, 2);
- }
- } while (ptr);
- }
-
- /*
- this does the pre-parsing.
- */
- void Execute(char *s, struct tm *tm)
- {
- char cmd[64],
- param[64],
- *ptr=s,
- done=0;
- int ii=0,
- minmem=-1, /* minimum conventional memory required */
- maxmem=-1, /* maximum conventional memory allowed */
- maxexp=-1, /* maximum expanded memory allowed */
- num, /* temp number for conventional memory */
- hiddenflag=0, /* 1 = yes */
- backflag=-1; /* 1 = start in background,
- 0 = start in foreground,
- -1 = use default */
-
- do { /* parse for prefixes */
- SkipSpace(&ptr);
- if (*ptr == '-') {
- ptr++;
- switch(*(ptr++)) {
- case 'b': backflag=1; break;
- case 'c': num=atoi(ptr);
- SkipNum(&ptr);
- if (num < 0)
- minmem=-num;
- else
- maxmem=num;
- break;
- case 'e': maxexp=atoi(ptr);
- SkipNum(&ptr);
- break;
- case 'h': hiddenflag=1;
- break;
- default: ptr-=2;
- done=1;
- break;
- }
- } else
- done=1;
- } while (!done);
- while (*ptr && !isspace(*ptr) && (ii < 64)) { /* copy command */
- cmd[ii++]=*ptr;
- ptr++;
- }
- if (ii >= 64) {
- cronlog("program name > 63 characters {%s}", s);
- return;
- }
- cmd[ii]=0;
- SkipSpace(&ptr); /* skip spaces */
- ii=0; /* everything to end-of-line */
- while (*ptr && (*ptr != '\n') && (ii < 64)) { /* are parameters for the command */
- param[ii++]=*ptr;
- ptr++;
- }
- if (ii >= 64) {
- cronlog("parameters > 63 characters {%s}", s);
- return;
- }
- param[ii]=0;
- Replace(param, "%M", tm->tm_mon+1); /* do necessary parameter */
- Replace(param, "%D", tm->tm_mday); /* replacements */
- Replace(param, "%h", tm->tm_hour);
- Replace(param, "%m", tm->tm_min);
- SpawnPif(cmd, param, minmem, maxmem, maxexp, hiddenflag, backflag);
- }
-
- /*
- this is the loop where stuff actually gets done.
- it checks the core image to see if anything is ready
- to be spawned & sends the necessary data for spawning
- */
- void DoCronStuff(struct tm *tm)
- {
- char *bufptr=buffer,
- tmp;
-
- while (*bufptr) {
- if (CheckNumInList(&bufptr, tm->tm_min) &&
- CheckNumInList(&bufptr, tm->tm_hour)) {
- tmp=CheckNumInList(&bufptr, tm->tm_mday);
- if (CheckNumInList(&bufptr, tm->tm_mon))
- if (CheckNumInList(&bufptr, tm->tm_wday) || tmp)
- Execute(bufptr, tm);
- }
- while ((*bufptr != '\n') && *bufptr)
- bufptr++;
- if (*bufptr == '\n')
- bufptr++;
- }
- }
-
- void main(int argc, char **argv)
- {
- struct tm *tm; /* structure for more readable time */
- OBJECT timer; /* TV timer object */
- char drive[MAXDRIVE], /* path to CRON.EXE */
- dir[MAXDIR];
- int key,
- errflag;
-
- DVinit(); /* initialize DV functions */
-
- bufsize=1024;
- fnsplit(argv[0], drive, dir, NULL, NULL);
- fnmerge(crontabname, drive, dir, "crontab", NULL);
- fnmerge(cronlogname, drive, dir, "cron", ".log");
- fnmerge(crontemplate, drive, dir, "crondos", ".dvp");
-
- errflag=0;
- while ((key=getopt(argc, argv, "c:d:l:m:")) != EOF) {
- switch(key) {
- case 'c': strcpy(crontabname, optarg); break;
- case 'd': strcpy(crontemplate, optarg); break;
- case 'l': if (!stricmp(optarg, "-"))
- *cronlogname=0;
- else
- strcpy(cronlogname, optarg);
- break;
- case 'm': bufsize=atoi(optarg);
- break;
- default: errflag=1;
- break;
- }
- }
- if (errflag) {
- DVError("format:\n\r %s [-c crontabname] [-d crontemplate] [-l-] "
- "[-l logfilename] [-m memsize]",
- argv[0]);
- exit(1);
- }
- printf("Buffer size: %d\n", bufsize);
- printf("CRONTAB: %s\n", crontabname);
- printf("Log file: %s\n", cronlogname);
- printf("Template: %s\n", crontemplate);
-
- if (!(buffer=malloc(bufsize))) { /* allocate buffer */
- DVError("Could not allocate CRONTAB buffer");
- exit(1);
- }
- if (access(crontemplate, 0)) { /* check that template */
- DVError("Template not found {%s}", crontemplate); /* exists */
- exit(1);
- }
-
- timer=TVtimer_new(); /* initialize timer */
- do {
- time(&now); /* get current time */
- tm=localtime(&now); /* in structure */
- TVtimer_begin(timer, 100*(60-tm->tm_sec)); /* start countdown until
- next minute */
- ReadCronFile(); /* load the CRON file */
- DoCronStuff(tm); /* execute instructions */
- TVtimer_wait(timer); /* give-up CPU until
- counter reaches 0 */
- } while (1); /* repeat indefinetly */
- }