home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume5 / retouch / retouch.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  6.1 KB  |  278 lines

  1. /* @(#) retouch.c 1.0 10/25/85
  2. */
  3. /* retouch.c: set update time to match SCCS id
  4.  
  5.    Copyright (c) 1985, Joel West (ihnp4!gould9!joel)
  6.    License for non-commercial use freely granted as long
  7.    as this notice is retained.
  8.  
  9.    The id should be of the form
  10.         @(#) xxxxxxx 10/23/85
  11.     or    @(#) xxxxxxx 85/10/23
  12.    it assumes date is the last non-blank thing on the line
  13.    and this program will only work between 1970 and 2000, inclusive
  14.  
  15.    works best if only one id (ignores others) and if id is at the
  16.    top of the file.
  17.  
  18.    Does not retouch if not found in first 10 lines; should be
  19.    an optionable parameter.  A line is a newline or a null,
  20.    so this just might work on a binary file.
  21.  
  22. */
  23.  
  24. #include <sys/types.h>
  25. typedef struct {
  26.     time_t actime;
  27.     time_t modtime;
  28. } utimbuf;
  29.  
  30. #include <sys/stat.h>
  31. #include <errno.h>
  32. #ifdef BSD
  33. extern int errno;
  34. #endif
  35.  
  36. #include <stdio.h>
  37. #define ungetchar(c) ungetc(c,stdin)
  38.  
  39. #ifdef BSD
  40. # include <strings.h>
  41. # include <sys/time.h>
  42. #else
  43. # include <string.h>
  44. # include <time.h>
  45. #endif
  46. #ifdef USG
  47. # define index(s,c) strchr(s,c)
  48. #endif
  49.  
  50. #ifndef TRUE
  51. # define TRUE (1)
  52. # define FALSE (0)
  53. #endif
  54.  
  55. /* below are hour and minute at local time that should be
  56.    time-stamped; default 00:00:00.  No user control over seconds  */
  57. #define STDHR 00
  58. #define STDMIN 00
  59.  
  60. #define SCCSKEY "@(#)"
  61. #define SCCSCHR '@'
  62.  
  63. #define EOL '\n'
  64. #define EOS '\0'
  65.  
  66. int optg = 0, optd = 0, optv = 0;
  67. long stddate;
  68.  
  69. main(argc,argv)
  70. int argc;
  71. char **argv;
  72. {    int depthlim,line,i,sccslen,touched;
  73.     char *p,*filenam,buff[1024];
  74.     int c,errind;
  75.  
  76.     depthlim = 10;
  77.     sccslen = strlen(SCCSKEY);
  78.     errind = 0;
  79.  
  80.     for (i = 1; i<argc && errind == 0; i++)
  81.     {   if (*argv[i] != '-')
  82.         break;
  83.         p = argv[i];
  84.         while (*(++p))
  85.         switch(*p)
  86.         {    case 'g':
  87.             optg++;
  88.             break;
  89.         case 'v':
  90.             optv++;
  91.             break;
  92.         case 'd':
  93.             if (optd)
  94.             errind++;
  95.             else
  96.             {   optd++;
  97.             stddate = dateatol(argv[++i]);
  98.             if (stddate < 0)
  99.             {   fprintf(stderr,"%s: invalid date format\n",argv[i]);
  100.                 exit (0);
  101.             }
  102.             }
  103.             break;
  104.         default:
  105.             errind++;
  106.         }
  107.     }
  108.  
  109.     if (errind || i >= argc)
  110.     {   fprintf(stderr, 
  111.             "usage: %s [-v ] [-g] [-d date] file1 [file2 ... ]\n", 
  112.             argv[0]);
  113.         exit (0);
  114.     }
  115.  
  116.     for (; i<argc; i++)
  117.     {   filenam = argv[i];
  118.         if (freopen(filenam, "r", stdin) == NULL)
  119.         {    perror(filenam);
  120.         exit(errno);
  121.         }
  122.         touched = 0;
  123.         if (optd)        /* one date for all */
  124.         {    setupdtime(filenam, stddate);
  125.         touched++;
  126.         goto settouch;
  127.         }
  128.         
  129.         for (line = 1; line <= depthlim; line++)
  130.         {    while ( 1 )
  131.         {   c = getchar();
  132.             if (c == EOF)
  133.             goto settouch;
  134.             if (c == EOS || c == EOL)
  135.             break;
  136.             if (c == SCCSCHR)
  137.             {
  138.             ungetchar(c);
  139.             gets(buff);        /* won't work on binary */
  140.             if (strncmp(buff, SCCSKEY, sccslen) == 0)
  141.             {    p = buff+strlen(buff);    /* use last nonblank */
  142.                 while (*(--p) == ' ')    /* field in string */
  143.                 ;
  144.                 while (*p != ' ' && *p != '\t')
  145.                 --p;
  146.                 if ( setupdtime(filenam, dateatol(++p)) )
  147.                 touched++;
  148.                 goto settouch;
  149.             }
  150.             }
  151.         } /* within line */
  152.         } /* end of line */
  153. settouch:
  154.         if (touched==0)
  155.         fprintf(stderr, "%s: not retouched\n", filenam);
  156.         else
  157.         if (optv)
  158.             fprintf(stderr, "%s: retouched\n", filenam);
  159.     } /* end of file */
  160. }
  161.  
  162. /* Reset the file's update time to the specified date.  If the date is dubious,
  163.    don't reset it at all
  164. */
  165. int setupdtime(fname, mtime)
  166. char *fname;
  167. long mtime;
  168. {    utimbuf timep;
  169.     struct stat statbuf;
  170.  
  171.     stat(fname, &statbuf);
  172.     timep.actime = statbuf.st_atime;    /* copy current accessed time */
  173.  
  174.     if (mtime > 0)            /* valid date */
  175.     {   timep.modtime = mtime;
  176.         utime(fname, &timep);
  177.         return (TRUE);
  178.     }
  179.     return (FALSE);
  180. }
  181.  
  182. #define NSECYR 31536000
  183. /* 365*24*60*60 */
  184. #define NSECDA 86400
  185. #define APPROXT(yr,mo,da) (((yr-70)*NSECYR) + ((mo*30)+da)*NSECDA)
  186. #define INVDATE (-1)
  187. long dateatol(string)
  188. char *string;
  189. {    char *p,*q;
  190.     int mdy[3],mo,da,yr,i,num;
  191.     struct tm *tmptr;
  192.     long timsec,approxsec,deltasec,lasttimsec,maxdelta,mindelta;
  193.     int deltasign;
  194.     static char *numstr = "0123456789";
  195.  
  196.     p = string;
  197.     while (*p == ' ')            /* skip leading blanks */
  198.         p++;
  199.     for (i = 0 ; i<3; i++)
  200.     {   num = 0;
  201.         q = NULL;                /* watch for null field */
  202.         while (*p != EOS && *p != '/' && *p != ' ')
  203.         {    q = index(numstr,*p++);
  204.         if (q == NULL)            /* invalid digit */
  205.             break;
  206.         num = num*10 +(q-numstr);
  207.         }
  208.         if (q)
  209.         mdy[i] = num;
  210.         else
  211.         return (INVDATE);        /* invalid or null field */
  212.         p++;    /* skip delimiter */
  213.     }
  214.     --p;
  215.     while (*p++ == ' ')
  216.         ;
  217.     if (*--p != EOS)            /* not end of string */
  218.         return (INVDATE);
  219.  
  220.     if (mdy[0] > 11)
  221.     {   yr = mdy[0];        /* assume YY/MM/DD */
  222.         mo = mdy[1] - 1;        /* months 0..11 not 1..12 */
  223.         da = mdy[2];
  224.     }
  225.     else
  226.     {   mo = mdy[0] - 1;        /* assume MM/DD/YY */
  227.         da = mdy[1];
  228.         yr = mdy[2];
  229.     }
  230.     
  231.     if (yr > 1900)
  232.         yr = yr - 1900;
  233.  
  234.     approxsec = APPROXT(yr,mo,da);
  235.     timsec = approxsec;
  236.     lasttimsec = 0;
  237.     mindelta = NSECDA;
  238.     maxdelta = NSECYR;
  239.     while (1)
  240.     {    tmptr = (optg ? gmtime(&timsec) : localtime(&timsec)) ;
  241. /* decode absolute time into local or gmt */
  242.          if (yr == tmptr->tm_year && 
  243.          mo == tmptr->tm_mon &&
  244.          da == tmptr->tm_mday)
  245.          {
  246. /* the date is right, set the time to midnight local time; this 
  247. may behave strangely on daylight savings time changeover days */
  248.         if (STDHR == tmptr->tm_hour &&
  249.             STDMIN == tmptr->tm_min &&
  250.             0 == tmptr->tm_sec)
  251.             break;            /* exactly right */
  252.         else
  253.         {   timsec -= (tmptr->tm_hour - STDHR) * 3600 + 
  254.                   (tmptr->tm_min - STDMIN) * 60 +
  255.                    tmptr->tm_sec;
  256.             maxdelta = mindelta;
  257.             mindelta = 1;
  258.         }
  259.         }
  260.         else
  261.         {    deltasec = APPROXT(tmptr->tm_year,tmptr->tm_mon,tmptr->tm_mday)
  262.                - approxsec;
  263.         deltasign = (deltasec < 0) ? -1 : 1;
  264. /* approximately the difference in the number of seconds between 
  265.    the guessed date and the actual date */
  266.         if (abs(deltasec) > abs(timsec-lasttimsec))
  267.             deltasec = timsec-lasttimsec;
  268.         deltasec = abs(deltasec);
  269.         deltasec = (deltasec > maxdelta) ? deltasec / 2 :
  270.             ((deltasec >= mindelta) ? (deltasec-1) : mindelta); 
  271.         lasttimsec = timsec;
  272.         timsec -= deltasec * deltasign;    /* binary convergence */
  273.          }
  274.     }
  275.  
  276.     return (timsec);
  277. }
  278.