gordon@prls.UUCP (Gordon Vickers) (10/28/88)
Posting-number: Volume 5, Issue 11 Submitted-by: "Gordon Vickers" <gordon@prls.UUCP> Archive-name: cronsort #! /bin/sh # # Program Name: Cronsort - Sorts crontab file chronologically # Syntex: cronsort [-[mw]] # Written in 'C' , should be highly portable (though I'm no expert). # Developed on : VAX 11/750 under Ultrix 2.0-1 # Source Size: Just 5,217 bytes when un-shar'ed # Article size: Less than 8K bytes # # Submitted by: Gordon Vickers ; {mips|pyramid|philabs}!prls!gordon # # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # README # cronsort.c # This archive created: Wed Oct 19 13:27:15 1988 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'README'" '(994 characters)' if test -f 'README' then echo shar: "will not over-write existing file 'README'" else sed 's/^ X//' << \SHAR_EOF > 'README' X XProgram Name: Cronsort - Sorts crontab entries chronologically XSyntex: cronsort [-[mw]] XWritten in 'C' , should be highly portable (though I'm no expert). XDeveloped on : VAX 11/750 under Ultrix XSource Size: Just 5,217 bytes when un-shar'ed X X Each crontab entry is sorted on four of the five time fields. X These fields are (in order of precedents) month of year, X day of month (default, else day of week), hour, minute. X X The command line option -w will cause a sort by day of week rather than X by day of month. In any event, the other three fields are also sorted on. X The -m option is for those who have difficulty remembering that a sort X on day of month is the default. X X The output of this program is a cronological list of all crontab entries X and these entries are printed to stdout. X X There is no manual page. Sorry, but I think the program's simplistic X use doesn't warrent the time required to fight with nroff again. X X Flames, thanks, and suggestions to : SHAR_EOF if test 994 -ne "`wc -c < 'README'`" then echo shar: "error transmitting 'README'" '(should have been 994 characters)' fi fi echo shar: "extracting 'cronsort.c'" '(5217 characters)' if test -f 'cronsort.c' then echo shar: "will not over-write existing file 'cronsort.c'" else sed 's/^ X//' << \SHAR_EOF > 'cronsort.c' X/* X * cronsort - chronilogically sort the crontab file by X * record, and by fields within each record X*/ X#include <stdio.h> X X#ifdef DEBUG X#define CRONTAB "crontab" X#else X#define CRONTAB "/usr/lib/crontab" X#endif X X#define FS 50 /* Maximum field size for each crontab field */ X X#define RECSIZ BUFSIZ /* RECSIZ must be at least as long as longest X CRONTAB entry. BUFSIZ if from <stdio.h> */ Xstruct entry { X int num; /* encoded value of time */ X char record[BUFSIZ]; /* a crontab entry */ X struct entry *next; /* next entry in chain */ X } ; X Xstruct eplist { X int num; /* encoded accumlitive time values */ X struct entry *pentry; /* points to struct that num came from */ X } *eplist; Xint entries = 0; /* will need to know how many struct entries there are */ X Xmain(argc,argv) X int argc; X char **argv; X{ X void Sortmoy(), Swaps(); X int i,error = 0, wflag = 0; X char c; X char dow[FS],moy[FS],dom[FS],hr[FS],min[FS]; X char record[RECSIZ], progname[BUFSIZ]; X struct entry *entry, *top; X struct eplist *teplist; X FILE *fd; X X strcat(progname,*argv); X for(++argv; *argv!=NULL; argv++){ X if(!strcmp(*argv,"-w")) X wflag = 1; X else if (!strcmp(*argv,"-m")) X wflag = 0; X else X error = 1; X } X X if(error) { X fprintf(stderr,"Syntex: %s [ -[wm] ] \n",progname); X fprintf(stderr," where -w will sort by day of week\n"); X fprintf(stderr," -m will sort by day of month (default)\n"); X exit(0); X } X X if( (fd = fopen(CRONTAB,"r")) == NULL) { X perror(*argv); X exit(0); X } X X top = (struct entry *)NULL; /* intialize pointer to NULL, keep lint happy */ X while( (fgets(record,RECSIZ,fd)) != NULL) { /* read the records */ X sscanf(record,"%c %*s",&c); X if( !Isdigit(c) && c != '*') X continue; /* crontab record format error or just a comment */ X X if(top == NULL) { X entry = (struct entry *)malloc(sizeof(struct entry)); X top = entry; /* top; i.e. top of list. Value should never be changed */ X } X else { /* add another structure to hold the record and stuf */ X entry->next = (struct entry *)malloc(sizeof(struct entry)); X entry = entry->next; X entry->next = NULL; X } X entries++; X X /* store it for printing later */ X strcat(entry->record,record); /* source of later output */ X X /* break it up into manageable pieces */ X sscanf(record,"%s%s%s%s%s%*s",min,hr,dom,moy,dow); X X /* store the pieces so we can sort them later */ X entry->num = (Parse(moy) * 100000) + X ( (wflag ? Parse(dow) : Parse(dom)) * 10000) + X (Parse(hr) * 100 ) + Parse(min) ; X } X X /* create an array of struct pointers and integers so we will only X * need a single sort routine */ X eplist = (struct eplist *)malloc(sizeof(struct eplist) * entries ); X X /* load eplist with addresses for each struct entry */ X for(teplist=eplist,entry = top; ; teplist++,entry=entry->next) { X teplist->num = entry->num; X teplist->pentry = entry; X if(entry->next == NULL) X break; X } X Sortint(eplist); X X /**** Print the resulting sort ****/ X for(i=0,teplist=eplist; i < entries ; i++, teplist++) { X entry = teplist->pentry; X printf("%s",entry->record); /* Don't need newline, it's in record */ X } X} X X/****** Isdigit() ********/ XIsdigit(c) X char c; X{ X return( c>='0' && c<='9' ? c : NULL); X} X X/******* Parse() *******/ XParse(field) X char *field; X{ X int num, Num = 99; /* Num set to some out-of-range value */ X char *p; X X p = field; X X /* align pointer to first digit */ X if(*p == '*') /* wild card, takes precedent over explicit values */ X return(0); X X X while(*p) { /* scan the field til NULL, find lowest value within */ X if(Isdigit(*p)) { X num = (int)( (*p) - '0'); X p++; X if(Isdigit(*p)) { X num = (num *10) + (int)( (*p) - '0'); X } X } X p++; X Num = num < Num ? num : Num; X } X return(Num + 1); /* since an asteric is evaluated as zero (above) */ X} X X/******* Sortint() ******** X sort numeric data, swapping order also requires swapping the pointer X to the struct entry that contains a copy of the data. X*/ XSortint(list) X struct eplist *list; X{ X register struct eplist *top, *chain; X register int ol, il ; /* Outter Loop, Inner Loop */ X register struct entry *tmp; X int tmpnum, swapped = 0; X X chain = list; X for(ol=entries; ol > 0 ;ol--) { X if( chain->pentry == NULL ) X break; X for(il=0,chain = list; il < ol; il++,chain++) { X if( (chain + 1)->pentry == NULL ) X break; X if(chain->num > (chain + 1)->num) { X /* do a swap */ X tmp = chain->pentry; X tmpnum = chain->num; X X chain->pentry = (chain + 1)->pentry; X chain->num = (chain + 1)->num; X X (chain + 1)->pentry = tmp; X (chain + 1)->num = tmpnum; X swapped = 1; X } X } X if(!swapped) /* A pass with no swapping means we've finnished early */ X break; X } X} SHAR_EOF if test 5217 -ne "`wc -c < 'cronsort.c'`" then echo shar: "error transmitting 'cronsort.c'" '(should have been 5217 characters)' fi fi exit 0 # End of shell archive