summaryrefslogtreecommitdiff
path: root/dviware/beebe/utils/xxu.c
blob: 8bdeada1d2f4dcbbf9b1058159d56f1c6d52d9c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* /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:<KERMIT>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 <directory> 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 <stdio.h>
#include <ctype.h>
#include <sys/file.h>		/* For access() */
#ifdef DODIRS
#include <sys/types.h>
#include <sys/dir.h>
#endif
#include <errno.h>

/* 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. */
}