Path: utzoo!mnetor!uunet!husc6!purdue!i.cc.purdue.edu!j.cc.purdue.edu!ain From: ain@j.cc.purdue.edu (Patrick White) Newsgroups: comp.sources.amiga Subject: amicron (sources) Message-ID: <6979@j.cc.purdue.edu> Date: 28 Apr 88 16:13:46 GMT Organization: PUCC Land, USA Lines: 619 Keywords: part 1 of 1, uncompiled Approved: ain@j.cc.purdue.edu (Patrick White) Submitted by: kim@amdahl.uts.amdhal.com (Kim DeVaughn) Summary: unix cron for the Amiga -- run a command at a particular time. Poster Boy: Patrick White (ain@j.cc.purdue.edu) Archive Name: sources/amiga/volume4/amicron24a.s.sh.Z Tested. NOTES: I re-did the arc to sepatate the binaries, sources & docs. There are some set-up files in the docs shar. -- Pat White (co-moderator comp.sources/binaries.amiga) ARPA/UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # Makefile.lat # Makefile.mnx # lmake # Amicron24.c # timer.c # This archive created: Wed Apr 27 10:12:49 1988 # By: Patrick White (PUCC Land, USA) echo shar: extracting Makefile.lat '(299 characters)' cat << \SHAR_EOF > Makefile.lat OBJS=lib:c.o AmiCron24.o timer.o LIBS=lib:lc.lib lib:amiga.lib NAME=AmiCron CC=lc CFLAGS= -csuw -dLATTICE -r -b -v $(NAME): $(OBJS) Blink from $(OBJS) lib $(LIBS) VERBOSE SC SD ND to $(NAME) AmiCron24.o: AmiCron24.c $(CC) $(CFLAGS) AmiCron24.c timer.o: timer.c $(CC) $(CFLAGS) timer.c SHAR_EOF if test 299 -ne "`wc -c Makefile.lat`" then echo shar: error transmitting Makefile.lat '(should have been 299 characters)' fi echo shar: extracting Makefile.mnx '(145 characters)' cat << \SHAR_EOF > Makefile.mnx AmiCron: Amicron.o timer.o ln -o AmiCron timer.o Amicron.o -lc32 Amicron.o: Amicron24.c cc +l Amicron24.c timer.o: timer.c cc +l timer.c SHAR_EOF if test 145 -ne "`wc -c Makefile.mnx`" then echo shar: error transmitting Makefile.mnx '(should have been 145 characters)' fi echo shar: extracting lmake '(142 characters)' cat << \SHAR_EOF > lmake lc -M -dLATTICE -csuw -r -b -v AmiCron24 timer Blink from lib:c.o AmiCron24.o timer.o lib lib:lc.lib lib:amiga.lib VERBOSE SC SD ND to AmiCronSHAR_EOF if test 142 -ne "`wc -c lmake`" then echo shar: error transmitting lmake '(should have been 142 characters)' fi echo shar: extracting Amicron24.c '(9440 characters)' cat << \SHAR_EOF > Amicron24.c /* * amicron.c (Version 2.4(a&L) by ) * * 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 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 25.12.87 * * Removed "CronErr", an obvious Unix "feature" * Version 2.33 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 10.01.88 * ______ / ______\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 , Lattice C, user interfaces, beer addict. Christof Bonnkirch, Aztec C, telecommunications, money adict. Heiko Rath alias
, 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: * Just use the supplied "makefile.manx" for Aztec C 3.4(b) or later. * Lattice C 4.0 users just execute "lmake" or use "makefile.lattice". * The whole compilation and link procedure (including timer.c) from RAM * took me 50 seconds with Lattice 4.0 and 67 seconds with Aztec 3.4b. * Please note that you need to link timer.o for the TimeDelay() function * if you don't use make or execute lmake. * * Well, the Lattice folks claim that LATTICE get's defined by their * compiler, but it didn't work for me. So, if you don't use make or lmake, * or define LATTICE, you'll get blasted by (my) Lattice if ya don't remove * all the lines marked with "LK" below... * */ #include #include #ifndef LATTICE /*LK*/ #include /*LK*/ #endif /*LK*/ #ifdef LATTICE /*LK*/ #include #include #endif /*LK -the last one*/ #define TRUE 1 #define FALSE 0 #define CRONTAB "S:CronTab" /* Our default path */ #define MAXLINE 132 #define SIZE 64 #define TITLE "\x9B1;33mAmiCron v2.4\x9B0m by \x9B1m\x9B0m & - \x9B3mThe Software Brewery\x9B0m -\n" #define WHERE "Im Wingertsberg 45, D-6108 Weiterstadt, \x9B1mW-Germany\x9B0m\n" int eof; short sleepy; char min[SIZE], hour[SIZE], day[SIZE], month[SIZE], wday[SIZE], command[SIZE]; char *tokv[] = { min, hour, day, month, wday }; char crontabs[200]; /* You might define quite a path! */ FILE *fd; /* * This is the basics, ready for bells and whistles * */ void main(argc, argv) int argc; char *argv[]; { void showhelp(); void wakeup(); /* Below we use the same functions & variables as in wakeup() just to get the current second */ register struct tm *tm; struct tm *localtime(); long cur_time; /* Tell the guy out there what he might do with this deamon * and who made it. */ printf(TITLE); printf(WHERE); printf("Usage: %s [Path & Filename]\n",argv[0]); printf(" or '%s ?' for help\n",argv[0]); /* Now let's see if the user told us to look someplace else * for our input file or if he want's some more usage hints */ if (argc == 2) { if (argv[1][0] == '?') { showhelp(); exit(10); } else (void)strcpy(crontabs, argv[1]); } else (void)strcpy(crontabs, CRONTAB); /* If there isn't a user path, we'll use the default */ /*Now tell the user with what path & filename we wound up*/ printf("CronTab path = %s \n",crontabs); for (;;) { wakeup(); time(&cur_time); /* get the current time */ tm = localtime(&cur_time); /* break it down */ /* Now we calculate the amount of seconds * 'till the next minute */ sleepy = (60-tm->tm_sec); /* PLEASE don't decrease the 60 above, believe me, * I know what I'm doing there! */ TimeDelay(sleepy,0,0); /* sleep 'till next minute */ } } void wakeup() { register struct tm *tm; struct tm *localtime(); long cur_time; char doit[80]; time(&cur_time); /* get the current time */ tm = localtime(&cur_time); /* break it down */ /* Now let's see if there is a CronTab file out there */ if ((fd = fopen(crontabs, "r")) == NULL) { fprintf(stderr, "Can't open %s\nTry again\n", crontabs); exit(1); } 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 !!! */ (void)strcpy(doit,"RUN >nil: "); (void)strcat(doit,command); (void)Execute(doit,NULL,NULL); } } fclose(fd); } /* * 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. */ int getline() { register char *p; register int i; char buffer[MAXLINE], *scanner(), *fgets(); if (fgets(buffer, sizeof buffer, fd) == NULL) { eof = TRUE; return(FALSE); } for (p = buffer, i = 0; i < 5; i++) { if ((p = scanner(tokv[i], p)) == (char *)NULL) return(FALSE); } (void)strcpy(command, p); /* scoop the command */ return(TRUE); } char *scanner(token, offset) register char *token; /* target buffer to receive scanned token */ register char *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. */ int match(left, right) 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 (right == n); case ',': if (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(right <= n); } } void showhelp() /* by */ { printf("\nWell, you really should read the .doc file,\n"); printf("but here are some more hints:\n"); printf("You might specify only ONE command line parameter,\n"); printf("the path were Amicron should look for it's command table,\n"); printf("including the filename of the command table.\n"); printf("If you don't supply a path, Amicron will use it's default\n"); printf("path (S:CronTab).\n"); } SHAR_EOF if test 9440 -ne "`wc -c Amicron24.c`" then echo shar: error transmitting Amicron24.c '(should have been 9440 characters)' fi echo shar: extracting timer.c '(4111 characters)' cat << \SHAR_EOF > timer.c /* SIMPLE TIMER EXAMPLE PROGRAM: * * Includes dynamic allocation of data structures needed to communicate * with the timer device as well as the actual device IO * * Author: Rob Peck, 12/1/85 */ /* Stripped to TimeDelay & supporting functions for Cron inclusion */ #include "exec/types.h" #include "exec/nodes.h" #include "exec/lists.h" #include "exec/memory.h" #include "exec/interrupts.h" #include "exec/ports.h" #include "exec/libraries.h" #include "exec/io.h" #include "exec/tasks.h" #include "exec/execbase.h" #include "exec/devices.h" #include "devices/timer.h" long TimerBase; /* to get at the time comparison functions */ /* *********************************************************************** */ /* Timer function - timedelay(seconds,microseconds) Your task is put to sleep for the specified time interval. If seconds > 0, then UNIT_VBLANK is used, delay is in multiples of 60ths of a second. If seconds < 0, then UNIT_MICROHZ is used for more precision. Returns value of 0 if no errors, nonzero (and no task sleeping) Notice that since this is a multi-tasking system, the delays shown here must be considered to be only approximate. Also note that this function is used primarily to show how a timer device is accessed, including the creation of the message port and a message structure (IOStdReq). Note that there is a Delay(interval) function already in the DOS.library. (See the DOS developer's manual for details). But this Delay() function leaves LOT to be desired, . */ /* *********************************************************************** */ extern struct MsgPort *CreatePort(); extern struct IORequest *CreateExtIO(); struct timerequest *PrepareTimer(precision) SHORT precision; { /* return a pointer to a time request. If any problem, return NULL */ int error; SHORT whichunit; struct MsgPort *timerport; struct timerequest *timermsg; timerport = CreatePort(0,0); if (timerport == NULL) return(NULL); /* Error during CreatePort */ timermsg = (struct timerequest *)CreateExtIO( timerport,sizeof(struct timerequest)); if (timermsg == NULL) { DeletePort(timerport); return(NULL); /* Error during CreateExtIO */ } if(precision) /* if true, use precision timer ( under 1 second ) */ whichunit = UNIT_MICROHZ; else whichunit = UNIT_VBLANK; error = OpenDevice(TIMERNAME, whichunit, timermsg, 0); if (error != 0) { DeleteExtIO(timermsg,sizeof(struct timerequest)); DeletePort(timerport); return(NULL); /* Error during OpenDevice */ } return(timermsg); } int GetTimerBase() { int tbase; struct timerequest *tr; tr = PrepareTimer(); tbase = (int)tr->tr_node.io_Device; DeleteTimer(tr); return(tbase); } int TimeDelay(seconds,microseconds,precision) /* more precise timer than AmigaDOS Delay() */ ULONG seconds,microseconds; int precision; { int precise; struct timerequest *tr; if(seconds < 0 || precision != 0) /* do delay in terms of microseconds */ precise = TRUE; /* yes, use the precision timer. */ else precise = FALSE; /* no, not necessary */ tr = PrepareTimer(precise); /* get a pointer to an initialized * timer request block */ if(tr == NULL) return(-1); /* any nonzero return says timedelay * routine didn't work. */ WaitForTimer(tr,seconds,microseconds); DeleteTimer(tr); /* deallocate temporary structures */ return(0); } /* end of timedelay */ int WaitForTimer(tr,seconds,microseconds) ULONG seconds,microseconds; struct timerequest *tr; { tr->tr_node.io_Command = TR_ADDREQUEST; /* add a new timer request */ tr->tr_time.tv_secs = seconds; /* seconds */ tr->tr_time.tv_micro = microseconds; /* microseconds */ DoIO( tr ); /* post request to the timer */ /* goes to sleep till done */ return(0); } int DeleteTimer(tr) struct timerequest *tr; { struct MsgPort *tp; tp = tr->tr_node.io_Message.mn_ReplyPort; if(tr != 0) { CloseDevice(tr); DeleteExtIO(tr,sizeof(struct timerequest)); } if(tp != 0) DeletePort(tp); return(0); } SHAR_EOF if test 4111 -ne "`wc -c timer.c`" then echo shar: error transmitting timer.c '(should have been 4111 characters)' fi # End of shell archive exit 0