home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pub
/
utils
/
xxu.c
< prev
Wrap
C/C++ Source or Header
|
2020-01-01
|
6KB
|
180 lines
/* X X U -- UNIX filename converter */
/*
Lowercases filenames and strips spurious pathnames from them. Handy for
use after UNZIPs or FTP MGETs or magnetic tape operations that leave your
UNIX directory full of uppercase filenames, possibly with foreign paths
included. Path stripping handles UNIX, DOS, VMS, and TOPS-20/TENEX
formats.
Usage: xxu file(s)
Action: Renames argument files as follows:
strips DOS or DEC device:, node:: names from front (up to rightmost ':')
strips DOS path name from front (up to rightmost '\') if present
strips VMS [directory] or DEC-20 <directory> name if present
strips UNIX path name from front (up to rightmost '/') if present
strips VMS version number from end (everything after ';') if present
strips DEC-20 attributes from end (everything after ';') if present
if name is all uppercase it is converted to lowercase
converts spaces to underscores
honors Ctrl-V quote for special characters
discards unquoted unprintable characters
if result is null, file is renamed to xxfile-n, where n is a number.
if result would write over an existing file, file also renamed to xxfile-n.
Typical usage: make a new directory, cd to it, then FTP files from
DOS, Windows, VMS, etc, or Unzip them from an archive, then "xxu *"
to fix the names. Files that already have lowercase names (and no path
part included) are not touched.
Author: F. da Cruz, The Kermit Project, Columbia University
Email: fdc@columbia.edu
Please send any changes back to the author.
Revised: Jul 1985: First version
Sep 1998: Provide for no rename(), handle spaces.
Jul 1999: Add support for DOS pathname stripping.
Oct 2000: Don't lowercase mixed-case names.
Copyright (C) 1999,2000
Trustees of Columbia University in the City of New York
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#ifdef SYSV
#include <sys/types.h>
#else
#ifdef M_XENIX
#include <sys/types.h>
#endif /* M_XENIX */
#endif /* SYSV */
#include <ctype.h>
#include <sys/file.h> /* For access() */
/* Define NO_RENAME on cc command line if rename() missing */
#ifdef NO_RENAME
/* Use rename() if available since rename() is atomic and this isn't. */
int
rename(oldname, newname) char *oldname, *newname; {
if (link(oldname,newname) < 0) {
perror("link");
return(-1);
} else if (unlink(oldname) < 0) {
perror("unlink");
return(-1);
} else
return(0);
}
#endif /* NO_RENAME */
char name[1024]; /* File name buffer */
char *pp, *cp, *xp; /* Character pointers */
char delim; /* Directory Delimiter */
int dc = 0, n = 0; /* Counters */
int quote = 0, indir = 0, done = 0; /* Flags */
main(argc,argv) int argc; char **argv; {
int lc;
if (argc < 2) { /* Give message if no args */
fprintf(stderr,"Usage: xxu file(s)\n");
exit(1);
}
n = 0; /* Unfixable filename counter */
while (--argc > 0) { /* For all files on command line... */
argv++;
xp = *argv; /* Copy pointer for simplicity */
lc = 0; /* For case conversion */
for (cp = xp; *cp; cp++) { /* Quick prescan for mixed case */
if (islower(*cp)) lc++;
}
printf("%s ",*argv); /* Echo name of this file */
pp = name; /* Point to translation buffer */
*name = '\0'; /* Initialize buffer */
dc = 0; /* Filename dot counter */
done = 0; /* Flag for early completion */
for (cp = xp; (*cp != '\0') && !done; cp++) { /* Loop thru chars... */
if (quote) { /* If this char quoted, */
*pp++ = *cp; /* include it literally. */
quote = 0;
} else if (indir) { /* If in directory name, */
if (*cp == delim)
indir = 0; /* look for end delimiter. */
} else switch (*cp) {
case '<': /* Discard DEC-20 directory name */
indir = 1;
delim = '>';
break;
case '[': /* Discard VMS directory name */
indir = 1;
delim = ']';
break;
case '/': /* Discard Unix path name */
case '\\': /* or DOS path name */
case ':': /* or DOS/DEC dev: or node:: name */
pp = name;
break;
#ifdef COMMENT
/* We don't have too many DEC-20s any more, but we do have *.tar.gz's */
case '.': /* DEC -20 generation number */
if (++dc == 1) /* Keep first dot */
*pp++ = *cp;
else /* Discard everything starting */
done = 1; /* with second dot. */
break;
#endif /* COMMENT */
case ';': /* VMS version or DEC-20 attribute */
done = 1; /* Discard everything starting with */
break; /* semicolon */
case '\026': /* Control-V quote for special chars */
quote = 1; /* Set flag for next time. */
break;
default:
if (lc == 0 && isupper(*cp)) /* Uppercase letter to lower */
*pp++ = tolower(*cp);
else if (*cp == ' ') /* change blanks to underscore */
*pp++ = '_';
else if (isprint(*cp)) /* Other printable, just keep */
*pp++ = *cp;
}
}
*pp = '\0'; /* Done with name, terminate it */
if (strcmp(name,xp) == 0) { /* If no renaming necessary, */
printf("(ok)\n"); /* just give message. */
continue;
}
while (*name == '\0' || access(name,0) == 0) { /* Find unique name */
sprintf(name,"xxfile-%d",n++);
}
printf("=> %s ",name); /* Tell what new name will be */
if (rename(xp,name) == 0) /* Try to rename it */
printf("(ok)\n"); /* Say what happened */
else
#ifndef NO_RENAME
perror("failed");
#else
printf("(failed)\n");
#endif /* NO_RENAME */
}
exit(0); /* Done. */
}