1*50bf276cStholo /*
2*50bf276cStholo * Copyright � 1994 the Free Software Foundation, Inc.
3*50bf276cStholo *
4*50bf276cStholo * Author: Richard Levitte (levitte@e.kth.se)
5*50bf276cStholo *
6*50bf276cStholo * This file is a part of GNU VMSLIB, the GNU library for porting GNU
7*50bf276cStholo * software to VMS.
8*50bf276cStholo *
9*50bf276cStholo * GNU VMSLIB is free software; you can redistribute it and/or modify
10*50bf276cStholo * it under the terms of the GNU General Public License as published by
11*50bf276cStholo * the Free Software Foundation; either version 2 of the License, or
12*50bf276cStholo * (at your option) any later version.
13*50bf276cStholo *
14*50bf276cStholo * GNU VMSLIB is distributed in the hope that it will be useful,
15*50bf276cStholo * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*50bf276cStholo * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*50bf276cStholo * GNU General Public License for more details.
18*50bf276cStholo */
19*50bf276cStholo
20*50bf276cStholo #include <string.h>
21*50bf276cStholo #include <file.h>
22*50bf276cStholo #include <rmsdef.h>
23*50bf276cStholo #include <fab.h>
24*50bf276cStholo #include <nam.h>
25*50bf276cStholo #include <stdlib.h>
26*50bf276cStholo #include <lib$routines.h>
27*50bf276cStholo #include <descrip.h>
28*50bf276cStholo #include "filutils.h"
29*50bf276cStholo
30*50bf276cStholo /* file_name_as_directory was snarfed from src/fileio.c in GNU Emacs. */
31*50bf276cStholo
32*50bf276cStholo char *
file_name_as_directory(out,in)33*50bf276cStholo file_name_as_directory (out, in)
34*50bf276cStholo char *out, *in;
35*50bf276cStholo {
36*50bf276cStholo int size = strlen (in) - 1;
37*50bf276cStholo int ext_point = 0;
38*50bf276cStholo
39*50bf276cStholo strcpy (out, in);
40*50bf276cStholo
41*50bf276cStholo /* Is it already a directory string? */
42*50bf276cStholo if (in[size] == ':' || in[size] == ']' || in[size] == '>')
43*50bf276cStholo return out;
44*50bf276cStholo /* Is it a VMS directory file name? If so, hack VMS syntax. */
45*50bf276cStholo else
46*50bf276cStholo if (! strchr (in, '/'))
47*50bf276cStholo {
48*50bf276cStholo ext_point = 1;
49*50bf276cStholo if (size > 3 && (! strcmp (&in[size - 3], ".DIR")
50*50bf276cStholo || ! strcmp (&in[size - 3], ".dir")))
51*50bf276cStholo ext_point = -3;
52*50bf276cStholo else
53*50bf276cStholo if (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
54*50bf276cStholo || ! strncmp (&in[size - 5], ".dir", 4))
55*50bf276cStholo && (in[size - 1] == '.' || in[size - 1] == ';')
56*50bf276cStholo && in[size] == '1')
57*50bf276cStholo ext_point = -5;
58*50bf276cStholo }
59*50bf276cStholo if (ext_point != 0)
60*50bf276cStholo {
61*50bf276cStholo register char *p, *dot;
62*50bf276cStholo char brack;
63*50bf276cStholo
64*50bf276cStholo /* dir:[000000]x.dir --> dir:x.dir --> dir:[x]
65*50bf276cStholo dir:[000000.x]y.dir --> dir:[x]y.dir --> dir:[x.y]
66*50bf276cStholo but dir:[000000.000000]x.dir --> dir:[000000.000000.x]
67*50bf276cStholo dir:[000000.000000.x]y.dir --> dir:[000000.000000.x.y] */
68*50bf276cStholo static char tem[256];
69*50bf276cStholo
70*50bf276cStholo p = dot = strchr(in,':');
71*50bf276cStholo if (p != 0 && (p[1] == '[' || p[1] == '<'))
72*50bf276cStholo {
73*50bf276cStholo p += 2;
74*50bf276cStholo if (strncmp(p,"000000",6) == 0)
75*50bf276cStholo {
76*50bf276cStholo p += 6;
77*50bf276cStholo if (strncmp(p,".000000",7) != 0
78*50bf276cStholo && (*p == ']' || *p == '>' || *p == '.'))
79*50bf276cStholo {
80*50bf276cStholo size = dot - in + 1;
81*50bf276cStholo strncpy(tem, in, size);
82*50bf276cStholo if (*p == '.')
83*50bf276cStholo tem[size++] = '[';
84*50bf276cStholo strcpy(tem + size, p + 1);
85*50bf276cStholo in = tem;
86*50bf276cStholo size = strlen(in) - 1;
87*50bf276cStholo }
88*50bf276cStholo }
89*50bf276cStholo }
90*50bf276cStholo /* x.dir -> [.x]
91*50bf276cStholo dir:x.dir --> dir:[x]
92*50bf276cStholo dir:[x]y.dir --> dir:[x.y] */
93*50bf276cStholo p = in + size;
94*50bf276cStholo while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
95*50bf276cStholo {
96*50bf276cStholo char *emergency_dir = 0;
97*50bf276cStholo int emergency_point = 0; /* relative to the end of `out' */
98*50bf276cStholo
99*50bf276cStholo if (p != in)
100*50bf276cStholo {
101*50bf276cStholo strncpy (out, in, p - in);
102*50bf276cStholo out[p - in] = '\0';
103*50bf276cStholo if (*p == ':')
104*50bf276cStholo {
105*50bf276cStholo brack = ']';
106*50bf276cStholo strcat (out, ":[");
107*50bf276cStholo emergency_dir = "000000";
108*50bf276cStholo emergency_point = 0;
109*50bf276cStholo }
110*50bf276cStholo else
111*50bf276cStholo {
112*50bf276cStholo brack = *p;
113*50bf276cStholo strcat (out, ".");
114*50bf276cStholo emergency_dir = "";
115*50bf276cStholo emergency_point = -1;
116*50bf276cStholo }
117*50bf276cStholo p++;
118*50bf276cStholo }
119*50bf276cStholo else
120*50bf276cStholo {
121*50bf276cStholo brack = ']';
122*50bf276cStholo strcpy (out, "[.");
123*50bf276cStholo emergency_dir = "";
124*50bf276cStholo emergency_point = -2;
125*50bf276cStholo }
126*50bf276cStholo if (strncmp (p, "000000.", 7) == 0
127*50bf276cStholo && (strncmp (p+7, "000000", 6) != 0
128*50bf276cStholo || (p[13] != ']' && p[13] != '>' && p[13] != '.')))
129*50bf276cStholo p += 7;
130*50bf276cStholo if (p < (in + size + ext_point))
131*50bf276cStholo {
132*50bf276cStholo register copy_len = ((in + size + ext_point) - p);
133*50bf276cStholo size = strlen (out) + copy_len;
134*50bf276cStholo strncat (out, p, copy_len);
135*50bf276cStholo }
136*50bf276cStholo else
137*50bf276cStholo {
138*50bf276cStholo size = strlen (out) + emergency_point;
139*50bf276cStholo strcpy (out + size, emergency_dir);
140*50bf276cStholo size += strlen (emergency_dir);
141*50bf276cStholo }
142*50bf276cStholo }
143*50bf276cStholo out[size++] = brack;
144*50bf276cStholo out[size] = '\0';
145*50bf276cStholo }
146*50bf276cStholo return out;
147*50bf276cStholo }
148*50bf276cStholo
149*50bf276cStholo /*
150*50bf276cStholo * Convert from directory name to filename.
151*50bf276cStholo * On VMS:
152*50bf276cStholo * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
153*50bf276cStholo * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
154*50bf276cStholo * On UNIX, it's simple: just make sure there is a terminating /
155*50bf276cStholo
156*50bf276cStholo * Value is nonzero if the string output is different from the input.
157*50bf276cStholo */
158*50bf276cStholo
159*50bf276cStholo /* directory_file_name was snarfed from src/fileio.c in GNU Emacs. */
160*50bf276cStholo
161*50bf276cStholo #include <stdio.h>
directory_file_name(src,dst)162*50bf276cStholo directory_file_name (src, dst)
163*50bf276cStholo char *src, *dst;
164*50bf276cStholo {
165*50bf276cStholo long slen;
166*50bf276cStholo long rlen;
167*50bf276cStholo char * ptr, * rptr;
168*50bf276cStholo char bracket;
169*50bf276cStholo struct FAB fab = cc$rms_fab;
170*50bf276cStholo struct NAM nam = cc$rms_nam;
171*50bf276cStholo char esa[NAM$C_MAXRSS];
172*50bf276cStholo
173*50bf276cStholo slen = strlen (src);
174*50bf276cStholo
175*50bf276cStholo if (! strchr (src, '/')
176*50bf276cStholo && (src[slen - 1] == ']'
177*50bf276cStholo || src[slen - 1] == ':'
178*50bf276cStholo || src[slen - 1] == '>'))
179*50bf276cStholo {
180*50bf276cStholo /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
181*50bf276cStholo fab.fab$l_fna = src;
182*50bf276cStholo fab.fab$b_fns = slen;
183*50bf276cStholo fab.fab$l_nam = &nam;
184*50bf276cStholo fab.fab$l_fop = FAB$M_NAM;
185*50bf276cStholo
186*50bf276cStholo nam.nam$l_esa = esa;
187*50bf276cStholo nam.nam$b_ess = sizeof esa;
188*50bf276cStholo nam.nam$b_nop |= NAM$M_SYNCHK;
189*50bf276cStholo
190*50bf276cStholo /* We call SYS$PARSE to handle such things as [--] for us. */
191*50bf276cStholo if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
192*50bf276cStholo {
193*50bf276cStholo slen = nam.nam$b_esl;
194*50bf276cStholo if (esa[slen - 1] == ';' && esa[slen - 2] == '.')
195*50bf276cStholo slen -= 2;
196*50bf276cStholo esa[slen] = '\0';
197*50bf276cStholo src = esa;
198*50bf276cStholo }
199*50bf276cStholo if (src[slen - 1] != ']' && src[slen - 1] != '>')
200*50bf276cStholo {
201*50bf276cStholo /* what about when we have logical_name:???? */
202*50bf276cStholo if (src[slen - 1] == ':')
203*50bf276cStholo { /* Xlate logical name and see what we get */
204*50bf276cStholo ptr = strcpy (dst, src); /* upper case for getenv */
205*50bf276cStholo while (*ptr)
206*50bf276cStholo {
207*50bf276cStholo if ('a' <= *ptr && *ptr <= 'z')
208*50bf276cStholo *ptr -= 040;
209*50bf276cStholo ptr++;
210*50bf276cStholo }
211*50bf276cStholo dst[slen - 1] = 0; /* remove colon */
212*50bf276cStholo if (!(src = getenv (dst)))
213*50bf276cStholo return 0;
214*50bf276cStholo /* should we jump to the beginning of this procedure?
215*50bf276cStholo Good points: allows us to use logical names that xlate
216*50bf276cStholo to Unix names,
217*50bf276cStholo Bad points: can be a problem if we just translated to a device
218*50bf276cStholo name...
219*50bf276cStholo For now, I'll punt and always expect VMS names, and hope for
220*50bf276cStholo the best! */
221*50bf276cStholo slen = strlen (src);
222*50bf276cStholo if (src[slen - 1] != ']' && src[slen - 1] != '>')
223*50bf276cStholo { /* no recursion here! */
224*50bf276cStholo strcpy (dst, src);
225*50bf276cStholo return 0;
226*50bf276cStholo }
227*50bf276cStholo }
228*50bf276cStholo else
229*50bf276cStholo { /* not a directory spec */
230*50bf276cStholo strcpy (dst, src);
231*50bf276cStholo return 0;
232*50bf276cStholo }
233*50bf276cStholo }
234*50bf276cStholo bracket = src[slen - 1];
235*50bf276cStholo
236*50bf276cStholo /* If bracket is ']' or '>', bracket - 2 is the corresponding
237*50bf276cStholo opening bracket. */
238*50bf276cStholo ptr = strchr (src, bracket - 2);
239*50bf276cStholo if (ptr == 0)
240*50bf276cStholo { /* no opening bracket */
241*50bf276cStholo strcpy (dst, src);
242*50bf276cStholo return 0;
243*50bf276cStholo }
244*50bf276cStholo if (!(rptr = strrchr (src, '.')))
245*50bf276cStholo rptr = ptr;
246*50bf276cStholo slen = rptr - src;
247*50bf276cStholo strncpy (dst, src, slen);
248*50bf276cStholo dst[slen] = '\0';
249*50bf276cStholo #if 0
250*50bf276cStholo fprintf (stderr, "dst = \"%s\"\nsrc = \"%s\"\nslen = %d\n",
251*50bf276cStholo dst, src, slen);
252*50bf276cStholo #endif
253*50bf276cStholo if (*rptr == '.')
254*50bf276cStholo {
255*50bf276cStholo dst[slen++] = bracket;
256*50bf276cStholo dst[slen] = '\0';
257*50bf276cStholo }
258*50bf276cStholo else
259*50bf276cStholo {
260*50bf276cStholo /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
261*50bf276cStholo then translate the device and recurse. */
262*50bf276cStholo if (dst[slen - 1] == ':'
263*50bf276cStholo && dst[slen - 2] != ':' /* skip decnet nodes */
264*50bf276cStholo && ((src[slen] == '['
265*50bf276cStholo && strcmp(src + slen + 1, "000000]") == 0)
266*50bf276cStholo || src[slen] == '<'
267*50bf276cStholo && strcmp(src + slen + 1, "000000>") == 0))
268*50bf276cStholo {
269*50bf276cStholo static char equiv_buf[256];
270*50bf276cStholo static struct dsc$descriptor_s equiv
271*50bf276cStholo = {sizeof (equiv_buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, equiv_buf};
272*50bf276cStholo static struct dsc$descriptor_s d_name
273*50bf276cStholo = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
274*50bf276cStholo short eqlen;
275*50bf276cStholo
276*50bf276cStholo dst[slen - 1] = '\0';
277*50bf276cStholo d_name.dsc$w_length = strlen (dst);
278*50bf276cStholo d_name.dsc$a_pointer = dst;
279*50bf276cStholo if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1
280*50bf276cStholo && (equiv_buf[eqlen] = '\0', ptr = equiv_buf) != 0
281*50bf276cStholo && (rlen = strlen (ptr) - 1) > 0
282*50bf276cStholo && (ptr[rlen] == ']' || ptr[rlen] == '>')
283*50bf276cStholo && ptr[rlen - 1] == '.')
284*50bf276cStholo {
285*50bf276cStholo char * buf = (char *) malloc (strlen (ptr) + 1);
286*50bf276cStholo int tmp = ptr[rlen];
287*50bf276cStholo if (buf == 0)
288*50bf276cStholo return 0; /* bad luck */
289*50bf276cStholo strcpy (buf, ptr);
290*50bf276cStholo buf[rlen - 1] = tmp;
291*50bf276cStholo buf[rlen] = '\0';
292*50bf276cStholo tmp = directory_file_name (buf, dst);
293*50bf276cStholo free (buf);
294*50bf276cStholo return tmp;
295*50bf276cStholo }
296*50bf276cStholo else
297*50bf276cStholo dst[slen - 1] = ':';
298*50bf276cStholo }
299*50bf276cStholo strcat (dst, "[000000]");
300*50bf276cStholo slen += 8;
301*50bf276cStholo }
302*50bf276cStholo rptr++;
303*50bf276cStholo rlen = strlen (rptr) - 1;
304*50bf276cStholo strncat (dst, rptr, rlen);
305*50bf276cStholo dst[slen + rlen] = '\0';
306*50bf276cStholo strcat (dst, ".DIR.1");
307*50bf276cStholo return 1;
308*50bf276cStholo }
309*50bf276cStholo
310*50bf276cStholo /* Process as Unix format: just remove any final slash.
311*50bf276cStholo But leave "/" unchanged; do not change it to "". */
312*50bf276cStholo strcpy (dst, src);
313*50bf276cStholo if (slen > 1 && dst[slen - 1] == '/')
314*50bf276cStholo {
315*50bf276cStholo dst[slen - 1] = 0;
316*50bf276cStholo return 1;
317*50bf276cStholo }
318*50bf276cStholo return 0;
319*50bf276cStholo }
320*50bf276cStholo
321*50bf276cStholo /* end of snarf. */
322