1 /* vmsify.c -- Module for vms <-> unix file name conversion
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006 Free Software Foundation, Inc.
4 This file is part of GNU Make.
5 
6 GNU Make is free software; you can redistribute it and/or modify it under the
7 terms of the GNU General Public License as published by the Free Software
8 Foundation; either version 2, or (at your option) any later version.
9 
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along with
15 GNU Make; see the file COPYING.  If not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
17 
18 /* Written by Klaus K�mpf (kkaempf@progis.de)
19    of proGIS Software, Aachen, Germany */
20 
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 
26 #if VMS
27 #include <unixlib.h>
28 #include <stdlib.h>
29 #include <jpidef.h>
30 #include <descrip.h>
31 #include <uaidef.h>
32 #include <ssdef.h>
33 #include <starlet.h>
34 #include <lib$routines.h>
35 /* Initialize a string descriptor (struct dsc$descriptor_s) for an
36    arbitrary string.   ADDR is a pointer to the first character
37    of the string, and LEN is the length of the string. */
38 
39 #define INIT_DSC_S(dsc, addr, len) do { \
40   (dsc).dsc$b_dtype = DSC$K_DTYPE_T;    \
41   (dsc).dsc$b_class = DSC$K_CLASS_S;    \
42   (dsc).dsc$w_length = (len);           \
43   (dsc).dsc$a_pointer = (addr);         \
44 } while (0)
45 
46 /* Initialize a string descriptor (struct dsc$descriptor_s) for a
47    NUL-terminated string.  S is a pointer to the string; the length
48    is determined by calling strlen(). */
49 
50 #define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
51 #endif
52 
53 /*
54   copy 'from' to 'to' up to but not including 'upto'
55   return 0 if eos on from
56   return 1 if upto found
57 
58   return 'to' at last char + 1
59   return 'from' at match + 1 or eos if no match
60 
61   if as_dir == 1, change all '.' to '_'
62   else change all '.' but the last to '_'
63 */
64 
65 static int
copyto(char ** to,char ** from,char upto,int as_dir)66 copyto (char **to, char **from, char upto, int as_dir)
67 {
68   char *s;
69 
70   s = strrchr (*from, '.');
71 
72   while (**from)
73     {
74       if (**from == upto)
75 	{
76 	  do
77 	    {
78 	      (*from)++;
79 	    }
80 	  while (**from == upto);
81 	  return 1;
82 	}
83       if (**from == '.')
84 	{
85 	  if ((as_dir == 1)
86 	      || (*from != s))
87 	    **to = '_';
88 	  else
89 	    **to = '.';
90 	}
91       else
92 	{
93 #ifdef HAVE_CASE_INSENSITIVE_FS
94 	  if (isupper ((unsigned char)**from))
95 	    **to = tolower ((unsigned char)**from);
96 	  else
97 #endif
98 	    **to = **from;
99 	}
100       (*to)++;
101       (*from)++;
102     }
103 
104   return 0;
105 }
106 
107 
108 /*
109   get translation of logical name
110 
111 */
112 
113 static char *
trnlog(char * name)114 trnlog (char *name)
115 {
116   int stat;
117   static char reslt[1024];
118   $DESCRIPTOR (reslt_dsc, reslt);
119   short resltlen;
120   struct dsc$descriptor_s name_dsc;
121   char *s;
122 
123   INIT_DSC_CSTRING (name_dsc, name);
124 
125   stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
126 
127   if ((stat&1) == 0)
128     {
129       return "";
130     }
131   if (stat == SS$_NOTRAN)
132     {
133       return "";
134     }
135   reslt[resltlen] = '\0';
136 
137   s = (char *)malloc (resltlen+1);
138   if (s == 0)
139     return "";
140   strcpy (s, reslt);
141   return s;
142 }
143 
144 static char *
showall(char * s)145 showall (char *s)
146 {
147   static char t[512];
148   char *pt;
149 
150   pt = t;
151   if (strchr (s, '\\') == 0)
152     return s;
153   while (*s)
154     {
155       if (*s == '\\')
156 	{
157 	  *pt++ = *s;
158 	}
159       *pt++ = *s++;
160     }
161   return pt;
162 }
163 
164 
165 enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
166 
167 /*
168   convert unix style name to vms style
169   type = 0 -> name is a full name (directory and filename part)
170   type = 1 -> name is a directory
171   type = 2 -> name is a filename without directory
172 
173   The following conversions are applied
174 			(0)		(1)			(2)
175 	input		full name	dir name		file name
176 
177 1	./		<cwd>		[]			<current directory>.dir
178 2	../		<home of cwd>	<home of cwd>		<home of cwd>.dir
179 
180 3	//		<dev of cwd>:	<dev of cwd>:[000000]	<dev of cwd>:000000.dir
181 4	//a		a:		a:			a:
182 5	//a/		a:		a:			a:000000.dir
183 
184 9	/		[000000]	[000000]		000000.dir
185 10	/a		[000000]a	[a]			[000000]a
186 11	/a/		[a]		[a]			[000000]a.dir
187 12	/a/b		[a]b		[a.b]			[a]b
188 13	/a/b/		[a.b]		[a.b]			[a]b.dir
189 14	/a/b/c		[a.b]c		[a.b.c]			[a.b]c
190 15	/a/b/c/		[a.b.c]		[a.b.c]			[a.b]c.dir
191 
192 16	a		a		[.a]			a
193 17	a/		[.a]		[.a]			a.dir
194 18	a/b		[.a]b		[.a.b]			[.a]b
195 19	a/b/		[.a.b]		[.a.b]			[.a]b.dir
196 20	a/b/c		[.a.b]c		[.a.b.c]		[.a.b]c
197 21	a/b/c/		[.a.b.c]	[.a.b.c]		[.a.b]c.dir
198 
199 22	a.b.c		a_b.c		[.a_b_c]		a_b_c.dir
200 
201 23	[x][y]z		[x.y]z		[x.y]z			[x.y]z
202 24	[x][.y]z	[x.y]z		[x.y]z			[x.y]z
203 
204 25  filenames with '$'  are left unchanged if they contain no '/'
205 25  filenames with ':' are left unchanged
206 26  filenames with a single pair of '[' ']' are left unchanged
207 
208   the input string is not written to
209 */
210 
211 char *
vmsify(char * name,int type)212 vmsify (char *name, int type)
213 {
214 /* max 255 device
215    max 39 directory
216    max 39 filename
217    max 39 filetype
218    max 5 version
219 */
220 #define MAXPATHLEN 512
221 
222   enum namestate nstate;
223   static char vmsname[MAXPATHLEN+1];
224   char *fptr;
225   char *vptr;
226   char *s,*s1;
227   int as_dir;
228   int count;
229 
230   if (name == 0)
231     return 0;
232   fptr = name;
233   vptr = vmsname;
234   nstate = N_START;
235 
236   /* case 25a */
237 
238   s = strpbrk (name, "$:");
239   if (s != 0)
240     {
241       char *s1;
242       char *s2;
243 
244       if (type == 1)
245 	{
246 	  s1 = strchr (s+1, '[');
247 	  s2 = strchr (s+1, ']');
248 	}
249 
250       if (*s == '$')
251 	{
252 	  if (strchr (name, '/') == 0)
253 	    {
254 	      if ((type == 1) && (s1 != 0) && (s2 == 0))
255 		{
256 		  strcpy (vmsname, name);
257 		  strcat (vmsname, "]");
258 		  return vmsname;
259 		}
260 	      else
261 		return name;
262 	    }
263 	}
264       else
265 	{
266 	  if ((type == 1) && (s1 != 0) && (s2 == 0))
267 	    {
268 	      strcpy (vmsname, name);
269 	      strcat (vmsname, "]");
270 	      return vmsname;
271 	    }
272 	  else
273 	    return name;
274 	}
275     }
276 
277   /* case 26 */
278 
279   s = strchr (name, '[');
280 
281   if (s != 0)
282     {
283       s1 = strchr (s+1, '[');
284       if (s1 == 0)
285 	{
286 	  if ((type == 1)
287 	       && (strchr (s+1, ']') == 0))
288 	    {
289 	      strcpy (vmsname, name);
290 	      strcat (vmsname, "]");
291 	      return vmsname;
292 	    }
293 	  else
294 	    return name;			/* single [, keep unchanged */
295 	}
296       s1--;
297       if (*s1 != ']')
298 	{
299 	  return name;			/* not ][, keep unchanged */
300 	}
301 
302       /* we have ][ */
303 
304       s = name;
305 
306       /* s  -> starting char
307 	 s1 -> ending ']'  */
308 
309       do
310 	{
311 	  strncpy (vptr, s, s1-s);	/* copy up to but not including ']' */
312 	  vptr += s1-s;
313 	  if (*s1 == 0)
314 	    break;
315 	  s = s1 + 1;			/* s -> char behind ']' */
316 	  if (*s != '[')		/* was '][' ? */
317 	    break;			/* no, last ] found, exit */
318 	  s++;
319 	  if (*s != '.')
320 	    *vptr++ = '.';
321 	  s1 = strchr (s, ']');
322 	  if (s1 == 0)			/* no closing ] */
323 	    s1 = s + strlen (s);
324 	}
325       while (1);
326 
327       *vptr++ = ']';
328 
329       fptr = s;
330 
331     }
332 
333   else		/* no [ in name */
334 
335     {
336 
337       int state;
338       int rooted = 1;	/* flag if logical is rooted, else insert [000000] */
339 
340       state = 0;
341 
342       do
343 	{
344 
345       switch (state)
346 	{
347 	  case 0:				/* start of loop */
348 	    if (*fptr == '/')
349 	      {
350 		fptr++;
351 		state = 1;
352 	      }
353 	    else if (*fptr == '.')
354 	      {
355 		fptr++;
356 		state = 10;
357 	      }
358 	    else
359 	      state = 2;
360 	    break;
361 
362 	  case 1:				/* '/' at start */
363 	    if (*fptr == '/')
364 	      {
365 		fptr++;
366 		state = 3;
367 	      }
368 	    else
369 	      state = 4;
370 	    break;
371 
372 	  case 2:				/* no '/' at start */
373 	    s = strchr (fptr, '/');
374 	    if (s == 0)			/* no '/' (16) */
375 	      {
376 		if (type == 1)
377 		  {
378 		    strcpy (vptr, "[.");
379 		    vptr += 2;
380 		  }
381 		copyto (&vptr, &fptr, 0, (type==1));
382 		if (type == 1)
383 		  *vptr++ = ']';
384 		state = -1;
385 	      }
386 	    else			/* found '/' (17..21) */
387 	      {
388 		if ((type == 2)
389 		    && (*(s+1) == 0))	/* 17(2) */
390 		  {
391 		    copyto (&vptr, &fptr, '/', 1);
392 		    state = 7;
393 		  }
394 		else
395 		  {
396 		    strcpy (vptr, "[.");
397 		    vptr += 2;
398 		    copyto (&vptr, &fptr, '/', 1);
399 		    nstate = N_OPEN;
400 		    state = 9;
401 		  }
402 	      }
403 	    break;
404 
405 	  case 3:				/* '//' at start */
406 	    while (*fptr == '/')	/* collapse all '/' */
407 	      fptr++;
408 	    if (*fptr == 0)		/* just // */
409 	      {
410 		char cwdbuf[MAXPATHLEN+1];
411 
412 		s1 = getcwd(cwdbuf, MAXPATHLEN);
413 		if (s1 == 0)
414 		  {
415 		    return "";		/* FIXME, err getcwd */
416 		  }
417 		s = strchr (s1, ':');
418 		if (s == 0)
419 		  {
420 		    return "";		/* FIXME, err no device */
421 		  }
422 		strncpy (vptr, s1, s-s1+1);
423 		vptr += s-s1+1;
424 		state = -1;
425 		break;
426 	      }
427 
428 	    s = vptr;
429 
430 	    if (copyto (&vptr, &fptr, '/', 1) == 0)	/* copy device part */
431 	      {
432 		*vptr++ = ':';
433 		state = -1;
434 		break;
435 	      }
436 	    *vptr = ':';
437 	    nstate = N_DEVICE;
438 	    if (*fptr == 0)	/* just '//a/' */
439 	      {
440 		strcpy (vptr+1, "[000000]");
441 		vptr += 9;
442 		state = -1;
443 		break;
444 	      }
445 	    *vptr = 0;
446 				/* check logical for [000000] insertion */
447 	    s1 = trnlog (s);
448 	    if (*s1 != 0)
449 	      {			/* found translation */
450 		char *s2;
451 		for (;;)	/* loop over all nested logicals */
452 		  {
453 		    s2 = s1 + strlen (s1) - 1;
454 		    if (*s2 == ':')	/* translation ends in ':' */
455 		      {
456 			s2 = trnlog (s1);
457 			free (s1);
458 			if (*s2 == 0)
459 			  {
460 			    rooted = 0;
461 			    break;
462 			  }
463 			s1 = s2;
464 			continue;	/* next iteration */
465 		      }
466 		    if (*s2 == ']')	/* translation ends in ']' */
467 		      {
468 			if (*(s2-1) == '.')	/* ends in '.]' */
469 			  {
470 			    if (strncmp (fptr, "000000", 6) != 0)
471 			      rooted = 0;
472 			  }
473 			else
474 			  {
475 			    strcpy (vmsname, s1);
476 			    s = strchr (vmsname, ']');
477 			    *s = '.';
478 			    nstate = N_DOT;
479 			    vptr = s;
480 			  }
481 		      }
482 		    break;
483 		  }
484 		free (s1);
485 	      }
486 	    else
487 	      rooted = 0;
488 
489 	    if (*vptr == 0)
490 	      {
491 		nstate = N_DEVICE;
492 	        *vptr++ = ':';
493 	      }
494 	    else
495 	      vptr++;
496 
497 	    if (rooted == 0)
498 	      {
499 	        strcpy (vptr, "[000000.");
500 		vptr += 8;
501 		s1 = vptr-1;
502 		nstate = N_DOT;
503 	      }
504 	    else
505 	      s1 = 0;
506 
507 	/* s1-> '.' after 000000 or NULL */
508 
509 	    s = strchr (fptr, '/');
510 	    if (s == 0)
511 	      {				/* no next '/' */
512 		if (*(vptr-1) == '.')
513 		  *(vptr-1) = ']';
514 		else if (rooted == 0)
515 		  *vptr++ = ']';
516 		copyto (&vptr, &fptr, 0, (type == 1));
517 		state = -1;
518 		break;
519 	      }
520 	    else
521 	      {
522 		while (*(s+1) == '/')	/* skip multiple '/' */
523 		  s++;
524 	      }
525 
526 	    if ((rooted != 0)
527 	        && (*(vptr-1) != '.'))
528 	      {
529 		*vptr++ = '[';
530 		nstate = N_DOT;
531 	      }
532 	    else
533 	      if ((nstate == N_DOT)
534 		 && (s1 != 0)
535 		 && (*(s+1) == 0))
536 		{
537 		  if (type == 2)
538 		    {
539 		      *s1 = ']';
540 		      nstate = N_CLOSED;
541 		    }
542 		}
543 	    state = 9;
544 	    break;
545 
546 	  case 4:				/* single '/' at start (9..15) */
547 	    if (*fptr == 0)
548 	      state = 5;
549 	    else
550 	      state = 6;
551 	    break;
552 
553 	  case 5:				/* just '/' at start (9) */
554 	    if (type != 2)
555 	      {
556 	        *vptr++ = '[';
557 		nstate = N_OPEN;
558 	      }
559 	    strcpy (vptr, "000000");
560 	    vptr += 6;
561 	    if (type == 2)
562 	      state = 7;
563 	    else
564 	      state = 8;
565 	    break;
566 
567 	  case 6:				/* chars following '/' at start 10..15 */
568 	    *vptr++ = '[';
569 	    nstate = N_OPEN;
570 	    s = strchr (fptr, '/');
571 	    if (s == 0)			/* 10 */
572 	      {
573 		if (type != 1)
574 		  {
575 		    strcpy (vptr, "000000]");
576 		    vptr += 7;
577 		  }
578 		copyto (&vptr, &fptr, 0, (type == 1));
579 		if (type == 1)
580 		  {
581 		    *vptr++ = ']';
582 		  }
583 		state = -1;
584 	      }
585 	    else			/* 11..15 */
586 	      {
587 		if ( (type == 2)
588 		   && (*(s+1) == 0))	/* 11(2) */
589 		  {
590 		    strcpy (vptr, "000000]");
591 		    nstate = N_CLOSED;
592 		    vptr += 7;
593 		  }
594 		copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
595 		state = 9;
596 	      }
597 	    break;
598 
599 	  case 7:				/* add '.dir' and exit */
600 	    if ((nstate == N_OPEN)
601 		|| (nstate == N_DOT))
602 	      {
603 		s = vptr-1;
604 		while (s > vmsname)
605 		  {
606 		    if (*s == ']')
607 		      {
608 			break;
609 		      }
610 		    if (*s == '.')
611 		      {
612 			*s = ']';
613 			break;
614 		      }
615 		    s--;
616 		  }
617 	      }
618 	    strcpy (vptr, ".dir");
619 	    vptr += 4;
620 	    state = -1;
621 	    break;
622 
623 	  case 8:				/* add ']' and exit */
624 	    *vptr++ = ']';
625 	    state = -1;
626 	    break;
627 
628 	  case 9:				/* 17..21, fptr -> 1st '/' + 1 */
629 	    if (*fptr == 0)
630 	      {
631 		if (type == 2)
632 		  {
633 		    state = 7;
634 		  }
635 		else
636 		  state = 8;
637 		break;
638 	      }
639 	    s = strchr (fptr, '/');
640 	    if (s == 0)
641 	      {
642 		if (type != 1)
643 		  {
644 		    if (nstate == N_OPEN)
645 		      {
646 			*vptr++ = ']';
647 			nstate = N_CLOSED;
648 		      }
649 		    as_dir = 0;
650 		  }
651 		else
652 		  {
653 		    if (nstate == N_OPEN)
654 		      {
655 			*vptr++ = '.';
656 			nstate = N_DOT;
657 		      }
658 		    as_dir = 1;
659 		  }
660 	      }
661 	    else
662 	      {
663 		while (*(s+1) == '/')
664 		  s++;
665 		if ( (type == 2)
666 		    && (*(s+1) == 0))		/* 19(2), 21(2)*/
667 		  {
668 		    if (nstate != N_CLOSED)
669 		      {
670 			*vptr++ = ']';
671 			nstate = N_CLOSED;
672 		      }
673 		    as_dir = 1;
674 		  }
675 		else
676 		  {
677 		    if (nstate == N_OPEN)
678 		      {
679 			*vptr++ = '.';
680 			nstate = N_DOT;
681 		      }
682 		    as_dir = 1;
683 		  }
684 	      }
685 	    if ( (*fptr == '.')			/* check for '..' or '../' */
686 		&& (*(fptr+1) == '.')
687 		&& ((*(fptr+2) == '/')
688 		    || (*(fptr+2) == 0)) )
689 	      {
690 		fptr += 2;
691 		if (*fptr == '/')
692 		  {
693 		    do
694 		      {
695 			fptr++;
696 		      }
697 		    while (*fptr == '/');
698 		  }
699 		else if (*fptr == 0)
700 		  type = 1;
701 		vptr--;				/* vptr -> '.' or ']' */
702 		s1 = vptr;
703 		for (;;)
704 		  {
705 		    s1--;
706 		    if (*s1 == '.')		/* one back */
707 		      {
708 			vptr = s1;
709 			nstate = N_OPEN;
710 			break;
711 		      }
712 		    if (*s1 == '[')		/* top level reached */
713 		      {
714 			if (*fptr == 0)
715 			  {
716 			    strcpy (s1, "[000000]");
717 			    vptr = s1 + 8;
718 			    nstate = N_CLOSED;
719 			    s = 0;
720 			    break;
721 			  }
722 			else
723 			  {
724 			    vptr = s1+1;
725 			    nstate = N_OPEN;
726 			    break;
727 			  }
728 		      }
729 		  }
730 	      }
731 	    else
732 	      {
733 		copyto (&vptr, &fptr, '/', as_dir);
734 		if (nstate == N_DOT)
735 		  nstate = N_OPEN;
736 	      }
737 	    if (s == 0)
738 	      {					/* 18,20 */
739 		if (type == 1)
740 		  *vptr++ = ']';
741 		state = -1;
742 	      }
743 	    else
744 	      {
745 		if (*(s+1) == 0)
746 		  {
747 		    if (type == 2)		/* 19,21 */
748 		      {
749 		        state = 7;
750 		      }
751 		    else
752 		      {
753 			*vptr++ = ']';
754 			state = -1;
755 		      }
756 		  }
757 	      }
758 	    break;
759 
760 	  case 10:				/* 1,2 first is '.' */
761 	    if (*fptr == '.')
762 	      {
763 		fptr++;
764 		state = 11;
765 	      }
766 	    else
767 	      state = 12;
768 	    break;
769 
770 	  case 11:				/* 2, '..' at start */
771 	    count = 1;
772 	    if (*fptr != 0)
773 	      {
774 		if (*fptr != '/')		/* got ..xxx */
775 		  {
776 		    return name;
777 		  }
778 		do				/* got ../ */
779 		  {
780 		    fptr++;
781 		    while (*fptr == '/') fptr++;
782 		    if (*fptr != '.')
783 		      break;
784 		    if (*(fptr+1) != '.')
785 		      break;
786 		    fptr += 2;
787 		    if ((*fptr == 0)
788 			|| (*fptr == '/'))
789 		      count++;
790 		  }
791 		while (*fptr == '/');
792 	      }
793 	    {					/* got '..' or '../' */
794 	      char cwdbuf[MAXPATHLEN+1];
795 
796 	      s1 = getcwd(cwdbuf, MAXPATHLEN);
797 	      if (s1 == 0)
798 		{
799 		  return "";	    /* FIXME, err getcwd */
800 		}
801 	      strcpy (vptr, s1);
802 	      s = strchr (vptr, ']');
803 	      if (s != 0)
804 		{
805 		  nstate = N_OPEN;
806 		  while (s > vptr)
807 		    {
808 		      s--;
809 		      if (*s == '[')
810 			{
811 			  s++;
812 			  strcpy (s, "000000]");
813 			  state = -1;
814 			  break;
815 			}
816 		      else if (*s == '.')
817 			{
818 			  if (--count == 0)
819 			    {
820 			      if (*fptr == 0)	/* had '..' or '../' */
821 				{
822 				  *s++ = ']';
823 				  state = -1;
824 				}
825 			      else			/* had '../xxx' */
826 				{
827 				  state = 9;
828 				}
829 			      *s = 0;
830 			      break;
831 			    }
832 			}
833 		    }
834 		}
835 	      vptr += strlen (vptr);
836 	    }
837 	    break;
838 
839 	  case 12:				/* 1, '.' at start */
840 	    if (*fptr != 0)
841 	      {
842 		if (*fptr != '/')
843 		  {
844 		    return name;
845 		  }
846 		while (*fptr == '/')
847 		  fptr++;
848 	      }
849 
850 	    {
851 	      char cwdbuf[MAXPATHLEN+1];
852 
853 	      s1 = getcwd(cwdbuf, MAXPATHLEN);
854 	      if (s1 == 0)
855 		{
856 		  return "";	    /*FIXME, err getcwd */
857 		}
858 	      strcpy (vptr, s1);
859 	      if (*fptr == 0)
860 		{
861 		  state = -1;
862 		  break;
863 		}
864 	      else
865 		{
866 		  s = strchr (vptr, ']');
867 		  if (s == 0)
868 		    {
869 		      state = -1;
870 		      break;
871 		    }
872 		  *s = 0;
873 		  nstate = N_OPEN;
874 		  vptr += strlen (vptr);
875 		  state = 9;
876 		}
877 	    }
878 	    break;
879 	}
880 
881 	}
882       while (state > 0);
883 
884 
885     }
886 
887 
888   /* directory conversion done
889      fptr -> filename part of input string
890      vptr -> free space in vmsname
891   */
892 
893   *vptr++ = 0;
894 
895   return vmsname;
896 }
897 
898 
899 
900 /*
901   convert from vms-style to unix-style
902 
903   dev:[dir1.dir2]	//dev/dir1/dir2/
904 */
905 
906 char *
unixify(char * name)907 unixify (char *name)
908 {
909   static char piece[512];
910   char *s, *p;
911 
912   if (strchr (name, '/') != 0)		/* already in unix style */
913     return name;
914 
915   p = piece;
916   *p = 0;
917 
918   /* device part */
919 
920   s = strchr (name, ':');
921 
922   if (s != 0)
923     {
924       *s = 0;
925       *p++ = '/';
926       *p++ = '/';
927       strcpy (p, name);
928       p += strlen (p);
929       *s = ':';
930     }
931 
932   /* directory part */
933 
934   *p++ = '/';
935   s = strchr (name, '[');
936 
937   if (s != 0)
938     {
939       s++;
940       switch (*s)
941         {
942 	  case ']':		/* [] */
943 	    strcat (p, "./");
944 	    break;
945 	  case '-':		/* [- */
946 	    strcat (p, "../");
947 	    break;
948 	  case '.':
949 	    strcat (p, "./");	/* [. */
950 	    break;
951 	  default:
952 	    s--;
953 	    break;
954         }
955       s++;
956       while (*s)
957         {
958 	  if (*s == '.')
959 	    *p++ = '/';
960 	  else
961 	    *p++ = *s;
962 	  s++;
963 	  if (*s == ']')
964 	    {
965 	      s++;
966 	      break;
967 	    }
968         }
969       if (*s != 0)		/* more after ']' ?? */
970         {
971 	  if (*(p-1) != '/')
972 	    *p++ = '/';
973 	  strcpy (p, s);		/* copy it anyway */
974         }
975     }
976 
977   else		/* no '[' anywhere */
978 
979     {
980       *p++ = 0;
981     }
982 
983   /* force end with '/' */
984 
985   if (*(p-1) != '/')
986     *p++ = '/';
987   *p = 0;
988 
989   return piece;
990 }
991 
992 /* EOF */
993