home *** CD-ROM | disk | FTP | other *** search
/ Tools en Utilities / CDASS_5.ISO / shell / file / doscvt24.arj / DOSCVT.C next >
Encoding:
C/C++ Source or Header  |  1993-03-06  |  7.8 KB  |  261 lines

  1. #define Version "DOSCVT V2.4"
  2.  
  3. /*
  4.  
  5.   doscvt [-d | -u ] [-v] [-z] [filename ...]
  6.  
  7.   -d    convert to MSDOS format.
  8.   -u    convert to UNIX.
  9.   -v    display the program version id.
  10.   -z    append a ^Z to the end of the DOS file
  11.  
  12.   defaults to -d on dos systems and -u on unix systems.
  13.  
  14.   Convert MS-DOS text file format to UNIX text file format
  15.   Namely, convert <CR><LF> pairs to just <LF> and remove
  16.   trailing ^Z EOF marker.
  17.   Also converts Unix format to MS-DOS format by adding <CR>
  18.   before <LF> and, optionally, adding ^Z at the end.
  19.   Works by converting the specified file into a temp file and,
  20.   when finished, renaming the temp over the original file name.
  21.   The accessed and modified times of the original are preserved.
  22.   Multiple filenames may be specified and each will be converted
  23.   in turn.  If no filename is specified, stdin will be converted
  24.   and written on stdout.
  25.  
  26.   Norm Brake
  27.   Modular Computer Systems, Inc.
  28.  
  29.   Internet:  norm@modcomp.com
  30.   Snailmail: PO Box 6099
  31.              Ft. Lauderdale, FL 33340-6099
  32.  
  33. */
  34.  
  35. #include <stdio.h>
  36.  
  37. /* include the stuff to preserve the time stamp. */
  38. /* this stuff is not ANSI, but I'm not proud */
  39.  
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #include <sys/utime.h>
  43.  
  44. #ifdef MSDOS
  45.  
  46. # define SUCCESS (1)    /* DOS success and failure exit codes */
  47. # define FAILURE (0)
  48.  
  49. /* include the stuff we need under DOS to change stdin and stdout */
  50. /* to binary mode */
  51.  
  52. #include <fcntl.h>
  53. #include <io.h>
  54.  
  55. #else
  56.  
  57. # define SUCCESS (0)    /* UNIX success and failure exit codes */
  58. # define FAILURE (1)
  59.  
  60. #endif
  61.  
  62. #define EPUTCHAR(c, f, n) if (fputc(c, f) == EOF) file_error(n);
  63.  
  64. struct stat hstat;
  65. struct utimbuf utb;
  66.  
  67. FILE     *f;        /* file to be converted */
  68. FILE     *t;        /* temp file */
  69.  
  70. int     fn = 1;        /* argv entry currently being processed */
  71. char    ts[255];    /* temp string for errors and system calls */
  72. char    *tn;        /* temp file name, gets results of tmpnam() */
  73.  
  74. typedef enum format {dos, unx} format_t;
  75.  
  76. #ifdef MSDOS
  77. /* under dos, we want the default to convert unix to dos */
  78.   format_t    fmt = dos;
  79. #else
  80. /* under unix, we want the default to convert dos to unix */
  81.   format_t    fmt = unx;
  82. #endif
  83.  
  84. int    vflag=0;    /* if true, -v specified on command line */
  85. int    zflag=0;    /* if true, append a ^Z to the file */
  86.  
  87. char    *cmd;        /* pointer to argv[0] */
  88. char    *filename;    /* name of file being processed */
  89.  
  90. /* display usage instructions */
  91. void
  92. usage(int vflag)
  93. {
  94.   fprintf(stderr,"%s\n",Version);
  95.   if ( ! vflag ) {
  96.     fprintf(stderr,"usage: %s [-u | -d ] [-v] [-z] [ <filename> ]\n", cmd);
  97.     fprintf(stderr,"        -u   :  convert <filename> to unix format\n");
  98.     fprintf(stderr,"        -d   :  convert <filename> to DOS format\n");
  99.     fprintf(stderr,"        -v   :  display the program version and exit\n");
  100.     fprintf(stderr,"        -z   :  append a CTRL-Z to the converted file\n");
  101.     exit(FAILURE);
  102.   } else {
  103.     exit(SUCCESS);
  104.   }
  105. }
  106.  
  107. /* issue a FATAL warning concerning a filename */
  108. void
  109. file_error(char *fname)
  110. {
  111.   sprintf(ts, "%s - '%s'", cmd, filename);
  112.   perror(ts);
  113.   exit(FAILURE);
  114. }
  115.  
  116. /* issue a FATAL warning message */
  117. void
  118. fatal(char *msg)
  119. {
  120.   fprintf(stderr,"%s: error: '%s' - %s\n",cmd, filename, msg);
  121.   remove(tn);
  122.   exit(FAILURE);
  123. }
  124.  
  125. /* Issue a non-fatal warning message */
  126. void
  127. warning(char *msg)
  128. {
  129.   fprintf(stderr,"%s: warning: '%s' - %s\n", cmd, filename, msg);
  130. }
  131.  
  132. /* MAIN Program */
  133. int
  134. main(int argc, char *argv[])
  135. {
  136.   int    c1, c2;
  137.  
  138. #ifdef MSDOS
  139.   /* With Microsoft C 5.1, tempnam ignores the directory parameter  */
  140.   /* if the environment variable "TMP" is defined and allocates the */
  141.   /* file in "TMP" instead.  If "TMP" points to another device      */
  142.   /* (such as a RAM Drive), the rename operation at the end will    */
  143.   /* fail.  Thus, we can not use "tempnam" under DOS.               */
  144.  
  145.   tn = "~dc~321~.tm~";            /* MSDOS temp file for conversion */
  146.  
  147.   /* MSDOS puts the entire path of the program into argv[0] which   */
  148.   /* makes error and usage reporting a little messy.  So...         */
  149.   
  150. cmd = "doscvt";            /* program name for reporting errors */
  151.  
  152. #else
  153.  
  154.   /* Under a UNIX system, we need the tempnam routine due to the     */
  155.   /* multi-user nature of the world.  We would not want concurrent   */
  156.   /* executions of the program to be using the same temp file.       */
  157.   /* Fortunately, tempnam works correctly under UNIX.                */
  158.  
  159.   tn = tempnam(".", "dc");        /* Unix temp file for conversion */
  160.  
  161.   cmd = argv[0];            /* program name for reporting errors */
  162.  
  163. #endif
  164.  
  165.   if (argc > 1) {            /* if we had some command args */
  166.     while (argv[fn][0]=='-') {        /* process any option switches */
  167.       switch (c1=argv[fn][1]) {
  168.       case 'd': fmt=dos; break;
  169.       case 'u': fmt=unx; break;
  170.       case 'z': zflag++; break;
  171.       case 'v': vflag++;
  172.       default: usage(vflag);        /* if we got an option we didn't */
  173.                     /* know, display how to run doscvt */
  174.       }
  175.       fn++;
  176.       argc--;
  177.     }
  178.   }
  179.  
  180.   /* We have processed all of the option args, now do the files */
  181.   do {
  182.     if (argc > 1) {            /* if a file was specified */
  183.       filename = argv[fn];        /* remember the file name  */
  184.       if (stat(filename, &hstat) != 0)    /* get the file modified time */
  185.     file_error(filename);        /* if stat failed, it won't read */
  186.       utb.actime  = hstat.st_atime;    /* copy the timestamp */
  187.       utb.modtime = hstat.st_mtime;    /* both accessed and modified */
  188. #if defined(__m88k__) && defined(realix)
  189.       utb.acusec  = hstat.st_ausec;    /* if this is realix and moto 88k, */
  190.       utb.modusec = hstat.st_musec;    /* time does down to micro seconds */
  191. #endif
  192.       if ((f = freopen(filename, "rb", stdin)) == NULL)    /* open in as stdin */
  193.     file_error(filename);
  194.       if ((f = freopen(tn, "wb", stdout)) == NULL)    /* open tn as stdout */
  195.     file_error(tn);
  196.     }
  197. #ifdef MSDOS
  198.     else {
  199.       /* Under MSDOS, stdin and stdout are text mode files by default.    */
  200.       /* If there were no files on the command files, we are filtering    */
  201.       /* stdin to stdout.  Under MSDOS, we need to change their modes    */
  202.       /* to binary for the following algorithm to work.            */
  203.       /* The code to do this is MSDOS (maybe MicroSoft C) specific.    */
  204.  
  205.       if (setmode(fileno(stdin), O_BINARY) == -1)
  206.     file_error("<STDIN>");
  207.       if (setmode(fileno(stdout), O_BINARY) == -1)
  208.     file_error("<STDOUT>");
  209.     }
  210. #endif
  211.  
  212.     /* copy and convert loop */
  213.     /* stop on a CTRL-Z or end-of-file */
  214.     /* if we see a CR and the next char is LF and */
  215.     /* we are converting to unix format, delete the CR */
  216.     /* If we se a CR-LF and converting to DOS, complain */
  217.     /* if we see a LF and converting to DOS, add the CR */
  218.     /* Check errors on the output since if we got a write */
  219.     /* error, we REALLY do not want to replace the input */
  220.     /* file with the output! */
  221.  
  222.     while (((c1=getchar()) != EOF) && (c1 != '\032')) {
  223.       if (c1 == '\r') {
  224.     if ((c2 = getchar())=='\n') {
  225.       if (fmt == unx)
  226.         c1 = '\n';
  227.       else
  228.         if (fmt == dos) 
  229.           fatal("is already MS-DOS format");
  230.     } else
  231.       ungetc(c2, stdin);
  232.       } else if (c1 ==  '\n') {
  233.     if (fmt == dos)
  234.       EPUTCHAR('\r', stdout, tn);
  235.       }
  236.       EPUTCHAR(c1, stdout, tn);
  237.     }
  238.  
  239.     /* if converting to DOS and the user wants it, */
  240.     /* put out a CTRL-Z EOF flag */
  241.     if ((fmt == dos) && (zflag))
  242.       EPUTCHAR('\032', stdout, tn);
  243.  
  244.     /* if we opened a file name, rename the tempfile */
  245.     /* to the original filename, and set it's timestamp */
  246.     /* to match that of the original file. */
  247.     if (argc > 1) { 
  248.       fclose(stdin);
  249.       fclose(stdout);
  250.       remove(filename);
  251.       rename(tn, filename);
  252.       if (utime(filename, &utb) != 0)
  253.     warning("unable to copy file's timestamp");
  254.     }
  255.  
  256.     fn++;    /* bump the argv index */
  257.     argc--;    /* count down until no more files to convert */
  258.   } while (argc > 1);
  259.   exit(SUCCESS);
  260. }
  261.