home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
492.lha
/
AmiCron_v4.2
/
AmiCron.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-06
|
14KB
|
525 lines
/****************************************************************************
* *
* A M I C R O N *
* *
* Version 4.2 - 03-Jan-91 *
* *
* by P. Sainio *
* *
****************************************************************************
This is my version of AmiCron, I hope you like it... It's still
in public domain so if you have any ideas let us know about them.
*
* amicron.c (Version 2.5(a&L) by <CB>)
*
* Public Domain (p) No Rights Reserved
*
* This program operates as a daemon, waking up every minute
* to execute the CRONTAB table.
*
* Put in startup-sequence like:
* run newcli con:0/140/160/50/CronTask s:startcron
* The startcron file needs to contains just one line:
* amicron
*
* Some notes are included below concerning the cron table
* file format. In this version the cron table file is left
* on disk and not moved to core, and the command character
* to signify a newline '%' is not used.
*
* Some cron table entry examples:
*
* Print the date in the crontask window every minute:
* * * * * * date
*
* Print the date in the crontask window on the hour, every hour:
* 0 * * * * date
*
* Run uupc at 4:30 am every day except Sat and Sun:
* 30 4 * * 1-5 uupc -siscuva
*
* Backup the files every other day at 7:30 pm:
* 30 19 * * 1,3,5 sdbackup -s LAST dh0: incbkup_1:
*
*/
/*
* Public Domain (p) by S. R. Sampson
* Version 2.3, October 1987
* Amiga port by Rick Schaeffer October 1987
*
* Rick Schaeffer UUCP: seismo!uunet!iscuva!ricks!ricks
* E. 13611 26th Ave. Phone: (509)928-3533
* Spokane, WA 99216
*
* Modified path for CronTab & CronErr to suit Amiga enviroment better
* Version 2.31 <CB> 15.12.87
*
* Fixed bug with CronTab entries specifying an event by date (month)
* i.e. "* * 24 12 * say Merry christmas", now works!
* Version 2.32 <CB> 25.12.87
*
* Removed "CronErr", an obvious Unix "feature"
* Version 2.33 <CB> 31.12.87
*
* Additional support for Lattice 4.0, changed to complete sleep (no more
* 5 I/O ints. per second), added command line parameter for CronTab path.
* Added feature to align Cron to start on 01 seconds, including "loss"
* due to lengthy command calls or extensive I/O.
* Version 2.4 <CB> 10.01.88
*
* GRRRRRRR. Just when I thought it was safe to release that thing, C=A brings
* out AmyDos 1.3. So to have the output of programs called by Cron visible, I
* changed the "Run >nil:" parameter for execute() back to "Run ". This means,
* that you will have to look at the annoying CLI[#] messages, each time some
* program is called. I was pleased with the way the old RUN >nil: worked, and
* will try to convince Andy Finkel to bring it back.
* In the meantime, this is:
* Version 2.5 <CB> 27.03.88
*
* Changed it to use ARP. There is two versions, one that detaches itself from
* self and the other that doesn't
* Version 4.2 <PS> 03.01.91
______ /
______\O - The Software Brewery -
\\
o Sparkling, fresh software from W.-Germany
@@@@@ Straight from the bar to your Amiga
|~~~|\
| | |/
|___| With our regards to the Software Distillery
Members are (listed alphabetically):
Christian Balzer alias <CB>, Lattice C, user interfaces, beer addict.
Christof Bonnkirch, Aztec C, telecommunications, money adict.
Heiko Rath alias <HR>, Assembler, ROM-Kernal stuff, Marabou addict.
Peter Stark alias PS, Lattice C, IO & utilities, WordStar addict.
Ralf Woitinas alias RAF, Assembler, anything, Ray-Tracing addict.
Torsten Wronski alias MM, Assembler, anything, girls addict.
Beverages: Altenmuenster Brauer Bier, Urfraenkisches Landbier, Grohe Bock.
Send exotic drinks, comments, critizism, flames to:
The Software Brewery
Christian Balzer
Im Wingertsberg 45
D-6108 Weiterstadt
West-Germany
Our BBS "AmigaNode" isn't online yet. As soon as it becomes available,
you'll be the first to know :-).
*
* Compilation notes:
* Program is compiled with Lattice C 5.05 and the makefile is included.
* I have removed some of the comments, sorry about that. If you're
* intrested see the original source.
*
* NOTE!!! There is no errorchecking for crontab-file...
*/
#define MAXLINE 132
#define SIZE 64
#define ABSEXECBASE ((struct ExecBase **)4L)
#define NOCRON "Can't get crontab-file"
#define CRONPORT "AmiCronV4.2"
#define NO_MESS_MEM "No memory for message!"
#define NO_REPLY "Could not create replyport!"
#define ERR_IN_FILE "Error reading crontab-file!"
#define NO_DEVICE "Could not open timer.device!"
#define NO_TIMER_PORT "Could not open timerport!"
#define NO_CRON_PORT "Could not create CronPort!"
#define EXITING "Quiting the AmiCron!"
struct cronmsg {
struct Message cm_Msg;
char *newfile;
};
struct iobuf {
unsigned char *base;
unsigned char *ptr;
int rcnt;
int size;
};
typedef char boolean;
extern struct ArpBase *ArpBase;
extern struct DOSBase *DOSBase;
extern struct IntuitionBase *IntuitionBase;
struct MsgPort *timerport,*cronport,*mycron=NULL,*replyport;
struct iobuf fd;
struct cronmsg *newcron;
struct NewShell nsh;
struct timerequest tr;
char min[SIZE],hour[SIZE],day[SIZE],month[SIZE],wday[SIZE],command[SIZE],eof,
*tokv[]={min,hour,day,month,wday},
*com="CronFile",*args,*help="Usage: AmiCron [CronFile]",
cronfile[256]="S:CronTab";
struct TextAttr myfont = {
"topaz.font",
TOPAZ_EIGHTY,0,0 };
struct IntuiText body1={
0,1,JAM1,10,5,&myfont,NULL,NULL },body2={
0,1,JAM1,10,14,&myfont,NULL,NULL },no1={
0,1,JAM1,6,3,&myfont,"Cancel",NULL },no2={
0,1,JAM1,6,3,&myfont,"Quit",NULL };
static void cleanup(void),alarm(int),wakeup(void),MyExit(void);
static ULONG systime(void);
static boolean getline(void),getfile(void),
match(register char *,register int);
static char *scanner(register char *,register char *),
*fgets(char *,int);
void __asm __saveds AmiCron(register __a0 char *cmd,register __d0 long len) {
ULONG current,signals,getsigs,timesig,messig;
long count;
register struct tm *tm;
count=GADS(cmd,len,help,&args,com);
if (count<0) {
body1.IText=args;
AutoRequest(NULL,&body1,NULL,&no1,0,0,188,50);
cleanup();
}
if (count)
strcpy(cronfile,args);
Forbid();
if (mycron=FindPort(CRONPORT)) {
Permit();
if (replyport=CreatePort(0,0)) {
if (newcron=AllocMem(sizeof(struct cronmsg),
MEMF_PUBLIC|MEMF_CLEAR)) {
newcron->cm_Msg.mn_Node.ln_Type=NT_MESSAGE;
newcron->cm_Msg.mn_ReplyPort=replyport;
newcron->newfile=cronfile;
PutMsg(mycron,newcron);
WaitPort(replyport);
FreeMem(newcron,sizeof(struct cronmsg));
}
else {
body1.IText=NO_MESS_MEM;
AutoRequest(NULL,&body1,NULL,&no1,0,0,sizeof(NO_MESS_MEM)*8+44,50);
}
DeletePort(replyport);
}
else {
body1.IText=NO_REPLY;
AutoRequest(NULL,&body1,NULL,&no1,0,0,sizeof(NO_REPLY)*8+44,50);
}
cleanup();
}
else {
if (!(cronport=CreatePort(CRONPORT,0))) {
body1.IText=NO_CRON_PORT;
AutoRequest(NULL,&body1,NULL,&no1,0,0,sizeof(NO_CRON_PORT)*8+44,50);
cleanup();
}
}
Permit();
if (timerport=CreatePort(0,0)) {
tr.tr_node.io_Message.mn_Node.ln_Type=NT_MESSAGE;
tr.tr_node.io_Message.mn_Length=sizeof(struct timerequest);
tr.tr_node.io_Message.mn_ReplyPort=timerport;
if (!OpenDevice(TIMERNAME,UNIT_VBLANK,&tr,0)) {
if (getfile()) {
signals=SIGBREAKF_CTRL_C|(timesig = 1<<timerport->mp_SigBit)|
(messig = 1<<cronport->mp_SigBit);
for (;;) {
wakeup();
current=systime();
tm=localtime(¤t);
alarm(60-tm->tm_sec);
do {
getsigs=Wait(signals);
if (getsigs & SIGBREAKF_CTRL_C)
cleanup();
if (getsigs & messig) {
if (newcron=(struct cronmsg *)GetMsg(cronport)) {
strcpy(cronfile,newcron->newfile);
ReplyMsg(newcron);
DosFreeMem(fd.base);
fd.base=NULL;
if (!getfile())
cleanup();
}
}
}
while (!(getsigs & timesig));
}
}
}
}
cleanup();
}
static void wakeup() {
register struct tm *tm;
long cur_time;
cur_time=systime(); /* get the current time */
tm = localtime(&cur_time); /* break it down */
/* Now let's see if there is a CronTab file out there <CB> */
eof = FALSE;
while (!eof) {
if (getline() && match(min,tm->tm_min) &&
match(hour,tm->tm_hour) && match(day,tm->tm_mday) &&
match(month,tm->tm_mon+1) && match(wday,tm->tm_wday)) {
/* Weird localtime months ^ range from 0-11 !!! <CB>*/
nsh.nsh_Pri=(*ABSEXECBASE)->ThisTask->tc_Node.ln_Pri;
nsh.nsh_Control=BACKGROUND_SHELL;
nsh.nsh_Input=Input();
nsh.nsh_Output=Output();
ASyncRun(command,NULL,(struct ProcessControlBlock *)&nsh);
}
}
}
/*
* A line consists of six fields. The first five are:
*
* minute: 0-59
* hour: 0-23
* day: 1-31
* month: 1-12
* weekday: 0-6 (Sunday = 0)
*
* The fields are seperated by spaces or tabs, with the
* first field left justified (no leading spaces or tabs).
* See below for optional field syntax.
*
* The last field is the command field. This command will
* be executed by the CLI just as if typed from a console.
*/
static boolean getline() {
register char *p;
register int i;
char buffer[MAXLINE];
if (fgets(buffer,sizeof buffer) == NULL) {
eof = TRUE;
return(FALSE);
}
for (p = buffer, i = 0; i < 5; i++) {
if ((p = scanner(tokv[i], p)) == (char *)NULL)
return(FALSE);
}
strcpy(command, p); /* scoop the command */
return(TRUE);
}
static char *scanner(register char *token,register char *offset) {
/* *token target buffer to receive scanned token */
/* *offset place holder into source buffer */
while ((*offset != ' ') && (*offset != '\t') && *offset)
*token++ = *offset++;
/*
* Check for possible error condition
*/
if (!*offset)
return ((char *)NULL);
*token = '\0';
while ((*offset == ' ') || (*offset == '\t'))
offset++;
return (offset);
}
/*
* This routine will match the left string with the right number.
*
* The string can contain the following syntax:
*
* * This will return TRUE for any number
* x,y [,z, ...] This will return TRUE for any number given.
* x-y This will return TRUE for any number within
* the range of x thru y.
*/
static boolean match(register char *left,register int right) {
register int n;
register char c;
n = 0;
if (!strcmp(left, "*"))
return(TRUE);
while ((c = *left++) && (c >= '0') && (c <= '9'))
n = (n * 10) + c - '0';
switch (c) {
case '\0':
return ((boolean)(right == n));
case ',':
if ((boolean)(right == n))
return(TRUE);
do {
n = 0;
while ((c = *left++) && (c >= '0') && (c <= '9'))
n = (n * 10) + c - '0';
if (right == n)
return(TRUE);
} while (c == ',');
return(FALSE);
case '-':
if (right < n)
return(FALSE);
n = 0;
while ((c = *left++) && (c >= '0') && (c <= '9'))
n = (n * 10) + c - '0';
return((boolean)(right <= n));
}
}
static boolean getfile(void) {
BPTR lock,file;
struct FileInfoBlock *fib;
boolean succ=FALSE;
if (lock=Lock(cronfile,ACCESS_READ)) {
if (fib=AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC)) {
if (Examine(lock,fib)) {
if (fd.base=DosAllocMem(fib->fib_Size)) {
if (file=Open(cronfile,MODE_OLDFILE)) {
fd.size=Read(file,fd.base,fib->fib_Size);
if (fd.size=fib->fib_Size)
fd.ptr=fd.base;
succ=TRUE;
Close(file);
}
}
}
FreeMem(fib,sizeof(struct FileInfoBlock));
}
UnLock(lock);
}
if (!succ) {
long length;
body1.IText=NOCRON;
body1.NextText=&body2;
body2.IText=cronfile;
length=strlen(cronfile);
AutoRequest(NULL,&body1,NULL,&no1,0,0,((length>sizeof(NOCRON))?
length : sizeof(NOCRON))*8+44,59);
}
return succ;
}
static char *fgets(char *buffer,int len) {
unsigned char ch;
int count=0;
while (len>count) {
if (fd.rcnt<fd.size) {
if ((ch=*fd.ptr++)=='\n') {
buffer[count++]='\0';
fd.rcnt++;
return buffer;
}
buffer[count++]=ch;
fd.rcnt++;
}
else {
fd.rcnt=0;
fd.ptr=fd.base;
if (count==0)
return NULL;
else {
buffer[count]='\0';
return buffer;
}
}
}
}
static ULONG systime() {
tr.tr_node.io_Command=TR_GETSYSTIME;
DoIO(&tr);
return (tr.tr_time.tv_secs+(((8*365+2)*24+6)*60*60));
/* To Greenwich Mean Time ^^^^^^^^^^^^^^^^^^^^^ */
}
static void alarm(int secs) {
tr.tr_node.io_Command=TR_ADDREQUEST;
tr.tr_time.tv_secs=secs;
tr.tr_time.tv_micro=0;
SendIO(&tr);
}
static void cleanup() {
if (cronport) {
Forbid();
while (newcron=(struct cronmsg *)GetMsg(cronport))
ReplyMsg(newcron);
DeletePort(cronport);
Permit();
if (fd.base)
DosFreeMem(fd.base);
if (timerport) {
if (tr.tr_node.io_Device) {
if (tr.tr_node.io_Command)
AbortIO(&tr);
CloseDevice(&tr);
}
else {
body1.IText=NO_DEVICE;
AutoRequest(NULL,&body1,NULL,&no1,0,0,sizeof(NO_DEVICE)*8+44,50);
}
DeletePort(timerport);
}
else {
body1.IText=NO_TIMER_PORT;
AutoRequest(NULL,&body1,NULL,&no1,0,0,sizeof(NO_TIMER_PORT)*8+44,50);
}
body1.IText=EXITING;
body1.NextText=NULL;
AutoRequest(NULL,&body1,NULL,&no2,0,0,sizeof(EXITING)*8+44,50);
}
MyExit();
}