Metropoli BBS
VIEWER: touchw.c MODE: TEXT (ASCII)
/*
  For MSC 5.0/QuickC: cl touch.c setargv /link /NOE
 */
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<errno.h>
#include<fcntl.h>
#include<sys\utime.h>
#include<sys\types.h>
#include<sys\stat.h>

#ifndef ERROR
#define ERROR -1
#endif

main(argc,argv)
int argc;
char **argv;
{
  int i, hdl;
  char *date = NULL,*time = NULL;
  struct utimbuf datetimes, *tptr;
  extern int errno;

  if(argc < 2)    /* if no filenames passed, print usage message */
  {
    printf("\nUsage: touch [/Dmm/dd/yy /Thh:mm:ss] <filename> [filename...]");
    exit(1);      /* set errorlevel to 1 */
  }

/* process any switches, only allowed in argv[1] and argv[2]*/

  for( i = 1; i < 3; i++)
    if(argv[i][0] == '/')             /* slash found? */
      if(toupper(argv[i][1]) == 'D')      /* if Date string */
        date = &argv[i][2];
      else if(toupper(argv[i][1]) == 'T')     /* if Time string */
        time = &argv[i][2];

/* if date or time switch set, set ptr to times structure */

  if(date || time)
  {
    convert_date_time(&datetimes,date,time);
    tptr = &datetimes;
  }
  else
    tptr = (struct utimbuf *)NULL;    /* else to NULL */

    /* increment argv and decrement argc
       if either date or time switches are on */
  if(date)
  {
    argv++;
    argc--;
  }
  if(time)
  {
    argv++;
    argc--;
  }
                   /* process each filename passed */
  for( i = 1; i < argc; )
  {
    if(utime(argv[i],tptr) == ERROR)   /* unable to update the time */
    {
    switch(errno)      /* print appropriate error message */
    {
      case EACCES:
        printf("\ntouch: Directory or Read-only file: %s",argv[i]);
        break;
      case EINVAL:
        printf("\ntouch: Bad time argument changing %s",argv[i]);
        exit(1);
      case EMFILE:
        printf("\ntouch: Too many open files (check FILES= in CONFIG.SYS)");
        exit(1);
      case ENOENT:
                 /* if file doesn't exist, create it  */
          if((hdl = open(argv[i], (O_WRONLY | O_CREAT),S_IWRITE)) == -1)
            printf("\ntouch: Unable to create %s",argv[i]);
          else
          {
            close(hdl);  
            continue;
          }
          break;
      }
    }
    i++;
  }
  exit(0);               /* set errorlevel to 0   */
}

/*
 * This function places date and time values in the datestr and timestr
 * pointers into a tm structure, overriding the current time.
 */
convert_date_time(struct utimbuf *datetimes, char *datestr, char *timestr)
{
  struct tm *current_time;

  time((time_t *)&datetimes->modtime);      /* get current time  */
  current_time = localtime(&datetimes->modtime);  /* get pointer to it */

  if(datestr)            /* if date passed, put it into place */
  {
    current_time->tm_mon = (get_date_time(&datestr) - 1);
    current_time->tm_mday = get_date_time(&datestr);
    if((current_time->tm_year = get_date_time(&datestr)) > 1900)
      current_time->tm_year -= 1900;
  }

  if(timestr)            /* if time passed, put into place */
  {
    current_time->tm_hour = get_date_time(&timestr);
    current_time->tm_min = get_date_time(&timestr);
    current_time->tm_sec = get_date_time(&timestr);
  }

  datetimes->modtime = mktime(current_time);    /* place in time_t */
}

/*
 * This function takes a pointer to a date or time pointer, gets the
 * next piece of the date or time string and returns it as an integer
 * value.  It advances the date or time pointer to point to the next
 * piece available.
 */
int  get_date_time(char **ptr)
{
  char phrase[15];
  char *p;

  strcpy(phrase,*ptr);         /* copy the current string  */

  if(p = strchr(phrase,'/'))     /* find next separator and set to NULL */
    *p = NULL;
  else if(p = strchr(phrase,':'))
    *p = NULL;

  (*ptr) += strlen(phrase);      /* advance pointer to next component   */

  if(**ptr == '/' || **ptr == ':')   /* if a separator, move past it  */
    (*ptr)++;

  return atoi(phrase);         /* return the current component  */
}

[ RETURN TO DIRECTORY ]