From:	CSBVAX::MRGATE!@KL.SRI.Com:info-vax-request@kl.sri.com@SMTP 25-JUN-1987 07:29
To:	EVERHART
Subj:	Re: 2 questions: VAX-C RTL calls and VMS .DIR file entries

Received: from csl.csl.sri.com (CSL.SRI.Com.#Internet) by KL.SRI.COM with TCP; Wed 24 Jun 87 23:51:49-PDT
Received: from ucbvax.Berkeley.EDU by csl.csl.sri.com (3.2/4.16)
	id AA06061 for info-vax@kl.sri.com; Wed, 24 Jun 87 14:00:48 PDT
Received: by ucbvax.Berkeley.EDU (5.57/1.26)
	id AA04584; Wed, 24 Jun 87 12:41:58 PDT
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 22 Jun 87 09:14:08 GMT
From: munnari!moncskermit!basser!nucs!numm!Sm@seismo.css.gov  (Scott Merrilees)
Organization: Dept of Mathematics, University of Newcastle, Australia
Subject: Re: 2 questions: VAX-C RTL calls and VMS .DIR file entries
Message-Id: <258@numm.nu>
References: <2405@usceast.UUCP>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com


Below are the directory routines I wrote a couple of months ago when I needed
a VMS implementation of the BSD opendir, closedir, readdir and rewinddir
routines.  The opendir() routine accepts a directory specification and prepares
the directory to be read, readdir() reads the next entry, etc.  The routines
are encapsulated in a DCL archive below.

Scott Merrilees [Samarium]		ACSnet:	Sm@numm.nu.oz
ARPA:	Sm%numm.nu.oz@seismo.css.gov	UUCP:	...!seismo!munnari!numm.nu.oz!Sm

.......................... Cut between dotted lines and save ....................
$!..............................................................................
$!
$! VAX/VMS archive file created by VMS_SHAR Version:'09-Jun-1987'
$! Copyright (c) 1987, by Michael Bednarek
$! To unpack, simply execute (@) the file.
$! This archive was created by C8262502
$!      on Monday 22-JUN-1987 17:53:00.02
$! It contains the following file(s):
$! AAAREADME.DOC CLOSEDIR.C NDIR.H OPENDIR.C READDIR.C REWINDDIR.C TEST.C
$!==============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1:Open/Write Out 'File_is
$ Open/Read In VMS_SHAR_DUMMY.DUMMY
$Next_Record: Read/End_Of_File=EOF In Record
$ Write Out F$Extract(1,255,Record)
$ Goto Next_Record
$EOF: Close Out
$ Close In
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2:Return
$Start:
$ File_is="AAAREADME.DOC"
$ Check_Sum_is=425232041
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X	Directory Reading Routines:
X
X	Linking:	It is necessary to link in the module c$$translate
X			from sys$library:vaxcrtl.olb as there is no
X			corresponding universal symbol in sys$share:vaxcrtl.exe.
X			Otherwise you could add transfer vectors and link
X			opendir,readdir,closedir and rewinddir into vaxcrtl
X			but this would be painfull when a new RTL arrived.
X			/* c$$translate translates vms error codes into	*/
X			/* *un%x error codes in errno.			*/
X
X	Extensions:	opendir() accepts an optional int argument,
X			flags, which currently has only one bit utilized,
X			bit _D_V_WILD allowing wildcard usage.
X
X	Kludges:	Since inodes are not used under VMS, ino_t was
X			specified as int and the first two words of the
X			file id were used. The third word is zero unless
X			you are using multi-volume disks.
X
X	Unimplemented:	seekdir() and telldir().
$ GoSub Convert_File
$ File_is="CLOSEDIR.C"
$ Check_Sum_is=1937127202
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X *	@(#) closedir.c V01-000 2-Apr-1987
X *
X *	Copyright (C) 1987, Scott Merrilees [Samarium]
X */
X#include	"ndir.h"
X
X/*
X *	 Close a directory, making sure RMS context is deallocated.
X */
X
Xvoid
Xclosedir(Dp)
X	register DIR *	Dp;
X{
X	Dp->_D_fab.fab$b_dns = 0;
X	Dp->_D_nam.nam$b_nop |= NAM$M_SYNCHK;
X	sys$parse(&Dp->_D_fab);
X	free(Dp->_D_dir);
X	free((char *)Dp);
X}
$ GoSub Convert_File
$ File_is="NDIR.H"
$ Check_Sum_is=1581550862
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X *	@(#) dir.h V01-000 2-Apr-1987
X *
X *	Copyright (C) 1987, Scott Merrilees [Samarium]
X */
X
X#ifndef	DIRSIZ
X
X#ifndef	FAB$C_BID
X#include	fab
X#endif	FAB$C_BID
X
X#ifndef	NAM$C_BID
X#include	nam
X#endif	NAM$C_BID
X
X#define DIRSIZ		NAM$C_MAXRSS		/* Maximum file name size */
X
X#ifndef	INO_T
Xtypedef	int		ino_t;			/* Pseudo inode type */
X#define	INO_T		int
X#endif	INO_T
X
Xstruct	direct
X{
X	union
X	{
X		ino_t	_d_ino;			/* Pseudo inode number */
X		unsigned short
X			_d_fid[3];		/* File ID */
X	}
X			_d_u0;
X#define			d_ino	_d_u0._d_ino
X#define			d_fid	_d_u0._d_fid
X	char		d_name[DIRSIZ + 1];	/* File name */
X};
X
Xtypedef struct
X{
X	char *		_D_dir;			/* Argument to opendir() */
X	struct	FAB	_D_fab;			/* FAB for RMS */
X	struct	NAM	_D_nam;			/* NAM for RMS */
X	char		_D_esa[NAM$C_MAXRSS];	/* Expanded string area */
X	char		_D_rsa[NAM$C_MAXRSS + 1];/*Resultant string area */
X	int		_D_flags;		/* Flags, see below */
X
X#define			_D_V_WILD	0	/* Wild directory allowed */
X#define			_D_S_WILD	1
X#define			_D_M_WILD	1
X}
X	DIR;
X
X/*
X *	Note:	seekdir() and telldir() are not implemented.
X */
Xextern	DIR		*opendir();
Xextern	struct direct	*readdir();
Xextern	void		closedir();
Xextern	void		rewinddir();
X
X#endif	DIRSIZ
$ GoSub Convert_File
$ File_is="OPENDIR.C"
$ Check_Sum_is=2019389696
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X *	@(#) opendir.c V01-000 2-Apr-1987
X *
X *	Copyright (C) 1987, Scott Merrilees [Samarium]
X */
X
X#include	"ndir.h"
X#include	errno
X#include	stsdef
X#include	varargs
X
X/*
X *	Pesudo directory open, actually allocate RMS context, using $parse,
X *	to do subsequent $search operations.
X */
X
XDIR *
Xopendir(name, va_alist)
X	char *		name;
X	va_dcl
X{
X	char *		malloc();
X	char *		strcpy();
X	register DIR *	Dp;
X	va_list		ap;
X
X	if ( (Dp = (DIR *)malloc(sizeof(DIR))) == (DIR *)0 )
X		return (DIR *)0;
X
X	va_count(Dp->_D_flags);
X	if (Dp->_D_flags == 1)
X		Dp->_D_flags = 0;
X	else
X	{
X		va_start_1(ap, 1);
X		Dp->_D_flags = va_arg(ap, int);
X		va_end(ap);
X	}
X
X	Dp->_D_fab = cc$rms_fab;
X	Dp->_D_fab.fab$b_fns = strlen(name);
X	if ( (Dp->_D_dir = malloc(Dp->_D_fab.fab$b_fns + 1)) == (char *)0 )
X	{
X		free((char *)Dp);
X		return (DIR *)0;
X	}
X	Dp->_D_fab.fab$l_fna = strcpy(Dp->_D_dir, name);
X	Dp->_D_fab.fab$l_nam = &Dp->_D_nam;
X
X	Dp->_D_nam = cc$rms_nam;
X	Dp->_D_nam.nam$l_esa = &Dp->_D_esa;
X	Dp->_D_nam.nam$l_rsa = &Dp->_D_rsa;
X	Dp->_D_nam.nam$b_ess = Dp->_D_nam.nam$b_rss = NAM$C_MAXRSS;
X
X	if ( !(sys$parse(&Dp->_D_fab) & STS$K_SUCCESS) )
X	{
X		c$$translate(Dp->_D_fab.fab$l_sts);
X		free(Dp->_D_dir);
X		free((char *)Dp);
X		return (DIR *)0;
X	}
X
X	if	/* Considered converting fred or fred.dir into [.fred]	*/
X	(	/* but only needed to use correct directory syntax.	*/
X		(Dp->_D_nam.nam$l_fnb & (NAM$M_EXP_NAME|NAM$M_EXP_TYPE|NAM$M_EXP_VER))
X		||
X		(Dp->_D_nam.nam$b_dev == 0)
X		||
X		(Dp->_D_nam.nam$b_dir == 0)
X		||
X		(
X			((Dp->_D_flags & _D_M_WILD) == 0)
X			&&
X			(Dp->_D_nam.nam$l_fnb & NAM$M_WILDCARD)
X		)
X	)
X		Dp->_D_fab.fab$l_sts = STS$K_ERROR;
X	else
X	{
X		Dp->_D_fab.fab$l_dna = Dp->_D_fab.fab$l_fna;
X		Dp->_D_fab.fab$b_dns = Dp->_D_fab.fab$b_fns;
X		Dp->_D_fab.fab$l_fna = "*.*;*";
X		Dp->_D_fab.fab$b_fns = 5;
X		sys$parse(&Dp->_D_fab);
X	}
X
X	if ( !(Dp->_D_fab.fab$l_sts & STS$K_SUCCESS) )
X	{
X		if ( Dp->_D_fab.fab$l_sts == STS$K_ERROR )
X			errno = ENOTDIR;
X		else
X			c$$translate(Dp->_D_fab.fab$l_sts);
X		Dp->_D_fab.fab$b_dns = 0;
X		Dp->_D_nam.nam$b_nop |= NAM$M_SYNCHK;
X		sys$parse(&Dp->_D_fab);
X		free(Dp->_D_dir);
X		free((char *)Dp);
X		return (DIR *)0;
X	}
X
X	return Dp;
X}
$ GoSub Convert_File
$ File_is="READDIR.C"
$ Check_Sum_is=1796104212
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X *	@(#) readdir.c V01-000 2-Apr-1987
X *
X *	Copyright (C) 1987, Scott Merrilees [Samarium]
X */
X#include	"ndir.h"
X#include	rmsdef
X#include	stsdef
X
X/*
X * Return the next entry in a directory as returned by $search.
X */
X
Xstruct direct *
Xreaddir(Dp)
X	register DIR *	Dp;
X{
X	static struct direct dir;
X
X	if ( !(sys$search(&Dp->_D_fab) & STS$K_SUCCESS) )
X	{
X		if ( Dp->_D_fab.fab$l_sts != RMS$_NMF )
X			c$$translate(Dp->_D_fab.fab$l_sts);
X		return (struct direct *)0;
X	}
X
X	dir.d_fid[0] = Dp->_D_nam.nam$w_fid[0];
X	dir.d_fid[1] = Dp->_D_nam.nam$w_fid[1];
X	dir.d_fid[2] = Dp->_D_nam.nam$w_fid[2];
X	Dp->_D_rsa[Dp->_D_nam.nam$b_rsl] = '\0';
X	strcpy(dir.d_name, Dp->_D_rsa);
X
X	return &dir;
X}
$ GoSub Convert_File
$ File_is="REWINDDIR.C"
$ Check_Sum_is=559161474
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X *	@(#) rewinddir.c V01-000 2-Apr-1987
X *
X *	Copyright (C) 1987, Scott Merrilees [Samarium]
X */
X#include	"ndir.h"
X#include	stsdef
X
X/*
X *	Rewind directory search. This operation is why the original
X *	directory specification was saved, as the directory may have
X *	been a search list.
X */
X
Xvoid
Xrewinddir(Dp)
X	register DIR *	Dp;
X{
X	if ( !(sys$parse(&Dp->_D_fab) & STS$K_SUCCESS) )
X		c$$translate(Dp->_D_fab.fab$l_sts);
X}
$ GoSub Convert_File
$ File_is="TEST.C"
$ Check_Sum_is=68367500
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/*
X *	test.c	Test directory routines.
X *
X *	Scott Merrilees [Samarium]
X */
X#include "ndir.h"
X#include stdio
X
Xmain()
X{
X	char		buf[BUFSIZ];
X	int		flags;
X	DIR *		Dp;
X	struct direct *	dp;
X	char		*gets();
X
X	printf("Flags:\t\t");
X	flags = atoi(gets(buf));
X	printf("Directory:\t");
X	gets(buf);
X
X	if ((Dp = opendir(buf, flags)) == (DIR *)0)
X		perror(buf);
X	else
X	{
X		while ((dp = readdir(Dp)) != (struct direct *)0)
X			printf("%s\n", dp->d_name);
X		rewinddir(Dp);
X		while ((dp = readdir(Dp)) != (struct direct *)0)
X			printf("%s\n", dp->d_name);
X		closedir(Dp);
X	}
X}
$ GoSub Convert_File
-- 
Scott Merrilees [Samarium]		ACSnet:	Sm@numm.nu.oz
ARPA:	Sm%numm.nu.oz@seismo.css.gov	UUCP:	...!seismo!munnari!numm.nu.oz!Sm
