/* /usr.MC68020/csc-sun/u/local/src/C/xxu.c, Sat Jun 27 13:53:01 1987, */ /* Add special[] processing, strip trailing dots from names */ /* X X U -- 20-to-Unix filename converter */ /* Change DEC-20 or VAX/VMS style filenames into normal Unix names. Handy for use after ftp MGETs, when you find your directory full of files with names like LIB:CKUFIO.C.2 or FRED::[ETHEL]A.B;37 when all you really wanted was ckufio.c and a.b. Usage: xxu file(s) Action: Renames argument files as follows: strips Unix path name from front (up to rightmost '/') if present strips DEC device:, node:: names from front (up to rightmost ':') if present strips DEC-20 or VMS [directory] name if present strips DEC-20 version number from end (everything after 2nd dot) if present strips VMS generation number from end (everything after ';') if present lowercases any uppercase letters honors DEC-20 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. Recommended procedure: make a new directory, cd to it, then FTP files from DEC-20 or VMS system, then do "xxu *". Author: F. da Cruz, CUCCA, July 85 Added directory handling: Brad Davis, UofU VCIS Group, Aug 85 */ #include #include #include /* For access() */ #ifdef DODIRS #include #include #endif #include /* A few names will be preserved in upper case or mixed case */ char* special[] = { /* "old name", "new name" */ "bugs", "BUGS", "install", "INSTALL", "makefile", "Makefile", "note", "NOTE", "readme", "README", "todo", "TODO", (char*)NULL, (char*)NULL }; char name[500]; /* 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 */ #ifdef DODIRS DIR *dir; struct direct *entry; #endif main(argc, argv) int argc; char **argv; { if (argc < 2) { /* Give message if no args */ #ifdef DODIRS (void)fprintf(stderr,"Usage: xxu directory(s)\n"); #else (void)fprintf(stderr,"Usage: xxu file(s)\n"); #endif exit(1); } n = 0; /* Unfixable filename counter */ while (--argc > 0) { /* For all files on command line... */ argv++; #ifdef DODIRS dir = opendir(*argv); while ((entry = readdir(dir)) != (struct direct *)NULL) { xp = entry->d_name; /* Copy pointer for simplicity */ if (*xp == '.') continue; /* leave . and .. alone */ #else xp = *argv; /* Copy pointer for simplicity */ #endif (void)printf("%s ",xp); /* 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; continue; } /* */ if (indir) { /* If in directory name, */ if (*cp == delim) indir = 0; /* look for end delimiter. */ continue; } 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 DEC dev: or node:: name */ pp = name; break; case '.': /* DEC -20 generation number */ if (++dc == 1) /* Keep first dot */ *pp++ = *cp; else /* Discard everything starting */ done = 1; /* with second dot. */ break; case ';': /* VMS generation or DEC-20 attrib */ 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 (isupper(*cp)) /* Uppercase letter to lowercase */ *pp++ = tolower(*cp); 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, */ (void)printf("(ok)\n"); /* just give message. */ continue; } /* Strip trailing dot (so makefile. becomes makefile) and then check for special Unix files with mixed case */ { char **p; if (*(pp-1) == '.') *(pp-1) = '\0'; for (p = special; (*p != (char*)NULL); p += 2) { if (strcmp(name,*p) == 0) { strcpy(name,*(p+1)); break; } } } while (*name == '\0' || (access(name,0) == 0) && (errno != ENOENT)) { /* Find unique name */ (void)sprintf(name,"xxfile-%d",n++); } (void)printf("=> %s ",name); /* Tell what new name will be */ if ((strcmp(xp,name) == 0) || (rename(xp,name) == 0)) /* Try to rename it */ (void)printf("(ok)\n"); /* Say what happened */ else perror("failed"); } #ifdef DODIRS } #endif exit(0); /* Done. */ }