xref: /openbsd-src/gnu/usr.bin/cvs/vms/filutils.c (revision 461cc63e7458ce60db55037c1a7656349538b52f)
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