home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / dirutl / touch.arc / TOUCH.C < prev    next >
C/C++ Source or Header  |  1987-09-27  |  7KB  |  270 lines

  1.  
  2. /*    touch.c     Modify the date/time of last write on the specified
  3.  *            files. If the file to be touched doesn't exist, create
  4.  *            it.
  5.  *
  6.  *    options     -d date     use the specified date instead of the
  7.  *                    current system date
  8.  *            -t time     use the specified time instead of the
  9.  *                    current system time
  10.  *            -v        list the touched files on stdout
  11.  *            -c        turn off auto-create
  12.  *
  13.  *    OS interface    Touch returns the number of specified files for which
  14.  *            the touch failed as an exit status for a normal exit or
  15.  *            256 in the case of a fatal error
  16.  *
  17.  *    compiler    turbo c
  18.  *
  19.  *    version hx    v1.0 - initial release: 9/26/87 - jrh
  20.  *            v1.1 - added -c option: 9/27/87 - jrh
  21.  *
  22.  *    author        Richard Hargrove
  23.  *            Texas Instruments, Inc.
  24.  *            P.O. Box 869305, m/s 8473
  25.  *            Plano, TX 75076
  26.  *            214/575-4128
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <fcntl.h>
  31. #include <sys/stat.h>
  32. #include <errno.h>        
  33. #include <ctype.h>
  34. #include <dos.h>
  35. #include <io.h>
  36. #include <getopt.h>
  37. #include <exparg.h>
  38.  
  39. #ifdef DEBUG
  40. #define STATIC
  41. #else
  42. #define STATIC static
  43. #endif
  44.  
  45. #define FALSE    0
  46. #define TRUE    1
  47. #define EOS    '\0'
  48. #define ERR    (-1)
  49.  
  50. typedef int    BOOLEAN;
  51.  
  52. STATIC char *usage = "usage: touch [-cv] [-d date] [-t time] filespec...\n";
  53. STATIC char *credit = "touch 1.1 -- by richard hargrove, sept. 27 1987\n";
  54.  
  55. STATIC char *optlist = "CcD:d:T:t:Vv";
  56.  
  57. STATIC struct date date_struct;
  58. STATIC struct time time_struct;
  59. STATIC struct ftime fdate_time;
  60. STATIC BOOLEAN verbose = FALSE;
  61. STATIC BOOLEAN autocreate = TRUE;
  62.  
  63. /*****************************************************************************/
  64.  
  65. STATIC void fatal (char *msg1)
  66. {
  67. #define FATAL_EXIT    255
  68.  
  69.     /*    Report a fatal error and terminate the process. 
  70.       */
  71.      
  72.     fprintf (stderr, "touch error : %s%s", msg1, usage);
  73.     exit (FATAL_EXIT);
  74. }
  75.  
  76. /*****************************************************************************/
  77.  
  78. STATIC void warn (char *fname, char *msg)
  79. {
  80.     /*    Report an non-fatal error and return.
  81.      */
  82.      
  83.     fprintf (stderr, "%s - %s", fname, msg);
  84. }
  85.  
  86. /*****************************************************************************/
  87.  
  88. STATIC int stoi (char **str)
  89. {
  90.     /*    Decode the string pointed to by *str to an integer. Stop
  91.      *    decoding upon encountering a non-numeric char. Update *str
  92.      *    to point to that char.
  93.      */
  94.  
  95.     unsigned char *tstr = (unsigned char *) *str;
  96.     int retval = 0;
  97.  
  98.     while (isdigit (*tstr)) {
  99.       retval *= 10;
  100.       retval += (*tstr++ & 0x0f);
  101.     }
  102.  
  103.     *str = (char *) tstr;
  104.     return (retval);
  105. }
  106. /*****************************************************************************/
  107.  
  108. STATIC void get_user_date (char *str, struct date *date_struct)
  109. {
  110.     /*    Parse the user supplied date and initialize the date struct
  111.      *    pointed to by date_struct.
  112.      */
  113.  
  114.     int mon, day, year;
  115.     static int days [] =
  116.       { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  117.  
  118.     /* parse month */
  119.     mon = stoi (&str);
  120.  
  121.     /* parse date */
  122.     str++;
  123.     day = stoi (&str);
  124.  
  125.     /* parse year */
  126.     str++;
  127.     year = stoi (&str);
  128.     if ((year > 79) && (year < 100)) year += 1900;
  129.  
  130.     /* adjust days for non-leap-year (2000 is a leap year) */
  131.     if ((year & 0x03) || (year == 2100)) days [2] = 28;
  132.  
  133.     /* set up return data */
  134.     if ((mon > 0) || (mon < 13) ||
  135.         (day > 0) || (day <= days [mon]) ||
  136.         (year > 1979) || (year < 2101)) {
  137.       date_struct->da_year = year;
  138.       date_struct->da_mon = (char) mon;
  139.       date_struct->da_day = (char) day;
  140.     }
  141.     else {
  142.       warn (" - invalid date : using system date", "\n");
  143.     }
  144. }
  145.  
  146. /*****************************************************************************/
  147.  
  148. STATIC void get_user_time (char *str, struct time *time_struct)
  149. {
  150.     /*    Parse the user supplied time and initialize the time struct
  151.      *    pointed to by time_struct.
  152.      */
  153.  
  154.     int hour, min, sec = 0;
  155.     BOOLEAN isok;
  156.     
  157.     /* parse hour */
  158.     if ((isok = isdigit (*str)) != FALSE) {
  159.       hour = stoi (&str);
  160.     }
  161.     
  162.     /* parse minute */
  163.     str++;
  164.     if (isok && ((isok = isdigit (*str)) != FALSE)) {
  165.       min = stoi (&str);
  166.     }
  167.  
  168.     /* parse optional seconds */
  169.     if (isok &&
  170.         (*str != EOS)) {
  171.       str++;
  172.       if ((isok = isdigit (*str)) != FALSE) {
  173.         sec = stoi (&str);
  174.       }
  175.     }
  176.  
  177.     /* setup return data */
  178.     if (isok &&
  179.         (hour >= 0) && (hour < 24) &&
  180.         (min >= 0) && (min < 60) &&
  181.         (sec >= 0) && (sec < 60)) {
  182.       time_struct->ti_hour = hour;
  183.       time_struct->ti_min = min;
  184.       time_struct->ti_sec = sec;
  185.     }    
  186.     else {
  187.       warn (" - invalid time : using system time", "\n");
  188.     }
  189. }
  190.  
  191. /*****************************************************************************/
  192.  
  193. main (int argc, char *argv [])
  194. {
  195.     int c;
  196.     int handle;
  197.     int file_errs = 0;
  198.     
  199.     argv = exparg (&argc, argv);    /* expand command line wild-cards */
  200.     getdate (&date_struct);        /* get system date and time */
  201.     gettime (&time_struct);
  202.     
  203.     /* handle command line options */
  204.     while ((c = getopt (argc, argv, optlist)) != EOF) {
  205.       c = tolower (c);
  206.       if (c == 'c') {
  207.         autocreate = FALSE;
  208.       }
  209.       else if (c == 'd') {
  210.         get_user_date (optarg, &date_struct);
  211.       }
  212.       else if (c == 't') {
  213.         get_user_time (optarg, &time_struct);
  214.       }
  215.       else if (c == 'v') {
  216.         verbose = TRUE;
  217.       }
  218.       else {
  219.         fatal ("invalid option specifier\n");
  220.       }
  221.     }
  222.     
  223.     /* reconfigure command line parameter support */
  224.     argc -= optind;
  225.     if (argc <= 0) {
  226.       fatal ("no files to touch\n");
  227.     }
  228.     argv = &argv [optind];
  229.  
  230.     /* encode the date and time */
  231.     fdate_time.ft_tsec = time_struct.ti_sec >> 1;
  232.     fdate_time.ft_min = time_struct.ti_min;
  233.     fdate_time.ft_hour = time_struct.ti_hour;
  234.     fdate_time.ft_day = date_struct.da_day;
  235.     fdate_time.ft_month = date_struct.da_mon;
  236.     fdate_time.ft_year =  date_struct.da_year - 1980;
  237.     
  238.     /* touch the files */
  239.     while (argc--) {
  240.       if ((handle = open (argv [argc],
  241.                   (autocreate ? O_WRONLY | O_CREAT : O_WRONLY),
  242.                   S_IWRITE)) != ERR) {
  243.         /* these can't fail */      
  244.         (void) setftime (handle, &fdate_time);
  245.         close (handle);
  246.         if (verbose) {
  247.           puts (argv [argc]);
  248.         }
  249.       }
  250.       else {
  251.         switch (errno) {
  252.           case ENOENT:    warn (argv [argc], "file not found\n");
  253.                       break;
  254.           case EMFILE:    warn (argv [argc], "too many open files\n");
  255.                       break;
  256.           case EACCES:    warn (argv [argc], "access denied\n");
  257.                       break;
  258.           case EINVACC:    warn (argv [argc], "who changed my code?\n");
  259.                       break;
  260.           default:        warn (argv [argc], "eh ? unknown error\n");
  261.                       fprintf (stderr, "error code : %d\n", errno);
  262.         }
  263.         errno = 0;
  264.         file_errs++;
  265.       }
  266.     }
  267.     
  268.     exit (file_errs);
  269. }
  270.