home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume5 / cronsort < prev    next >
Text File  |  1989-02-03  |  8KB  |  267 lines

  1. Path: xanth!nic.MR.NET!hal!ncoast!allbery
  2. From: gordon@prls.UUCP (Gordon Vickers)
  3. Newsgroups: comp.sources.misc
  4. Subject: v05i011: cronsort - chronologically sort the crontab file
  5. Message-ID: <8810241638.AA10328@mips.mips.com>
  6. Date: 28 Oct 88 02:37:04 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: gordon@prls.UUCP (Gordon Vickers)
  9. Lines: 255
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 5, Issue 11
  13. Submitted-by: "Gordon Vickers" <gordon@prls.UUCP>
  14. Archive-name: cronsort
  15.  
  16. #! /bin/sh
  17. #
  18. #   Program Name: Cronsort - Sorts crontab file chronologically
  19. #   Syntex: cronsort [-[mw]]
  20. #   Written in 'C' , should be highly portable (though I'm no expert).
  21. #   Developed on : VAX 11/750 under Ultrix 2.0-1
  22. #   Source Size:  Just 5,217 bytes when un-shar'ed
  23. #   Article size: Less than 8K bytes
  24. #
  25. #   Submitted by: Gordon Vickers ;  {mips|pyramid|philabs}!prls!gordon
  26. #
  27. # This is a shell archive, meaning:
  28. # 1. Remove everything above the #! /bin/sh line.
  29. # 2. Save the resulting text in a file.
  30. # 3. Execute the file with /bin/sh (not csh) to create:
  31. #    README
  32. #    cronsort.c
  33. # This archive created: Wed Oct 19 13:27:15 1988
  34. export PATH; PATH=/bin:/usr/bin:$PATH
  35. echo shar: "extracting 'README'" '(994 characters)'
  36. if test -f 'README'
  37. then
  38.     echo shar: "will not over-write existing file 'README'"
  39. else
  40. sed 's/^    X//' << \SHAR_EOF > 'README'
  41.     X
  42.     XProgram Name: Cronsort - Sorts crontab entries chronologically
  43.     XSyntex: cronsort [-[mw]]
  44.     XWritten in 'C' , should be highly portable (though I'm no expert).
  45.     XDeveloped on : VAX 11/750 under Ultrix
  46.     XSource Size:  Just 5,217 bytes when un-shar'ed
  47.     X
  48.     X     Each crontab entry is sorted on four of the five time fields.
  49.     X     These fields are (in order of precedents) month of year,
  50.     X  day of month (default, else day of week), hour, minute.
  51.     X
  52.     X    The command line option -w will cause a sort by day of week rather than
  53.     X  by day of month. In any event, the other three fields are also sorted on.
  54.     X  The -m option is for those who have difficulty remembering that a sort
  55.     X  on day of month is the default.
  56.     X
  57.     X    The output of this program is a cronological list of all crontab entries
  58.     X  and these entries are printed to stdout.
  59.     X
  60.     X    There is no manual page. Sorry, but I think the program's simplistic
  61.     X  use doesn't warrent the time required to fight with nroff again.
  62.     X
  63.     X    Flames, thanks, and suggestions to :
  64. SHAR_EOF
  65. if test 994 -ne "`wc -c < 'README'`"
  66. then
  67.     echo shar: "error transmitting 'README'" '(should have been 994 characters)'
  68. fi
  69. fi
  70. echo shar: "extracting 'cronsort.c'" '(5217 characters)'
  71. if test -f 'cronsort.c'
  72. then
  73.     echo shar: "will not over-write existing file 'cronsort.c'"
  74. else
  75. sed 's/^    X//' << \SHAR_EOF > 'cronsort.c'
  76.     X/*
  77.     X * cronsort - chronilogically sort the crontab file by
  78.     X *            record, and by fields within each record
  79.     X*/
  80.     X#include <stdio.h>
  81.     X
  82.     X#ifdef DEBUG
  83.     X#define CRONTAB "crontab" 
  84.     X#else
  85.     X#define CRONTAB "/usr/lib/crontab" 
  86.     X#endif
  87.     X
  88.     X#define FS      50       /* Maximum field size for each crontab field */
  89.     X
  90.     X#define RECSIZ  BUFSIZ   /* RECSIZ must be at least as long as longest 
  91.     X                            CRONTAB entry. BUFSIZ if from <stdio.h> */
  92.     Xstruct entry {
  93.     X               int     num;            /* encoded value of time   */
  94.     X               char    record[BUFSIZ]; /* a crontab entry         */
  95.     X               struct entry *next;     /* next entry in chain     */
  96.     X             } ;
  97.     X
  98.     Xstruct eplist {
  99.     X                int      num;         /* encoded accumlitive time values */
  100.     X                struct entry *pentry; /* points to struct that num came from */
  101.     X              } *eplist;
  102.     Xint entries = 0;   /* will need to know how many struct entries there are */
  103.     X
  104.     Xmain(argc,argv)
  105.     X  int    argc;
  106.     X  char **argv;
  107.     X{
  108.     X   void Sortmoy(), Swaps();
  109.     X   int i,error = 0, wflag = 0;
  110.     X   char c;
  111.     X   char dow[FS],moy[FS],dom[FS],hr[FS],min[FS];
  112.     X   char record[RECSIZ], progname[BUFSIZ];
  113.     X   struct entry *entry, *top;
  114.     X   struct eplist *teplist;
  115.     X   FILE *fd;
  116.     X
  117.     X   strcat(progname,*argv);
  118.     X   for(++argv; *argv!=NULL; argv++){
  119.     X      if(!strcmp(*argv,"-w"))
  120.     X        wflag = 1;
  121.     X      else if (!strcmp(*argv,"-m"))
  122.     X        wflag = 0;
  123.     X      else
  124.     X        error = 1;
  125.     X  }
  126.     X
  127.     X   if(error) {
  128.     X     fprintf(stderr,"Syntex: %s [ -[wm] ] \n",progname);
  129.     X     fprintf(stderr,"  where  -w  will sort by day of week\n");
  130.     X     fprintf(stderr,"         -m  will sort by day of month (default)\n");
  131.     X     exit(0);
  132.     X   }
  133.     X
  134.     X   if( (fd = fopen(CRONTAB,"r")) == NULL) {
  135.     X      perror(*argv);
  136.     X      exit(0);
  137.     X   }
  138.     X
  139.     X   top = (struct entry *)NULL; /* intialize pointer to NULL, keep lint happy */
  140.     X   while( (fgets(record,RECSIZ,fd)) != NULL) { /* read the records */
  141.     X     sscanf(record,"%c %*s",&c);
  142.     X     if( !Isdigit(c) && c != '*')
  143.     X       continue;  /* crontab record format error or just a comment */
  144.     X
  145.     X     if(top == NULL) {
  146.     X         entry = (struct entry *)malloc(sizeof(struct entry));
  147.     X         top = entry; /* top; i.e. top of list. Value should never be changed */
  148.     X     }
  149.     X     else { /* add another structure to hold the record and stuf */
  150.     X         entry->next = (struct entry *)malloc(sizeof(struct entry));
  151.     X         entry = entry->next;
  152.     X         entry->next = NULL;
  153.     X     }
  154.     X     entries++;
  155.     X
  156.     X     /* store it for printing later */
  157.     X     strcat(entry->record,record); /* source of later output */
  158.     X
  159.     X     /* break it up into manageable pieces */
  160.     X     sscanf(record,"%s%s%s%s%s%*s",min,hr,dom,moy,dow);
  161.     X
  162.     X     /* store the pieces so we can sort them later */
  163.     X     entry->num = (Parse(moy) * 100000) +
  164.     X                  ( (wflag ? Parse(dow) : Parse(dom)) * 10000) +
  165.     X                  (Parse(hr) * 100 ) + Parse(min) ;
  166.     X   }
  167.     X
  168.     X   /* create an array of struct pointers and integers so we will only
  169.     X   *  need a single sort routine */
  170.     X   eplist = (struct eplist *)malloc(sizeof(struct eplist) * entries );
  171.     X
  172.     X   /* load eplist with addresses for each struct entry */
  173.     X   for(teplist=eplist,entry = top;  ; teplist++,entry=entry->next) {
  174.     X      teplist->num = entry->num;
  175.     X      teplist->pentry = entry;
  176.     X      if(entry->next == NULL)
  177.     X         break;
  178.     X   }
  179.     X   Sortint(eplist);
  180.     X   
  181.     X   /**** Print the resulting sort  ****/
  182.     X   for(i=0,teplist=eplist; i < entries ; i++, teplist++) {
  183.     X     entry = teplist->pentry;
  184.     X     printf("%s",entry->record); /* Don't need newline, it's in record */
  185.     X   }
  186.     X}
  187.     X
  188.     X/****** Isdigit() ********/
  189.     XIsdigit(c)
  190.     X  char c;
  191.     X{
  192.     X   return( c>='0' && c<='9' ? c : NULL);
  193.     X}
  194.     X
  195.     X/******* Parse() *******/
  196.     XParse(field)
  197.     X  char *field;
  198.     X{
  199.     X   int num, Num = 99;  /* Num set to some out-of-range value */
  200.     X   char *p;
  201.     X
  202.     X   p = field;
  203.     X
  204.     X   /* align pointer to first digit */
  205.     X   if(*p == '*')   /* wild card, takes precedent over explicit values */
  206.     X     return(0);
  207.     X
  208.     X
  209.     X  while(*p) {        /* scan the field til NULL, find lowest value within */
  210.     X   if(Isdigit(*p)) {
  211.     X      num = (int)( (*p) - '0');
  212.     X      p++;
  213.     X      if(Isdigit(*p)) {
  214.     X         num = (num *10) + (int)( (*p) - '0');
  215.     X      }
  216.     X   }
  217.     X   p++;
  218.     X   Num = num < Num ? num : Num;
  219.     X  }
  220.     X  return(Num + 1); /* since an asteric is evaluated as zero (above) */
  221.     X}
  222.     X
  223.     X/******* Sortint() ********
  224.     X sort numeric data, swapping order also requires swapping the pointer
  225.     X to the struct entry that contains a copy of the data.
  226.     X*/
  227.     XSortint(list)
  228.     X  struct eplist *list;
  229.     X{
  230.     X  register struct eplist *top, *chain;
  231.     X  register int ol, il ; /* Outter Loop, Inner Loop */
  232.     X  register struct entry *tmp;
  233.     X  int tmpnum, swapped = 0;
  234.     X
  235.     X  chain = list;
  236.     X  for(ol=entries; ol > 0 ;ol--) {
  237.     X     if( chain->pentry == NULL )
  238.     X        break;
  239.     X     for(il=0,chain = list; il < ol; il++,chain++) {
  240.     X       if( (chain + 1)->pentry == NULL )
  241.     X          break;
  242.     X       if(chain->num > (chain + 1)->num) {
  243.     X          /* do a swap */
  244.     X          tmp = chain->pentry;
  245.     X          tmpnum = chain->num;
  246.     X
  247.     X          chain->pentry = (chain + 1)->pentry;
  248.     X          chain->num = (chain + 1)->num;
  249.     X
  250.     X          (chain + 1)->pentry = tmp;
  251.     X          (chain + 1)->num = tmpnum;
  252.     X          swapped = 1;
  253.     X       }
  254.     X     }
  255.     X   if(!swapped) /* A pass with no swapping means we've finnished early */
  256.     X     break;
  257.     X  }
  258.     X}
  259. SHAR_EOF
  260. if test 5217 -ne "`wc -c < 'cronsort.c'`"
  261. then
  262.     echo shar: "error transmitting 'cronsort.c'" '(should have been 5217 characters)'
  263. fi
  264. fi
  265. exit 0
  266. #    End of shell archive
  267.