home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / vms2unix.c < prev    next >
C/C++ Source or Header  |  1997-10-06  |  13KB  |  629 lines

  1. /*
  2.  *    vms2unix.c
  3.  *
  4.  *    Miscellaneous routines for UNIX/VMS compatibility.
  5.  *
  6.  * $Header: /usr/build/vile/vile/RCS/vms2unix.c,v 1.31 1997/10/06 23:33:39 tom Exp $
  7.  *
  8.  */
  9. #include    "estruct.h"
  10. #include    "edef.h"
  11. #include    "dirstuff.h"
  12.  
  13. #define PERIOD    '.'
  14. #define COLON     ':'
  15. #define SEMICOLON ';'
  16.  
  17. static const char RootDir[] = "000000";
  18. static const char DirType[] = ".DIR";
  19.  
  20. #if SYS_VMS
  21. #include    <starlet.h>
  22. #include    <unixio.h>
  23.  
  24. #define    zfab    dirp->dd_fab
  25. #define    znam    dirp->dd_nam
  26. #define    zrsa    dirp->dd_ret.d_name
  27. #define    zrsl    dirp->dd_ret.d_namlen
  28. #define    zesa    dirp->dd_esa
  29.  
  30. DIR *
  31. opendir(char *filename)
  32. {
  33.     DIR    *dirp = typecalloc(DIR);
  34.     long    status;
  35.  
  36.     if (dirp == 0)
  37.         return (0);
  38.  
  39.     zfab = cc$rms_fab;
  40.     zfab.fab$l_fop = FAB$M_NAM;
  41.     zfab.fab$l_nam = &znam;        /* FAB => NAM block    */
  42.     zfab.fab$l_dna = "*.*;*";    /* Default-selection    */
  43.     zfab.fab$b_dns = strlen(zfab.fab$l_dna);
  44.  
  45.     zfab.fab$l_fna = filename;
  46.     zfab.fab$b_fns = strlen(filename);
  47.  
  48.     znam = cc$rms_nam;
  49.     znam.nam$b_ess = NAM$C_MAXRSS;
  50.     znam.nam$l_esa = zesa;
  51.     znam.nam$b_rss = NAM$C_MAXRSS;
  52.     znam.nam$l_rsa = zrsa;
  53.  
  54.     if (sys$parse(&zfab) != RMS$_NORMAL) {
  55.         (void)closedir(dirp);
  56.         dirp = 0;
  57.     }
  58.     return (dirp);
  59. }
  60.  
  61. DIRENT *
  62. readdir(DIR *dirp)
  63. {
  64.     if (sys$search(&zfab) == RMS$_NORMAL) {
  65.         zrsl = znam.nam$b_rsl;
  66.         return (&(dirp->dd_ret));
  67.     }
  68.     return (0);
  69. }
  70.  
  71. int
  72. closedir(DIR *dirp)
  73. {
  74.     cfree(dirp);
  75.     return 0;
  76. }
  77.  
  78. char *
  79. tempnam(const char *head, const char *tail)
  80. {
  81.     char    temp[NFILEN];
  82.     char    leaf[NFILEN];
  83.     return mktemp(
  84.         strmalloc(
  85.             pathcat(temp,
  86.                 head,
  87.                 strcat(strcpy(leaf, tail), "XXXXXX"))));
  88. }
  89. #endif
  90.  
  91. #if OPT_VMS_PATH
  92. /*
  93.  * These functions are adapted from my port2vms library -- T.Dickey
  94.  */
  95.  
  96. /******************************************************************************
  97.  * Translate a UNIX-style name into a VMS-style name.                         *
  98.  ******************************************************************************/
  99.  
  100. static    int    DotPrefix (char *s);
  101. static    char    CharToVms (int c);
  102. static    int    leading_uc (char *dst, char *src);
  103. static    int    is_version (char *s);
  104.  
  105. static    int    leaf_dot;   /* counts dots found in a particular leaf */
  106. static    int    leaf_ver;   /* set if we found a DECshell version */
  107.  
  108. /*
  109.  * If we have a dot in the second character position, force that to a dollar
  110.  * sign.  Otherwise, keep the first dot in each unix leaf as a dot in the
  111.  * resulting vms name.
  112.  */
  113. static int
  114. DotPrefix(char * s)
  115. {
  116.     if (s[0] != EOS
  117.      && s[1] == PERIOD
  118.      && s[2] != EOS
  119.      && strchr("sp", s[0]))    /* hack for SCCS */
  120.         return (-1);
  121.     return (0);
  122. }
  123.  
  124. static char
  125. CharToVms(int c)
  126. {
  127.     if (c == PERIOD) {
  128.         if (leaf_dot++)
  129.             c = '$';
  130.     } else if (!isAlnum(c) && !strchr("_-", c)) {
  131.         c = '$';
  132.     }
  133.     return (c);
  134. }
  135.  
  136. static int
  137. leading_uc(char * dst, char * src)
  138. {
  139.     char    *base = dst;
  140.     register int    c;
  141.  
  142.     while ((c = *src) != EOS && c != SLASHC) {
  143.         if (isAlpha(c)) {
  144.             if (isLower(c))
  145.                 return (0);
  146.         } else if (!strchr("0123456789$_", c))
  147.             return (0);
  148.         *dst++ = c;
  149.         *dst   = EOS;
  150.         src++;
  151.     }
  152.     *dst = EOS;
  153.     if ((*base) && (dst = getenv(base)) != 0) {
  154.         c = strlen(base);
  155.         dst = skip_blanks(dst);
  156.         (void)strcpy(base, dst);
  157.         return (c);
  158.     }
  159.     return (0);
  160. }
  161.  
  162. /*
  163.  * Returns true if the string points to a valid VMS version indicator, which
  164.  * may begin with a '.' or ';', e.g.,
  165.  *    ;1
  166.  *    ;*
  167.  *    ;-1
  168.  */
  169. static int
  170. is_version(char *s)
  171. {
  172.     char     *t;
  173.  
  174.     if (*s == PERIOD
  175.      || *s == SEMICOLON) {
  176.         if (*++s == EOS
  177.          || !strcmp(s, "*")
  178.          || !strcmp(s, "0")
  179.          || (strtol(s, &t, 10) && *t == EOS))
  180.              return TRUE;
  181.     }
  182.     return FALSE;
  183. }
  184.  
  185. static char *
  186. path_suffix(char *path)
  187. {
  188.     char *leaf = pathleaf(path);
  189.     char *type = strchr(leaf, '.');
  190.     if (type == 0)
  191.         type = skip_string(leaf);
  192.     return type;
  193. }
  194.  
  195. static char *
  196. path_version(char *path)
  197. {
  198.     char *vers = strchr(path, SEMICOLON);
  199.     if (vers == 0)
  200.         vers = skip_string(path);
  201.     return vers;
  202. }
  203.  
  204. char *
  205. unix2vms_path(char *dst, const char *src)
  206. {
  207. #if !SYS_VMS
  208.     char    tmp2[NFILEN];
  209. #endif
  210.     char    tmp[NFILEN],
  211.         leading[NFILEN],
  212.         *t,
  213.         *s = strcpy(tmp, src),    /* ... to permit src == dst */
  214.         *d = dst,
  215.         c  = '?';
  216.     int    bracket    = FALSE,    /* true when "[" passed. */
  217.         on_top    = FALSE,    /* true when no "[." lead */
  218.         node    = FALSE,    /* true when node found */
  219.         device    = FALSE,    /* true when device found */
  220.         len;
  221.  
  222.     /*
  223.      * If VMS 'getenv()' is given an upper-case name, it assumes that it
  224.      * corresponds to a logical device assignment.  As a special case, if
  225.      * we have a leading token of this form, translate it.
  226.      */
  227.     if ((len = leading_uc(leading,s)) != 0) {
  228.         s  += len;
  229.         len = strlen(strcpy(d, leading));
  230.         while (len > 1 && d[len-1] == ' ')
  231.             len--;
  232.         if (*s) {        /* text follows leading token */
  233.             s++;        /* skip (assumed) SLASHC */
  234.             if ((len > 1)
  235.             &&  (d[len-1] == COLON)) {
  236.                 on_top = TRUE;
  237.             } else if (strchr(s, SLASHC)) {    /* must do a splice */
  238.                 if ((len > 2)
  239.                 &&  (d[len-1] == RBRACK)) {
  240.                     bracket++;
  241.                     if (d[len-2] == PERIOD)
  242.                         /* rooted-device ? */
  243.                         len -= 2;
  244.                     else
  245.                         len--;
  246.                 }
  247.             }
  248.         }
  249.         d[len] = EOS;
  250.         if ((t = strchr(d, COLON)) != NULL) {
  251.             if (t[1] == COLON) {
  252.                 node = TRUE;
  253.                 if ((t = strchr(t+2, COLON)) != NULL)
  254.                     device = TRUE;
  255.             } else
  256.                 device = TRUE;
  257.         }
  258.         d  += len;
  259.     } else if (*s == '~') {        /* process home-directory reference */
  260.         char *home = getenv("SYS$LOGIN");
  261. #if !SYS_VMS
  262.         if (home == 0)
  263.             home = unix2vms_path(tmp2, getenv("HOME"));
  264. #endif
  265.         node =
  266.         device = TRUE;
  267.         s++;
  268.  
  269.         len = strlen(strcpy(d, home));
  270.  
  271.         if (d[len-1] == RBRACK) {
  272.             bracket++;
  273.             if (strcmp(s, "/")) { /* strip right-bracket to allow new levels */
  274.                 if (d[len-2] == PERIOD)
  275.                     len--;
  276.                 d[len-1] = PERIOD;
  277.             } else {
  278.                 s++;
  279.                 len--;
  280.             }
  281.         }
  282.         d += len;
  283.     }
  284.  
  285.     /* look for node-name in VMS-format */
  286.     if (!node
  287.     &&  (t = strchr(s, '!')) != 0
  288.     &&  (t[1] == SLASHC || t[1] == EOS)) {
  289.         leaf_dot = DotPrefix(s);
  290.         while (s < t)
  291.             *d++ = CharToVms(*s++);
  292.         *d++ = COLON;
  293.         *d++ = COLON;
  294.         s++;        /* skip over '!' */
  295.     }
  296.  
  297.     /* look for device-name, indicated by a leading SLASHC */
  298.     if (!device
  299.     &&  (*s == SLASHC)) {
  300.         leaf_dot = DotPrefix(++s);
  301.         if ((t = strchr(s, SLASHC)) == 0)
  302.             t = skip_string(s);
  303.         else if (t[1] == EOS)
  304.             on_top = TRUE;
  305.         while (s < t)
  306.             *d++ = CharToVms(*s++);
  307.         if (d != dst)
  308.             *d++ = COLON;
  309.     }
  310.  
  311.     /* permit leading "./" to simplify cases in which we concatenate */
  312.     if (!strncmp(s, "./", 2))
  313.         s += 2;
  314.  
  315.     /* translate repeated leading "../" */
  316.     while (!strncmp(s, "../", 3)) {
  317.         s += 3;
  318.         if (!bracket++)
  319.             *d++ = LBRACK;
  320.         *d++ = '-';
  321.     }
  322.     if (!strcmp(s, "..")) {
  323.         s += 2;
  324.         if (!bracket++)
  325.             *d++ = LBRACK;
  326.         *d++ = '-';
  327.     }
  328.  
  329.     if (strchr(s, SLASHC)) {
  330.         if (!bracket++)
  331.             *d++ = LBRACK;
  332.         if (*s == SLASHC) {
  333.             s++;
  334.         } else if (!on_top) {
  335.             *d++ = PERIOD;
  336.         }
  337.         while ((c = *s++) != EOS) {
  338.             if (c == PERIOD) {
  339.                 c = '$';
  340.                 if (*s == SLASHC) /* ignore "./" */
  341.                     continue;
  342.             }
  343.             if (c == SLASHC) {
  344.                     leaf_dot = DotPrefix(s);
  345.                 if (strchr(s, SLASHC))
  346.                     *d++ = PERIOD;
  347.                 else {
  348.                     break;
  349.                 }
  350.             } else {
  351.                 *d++ = CharToVms(c);
  352.             }
  353.         }
  354.     }
  355.     if (bracket) {
  356.         if (on_top && d[-1] == LBRACK) {
  357.             (void)strcpy(d, RootDir);
  358.             d += strlen(d);
  359.         }
  360.         *d++ = RBRACK;
  361.     }
  362.     if (c != EOS && *s) {
  363.         leaf_dot = DotPrefix(s);
  364.         while ((c = *s) != EOS) {
  365.             if ((leaf_ver = is_version(s)) == TRUE) {
  366.                 leaf_dot = TRUE; /* no longer pertinent */
  367.                 (void)strcpy(d, s);
  368.                 *d = SEMICOLON;    /* make this unambiguous */
  369.                 d += strlen(d);
  370.                 break;
  371.             } else {
  372.                 *d++ = CharToVms(c);
  373.             }
  374.             s++;
  375.         }
  376.         if (!leaf_dot)
  377.             *d++ = PERIOD;
  378.         if (!leaf_ver)
  379.             *d++ = SEMICOLON;
  380.     }
  381.     *d = EOS;
  382.     return mkupper(dst);
  383. }
  384.  
  385. /******************************************************************************
  386.  * Returns a pointer to a pathname's suffix iff it is likely a directory's    *
  387.  ******************************************************************************/
  388. char *
  389. is_vms_dirtype(char *path)
  390. {
  391.     register char *t = path_suffix(path);
  392.     register char *v = path_version(t);
  393.     size_t len = (v-t);
  394.  
  395.     if (len == sizeof(DirType)-1
  396.      && !strncmp(t, DirType, len)
  397.      && (!*v || !strcmp(v, ";1"))) {
  398.         return t;
  399.     }
  400.     return 0;
  401. }
  402.  
  403. /******************************************************************************
  404.  * Returns a pointer to a pathname's leaf iff it is the root directory        *
  405.  ******************************************************************************/
  406. char *
  407. is_vms_rootdir(char *path)
  408. {
  409.     char *type;
  410.     if ((type = is_vms_dirtype(path)) != 0) {
  411.         char *leaf = pathleaf(path);
  412.         size_t len = (type - leaf);
  413.         if (len == sizeof(RootDir)-1
  414.          && !strncmp(leaf, RootDir, len))
  415.              return leaf;
  416.     }
  417.     return 0;
  418. }
  419.  
  420. /******************************************************************************
  421.  * Convert a VMS directory-filename into the corresponding pathname           *
  422.  ******************************************************************************/
  423. void
  424. vms_dir2path(char *path)
  425. {
  426.     char *s;
  427.  
  428.     if ((s = is_vms_rootdir(path)) != 0) {
  429.         *s = EOS;
  430.     } else {
  431.         if ((s = strrchr(path, RBRACK)) != 0
  432.          && (s[1] != EOS)) {
  433.             char *t;
  434.             if ((t = is_vms_dirtype(s)) != 0) {
  435.                 *s = '.';
  436.                 *t++ = RBRACK;
  437.                 *t = EOS;
  438.             }
  439.         }
  440.     }
  441. }
  442.  
  443. /******************************************************************************
  444.  * Convert a VMS pathname into the name of the corresponding directory-file.  *
  445.  *                                                                            *
  446.  * Note that this returns a pointer to a static buffer which is overwritten   *
  447.  * by each call.                                                              *
  448.  ******************************************************************************/
  449.  
  450. char *
  451. vms_path2dir(const char *src)
  452. {
  453.     static    char    buffer[NFILEN];
  454.     register char    *s    = skip_string(strcpy(buffer, src));
  455.  
  456.     if (s != buffer && *(--s) == RBRACK) {
  457.         (void)strcpy(s, DirType);
  458.         while (--s >= buffer) {
  459.             if (*s == PERIOD) {
  460.                 *s = RBRACK;
  461.                 if (s == buffer+1) {    /* absorb "]" */
  462.                     register char *t = s + 1;
  463.                     s = buffer;
  464.                     while ((*s++ = *t++) != EOS)
  465.                         /*EMPTY*/;
  466.                 }
  467.                 break;
  468.             }
  469.             if (*s == LBRACK) {        /* absorb "[" */
  470.                 register char *t = s + 1;
  471.                 if (is_vms_rootdir(t)
  472.                  && (s == buffer || s[-1] == COLON)) {
  473.                     (void) lsprintf(t, "%s%c%s%s",
  474.                         RootDir,
  475.                         RBRACK,
  476.                         RootDir,
  477.                         DirType);
  478.                 } else {
  479.                     while ((*s++ = *t++) != EOS)
  480.                         /*EMPTY*/;
  481.                 }
  482.                 break;
  483.             }
  484.         }
  485.     }
  486.     return (buffer);
  487. }
  488.  
  489. /******************************************************************************
  490.  * Translate a VMS-style pathname to a UNIX-style pathname                    *
  491.  ******************************************************************************/
  492.  
  493. char *
  494. vms2unix_path(char *dst, const char *src)
  495. {
  496.     char    current[NFILEN];
  497.     int    need_dev = FALSE,
  498.         have_dev = FALSE;
  499.     char    tmp[NFILEN],
  500.         *output = dst,
  501.         *base = tmp,
  502.         *s = strcpy(tmp, src),    /* ... to permit src == dst */
  503.         *d;
  504.  
  505.     strip_version(s);
  506.  
  507.     /* look for node specification */
  508.     if ((s = strchr(base, COLON)) != 0
  509.     &&  (s[1] == COLON)) {
  510.         while (base < s) {
  511.             *dst++ = *base++;
  512.         }
  513.         *dst++ = '!';
  514.         base += 2;
  515.         need_dev = TRUE;
  516.     }
  517.  
  518.     /*
  519.      * Look for device specification.  If not found, see if the path must
  520.      * begin at the top of the device.  In this case, it would be ambiguous
  521.      * if no device is supplied.
  522.      */
  523.     if ((s = strchr(base, COLON)) != NULL) {
  524.         *dst++ = SLASHC;
  525.         while (base < s) {
  526.             *dst++ = *base++;
  527.         }
  528.         base++;            /* skip over ":" */
  529.         have_dev = TRUE;
  530.     } else if (need_dev
  531.     ||      ((base[0] == LBRACK)
  532.     &&       (base[1] != '-')
  533.     &&       (base[1] != PERIOD)
  534.     &&       (base[1] != RBRACK))) {    /* must supply a device */
  535.         register char    *a = getcwd(current, NFILEN),
  536.                 *b = strchr(a ? a : "?", COLON);
  537.         if ((b != 0)
  538.         &&  (b[1] == COLON)) {    /* skip over node specification */
  539.             a = b + 2;
  540.             b = strchr(a, COLON);
  541.         }
  542.         if (b != 0) {
  543.             *dst++ = SLASHC;    /* begin the device */
  544.             while (a < b) {
  545.                 *dst++ = *a++;
  546.             }
  547.             have_dev = TRUE;
  548.         }            /* else, no device in getcwd! */
  549.     }
  550.  
  551.     /* translate directory-syntax */
  552.     if ((s = strchr(base, LBRACK)) != NULL) {
  553.         int bracketed = TRUE;
  554.         if (s[1] == RBRACK) {
  555.             if (dst != output && *dst != SLASHC)
  556.                 *dst++ = SLASHC;
  557.             *dst++ = PERIOD;
  558.             if (s[2] != EOS)
  559.                 *dst++ = SLASHC;
  560.             s += 2;
  561.             d = s;
  562.             bracketed = FALSE;
  563.         } else if (s[1] == PERIOD) {
  564.             if (have_dev && dst[-1] != SLASHC)
  565.                 *dst++ = SLASHC;
  566.             s += 2;
  567.             d = s;
  568.         } else if (s[1] == '-' && strchr("-.]", s[2])) {
  569.             s++;
  570.             while (*s == '-') {
  571.                 s++;
  572.                 *dst++ = PERIOD;
  573.                 *dst++ = PERIOD;
  574.                 if (*s == PERIOD
  575.                  && (s[1] == '-' || s[1] == RBRACK))
  576.                     /* allow "-.-" */
  577.                     s++;
  578.                 if (*s == '-')
  579.                     *dst++ = SLASHC;
  580.             }
  581.             d = s;
  582.         } else if (!strncmp(s+1, RootDir, sizeof(RootDir)-1)
  583.                 && strchr(".]", s[sizeof(RootDir)])) {
  584.             s += sizeof(RootDir);
  585.             d = s;
  586.         } else {
  587.             d = s;
  588.             *s++ = SLASHC;
  589.         }
  590.         /* expect s points to the last token before right-bracket */
  591.         if (bracketed) {
  592.             while (*s && *s != RBRACK) {
  593.                 if (*s == PERIOD)
  594.                     *s = SLASHC;
  595.                 s++;
  596.             }
  597.             if (*s)
  598.                 *s = s[1] ? SLASHC : EOS;
  599.         }
  600.     } else {
  601.         if (have_dev && dst[-1] != SLASHC)
  602.             *dst++ = SLASHC;
  603.         d = base;
  604.     }
  605.  
  606.     /*
  607.      * Copy the remainder of the string, trimming trailing "."
  608.      */
  609.     for (s = dst; *d; s++, d++) {
  610.         *s = *d;
  611.         if (*s == PERIOD && d[1] == EOS)
  612.             *s = EOS;
  613.     }
  614.     *s = EOS;
  615.  
  616.     s = vms_pathleaf(dst);
  617.  
  618.     /* SCCS hack */
  619.     if (*s == '$') {
  620.         *s++ = PERIOD;
  621.     } else if (s[0] == 's' && s[1] == '$') {
  622.         s[1] = PERIOD;
  623.         s += 2;
  624.     }
  625.  
  626.     return mklower(output);
  627. }
  628. #endif    /* OPT_VMS_PATH */
  629.