summaryrefslogtreecommitdiff
path: root/vms/filutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'vms/filutils.c')
-rw-r--r--vms/filutils.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/vms/filutils.c b/vms/filutils.c
new file mode 100644
index 0000000..8cae5f7
--- /dev/null
+++ b/vms/filutils.c
@@ -0,0 +1,321 @@
+/*
+ * 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 <string.h>
+#include <file.h>
+#include <rmsdef.h>
+#include <fab.h>
+#include <nam.h>
+#include <stdlib.h>
+#include <lib$routines.h>
+#include <descrip.h>
+#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 <stdio.h>
+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 *) xmalloc (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. */