/* * Copyright © 1994 the Free Software Foundation, Inc. * * Author: Richard Levitte (levitte@e.kth.se) * * This file is a part of GNU VMSLIB, the GNU library for porting GNU * software to VMS. * * GNU VMSLIB is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GNU VMSLIB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include "filutils.h" /* file_name_as_directory was snarfed from src/fileio.c in GNU Emacs. */ char * file_name_as_directory (out, in) char *out, *in; { int size = strlen (in) - 1; int ext_point = 0; strcpy (out, in); /* Is it already a directory string? */ if (in[size] == ':' || in[size] == ']' || in[size] == '>') return out; /* Is it a VMS directory file name? If so, hack VMS syntax. */ else if (! strchr (in, '/')) { ext_point = 1; if (size > 3 && (! strcmp (&in[size - 3], ".DIR") || ! strcmp (&in[size - 3], ".dir"))) ext_point = -3; else if (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4) || ! strncmp (&in[size - 5], ".dir", 4)) && (in[size - 1] == '.' || in[size - 1] == ';') && in[size] == '1') ext_point = -5; } if (ext_point != 0) { register char *p, *dot; char brack; /* dir:[000000]x.dir --> dir:x.dir --> dir:[x] dir:[000000.x]y.dir --> dir:[x]y.dir --> dir:[x.y] but dir:[000000.000000]x.dir --> dir:[000000.000000.x] dir:[000000.000000.x]y.dir --> dir:[000000.000000.x.y] */ static char tem[256]; p = dot = strchr(in,':'); if (p != 0 && (p[1] == '[' || p[1] == '<')) { p += 2; if (strncmp(p,"000000",6) == 0) { p += 6; if (strncmp(p,".000000",7) != 0 && (*p == ']' || *p == '>' || *p == '.')) { size = dot - in + 1; strncpy(tem, in, size); if (*p == '.') tem[size++] = '['; strcpy(tem + size, p + 1); in = tem; size = strlen(in) - 1; } } } /* x.dir -> [.x] dir:x.dir --> dir:[x] dir:[x]y.dir --> dir:[x.y] */ p = in + size; while (p != in && *p != ':' && *p != '>' && *p != ']') p--; { char *emergency_dir = 0; int emergency_point = 0; /* relative to the end of `out' */ if (p != in) { strncpy (out, in, p - in); out[p - in] = '\0'; if (*p == ':') { brack = ']'; strcat (out, ":["); emergency_dir = "000000"; emergency_point = 0; } else { brack = *p; strcat (out, "."); emergency_dir = ""; emergency_point = -1; } p++; } else { brack = ']'; strcpy (out, "[."); emergency_dir = ""; emergency_point = -2; } if (strncmp (p, "000000.", 7) == 0 && (strncmp (p+7, "000000", 6) != 0 || (p[13] != ']' && p[13] != '>' && p[13] != '.'))) p += 7; if (p < (in + size + ext_point)) { register copy_len = ((in + size + ext_point) - p); size = strlen (out) + copy_len; strncat (out, p, copy_len); } else { size = strlen (out) + emergency_point; strcpy (out + size, emergency_dir); size += strlen (emergency_dir); } } out[size++] = brack; out[size] = '\0'; } return out; } /* * Convert from directory name to filename. * On VMS: * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1 * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1 * On UNIX, it's simple: just make sure there is a terminating / * Value is nonzero if the string output is different from the input. */ /* directory_file_name was snarfed from src/fileio.c in GNU Emacs. */ #include directory_file_name (src, dst) char *src, *dst; { long slen; long rlen; char * ptr, * rptr; char bracket; struct FAB fab = cc$rms_fab; struct NAM nam = cc$rms_nam; char esa[NAM$C_MAXRSS]; slen = strlen (src); if (! strchr (src, '/') && (src[slen - 1] == ']' || src[slen - 1] == ':' || src[slen - 1] == '>')) { /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */ fab.fab$l_fna = src; fab.fab$b_fns = slen; fab.fab$l_nam = &nam; fab.fab$l_fop = FAB$M_NAM; nam.nam$l_esa = esa; nam.nam$b_ess = sizeof esa; nam.nam$b_nop |= NAM$M_SYNCHK; /* We call SYS$PARSE to handle such things as [--] for us. */ if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL) { slen = nam.nam$b_esl; if (esa[slen - 1] == ';' && esa[slen - 2] == '.') slen -= 2; esa[slen] = '\0'; src = esa; } if (src[slen - 1] != ']' && src[slen - 1] != '>') { /* what about when we have logical_name:???? */ if (src[slen - 1] == ':') { /* Xlate logical name and see what we get */ ptr = strcpy (dst, src); /* upper case for getenv */ while (*ptr) { if ('a' <= *ptr && *ptr <= 'z') *ptr -= 040; ptr++; } dst[slen - 1] = 0; /* remove colon */ if (!(src = getenv (dst))) return 0; /* should we jump to the beginning of this procedure? Good points: allows us to use logical names that xlate to Unix names, Bad points: can be a problem if we just translated to a device name... For now, I'll punt and always expect VMS names, and hope for the best! */ slen = strlen (src); if (src[slen - 1] != ']' && src[slen - 1] != '>') { /* no recursion here! */ strcpy (dst, src); return 0; } } else { /* not a directory spec */ strcpy (dst, src); return 0; } } bracket = src[slen - 1]; /* If bracket is ']' or '>', bracket - 2 is the corresponding opening bracket. */ ptr = strchr (src, bracket - 2); if (ptr == 0) { /* no opening bracket */ strcpy (dst, src); return 0; } if (!(rptr = strrchr (src, '.'))) rptr = ptr; slen = rptr - src; strncpy (dst, src, slen); dst[slen] = '\0'; #if 0 fprintf (stderr, "dst = \"%s\"\nsrc = \"%s\"\nslen = %d\n", dst, src, slen); #endif if (*rptr == '.') { dst[slen++] = bracket; dst[slen] = '\0'; } else { /* If we have the top-level of a rooted directory (i.e. xx:[000000]), then translate the device and recurse. */ if (dst[slen - 1] == ':' && dst[slen - 2] != ':' /* skip decnet nodes */ && ((src[slen] == '[' && strcmp(src + slen + 1, "000000]") == 0) || src[slen] == '<' && strcmp(src + slen + 1, "000000>") == 0)) { static char equiv_buf[256]; static struct dsc$descriptor_s equiv = {sizeof (equiv_buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, equiv_buf}; static struct dsc$descriptor_s d_name = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; short eqlen; dst[slen - 1] = '\0'; d_name.dsc$w_length = strlen (dst); d_name.dsc$a_pointer = dst; if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1 && (equiv_buf[eqlen] = '\0', ptr = equiv_buf) != 0 && (rlen = strlen (ptr) - 1) > 0 && (ptr[rlen] == ']' || ptr[rlen] == '>') && ptr[rlen - 1] == '.') { char * buf = (char *) malloc (strlen (ptr) + 1); int tmp = ptr[rlen]; if (buf == 0) return 0; /* bad luck */ strcpy (buf, ptr); buf[rlen - 1] = tmp; buf[rlen] = '\0'; tmp = directory_file_name (buf, dst); free (buf); return tmp; } else dst[slen - 1] = ':'; } strcat (dst, "[000000]"); slen += 8; } rptr++; rlen = strlen (rptr) - 1; strncat (dst, rptr, rlen); dst[slen + rlen] = '\0'; strcat (dst, ".DIR.1"); return 1; } /* Process as Unix format: just remove any final slash. But leave "/" unchanged; do not change it to "". */ strcpy (dst, src); if (slen > 1 && dst[slen - 1] == '/') { dst[slen - 1] = 0; return 1; } return 0; } /* end of snarf. */