home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / pub / public_html / xxu.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  6KB  |  177 lines

  1. /*  X X U  --  UNIX filename converter  */
  2.  
  3. /*
  4.   Lowercases filenames and strips spurious pathnames from them.  Handy for
  5.   use after UNZIPs or FTP MGETs or magnetic tape operations that leave your
  6.   UNIX directory full of uppercase filenames, possibly with foreign paths
  7.   included.  Path stripping handles UNIX, DOS, VMS, and TOPS-20/TENEX
  8.   formats.
  9.  
  10.   Usage: xxu file(s)
  11.  
  12.   Action: Renames argument files as follows:
  13.    strips DOS or DEC device:, node:: names from front (up to rightmost ':')
  14.    strips DOS path name from front (up to rightmost '\') if present
  15.    strips VMS [directory] or DEC-20 <directory> name if present
  16.    strips UNIX path name from front (up to rightmost '/') if present
  17.    strips VMS version number from end (everything after ';') if present
  18.    strips DEC-20 attributes from end (everything after ';') if present
  19.    lowercases any uppercase letters
  20.    converts spaces to underscores
  21.    honors Ctrl-V quote for special characters
  22.    discards unquoted unprintable characters
  23.    if result is null, file is renamed to xxfile-n, where n is a number.
  24.    if result would write over an existing file, file also renamed to xxfile-n.
  25.  
  26.   Typical usage: make a new directory, cd to it, then FTP files from
  27.   DOS, Windows, VMS, etc, or Unzip them from an archive, then "xxu *"
  28.   to fix the names.  Files that already have lowercase names (and no path
  29.   part included) are not touched.
  30.  
  31.   Author:  F. da Cruz, The Kermit Project, Columbia University
  32.   Email:   fdc@columbia.edu
  33.  
  34.   Please send any changes back to the author.
  35.  
  36.   Revised: Jul 1985: First version
  37.            Sep 1998: Provide for no rename(), handle spaces.
  38.            Jul 1999: Add support for DOS pathname stripping.
  39.  
  40.   Copyright (C) 1999
  41.   Trustees of Columbia University in the City of New York
  42.  
  43.   This program is free software; you can redistribute it and/or modify
  44.   it under the terms of the GNU General Public License as published by
  45.   the Free Software Foundation; either version 2 of the License, or
  46.   (at your option) any later version.
  47.  
  48.   This program is distributed in the hope that it will be useful,
  49.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  50.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  51.   GNU General Public License for more details.
  52.  
  53.   You should have received a copy of the GNU General Public License
  54.   along with this program; if not, write to the Free Software
  55.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  56. */
  57. #include <stdio.h>
  58. #ifdef SYSV
  59. #include <sys/types.h>
  60. #else
  61. #ifdef M_XENIX
  62. #include <sys/types.h>
  63. #endif /* M_XENIX */
  64. #endif /* SYSV */
  65. #include <ctype.h>
  66. #include <sys/file.h>            /* For access() */
  67.  
  68. /* Define NO_RENAME on cc command line if rename() missing */
  69.  
  70. #ifdef NO_RENAME
  71. /* Use rename() if available since rename() is atomic and this isn't. */
  72. int
  73. rename(oldname, newname) char *oldname, *newname; {
  74.     if (link(oldname,newname) < 0) {
  75.     perror("link");
  76.     return(-1);
  77.     } else if (unlink(oldname) < 0) {
  78.     perror("unlink");
  79.     return(-1);
  80.     } else
  81.       return(0);
  82. }
  83. #endif /* NO_RENAME */
  84.  
  85. char name[1024];            /* File name buffer */
  86. char *pp, *cp, *xp;            /* Character pointers */
  87. char delim;                /* Directory Delimiter */
  88. int dc = 0, n = 0;            /* Counters */
  89. int quote = 0, indir = 0, done = 0;    /* Flags */
  90.  
  91. main(argc,argv) int argc; char **argv; {
  92.     int lc;
  93.  
  94.     if (argc < 2) {            /* Give message if no args */
  95.     fprintf(stderr,"Usage: xxu file(s)\n");
  96.     exit(1);
  97.     }
  98.     n = 0;                /* Unfixable filename counter */
  99.     while (--argc > 0) {        /* For all files on command line... */
  100.     argv++;
  101.     xp = *argv;            /* Copy pointer for simplicity */
  102.     lc = 0;                /* For case conversion */
  103.     for (cp = xp; *cp; cp++) {    /* Quick prescan for mixed case */
  104.         if (islower(*cp)) lc++;
  105.     }
  106.     printf("%s ",*argv);        /* Echo name of this file */
  107.  
  108.     pp = name;            /* Point to translation buffer */
  109.     *name = '\0';            /* Initialize buffer */
  110.     dc = 0;                /* Filename dot counter */
  111.     done = 0;            /* Flag for early completion */
  112.  
  113.     for (cp = xp; (*cp != '\0') && !done; cp++) { /* Loop thru chars... */
  114.  
  115.         if (quote) {        /* If this char quoted, */
  116.         *pp++ = *cp;        /*  include it literally. */
  117.         quote = 0;
  118.         } else if (indir) {        /* If in directory name, */
  119.         if (*cp == delim)
  120.           indir = 0;        /* look for end delimiter. */
  121.         } else switch (*cp) {
  122.           case '<':            /* Discard DEC-20 directory name */
  123.         indir = 1;
  124.         delim = '>';
  125.         break;
  126.           case '[':            /* Discard VMS directory name */
  127.         indir = 1;
  128.         delim = ']';
  129.         break;
  130.           case '/':            /* Discard Unix path name */
  131.           case '\\':        /*  or DOS path name */
  132.           case ':':               /*  or DOS/DEC dev: or node:: name */
  133.         pp = name;
  134.         break;
  135. #ifdef COMMENT
  136. /* We don't have too many DEC-20s any more, but we do have *.tar.gz's */
  137.           case '.':            /* DEC -20 generation number */
  138.         if (++dc == 1)        /* Keep first dot */
  139.           *pp++ = *cp;
  140.         else            /* Discard everything starting */
  141.           done = 1;        /* with second dot. */
  142.         break;
  143. #endif /* COMMENT */
  144.           case ';':            /* VMS version or DEC-20 attribute */
  145.         done = 1;        /* Discard everything starting with */
  146.         break;            /* semicolon */
  147.           case '\026':        /* Control-V quote for special chars */
  148.         quote = 1;        /* Set flag for next time. */
  149.         break;
  150.           default:
  151.         if (lc == 0 && isupper(*cp)) /* Uppercase letter to lower */
  152.           *pp++ = tolower(*cp);
  153.         else if (*cp == ' ')    /* change blanks to underscore */
  154.           *pp++ = '_';
  155.         else if (isprint(*cp))    /* Other printable, just keep */
  156.           *pp++ = *cp;
  157.         }
  158.     }
  159.     *pp = '\0';            /* Done with name, terminate it */
  160.     if (strcmp(name,xp) == 0) {    /* If no renaming necessary, */
  161.         printf("(ok)\n");        /*  just give message. */
  162.         continue;
  163.         }
  164.     while (*name == '\0' || access(name,0) == 0) { /* Find unique name */
  165.         sprintf(name,"xxfile-%d",n++);
  166.     }
  167.     printf("=> %s ",name);        /* Tell what new name will be */
  168.     if (rename(xp,name) == 0)    /* Try to rename it */
  169.       printf("(ok)\n");        /* Say what happened */
  170. #ifndef NO_RENAME
  171.     else
  172.       perror("failed");
  173. #endif /* NO_RENAME */
  174.     }
  175.     exit(0);                /* Done. */
  176. }
  177.