150bf276cStholo /*
250bf276cStholo * Copyright � 1994 the Free Software Foundation, Inc.
350bf276cStholo *
450bf276cStholo * Author: Richard Levitte (levitte@e.kth.se)
550bf276cStholo *
650bf276cStholo * This file is a part of GNU VMSLIB, the GNU library for porting GNU
750bf276cStholo * software to VMS.
850bf276cStholo *
950bf276cStholo * GNU VMSLIB is free software; you can redistribute it and/or modify
1050bf276cStholo * it under the terms of the GNU General Public License as published by
1150bf276cStholo * the Free Software Foundation; either version 2 of the License, or
1250bf276cStholo * (at your option) any later version.
1350bf276cStholo *
1450bf276cStholo * GNU VMSLIB is distributed in the hope that it will be useful,
1550bf276cStholo * but WITHOUT ANY WARRANTY; without even the implied warranty of
1650bf276cStholo * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1750bf276cStholo * GNU General Public License for more details.
1850bf276cStholo */
1950bf276cStholo
20*43c1707eStholo #ifndef __VMS_VER
21*43c1707eStholo #define __VMS_VER 0
22*43c1707eStholo #endif
23*43c1707eStholo #ifndef __DECC_VER
24*43c1707eStholo #define __DECC_VER 0
25*43c1707eStholo #endif
26*43c1707eStholo
2750bf276cStholo #include <varargs.h>
2850bf276cStholo #include <rms.h>
2950bf276cStholo #include <descrip.h>
3050bf276cStholo #include <string.h>
3150bf276cStholo #include <errno.h>
3250bf276cStholo
3350bf276cStholo #ifdef __GNUC__
3450bf276cStholo #include <sys/stat.h>
3550bf276cStholo #else
3650bf276cStholo #include <stat.h>
3750bf276cStholo #endif
3850bf276cStholo #include <lib$routines.h>
3950bf276cStholo
4050bf276cStholo #include "ndir.h"
4150bf276cStholo #include "filutils.h"
4250bf276cStholo
4350bf276cStholo /* The following was snarfed from lib-src/alloca.c in GNU Emacs,
4450bf276cStholo the hacked. */
4550bf276cStholo
4650bf276cStholo #if __STDC__
4750bf276cStholo typedef void procedure;
4850bf276cStholo typedef void *pointer;
4950bf276cStholo #else
5050bf276cStholo typedef int procedure;
5150bf276cStholo typedef char *pointer;
5250bf276cStholo #endif
5350bf276cStholo
5450bf276cStholo /* Different portions of Emacs need to call different versions of
5550bf276cStholo malloc. The Emacs executable needs alloca to call xmalloc, because
5650bf276cStholo ordinary malloc isn't protected from input signals. On the other
5750bf276cStholo hand, the utilities in lib-src need alloca to call malloc; some of
5850bf276cStholo them are very simple, and don't have an xmalloc routine.
5950bf276cStholo
6050bf276cStholo Non-Emacs programs expect this to call use xmalloc.
6150bf276cStholo
6250bf276cStholo Callers below should use malloc.
6350bf276cStholo
6450bf276cStholo There is some need for BLOCK_INPUT and UNBLOCK_INPUT, but it is really
6550bf276cStholo only used in Emacs, so that's the only time it's used. Otherwise,
6650bf276cStholo they are just empty statements. */
6750bf276cStholo
6850bf276cStholo #ifndef emacs
6950bf276cStholo #include "misc.h"
7050bf276cStholo #define malloc xmalloc
7150bf276cStholo #define free xfree
7250bf276cStholo #endif
7350bf276cStholo
7450bf276cStholo #if 0
7550bf276cStholo extern pointer malloc ();
7650bf276cStholo extern procedure free ();
7750bf276cStholo #endif
7850bf276cStholo
7950bf276cStholo /* end of snarf. */
8050bf276cStholo
8150bf276cStholo #ifndef BLOCK_INPUT
8250bf276cStholo #define BLOCK_INPUT
8350bf276cStholo #endif
8450bf276cStholo #ifndef UNBLOCK_INPUT
8550bf276cStholo #define UNBLOCK_INPUT
8650bf276cStholo #endif
8750bf276cStholo
8850bf276cStholo static struct direct *vms_low_readdir ();
8950bf276cStholo
9050bf276cStholo typedef struct
9150bf276cStholo {
9250bf276cStholo DIR s_dir;
9350bf276cStholo unsigned long context;
9450bf276cStholo unsigned long uflags;
9550bf276cStholo struct dsc$descriptor_s dir_spec;
9650bf276cStholo struct dsc$descriptor_s file_spec;
9750bf276cStholo int version_flag;
9850bf276cStholo unsigned long status;
9950bf276cStholo } VMS_DIR;
10050bf276cStholo
10150bf276cStholo DIR *
vms_opendir(infilename,filepattern)102*43c1707eStholo vms_opendir (infilename, filepattern)
10350bf276cStholo char *infilename; /* name of directory */
10450bf276cStholo char *filepattern;
10550bf276cStholo {
10650bf276cStholo register VMS_DIR *dirp; /* -> malloc'ed storage */
10750bf276cStholo register unsigned int length = 1024;
10850bf276cStholo register int fd; /* file descriptor for read */
10950bf276cStholo char *filename;
11050bf276cStholo struct stat sbuf; /* result of fstat */
11150bf276cStholo
11250bf276cStholo filename = (char *) malloc(length+1);
11350bf276cStholo strcpy(filename, infilename);
11450bf276cStholo
115461cc63eStholo strip_trailing_slashes (filename);
11650bf276cStholo if(strcmp(filename, ".") == 0)
11750bf276cStholo {
11850bf276cStholo getcwd(filename, length+1, 1); /* Get a VMS filespec */
11950bf276cStholo length = strlen(filename);
12050bf276cStholo }
12150bf276cStholo
12250bf276cStholo BLOCK_INPUT;
12350bf276cStholo if ((filename[length-1] != ']'
12450bf276cStholo && filename[length-1] != '>'
12550bf276cStholo && filename[length-1] != ':'
12650bf276cStholo && (stat (filename, &sbuf) < 0
12750bf276cStholo || (sbuf.st_mode & S_IFMT) != S_IFDIR)))
12850bf276cStholo {
12950bf276cStholo errno = ENOTDIR;
13050bf276cStholo UNBLOCK_INPUT;
13150bf276cStholo free(filename);
13250bf276cStholo return 0; /* bad luck today */
13350bf276cStholo }
13450bf276cStholo
13550bf276cStholo if ((dirp = (VMS_DIR *) xmalloc (sizeof (VMS_DIR))) == 0)
13650bf276cStholo {
13750bf276cStholo errno = ENOMEM;
13850bf276cStholo UNBLOCK_INPUT;
13950bf276cStholo free(filename);
14050bf276cStholo return 0; /* bad luck today */
14150bf276cStholo }
14250bf276cStholo
14350bf276cStholo {
14450bf276cStholo int count;
14550bf276cStholo va_count(count);
14650bf276cStholo if (count == 2)
14750bf276cStholo {
14850bf276cStholo dirp->file_spec.dsc$a_pointer =
14950bf276cStholo (char *) xmalloc (strlen (filepattern) + 1);
15050bf276cStholo strcpy (dirp->file_spec.dsc$a_pointer, filepattern);
15150bf276cStholo }
15250bf276cStholo else
15350bf276cStholo {
15450bf276cStholo dirp->file_spec.dsc$a_pointer =
15550bf276cStholo (char *) xmalloc (4);
15650bf276cStholo strcpy (dirp->file_spec.dsc$a_pointer, "*.*");
15750bf276cStholo }
15850bf276cStholo dirp->file_spec.dsc$w_length = strlen (dirp->file_spec.dsc$a_pointer);
15950bf276cStholo dirp->file_spec.dsc$b_dtype = DSC$K_DTYPE_T;
16050bf276cStholo dirp->file_spec.dsc$b_class = DSC$K_CLASS_S;
16150bf276cStholo dirp->version_flag = strchr (dirp->file_spec.dsc$a_pointer, ';') != 0;
16250bf276cStholo }
16350bf276cStholo dirp->dir_spec.dsc$a_pointer = (char *) xmalloc (strlen (filename) + 10);
16450bf276cStholo UNBLOCK_INPUT;
16550bf276cStholo file_name_as_directory (dirp->dir_spec.dsc$a_pointer, filename);
16650bf276cStholo dirp->dir_spec.dsc$w_length = strlen (dirp->dir_spec.dsc$a_pointer);
16750bf276cStholo dirp->dir_spec.dsc$b_dtype = DSC$K_DTYPE_T;
16850bf276cStholo dirp->dir_spec.dsc$b_class = DSC$K_CLASS_S;
16950bf276cStholo dirp->context = 0;
17050bf276cStholo dirp->uflags = 2;
17150bf276cStholo dirp->s_dir.dd_fd = 0;
17250bf276cStholo dirp->s_dir.dd_loc = dirp->s_dir.dd_size = 0; /* refill needed */
17350bf276cStholo
17450bf276cStholo free(filename);
17550bf276cStholo
17650bf276cStholo /* In the cases where the filename ended with `]', `>' or `:',
17750bf276cStholo we never checked if it really was a directory, so let's do that
17850bf276cStholo now, by trying to read the first entry. */
17950bf276cStholo if (vms_low_readdir ((DIR *) dirp) == (struct direct *) -1)
18050bf276cStholo {
181*43c1707eStholo vms_closedir (dirp); /* was: xfree (dirp); */
18250bf276cStholo errno = ENOENT;
18350bf276cStholo return 0;
18450bf276cStholo }
18550bf276cStholo dirp->s_dir.dd_loc = 0; /* Make sure the entry just read is
18650bf276cStholo reused at the next call to readdir. */
18750bf276cStholo
18850bf276cStholo return (DIR *) dirp; /* I had to cast, for VMS sake. */
18950bf276cStholo }
19050bf276cStholo
1912286d8edStholo int
vms_closedir(dirp)192*43c1707eStholo vms_closedir (dirp)
193*43c1707eStholo register DIR *dirp; /* stream from vms_opendir */
19450bf276cStholo {
19550bf276cStholo {
19650bf276cStholo VMS_DIR *vms_dirp = (VMS_DIR *) dirp;
19750bf276cStholo
19850bf276cStholo if (vms_dirp->context != 0)
19950bf276cStholo lib$find_file_end (&(vms_dirp->context));
20050bf276cStholo xfree (vms_dirp->dir_spec.dsc$a_pointer);
20150bf276cStholo xfree (vms_dirp->file_spec.dsc$a_pointer);
20250bf276cStholo }
20350bf276cStholo
20450bf276cStholo xfree ((char *) dirp);
2052286d8edStholo return 0;
20650bf276cStholo }
20750bf276cStholo
20850bf276cStholo struct direct dir_static; /* simulated directory contents */
20950bf276cStholo
21050bf276cStholo static struct direct *
vms_low_readdir(dirp)21150bf276cStholo vms_low_readdir (dirp)
21250bf276cStholo register DIR *dirp;
21350bf276cStholo {
21450bf276cStholo static char rbuf[257];
21550bf276cStholo static struct dsc$descriptor_s rdsc =
21650bf276cStholo { sizeof (rbuf), DSC$K_DTYPE_T, DSC$K_CLASS_S, rbuf };
21750bf276cStholo VMS_DIR * vms_dirp = (VMS_DIR *) dirp;
21850bf276cStholo
21950bf276cStholo if (dirp->dd_size == 0)
22050bf276cStholo {
22150bf276cStholo char *cp, *cp2;
22250bf276cStholo unsigned long status;
22350bf276cStholo
22450bf276cStholo status = lib$find_file (&vms_dirp->file_spec, &rdsc, &vms_dirp->context,
22550bf276cStholo &vms_dirp->dir_spec, 0, 0, &vms_dirp->uflags);
22650bf276cStholo vms_dirp->status = status;
22750bf276cStholo if (status == RMS$_NMF || status == RMS$_FNF)
22850bf276cStholo return 0;
22950bf276cStholo if (status != RMS$_NORMAL)
23050bf276cStholo return (struct direct *) -1;
23150bf276cStholo
23250bf276cStholo rbuf [256] = '\0';
23350bf276cStholo if (cp = strchr (rbuf, ' '))
23450bf276cStholo *cp = '\0';
23550bf276cStholo if ((cp = strchr (rbuf, ';')) != 0
23650bf276cStholo && !vms_dirp->version_flag)
23750bf276cStholo *cp = '\0';
23850bf276cStholo
23950bf276cStholo for (cp2 = rbuf - 1; cp2 != 0;)
24050bf276cStholo {
24150bf276cStholo char *cp2tmp = 0;
24250bf276cStholo cp = cp2 + 1;
24350bf276cStholo cp2 = strchr (cp, ']');
24450bf276cStholo if (cp2 != 0)
24550bf276cStholo cp2tmp = strchr (cp2 + 1, '>');
24650bf276cStholo if (cp2tmp != 0)
24750bf276cStholo cp2 = cp2tmp;
24850bf276cStholo }
24950bf276cStholo
25050bf276cStholo /* Propagate names as lower case only,
25150bf276cStholo directories have ".dir" truncated,
25250bf276cStholo do not propagate null extensions "makefile." */
25350bf276cStholo {
25450bf276cStholo char *p, *q;
25550bf276cStholo
25650bf276cStholo if(strcmp(cp, "CVS.DIR") == 0)
25750bf276cStholo strcpy(dirp->dd_buf, "CVS");
25850bf276cStholo else
25950bf276cStholo {
26050bf276cStholo for(p = cp, q = dirp->dd_buf; *p;)
26150bf276cStholo {
26250bf276cStholo if(strcmp(p, ".DIR") == 0)
26350bf276cStholo break;
26450bf276cStholo else
26550bf276cStholo *q++ = tolower(*p++);
26650bf276cStholo }
26750bf276cStholo *q = '\0';
26850bf276cStholo if(*(q-1) == '.')
26950bf276cStholo *(q-1) = '\0';
27050bf276cStholo }
27150bf276cStholo }
27250bf276cStholo #if 0
27350bf276cStholo strcpy (dirp->dd_buf, cp);
27450bf276cStholo #endif
27550bf276cStholo
27650bf276cStholo dirp->dd_size = strlen (dirp->dd_buf);
27750bf276cStholo dirp->dd_loc = 0;
27850bf276cStholo }
27950bf276cStholo
28050bf276cStholo if (vms_dirp->status != RMS$_NORMAL)
28150bf276cStholo return 0;
28250bf276cStholo
28350bf276cStholo dir_static.d_ino = -1; /* Couldn't care less... */
28450bf276cStholo dir_static.d_namlen = strlen (dirp->dd_buf);
28550bf276cStholo dir_static.d_reclen = sizeof (struct direct)
28650bf276cStholo - MAXNAMLEN + 3
28750bf276cStholo + dir_static.d_namlen - dir_static.d_namlen % 4;
28850bf276cStholo strcpy (dir_static.d_name, dirp->dd_buf);
28950bf276cStholo dir_static.d_name[dir_static.d_namlen] = '\0';
29050bf276cStholo dirp->dd_loc = dirp->dd_size; /* only one record at a time */
29150bf276cStholo
29250bf276cStholo return &dir_static;
29350bf276cStholo }
29450bf276cStholo
29550bf276cStholo /* ARGUSED */
29650bf276cStholo struct direct *
vms_readdir(dirp)297*43c1707eStholo vms_readdir (dirp)
298*43c1707eStholo register DIR *dirp; /* stream from vms_opendir */
29950bf276cStholo {
30050bf276cStholo register struct direct *dp;
30150bf276cStholo
30250bf276cStholo for (; ;)
30350bf276cStholo {
30450bf276cStholo if (dirp->dd_loc >= dirp->dd_size)
30550bf276cStholo dirp->dd_loc = dirp->dd_size = 0;
30650bf276cStholo
30750bf276cStholo dp = vms_low_readdir (dirp);
30850bf276cStholo if (dp == 0 || dp == (struct direct *) -1)
30950bf276cStholo return 0;
31050bf276cStholo return dp;
31150bf276cStholo }
31250bf276cStholo }
313