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