File: Frontport_documentation.txt

Copyright 2000, John E. Malmberg
All Rights Reserved

E-mail: WB8TYW@QSL.NET

Documentation for the Frontport library.


License:

This program 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.

This program 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


Abstract:

The Frontport library is a shared image that is used to assist in
porting programs from other operating systems to versions of OpenVMS
from 5.5-2 to the current version.  At this writing it has only been
built on OpenVMS VAX 7.1 and OpenVMS ALPHA 7.2.

This was originally designed as an assist to porting a fully functional
version of SAMBA to OpenVMS.

These routines consist of a set of four shared images for Alpha and for
VAX.  Three of these images are actually used.  The fourth image is
linked against the COMPAQ C BACKPORT library.  Logical names are used
to reference the images.  The logical names are:

FRONTPORTP__CRTL

This is a privileged library that must be installed protected.  It is
presently only used to provide fcntl() functionality to lookup the
process id of a blocked lock.  If this routine is not present, only
this functionality will be missing.

FRONTPORT___SET_USER

This is a routine that sets the username and UIC as part of the
implementation of setuid().  If this routine is not present, only this
functionality will be missing.

FRONTPORT__CRTL

This is the library that contains all of the non-privileged routines.


The first two images are helper images for special routines that must
be locally linked against the system image.  The examples below are
for an Alpha running OpenVMS 7.2.  Substitute VAX for AXP and the VMS
Version for other versions.  This naming convention allows a single
directory to be shared between both VAX and ALPHA.

FRONTPORTP__CRTL FRONTPORTP_AXP_V7_2.EXE

FRONTPORT___SET_USER_AXP_V7_2.EXE

FRONTPORT.EXE_AXP

FRONTPORT_BACK.EXE_AXP


The command file FRONTPORT_STARTUP.COM will install the
FRONTPORT.EXE_AXP image, and rebuild the two helper images as needed.
It assigns the logical names to these images.

The routine fcntl() is not present in OpenVMS 7.1 unless a DEC C ECO
is applied.  A dummy module fake_fcntl.c contains a fcntl() routine
that provides only the dup functionality, and can be used to resolve
the image at link time.  If this is done the F_SETFL and F_GETFL
commands will not be available.


Disclaimers:

At present I can only test on OpenVMS/VAX 7.1 and OpenVMS/AXP 7.2.
These routines are as is, and no warrantee is provided.  Fixes will
be incorporated only as I have time to do so.  Bug reports are
welcomed, but there is no guarantee that I will be able to respond
or acknowledge them.

Support for ODS5 file specifications is implemented at the time that
this is written, and these routines seem to properly handle them.
Some of the underlying DEC C runtime routines may not fully operate
on ODS-5 specifications.


Installation:

The FRONTPORT library is distributed in two kits.  The base kit
contains the binaries and command files needed to link and install
the FRONTPORT shared images.  The source kit contains all of the
sources.

Both kits are distributed as .ZIP archives.

Create a directory such as SYS$SYSDEVICE:[FRONTPORT] and UNZIP the
base kit into the directory.  Execute the command file
@frontport_startup.com on each node of a cluster.

The call to the frontport_startup.com must also be executed from
the SYSTARTUP_*.COM

Building the library from sources is covered toward the end of this
document.


Building Programs:

The program to be ported will need to be modified to include the
following lines.  Many GNU programs already have a "config.h" file
that is the place to put these.

#define FRONTPORT_HIDE_DECC 1
#include "frontport.h"

The first define causes the standard C RTL definitions to be hidden.
The FRONTPORT library routines all have the prefix "fport__" on them
to make sure that their symbols do not conflict with other shared
images.

The include path for the C compiler must be set to reference
FRONTPORT__DIR:.  There are two underscores in that name and all of
the public symbols and logical names to prevent name space
collisions with programs.  Private symbols will have three
underscores in them.  They are not generally meant for external use.

The application is then linked against the shared image referenced
by the logical name FRONTPORT__CRTL.

Some UNIX programs expect that the C runtime routines read() and
write() work on an arbitrary stream of bytes, and pay no
attention to record boundaries.  When the options is set to allow
fcnt() locking to work in this library, all reads and writes must
be in complete records.  To resolve this conflict, additional
wrapper routines will cover up selected C I/O routines when the
following define is set.

#define FPORT__STREAM_UNIXIO 1

Note that in this mode, writing into the middle of an existing file
will only work for fixed format files.  I will be looking into a
future enhancement to allow this to work for stream files.


The fport__vms_crypt() routine will not replace the UNIX crypt()
function.  It does not produce the same encryption as the UNIX crypt
function.  A "#define crypt fport__vms_crypt" must be put in the
source to make this visible.


Library description:

Some of the additional routines in the FRONTPORT library can be used
to vary the behavior by setting global flags.

Logical names are also used to by some of the routines.  The logical
names have a default prefix, but an option routine is available to
customize this on a per program basis.


Option getting and setting routines.

unsigned long fport__get_fname_options(void)

Set file name processing options based on a bitmap.  The options
are described below with the prefix of FPORT__M_FNAME_ .


FPORT__M_FNAME_CASE_ACE

When set and combined with FPORT__M_FNAME_PWRK will cause the exact
case to be stored in an ACE per Richard Levitte's suggestion.
(not implemented)


FPORT__M_FNAME_CASE_MEYER

When set and combined with FPORT__M_FNAME_PWRK will cause the exact
case to be encoded as in Eckart Meyer's port of SAMBA.
(not implemented)


FPORT__M_FNAME_EXTLASTDOT

When set (default) causes new files that have multiple dots in
their filenames to have the last dot considered the delimiter for
the extension.

When clear it causes the first dot to be interpreted as the
delimiter for the extension.

Note: The behavior of the FRONTPORT library when this option is set
is to try first using the last dot as the delimiter and if that
does not succeed, to try again by interpreting the first dot.


FPORT__M_FNAME_MULTINET

When set it causes filenames to be encoded / decoded by the same as
Process Software's Multinet product.
(not implemented)


FPORT__M_FNAME_ODS5

When set it causes filenames to be displayed or encoded / decoded as
if on an ODS-5 volume on an ODS-5 volume.  This is also the default
setting.  If clear it causes ODS-5 volumes to be treated as ODS-2.


FPORT__M_FNAME_PWRK

When set it causes file names to be encoded/decoded according to
Compaq's Pathworks apparent conventions.  Default is set.  Since no
other options are implemented, currently changing the setting has
no effect.


FPORT__M_FNAME_DUNDER

When set it causes true double underscores in filenames not be
encoded as "_5F_" when saved on OpenVMS on ODS-2 volumes.  Either
setting of this option can cause some files to be inaccessible.



uid_t fport__get_root_uid(void)

This routine gets the current uid that will be converted to zero as
a root alias.  The corresponding set routine allows you to specify
a specific OpenVMS account to be treated as "root" or uid 0 by the
program you are porting.  This allows better control of security.


unsigned long fport__get_stat_options(void)

Sets the protection mode and stat structure behavior based on a
bitmap.  The options are described below with the prefix
FPORT__M_STAT_ .

FPORT__M_STAT_FCNTL_LOCK

When set this causes files to be opened with no explicit file
locking present.  It is expected that the program will use fcntl()
to manually lock access.

When clear (default), files will be opened exclusively locked.
This is the default VMS behavior.


FPORT__M_STAT_SAMBA

When set this causes the protection mode bits returned from stat()
and fstat() to be encoded with special data for SAMBA to interpret.

When clear (default), no changes are done on the returned
protection mode.


FPORT__M_STAT_SET_SAMBA_SYSTEM_ACE

The FPORT__M_STAT_SAMBA must also be set to for this option to be
used.  When set this causes the presence of a SAMBA__SYSTEM ACE
on the file to mark it as having a DOS SYSTEM attribute.
(not implemented)

When clear (default), a file that requires SYSPRV or higher to
access it will be marked as having a DOS SYSTEM attribute.


FPORT__M_STAT_SWAP_CTIME

Under some conditions it has been reported that the st_ctime and
st_mtime are reported as reverse from SAMBA.  This option swaps
them as reported from fport__stat() and fport__fstat().
Note, OpenVMS treats st_ctime as the create time of the file, UNIX
treats it as a date of a significant modification.


FPORT__M_STAT_USEACL

When set this causes the fport__fstat() and fport__stat() routines
to modify the mode_t protection mask based on any ACL that may be
on the file.

When clear (default), the protection mask will reflect only the
UIC based protection.


unsigned long fport__vms_support_flags(void)

This routine returns flags to indicate if the version of OpenVMS
supports a specific option.  Currently the supported bits are
FPORT__M_VMS_EFS and FPORT__M_VMS_DEEPDIR.

FPORT__M_VMS_EFS

This indicates that the version of OpenVMS supports Extended
Filenames.  (OpenVMS 7.2 Alpha and later)

FPORT__M_VMS_DEEPDIR

This indicates that the version of OpenVMS supports deep nesting
of directories.  (OpenVMS 7.2 and later)


void fport__set_fname_options(unsigned long options)

Sets the options globally for filename processing.  See
fport__get_fname_options for details.


void fport__set_global_options(void)

This routine sets global options based on logical names to
simplify programming.  Logical names with the prefix
FRONTPORT__ will be used.

This routine is to simplify the setting of options for
small programs.

FRONTPORT__DEVICE_PREFIX = ?
Default is "FPORT__VMS_DEV_".  Maximum of 40 characters.

FRONTPORT__FNAME_CASE = (NONE, ACE, MEYER)
Default is NONE.
(None are implemented)

FRONTPORT__FNAME_EXTLASTDOT = (TRUE, FALSE)
When true, the last dot found in a UNIX file specification is assumed
to delimit the extension.  When false, the first dot found is assumed
to delimit the extension.
Default is TRUE.

FRONTPORT__FNAME_ODS5 = (TRUE, FALSE)
When true, if the file system is detected to be ODS-5, then ODS-5
parsing of the will be attempted.  Since I have not fully tested the
ODS-5 code yet, this allows reversion to the ODS-2 behavior.
Default is TRUE

FRONTPORT__FNAME_XLATE = (PATHWORKS, MULTINET)
Default is PATHWORKS.
(No others implemented)

FRONTPORT__STAT_SWAP_CTIME = (TRUE, FALSE)
Default is FALSE.

FRONTPORT__TEMPLATE_PREFIX = ?
Default is "FPORT__TEMPLATES:TEMPLATE"



void fport__set_root_uid(uid_t)

This routine sets the uid that will be used to replace zero for the
root.  The default is [1,4].



void fport__set_stat_options(unsigned long)

Sets the options globally for stat and protection mode handling.  See
fport__get_stat_options for details.


void fport__set_template_prefix(const char * templprefix)

Stores a default prefix for use in determining the directory and the
filename part of the template specification.  If no prefix is set, the
name "FPORT__TEMPLATES:TEMPLATE" is used.

When creating a file, the FRONTPORT library will look up the template
file of the same extension and use it's attributes on the new file.


void fport__set_unix_device_prefix(const char * devprefix)

This changes the device prefix from "FPORT__VMS_DEV_" to be the one
passed.  The device prefix is used to translate UNIX /dev/nnn
specifications to logical names or files.  For instance /dev/tty will
be translated by default to FPORT__VMS_DEV_TTY:.  This allows you to
have specific device logical names for your program independent of
other programs.



Debugger Assistance Routines:

These routines are used to assist in debugging C programs.  The user
typically does not know how to interpret or address some structures or
other information in the debugger.  These routines can be called from
the debugger to provide this information.

They are not intended to be called directly from a program.

To use in the OpenVMS debugger, use these steps for the example of
using of using the fport__print_fstat() routine.


DBG> examine file_number		! Get the file descriptor number

DBG> set image frontport__crtl		! Set the image to the frontport C
					! library wrapper
DBG> set module fport__print_fstat	! Make the image known to the DEBUGGER
DBG>call fport__print_fstat(nnnn)	! Print information from the
					! previously obtained file descriptor.

If you need information that is not printed, or like SAMBA, the
application being debugged has closed stdout or otherwise redirected
it, you can use the debugger to examine the contents.  You can set a
breakpoint on the routine before you call it.  Of course this requires
that the library has been linked in DEBUG and the source is available.
The FRONTPORT.MMS script will build the library in debug mode and the
assistant routines also in debug and no optimize mode.


DBG>set module fport__print_fstat
void fport__print_fstat(int file_number);

This routine calls the fstat routine.  It prints the filename and the
device.


DBG>set module fport__print_fstat
void fport__print_file_stat(FILE * fileptr);

This routine prints out the file descriptor number and then calls
fport__print_fstat().


DBG>set module fport__print_errno
int fport__print_errno(void);

This routine calls perror("errno = ") and returns errno.  The errno
variable is actually hidden under a global symbol and difficult to
expose from the debugger with out this routine.


DBG>set module fport__print_procinfo
void fport__print_procinfo(void);

This routine prints out information about the current process.  At the
time of this writing, it only displays the current and authorized
privileges.  More information may be added in the future.



Alphabetical standard routine reference:

int fport__add_history(const char * line)

This adds a line to the READLINE history buffer.  This is part of UNIX
READLINE library emulation.
(The history buffer is not used by the readline() function for this
release)


int fport__chdir(const char * vmspath)

Wrapper for chdir().  Handles filename translation.


unsigned long fport__check_disk_type(const char * path)

This routine checks the disk type.  The bit value FPORT__M_DISK_ODS5
is set for an ODS-5 volume.  The bit value FPORT__M_DISK_NOFILE if the
device is not a disk.  The bit value FPORT__M_DISK_NODEV is set if the
device does not exist.

This routine is used internally by the frontport library.  More bit
options may be added with later releases.


int fport__check_rms_lock
    (struct stat * statbuf, unsigned long * rab2ptr, unsigned int
     rqmode, unsigned long * blkpid)

This routine is mainly intended for internal use.  It is used as a
wrapper to set up the call for the User Written System Service that
actually does the check in EXECUTIVE mode.


int fport__chmod(const char * vmspath, mode_t mode)

Wrapper for chmod().  Handles filename translation and SAMBA mode
translation.


int fport__chown(const char * vmspath, uid_t uid, gid_t gid)

Wrapper for chown().  Handles filename translation.  Also will
translate uid of 0 to the current root alias.


int fport__close(int filedesc)

Wrapper for close.  In addition to normal close() operations, this
cleans up the fcntl() locks on this stream.  It flushes out to disk
any unwritten data through from the fport__write() routines.


int fport__closedir(FPORT__DIR * dirp)

Wrapper for closedir().  Cleans up after fport__opendir().


int fport__close_lock_stream(int filedesc)

This routine is mainly intended for internal use.  It is used to clean
up the fcntl() locks on this stream.


uid_t fport__convert_root_to_uid(uid_t test)

This routine is used to test if the given uid is 0, and replaces it
with the current alias.  The default alias is [1,4].  If the given uid
is not 0, it is returned unchanged.  This is intended mainly for
internal use.


uid_t fport__convert_uid_to_root(uid_t test)

This routine is used to test if the given uid is the same as the alias
for root, and replaces it with 0.  If it is not root then it is
returned unchanged.  This is intended mainly for internal use.


int fport__creat(const char * vmsfile, mode_t mode)

Wrapper for creat().  This handles filename translation and SAMBA mode
translation.  The attributes for a new file will be inherited from the
template directory if a matching template is found.  Otherwise the
normal DEC C defaults will apply.

When creating a file, the routine fport__get_default_attr() is used to
lookup the file extension in a template directory and sets the
attributes to match.  The template directory is set by using the
routine fport__set_template_prefix().

The RMS context information is stored for later use by fport__fcntl().


#define crypt fport__vms_crypt
char * fport__vms_crypt(const char * key, const char * salt);

This implements a fake crypt function.  It uses the values from a
previous call to fport__getpwnam() to calculate a password encryption
for OpenVMS using SYS$HASH_PASSWORD.  This encrypted password is
returned in hex in an ASCII string.

This routine is not automatically exposed from the header to replace
the crypt function.  It does not do a UNIX crypt function.


char * fport__ctime(const time_t * clock)

This implements the ctime() routine.  Provided for versions of OpenVMS
that do not have it.


int fport__delete(const char *vmsfile)

Wrapper for delete().  This handles filename translation.


void fport__dlclose(void * handle)

Wrapper for dlclose.()  Implementation is in progress so that it will
work with prior versions of OpenVMS.  (Not implemented on VAX, and
will produce Informational compile diagnostics, may not compile on
ALPHA for versions of OpenVMS prior to 7.2)

char * fport__dlerror(void)

Wrapper for dlerror().  Implementation is in progress so that it will
work with prior versions of OpenVMS.  (Not implemented on VAX, and
will produce Informational compile diagnostics, may not compile on
ALPHA for versions of OpenVMS prior to 7.2)


void * fport__dlopen(const char * pathname, int mode)

Wrapper for dlopen().  This wrapper will convert filenames as
previously described.  Implementation is in progress so that it will
work with prior versions of OpenVMS.  (Not implemented on VAX, and
will produce Informational compile diagnostics, may not compile on
ALPHA for versions of OpenVMS prior to 7.2)


void * fport__dlsym(void * handle, char * name)

Wrapper for dlsym().  Implementation is in progress so that it will
work with prior versions of OpenVMS.  (Not implemented on VAX, and
will produce Informational compile diagnostics, may not compile on
ALPHA for versions of OpenVMS prior to 7.2)


int fport__dup(int filedesc)

Wrapper for dup().  Stores context information for later use by
fport__fcntl().


int fport__dup2(int filedesc1, int filedesc2)

Wrapper for dup2().  Stores context information for later use by
fport__fcntl()


int fport__fclose(FILE * fileptr)

Wrapper for fclose().  In addtion to normal fclose() operation, cleans
up lock information from fport__fcntl.



int fport__fcntl(int filedesc, int cmd, ...)

Wrapper for fcntl().  Implements file locking.  This is accomplished
by opening a second RMS stream in record mode on the file
specification.  Passes through the non-locking functions to the
underlying C RTL.  A fake_fcntl() module provides the dup() and dup2()
functionality for earlier versions of OpenVMS.

Note that this function will extend the file if needed to lock a
range.  UNIX programs expect to be able to lock non-existant parts of
a file.  This may cause portability problems with programs.


FILE * fport__fdopen(int filedesc, char * amode)

Wrapper for fdopen().  Currently does nothing but call fdopen().


char * fport__fgetname(FILE * fileptr, char * buffer)

Wrapper for fgetname().  Returns the filename in UNIX format.


int fport__fileno(FILE * fileptr)

Wrapper for fileno().  Currently does nothing but call fileno().


FILE * fport__fopen(const char * filename, const char * amode)

Wrapper for fopen().  See the description of fport__creat().


FILE * fport__freopen(const char *file, const char * a_mode,
		      FILE * fileptr)

Wrapper for freopen().  See the description of fport__creat().


int fport__fstat(int file_desc, fport__stat_t * statbuf)

Wrapper for fstat().  Time is always returned in UTC.  The mode bits
may be modified as a result of ACLs or special SAMBA modes.


int fport__fstatvfs(int file_desc, struct statvs * statbuf)

Implements statvfs() to return information about the file system the
open file resides on.


#define FPORT__STREAM_UNIXIO 1
int fport__fsync(int filedesc)

Implements the fsync() function for random access to buffered I/O.  It
makes sure that the buffer is flushed to the current record boundary.
Currently only reliable on fixed format files.


void fport__ftime(struct timeb * tb)

Implements the ftime() routine for versions of OpenVMS that do not
have it.


int fport__ftrunctate(int filedesc, off_t length)

Wrapper for ftruncate.  This wrapper marks a high-water setting.  This
is moved if any subsequent writes are done to the file.  If no more
writes are done to the file, it will be truncated after it is closed.
If this is used to extend a file, no extension is done until a
subsequent write.


char * fport__getcwd(char * buffer, size_t len)

Wrapper for getcwd().  File specification is returned in UNIX format.


#define getenv fport__getenv_trnlnm
char * fport__getenv_trnlnm(const char * name, ...)

Procedure for translating logical names similar to a common use of
getenv().  I do not recommend using the DEC C getenv() for this inside
of a loop, as it's behavior varies with the version of the underlying
C run time library.  Using this routine will give consistent results.

fport__getenv_trnlnm with only one parameter will just translate the
name into up to 2047 bytes into local static storage for the procedure.
This will be overwritten by subsequent calls.

The second parameter is the size of an optional buffer pointed to the
third parameter.  This buffer will contain the translated name instead
of the static buffer.

In the event that the logical name can not be translated, or only two
parameters are given, the result will be a null pointer.  This is
consistent with the allowed behavior for getenv().


#define getegid fport__getgid
short_gid_t fport__getgid(void)

Gets the current gid, converting from the VMS group designated to the
UNIX root id if needed.


#define getgid fport__getgid_set
short_gid_t fport__getgid_set(void)

Gets the last GID that was set with fport__setgid().  This is used for
some programs that test a setgid() call with a getgid() call
immediately following.


struct group * fport__getgrgid(long_gid_t gid)

Looks up a UIC based group identifier or numeric rights ID and returns
a pointer to a group structure that contains a pointer to the text
name for the group.  If needed will substitute the designated VMS
group for the UNIX group of 0.  For OpenVMS this will also translate
rights identifiers to names.  The group structure can be overwritten
by a subsequent call to fport__getgrgid() or fport__getgrnam().


struct group * fport__getgrnam(const char * name)

Looks up the UIC or numeric rightslist value for the given name, and
then call fport__getgrgid() to return a pointer to the group structure.


int fport__getgroups(int gidsetsize, long_gid_t * gid)

Populates an array with all of the identifiers currently held by the
user.


char * fport__getname(int filedesc, char * buffer)

Wrapper for getname().  Returns the file specification in UNIX format.


char * fport__getopt(int argc, const char * argv[],
		     const char * optstring)

This is a modified version of the GNU getopt() function.  The
modifications allow the use of "/" instead of "-" for long file
options.  This allows GNU applications to have more of a OpenVMS look
and feel with out much work.  To take advantage of this, the program
must be written to use the gnu getopt function.
(The enhancements have not been tested from this repackaged version.)


char * fport__getpass(const char * prompt)

This implements the getpass() routine.  It will read up to 39
characters from the input stream.  Note that OpenVMS will only allow
39 character passwords and Windows NT 4.0 will only allow 14 character
passwords.  If standard input is not a terminal, this routine will
return a null password.  This routine creates a channel to the
standard input device that is shared with the fport__readline()
function.


struct fport__passwd_st * fport__getpwnam(const char * username)

This implements an enhanced getpwnam().  The structure returned has
more members to it than the DEC C one does, for ones that SAMBA
expects, and most of the other fields of the user authorization
record.  The user must have the appropriate privileges to obtain the
information for this call to work.

The directory name and login command file name will be returned in
UNIX format.  The pw_gecos field is populated with the data from the
VMS UAF owner field.  The VMS password hash is returned in hexadecimal.


struct fport__passwd_st * fport___getpasswd_st(void)

This routine will return a pointer to the last structure that was
looked up with the fport__getpwnam().  This is used to implement the
fport__vms_crypt() function.


struct fport__passwd_st * fport__getpwuid(uid_t uid)

This routine translates the uid to a username and then calls
fport__getwpnam().


int fport__gettimeofday(struct timeval * tv, void * tz)

Implements the gettimeofday() routine.


#define geteuid fport__getuid
uid_t fport__getuid(void)

This routine will return the current uid.  It will be converted from
a VMS UID to the UNIX root uid if needed.


char * fport___getusername(void).

This routine will return a pointer to the last username that was
looked up with fport__getpwnam().


mode_t fport__get_acl_mode(const char * file_spec, mode_t umode)

This routine modifies the umode protection mask passed based on any
ACLs that are present on a file.


void fport__get_default_file_attr(char * vmspath,
				  const char *filename, char * attr)

This routine converts the given file specification to be in a properly
encoded VMS file specification.  It also looks up the default file
attributes for a file based on a template of the same extension found
in a template directory.

The template directory name is based on the settings of
fport__set_template_prefix().  This defaults to
"FPORT__TEMPLATES:TEMPLATE"


uid_t fport__get_root_uid(void)

Gets the current VMS UIC that corresponds to the UNIX UID of 0.  The
default is [1,4] for the SYSTEM account.


mode_t fport__get_samba_mode(const char * filename, mode_t umode)

This routine looks up special SAMBA DOS attributes for a file and does
a logical OR of them with the umode parameter.

The DOS Archive bit is clear if a backup date is recorded for the
file.  SAMBA encodes this as S_IXUSR.

If the FPORT__M_STAT_SET_SAMBA_SYSTEM_ACE option is clear (current
default) then the SYSTEM bit is set if SYSPRV or higher is needed for
write access to the file.  If the option is set, then the presence of
the SAMBA__SYSTEM ACE on the file will be used as the indicator.
SAMBA encodes this as S_IXGRP.

If the FPORT__M_STAT_SET_SAMBA_READONLY_ACE option is clear (current
default) then the READONLY bit is set if the user normally does not
have privileges to modify the file.  This may generate a false
READONLY setting if the UIC based protection is set to World + Group
+ Owner readonly already, but an ACE grants the user access.  If the
option is set, then the presence of the SAMBA__READONLY ACE on the
file will be used as the indicator.  SAMBA encodes this as all three
of the S_IWUSR, S_IWGRP, S_IWOTH being clear.


Using ACEs as these indicators is currently not implemented.
Activating the option bits for this will cause those attributes to
not be displayed.

Some more work on this will be done later.


struct tm * fport__gmtime(const time_t * clock)

Implements the gmtime() routine.


FPORT__HIST_ENTRY **fport__history_list(void)

Returns a pointer to an array of input history lines that were
maintained by fport__add_history() function.  This is part of UNIX
READLINE library emulation.  The fport__readline() function does not
currently use the history lines.


int fport__kill(int pid, int sig);

Wrapper for the kill() function.  This version always just returns the
current pid for a signal value of 0.


struct tm * fport__localtime(const time_t * clock)

Implements the localtime() routine.


#define FPORT__STREAM_UNIXIO 1
off_t fport__lseek(int filedesc, off_t offset, int direction)

Attempts to handles random byte access for RMS files.  Currently will
only work reliably for fixed format files.  Attempting to lseek() to
write into the middle of a stream file opened in record mode will
cause an extra record terminating characters to be inserted.


int fport__mkdir(const char * dirspec, mode_t mode)

Wrapper for the mkdir() function.  This handles the filename
translation.


time_t  fport__mktime(struct tm * tm)

Implements the mktime routine.


void fport__nt_time_to_vms(void * vms_time, const void * nt_time)

This routine converts an NT 64 bit time to a VMS 64 bit time with no
loss of precision.

The arguments are two member longword arrays.  Void pointers are used
because of the variety of ways the time quad word can be stored.


int fport__open(const char *filename, int flags, ...)

See the description for creat().  This routine accepts a third
optional parameter of the protection mode.


FPORT__DIR fport__opendir(const char * dirspec)

Wrapper for opendir().  The FPORT__DIR structure is modified from the
standard DIR structure in that it has an additional field.  If you
pass it the UNIX path of "/", it will use the logical name that
fport__unix_dev_translate() will substitute for it.  If you pass it
the UNIX path of /DEV it will check to see if the logical name
fport__unix_dev_translate() will substitute for it is a search list,
then the logical names in the search list will be listed by the
subsequent readdir().  If no logical name exists, it then readdir will
return a list of all devices known on the system.

See the description for fport__unix_dev_translate() for more
information on device translation.


void fport__pwrk_fname_to_unix(char * outfile, const char * infile,
			       long option)

This routine is called by fport__vms_fname_to_unix() when
FPORT__M_FNAME_PWRK is set.  This routine decodes a VMS file name
encoded into Compaq's PATHWORKS format to be the expected UNIX format.
This routine is mainly for internal use.  The option flags control
aspects of the translation.


#define FPORT__STREAM_UNIXIO 1
ssize_t fport__read(int filedesc, void* buffer, size_t nbytes)

This routine buffers read information to give the illusion that a VMS
file read in record mode is still a continuous stream of bytes.


struct dirent * fport__readdir(FPORT__DIR * dirp)

Wrapper for readdir().  See the description for fport__opendir().


char * fport__readline(const char * prompt)

Implements a readline simulation using SYS$QIOW.  At the present time
using the history list is not implemented, but single line recall and
editing is available.  This is part of UNIX READLINE library
emulation.  This routine creates a channel to the standard input
device that is shared with the fport__getpass() function.



#define fport__remove fport__delete

Alias for fport__delete().  No function has been implemented.  The two
routines have the same functionality.


int fport__rename(const char * name1, const char * name2)

Wrapper for rename().  Accepts UNIX format file specifications.  This
will change the protection of a directory to allow it to be renamed,
if the user normally has permission to change the protection of a
directory.


void fport__report_version(void)

This routine prints out the version of the FRONTPORT library and some
information that can be used to help diagnose problems.


void fport__rewinddir(FPORT__DIR * dirp)

Wrapper for rewinddir().  See the description for fport__opendir().


int fport__rmdir(const char * dirname);

Wrapper for rmdir().  This handles the filename translation.


void fport__seekdir(FPORT__DIR * dirp, long int loc)

Wrapper for seekdir().  See the description for fport__opendir().


mode_t fport__samba_to_unix_chmod(mode_t mode)

This routine strips off the SAMBA encoded mode bits from the
protection mode.


#define setegid fport__setgid
int fport__setgid(gid_t gid)

Wrapper for setgid().  Routine always returns success, and does not
change the group identification number as this has no meaning in
OpenVMS.  The group uid is stored for later return by
fport__getgid_set().


#int seteuid fport__setuid
int fport__setuid(uid_t uid)

An implementation of setuid().  This routine changes the UIC, the
Username, and loads the appropriate identifiers for the new user.
Requires the FRONTPORT___SET_USER shared image to be installed.


unsigned long fport__set_file_modtime(const char * filename,
				      const long * vmsdate)

This procedure sets the file specified in VMS convention with the
revision date supplied in VMS quadword format.  No filename conversion
is done.  Used by utime().


void fport__set_global_options(void)

This procedure sets global options in one convenient routine by
reading logical names.  This was documented in an earlier section.


void fport__set_root_uid(uid_t alias)

Sets the VMS UIC that corresponds to the UNIX uid of 0.  Use this
function to allow running of UNIX code that assumes it must be
running under root.


void fport__set_samba_mode(const char * vmspath, mode_t mode)

This routine is for future implementation.  Due to differences in the
OpenVMS security model and Windows NT, it will require more work.

With the current UIC based protection mapping, it is not possible to
be able to properly reverse a protection change operation.  For
example, making a file READONLY from a DOS point of view requires
removing write access from the world and group also.  Removing
READONLY from a DOS point of view should not imply adding world and
group write access in addition to owner.


int fport__snprintf(char * str, size_t n, const char *format, ...)

This implements the snprintf() as a wrapper to sprintf() routine.  The
destination string is limited to 65535 characters.


int fport__stat(const char * filename, fport__stat_t * statbuf)

Wrapper for stat().  Behavior is controlled by the
FPORT__M_STAT_USEACL, FPORT__M_STAT_SAMBA options.


int fport__statvfs(const char * filename, struct statvs * statbuf)

Implements statvfs().  Returns information about the file system that
the filename is on.


int fport__system(const char * command)

This routine implements the system() routine.  It changes the
effective uid to be the original uid just before the command is
spawned and then changes it back.  This appears to be the way UNIX
code expects it to work.


time_t fport__time(time_t * clock)

Implements the time() routine.


long int fport__telldir(FPORT__DIR * dirp)

Wrapper for telldir().  See the description for fport__opendir().


int fport__truncate(const char * filename, off_t length)

Wrapper for truncate().  Handles the filename translation.


void fport__tzset(void)

Sets the global variables daylight, timezone, and tzname[2].  The
first logical name found of the set TZ, SYS$TIMEZONE_RULE, UCX$TZ,
POSIX_TZ, POSIX$DEFAULT_TZ will be used.


int fport__umask(mode_t mode)

Wrapper for umask().  Behavior is controlled by the
FPORT__M_STAT_SAMBA option.


void fport__unix_dev_translate(char * outfile, const char * infile)

This routine looks to see if infile is of the format "/dev/nnnn"
format and then translates it to a logical name with a prefix
determined by fport__set_unix_device_prefix().  The default prefix is
FPORT__VMS_DEV_.

For example /dev/nl would be interpreted as FPORT__VMS_DEV_NL:.

It also will interpret "/" as the same prefix and adding the suffix
"ROOT".   This allows a programmer to designate what is the "ROOT"
directory.  If the resulting logical name does not exist, then
SYS$LOGIN: is used.

This routine is called by all routines in this library that accept
UNIX file specifications.  The routines that convert from VMS file
specifications to UNIX file specifications reverse this by calling
fport__vms_dev_translate().



void fport__unix_fname_to_pwrk(char * vmspath, const char *filename,
			       unsigned long options)

This routine will convert a UNIX style filename to a format that is
compatible with Compaq's Pathworks product if the target device is on
an ODS-2 device.  This routine is used by all functions in this
library that accept a UNIX file specification.  It is called by the
fport__unix_fname_to_vms() routine.


void fport__unix_fname_to_vms(char * vmspath, const char *filename,
			      unsigned long options)

This routine converts a UNIX style filename into a VMS style filename
encoding the characters that are not legal VMS characters by the
specified FPORT__M_FNAME_* option.  At the present time only
FPORT__M_FNAME_PWRK is implemented.


void fport__unix_time_t_to_vms(void * vms_time, time_t unix_time)

This routine converts a UNIX time_t format to a VMS quadword format.
The vms_time is passed as two element longword array or equivalent
size structure.


int fport__utime(const char * fname, const struct utimbuf * times)

Implementation of utime().  This routine only sets the modification
date of the file.  The access time parameter is currently ignored.
Support for it will need to be added later where it is supported.


int fport__vms_dev_translate(char *outfile, const char * unixpath,
			     char sep)

This routine is the reverse of the fport__unix_dev_translate()
routine.  When this routine is passed a logical name matching one
generated by the fport__unix_dev_translate(), it will decode it into
the UNIX device specification that produced it.  This is to allow file
specifications to be translated in both directions.



void fport__vms_dir_to_fname(char * vmsdirpath, const char * vmspath)

This converts a VMS directory specification into a file specification.


void fport__vms_fname_to_unix(char * unixpath, const char * vmspath,
			      options)

This converts a VMS file specification to a UNIX specification,
decoding special characters as needed and controlled by the
FPORT__M_FNAME options.  This calls the fport__pwrk_fname_to_unix()
to do the translation.  Currently only Pathworks and ODS-5 encoding
is translated.


void fport__vms_time_to_nt(void * nt_time, const void * vms_time)

This routine converts a VMS quadword time to NT time format with no
loss of precision.


unsigned long fport__vms_statvfs(char * devname, struct statvfs * buf)

This routine implements a statvfs() routine on a VMS device
specification.  It is used by fport__statvfs() and fport__fstatvfs().
This routine is mainly for internal use.  The devname parameter should
be declared as const, and will probably be with the next revision.


unsigned long fport__vms_support_flags(void)

This routine is used to determine what options the version of OpenVMS
that it is running on will support.  Currently the flags returned are:
    FPORT__M_VMS_EFS - VMS version supports EFS.
    FPORT__M_VMS_DEEPDIR - VMS version supports 255 directory levels.


int fport__vsnprintf(char * str, size_t n, const char *format,
		     va_list ap)

This implements the vsnprintf() routine as a wrapper to vsprintf()
routine.  The destination string is limited to 65535 characters.


#define FPORT__STREAM_UNIXIO 1
int fport__write()

This buffers write requests until an entire record can be written.
It provides the illusion that an RMS file can be written to as a
stream of bytes while open in record context.



Some special notes:

The file fake_fcntl.c is provided for those versions of VMS that the
DEC C RTL does not contain any fcntl() function.  This is to allow the
library to be linked on those systems.  Some of the I/O fcntl()
functions may not be available when this is done.

grp.h is provided to allow UNIX programs that reference it to compile.
Only the getgrgid() and getgrnam() routines are implemented at this
time.


Building the FRONTPORT library:

The source kit is a ZIP archive.

The source files can be in a different directory than the default
directory.  This allows you to have the files that are not being
modified in a CMS library.

You need to have your default set to the directory where you want the
binary files to be created.  The command procedure
SETUP_FRONTPORT_BUILD.COM must be run out of the directory where the
source files are.  This will set up the needed logical names and
symbols to do the build.

I strongly recommend that you NOT set your default to a CMS reference
directory.

Either Compaq Module Management System (MMS) or the MadGoat Make (MMK)
should be able to build the main shared image.

The command MMS/DESCRIP=FRONTPORT will compile and link the shared
image.

To build and install the helper images, you must copy the startup
command files to the default directory and run the command file
FRONTPORT_STARTUP.COM.  The DEC C compiler is required.


If I receive patches to allow GCC to build these routines or to allow
older versions of OpenVMS than I can test with, I will try to
accommodate them, but I can only test DECC on close to the latest
version of OpenVMS at this time.

This is a spare time project, so I will not commit to any release
schedule for any enhancements.


Acknowledgements:

This library is not a sole effort.  The following people need to be
acknowledged.

The UTC time routines were originally written by Eckart Meyer. Eckart
Meyer also provided the base code for many other of the routines.

The code for looking up the holder of a blocked lock as part of fcntl()
is from Usenet postings by Hein van den Heuvel.

The getopt routines are from the FSF GNU project.

The utime setting routines are based on code from Eckart Meyer and
Joe Medows.

The user written system used the code from SYS$EXAMPLES: for VAX and
ALPHA as templates.

The set user macro routines were written by Geoff Fitch., "ABS STINE",
and "DSA".

Glenn C. Everhart has provided me with sample routines that will be
used to derive additional functionality in the future in the area of
case preserved storage and display of filenames, and also in a future
implementation of DOS attributes.


All trademarks mentioned here in are the properties of their owners.
OpenVMS, and VMS are trademarks of Compaq Computer Corporation.  UNIX
is a trade mark of "The Open Group".