aboutsummaryrefslogtreecommitdiff
path: root/unix/boot/bootlib
diff options
context:
space:
mode:
Diffstat (limited to 'unix/boot/bootlib')
-rw-r--r--unix/boot/bootlib/README53
-rw-r--r--unix/boot/bootlib/_bytmov.c41
-rw-r--r--unix/boot/bootlib/bootlib.h36
-rw-r--r--unix/boot/bootlib/envinit.c269
-rw-r--r--unix/boot/bootlib/index.c39
-rw-r--r--unix/boot/bootlib/kproto32.h80
-rw-r--r--unix/boot/bootlib/kproto64.h80
-rw-r--r--unix/boot/bootlib/mkpkg49
-rw-r--r--unix/boot/bootlib/mkpkg.sh16
-rw-r--r--unix/boot/bootlib/osaccess.c27
-rw-r--r--unix/boot/bootlib/osamovb.c34
-rw-r--r--unix/boot/bootlib/oschdir.c43
-rw-r--r--unix/boot/bootlib/osclose.c29
-rw-r--r--unix/boot/bootlib/oscmd.c27
-rw-r--r--unix/boot/bootlib/oscreatedir.c18
-rw-r--r--unix/boot/bootlib/oscrfile.c36
-rw-r--r--unix/boot/bootlib/osdelete.c19
-rw-r--r--unix/boot/bootlib/osdir.c93
-rw-r--r--unix/boot/bootlib/osfcopy.c84
-rw-r--r--unix/boot/bootlib/osfdate.c20
-rw-r--r--unix/boot/bootlib/osfiletype.c116
-rw-r--r--unix/boot/bootlib/osfn2vfn.c81
-rw-r--r--unix/boot/bootlib/osfpathname.c41
-rw-r--r--unix/boot/bootlib/osgetenv.c127
-rw-r--r--unix/boot/bootlib/osgetowner.c28
-rw-r--r--unix/boot/bootlib/osopen.c29
-rw-r--r--unix/boot/bootlib/osproto.h136
-rw-r--r--unix/boot/bootlib/osputenv.c72
-rw-r--r--unix/boot/bootlib/osread.c18
-rw-r--r--unix/boot/bootlib/ossetfmode.c18
-rw-r--r--unix/boot/bootlib/ossetowner.c21
-rw-r--r--unix/boot/bootlib/ossettime.c24
-rw-r--r--unix/boot/bootlib/osstrpak.c34
-rw-r--r--unix/boot/bootlib/osstrupk.c44
-rw-r--r--unix/boot/bootlib/ossubdir.c31
-rw-r--r--unix/boot/bootlib/ossymlink.c35
-rw-r--r--unix/boot/bootlib/ossysfile.c113
-rw-r--r--unix/boot/bootlib/ostime.c113
-rw-r--r--unix/boot/bootlib/oswrite.c49
-rw-r--r--unix/boot/bootlib/rindex.c33
-rw-r--r--unix/boot/bootlib/tape.c271
-rw-r--r--unix/boot/bootlib/vfn2osfn.c147
42 files changed, 2674 insertions, 0 deletions
diff --git a/unix/boot/bootlib/README b/unix/boot/bootlib/README
new file mode 100644
index 00000000..b934f681
--- /dev/null
+++ b/unix/boot/bootlib/README
@@ -0,0 +1,53 @@
+BOOTLIB -- C callable file primitives used by the bootstrap utilities.
+
+This is a somewhat adhoc interface consisting of a collection of low level
+functions required by the bootstrap utilities. As far as possible these
+use the iraf kernel, but occasionally non-kernel facilities are required or
+desirable. The purpose of this interface is to isolate the machine dependence
+of the bootstrap utilities from the bulk of the code, making it easier to
+maintain IRAF on different hosts, as well as to make it easier to port IRAF
+to a new host. No attempt has been made to specify this interface carefully;
+it is not necessary since only a limited number of programs use the routines.
+
+Partial list of functions (grows sporadically):
+
+ char * vfn2osfn (vfn, mode) # Map filenames
+ char * osfn2vfn (osfn)
+
+ fd = os_diropen (dir) # Read directories
+ os_dirclose (fd)
+ os_gfdir (fd, fname, maxch)
+
+ bool os_access (fname, mode, type) # General file
+ os_chdir (dir)
+ os_close (fd)
+ os_cmd (cmd)
+ os_close (fd
+ os_createdir (dirname, mode)
+ os_createfile (fname, mode, type)
+ os_delete (fname)
+ os_fcopy (oldfile, newfile)
+ os_fpathname (vfn, pathname, maxch)
+ long os_fdate (file)
+ char * os_getenv (ennvar)
+ fd = os_open (fname, mode, type)
+ os_setfmode (fname, mode)
+ os_setowner (fname, uid, gid)
+ os_setmtime (fname, mtime)
+ os_sysfile (fname, outstr, maxch)
+ os_read (fd, buf, nbytes)
+ os_write (fd, buf, nbytes)
+
+ fd = tape_open (fname, mode) # Tape or disk file
+ tape_close (fd)
+ tape_read (fd, buf, nbytes)
+ tape_write (fd, buf, nbytes)
+
+
+Tasks which use this library must also use the kernel library (libos.a).
+Tasks which use full filename mapping will also need libsys.a and libvops.a,
+however the system can be bootstrapped with simpler filename mapping and
+then the utilities relinked with full filename mapping, once the system
+libraries have been generated. Note that no VOS level i/o is used (only
+kernel level i/o functions are used), hence an IRAF main is not required
+to initialize the VOS i/o system.
diff --git a/unix/boot/bootlib/_bytmov.c b/unix/boot/bootlib/_bytmov.c
new file mode 100644
index 00000000..849d8e52
--- /dev/null
+++ b/unix/boot/bootlib/_bytmov.c
@@ -0,0 +1,41 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#define import_spp
+#define import_knames
+#include <iraf.h>
+
+/* BYTMOV -- Byte move from array "a" to array "b". The move must be
+ * nondestructive, allowing a byte array to be shifted left or right a
+ * few bytes, hence comparison of the addresses of the arrays is necessary
+ * to determine if they overlap.
+ */
+void
+BYTMOV (
+ XCHAR *a, /* input byte array */
+ XINT *aoff, /* first byte in A to be moved */
+ XCHAR *b, /* output byte array */
+ XINT *boff, /* first byte in B to be written */
+ XINT *nbytes /* number of bytes to move */
+)
+{
+ register char *ip, *op;
+ register int n = *nbytes;
+ char *ap, *bp;
+
+ ap = (char *)a + (*aoff - 1);
+ bp = (char *)b + (*boff - 1);
+
+ /* If the two arrays are the same return immediately. If the move is
+ * to the left then copy left to right, else copy right to left.
+ */
+ if (ap == bp) {
+ return;
+ } else if (bp < ap) {
+ for (ip=ap, op=bp; --n >= 0; )
+ *op++ = *ip++;
+ } else {
+ for (ip = &ap[n], op = &bp[n]; --n >= 0; )
+ *--op = *--ip;
+ }
+}
diff --git a/unix/boot/bootlib/bootlib.h b/unix/boot/bootlib/bootlib.h
new file mode 100644
index 00000000..b1bbbc7a
--- /dev/null
+++ b/unix/boot/bootlib/bootlib.h
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <ctype.h>
+#define import_spp
+#define NOKNET
+#define import_knames
+#include <iraf.h>
+
+#define SZ_FBUF 512 /* File i/o buffer size */
+
+#ifdef VMS
+#define rindex strrchr
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+#else
+#include <sys/time.h>
+#endif
+
+
+# ifdef FINIT
+int bdebug = 0; /* print debug stuff */
+int osfiletype; /* type of single output file */
+XCHAR text[SZ_FBUF]; /* output text line if textfile */
+XCHAR *txop; /* next char in output buf */
+# else
+extern int bdebug;
+extern int osfiletype;
+extern XCHAR text[];
+extern XCHAR *txop;
+# endif
+
+char *vfn2osfn();
+char *osfn2vfn();
+char *os_strpak();
+XCHAR *os_strupk();
diff --git a/unix/boot/bootlib/envinit.c b/unix/boot/bootlib/envinit.c
new file mode 100644
index 00000000..e70a8d86
--- /dev/null
+++ b/unix/boot/bootlib/envinit.c
@@ -0,0 +1,269 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#define import_spp
+#define import_xnames
+#include <iraf.h>
+
+#define isspace(c) ((c)==' '||(c)=='\t'||(c)=='\n')
+#define SETENV "zzsetenv.def"
+#define SZ_VALUE SZ_COMMAND
+#define MAXLEV 8
+#define PKGLIBS "pkglibs"
+#define IRAFARCH "IRAFARCH"
+#define ARCH "arch"
+
+extern char *_os_getenv (char *envvar, char *outstr, int maxch);
+extern char *os_getenv (char *envvar);
+extern char *os_strpak (XCHAR *sppstr, char *cstr, int maxch);
+extern char *vfn2osfn (char *vfn, int new);
+extern XCHAR *os_strupk (char *str, XCHAR *outstr, int maxch);
+extern void os_putenv (char *name, char *value);
+extern int bdebug;
+
+void _envinit (void);
+void loadenv (char *osfn);
+
+
+
+/* LOADPKGENV -- Load the environment definitions for the named package.
+ * [e.g., loadpkgenv ("noao")]. This assumes that the root directory of
+ * the named package is already defined, and that this directory contains
+ * a subdirectory lib containing the file zzsetenv.def. If none of these
+ * assumptions are true, call loadenv(osfn) with the host filename of the
+ * file to be loaded.
+ */
+void
+loadpkgenv (char *pkg)
+{
+ char vfn[SZ_PATHNAME+1];
+ char pkglibs[SZ_COMMAND+1];
+ char newlibs[SZ_COMMAND+1];
+
+ /* Initialize the default IRAF environment. */
+ _envinit();
+
+ /* If no package name is given or the IRAF environment is being
+ * loaded we are done.
+ */
+ if (!pkg || strcmp(pkg,"iraf")==0)
+ return;
+
+ strcpy (vfn, pkg);
+ strcat (vfn, "$lib/");
+ strcat (vfn, SETENV);
+
+ /* Load the package environment. The new values are added to the
+ * environment in the conventional way except for the value of
+ * "pkglibs". As each package environment is loaded we want to
+ * add the newly defined package libraries to the current list
+ * of package libraries, otherwise the most recent package environment
+ * overrides the earlier ones. It is still possible that user
+ * defined environment variables will be redefined but there is
+ * little we can do about that; "pkglibs" is special though since
+ * it is a part of the loadpkgenv facility.
+ */
+ _os_getenv (PKGLIBS, pkglibs, SZ_COMMAND);
+ loadenv (vfn2osfn (vfn, 0));
+ _os_getenv (PKGLIBS, newlibs, SZ_COMMAND);
+
+ if (strlen(newlibs) > 0 && strcmp (newlibs, pkglibs)) {
+ char *ip, *op;
+ char *otop;
+
+ /* Find the end of the current pkglibs file list. */
+ for (ip=op=pkglibs; *ip; ip++)
+ if (!isspace(*ip))
+ op = ip + 1;
+
+ /* Concatenate the new files list segment. */
+ if (op > pkglibs)
+ *op++ = ',';
+ for (ip=newlibs, otop=pkglibs+SZ_COMMAND; *ip && op < otop; ip++)
+ if (!isspace(*ip))
+ *op++ = *ip;
+
+ /* Blank fill to the next SZ_LINE increment to optimize resets. */
+ while (op < otop && ((op-pkglibs) % SZ_LINE))
+ *op++ = ' ';
+ *op++ = EOS;
+
+ /* Reset the stored value in the environment. */
+ os_putenv (PKGLIBS, pkglibs);
+ }
+}
+
+
+#ifdef NOVOS
+void _envinit (void) {}
+void loadenv (char *osfn) { printf ("HSI is compiled NOVOS\n"); }
+#else
+
+/* ENVINIT -- Initialize the VOS environment list by scanning the file
+ * hlib$zzsetenv.def. HLIB is defined in terms of HOST which is sufficiently
+ * well known to have a value before the environment list is loaded.
+ */
+void
+_envinit (void)
+{
+ static int initialized = 0;
+ char osfn[SZ_PATHNAME+1], *hlib;
+ char irafarch[SZ_PATHNAME+1];
+
+ extern void ENVINIT(), ENVRESET();
+
+
+ if (initialized++)
+ return;
+
+ if ( (hlib = os_getenv ("hlib")) ) {
+ strcpy (osfn, hlib);
+ strcat (osfn, SETENV);
+ } else {
+ fprintf (stderr, "cannot translate logical name `hlib'");
+ fflush (stderr);
+ }
+
+ ENVINIT();
+ loadenv (osfn);
+
+ /* If the variable "IRAFARCH" is defined and "arch" is not, add
+ * a definition for the latter. "arch" is used to construct
+ * pathnames but the HSI architecture support requires only that
+ * IRAFARCH be predefined.
+ */
+ if (_os_getenv (IRAFARCH, irafarch, SZ_PATHNAME))
+ if (!_os_getenv (ARCH, osfn, SZ_PATHNAME)) {
+ XCHAR x_name[SZ_PATHNAME+1];
+ XCHAR x_value[SZ_PATHNAME+1];
+
+ sprintf (osfn, ".%s", irafarch);
+ os_strupk (ARCH, x_name, SZ_PATHNAME);
+ os_strupk (osfn, x_value, SZ_PATHNAME);
+ ENVRESET (x_name, x_value);
+ }
+}
+
+
+/* LOADENV -- Load environment definitions from the named host file.
+ */
+void
+loadenv (char *osfn)
+{
+ register char *ip;
+ register XCHAR *op;
+
+ char lbuf[SZ_LINE+1];
+ char pkname[SZ_FNAME+1], old_value[SZ_VALUE+1];
+ XCHAR name[SZ_FNAME+1], value[SZ_VALUE+1];
+ FILE *fp, *sv_fp[MAXLEV];
+ int lev=0;
+
+ extern void ENVRESET();
+
+
+ if ((fp = fopen (osfn, "r")) == NULL) {
+ printf ("envinit: cannot open `%s'\n", osfn);
+ fflush (stdout);
+ return;
+ }
+
+ for (;;) {
+ /* Get next line from input file. */
+ if (fgets (lbuf, SZ_LINE, fp) == NULL) {
+ /* End of file. */
+ if (lev > 0) {
+ fclose (fp);
+ fp = sv_fp[--lev];
+ continue;
+ } else
+ break;
+
+ } else {
+ /* Skip comments and blank lines. */
+ for (ip=lbuf; isspace(*ip); ip++)
+ ;
+ if (strncmp (lbuf, "set", 3) != 0) {
+ if (strncmp (lbuf, "reset", 5) != 0)
+ continue;
+ else
+ ip += 5;
+ } else
+ ip += 3;
+
+ /* Check for @file inclusion. */
+ while (isspace(*ip))
+ ip++;
+
+ if (*ip == '@') {
+ sv_fp[lev++] = fp;
+ if (lev >= MAXLEV) {
+ printf ("envinit: nesting too deep\n");
+ fflush (stdout);
+ break;
+
+ } else {
+ char *fname;
+ fname = ++ip;
+
+ while (*ip)
+ if (isspace(*ip)) {
+ *ip = '\0';
+ break;
+ } else
+ ip++;
+
+ if ((fp = fopen (vfn2osfn(fname,0), "r")) == NULL) {
+ printf ("envinit: cannot open `%s'\n", fname);
+ fflush (stdout);
+ break;
+ }
+ }
+ continue;
+ }
+
+ /* fall through */
+ }
+
+ /* Extract name field. */
+ for (op=name; *ip && *ip != '=' && !isspace(*ip); op++)
+ *op = *ip++;
+ *op = XEOS;
+
+ /* Extract value field; may be quoted. Newline may be escaped
+ * to break a long value string over several lines of the input
+ * file.
+ */
+ for (; *ip && (*ip == '=' || *ip == '"' || isspace (*ip)); ip++)
+ ;
+ for (op=value; *ip && *ip != '"' && *ip != '\n'; op++)
+ if (*ip == '\\' && *(ip+1) == '\n') {
+again: if (fgets (lbuf, SZ_LINE, fp) == NULL)
+ break;
+ for (ip=lbuf; isspace(*ip); ip++)
+ ;
+ if (*ip == '#')
+ goto again;
+ } else
+ *op = *ip++;
+ *op = XEOS;
+
+ /* Allow the user to override the values of environment variables
+ * by defining them in their host environment. Once again,
+ * "pkglibs" requires special treatment as we want to permit
+ * redefinitions to allow concatenation in loadpkgenv().
+ */
+ os_strpak (name, pkname, SZ_FNAME);
+ if (strcmp (pkname, PKGLIBS) &&
+ _os_getenv (pkname, old_value, SZ_VALUE)) {
+ if (bdebug)
+ printf ("%s = %s\n", pkname, old_value);
+ } else
+ ENVRESET (name, value);
+ }
+
+ fclose (fp);
+}
+#endif
diff --git a/unix/boot/bootlib/index.c b/unix/boot/bootlib/index.c
new file mode 100644
index 00000000..e3387060
--- /dev/null
+++ b/unix/boot/bootlib/index.c
@@ -0,0 +1,39 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+
+#ifdef LINUX
+#define NOINDEX
+#endif
+#ifdef MACOSX
+/* The following effectively disables the local version. */
+#define index strindex
+#endif
+
+/* index and rindex are provided by most systems and are redundantly defined
+ * here only in case they are missing (we probably should be using the more
+ * modern strchr etc. but that is another thing). Linux (slackware at least)
+ * defines these in the same libc.a object module as strchr etc. (this is a
+ * bug), which causes a library conflict. Hence on Linux systems we omit
+ * these functions.
+ */
+#ifndef NOINDEX
+
+/* INDEX -- Return pointer to the first occurrence of a character in a string,
+ * or null if the char is not found.
+ */
+char *
+index ( char *str, int ch)
+{
+ register char *ip;
+ register int cch;
+
+ for (ip=str; (cch = *ip); ip++)
+ if (cch == ch)
+ return (ip);
+
+ return (NULL);
+}
+
+#endif
diff --git a/unix/boot/bootlib/kproto32.h b/unix/boot/bootlib/kproto32.h
new file mode 100644
index 00000000..e407cff5
--- /dev/null
+++ b/unix/boot/bootlib/kproto32.h
@@ -0,0 +1,80 @@
+/* _bytmov.c */
+extern void bytmov_(short *a, int *aoff, short *b, int *boff, int *nbytes);
+/* envinit.c */
+extern void loadpkgenv(char *pkg);
+extern void _envinit(void);
+extern void loadenv(char *osfn);
+/* index.c */
+/* osaccess.c */
+extern int os_access(char *fname, int mode, int type);
+/* osamovb.c */
+extern void os_amovb(char *a, char *b, int nbytes);
+/* oschdir.c */
+extern int os_chdir(char *dir);
+/* osclose.c */
+extern void os_close(int fd);
+/* oscmd.c */
+extern int os_cmd(char *cmd);
+/* oscreatedir.c */
+extern int os_createdir(char *dirname, int mode);
+/* oscrfile.c */
+extern int os_createfile(char *fname, int mode, int type);
+/* osdelete.c */
+extern int os_delete(char *fname);
+/* osdir.c */
+extern int os_diropen(char *dirname);
+extern int os_dirclose(int chan);
+extern int os_gfdir(int chan, char *fname, int maxch);
+/* osfcopy.c */
+extern int os_fcopy(char *oldfile, char *newfile);
+/* osfdate.c */
+extern long os_fdate(char *fname);
+/* osfiletype.c */
+extern int os_filetype(char *fname);
+/* osfn2vfn.c */
+extern char *osfn2vfn(char *osfn);
+/* osfpathname.c */
+extern int os_fpathname(char *vfn, char *osfn, int maxch);
+/* osgetenv.c */
+extern char *os_getenv(char *envvar);
+extern char *_os_getenv(char *envvar, char *outstr, int maxch);
+/* osgetowner.c */
+extern void os_getowner(char *fname, int *uid, int *gid);
+/* osopen.c */
+extern int os_open(char *vfn, int mode, int type);
+/* osputenv.c */
+extern void os_putenv(char *name, char *value);
+/* osread.c */
+extern int os_read(int fd, char *buf, int nbytes);
+/* ossetfmode.c */
+extern int os_setfmode(char *fname, int mode);
+/* ossetowner.c */
+extern int os_setowner(char *fname, int uid, int gid);
+/* ossettime.c */
+extern int os_setmtime(char *fname, long mtime);
+/* osstrpak.c */
+extern char *os_strpak(short *sppstr, char *cstr, int maxch);
+/* osstrupk.c */
+extern short *os_strupk(char *str, short *outstr, int maxch);
+/* ossubdir.c */
+extern char *os_subdir(char *dir, char *subdir);
+/* ossymlink.c */
+extern int os_symlink(char *fname, char *valbuf, int maxch);
+/* ossysfile.c */
+extern int os_sysfile(char *sysfile, char *fname, int maxch);
+/* ostime.c */
+extern long os_utime(long iraf_time);
+extern long os_itime(long unix_time);
+/* oswrite.c */
+extern int os_write(int fd, char *buf, int nbytes);
+/* rindex.c */
+/* tape.c */
+extern int tape_open(char *fname, int mode);
+extern int tape_close(int fd);
+extern int tape_read(int fd, char *buf, int maxbytes);
+extern int tape_write(int fd, char *buf, int nbytes);
+/* vfn2osfn.c */
+extern char *vfn2osfn(char *vfn, int new);
+extern int kigets_(void);
+extern void kisend_(void);
+extern void kirece_(void);
diff --git a/unix/boot/bootlib/kproto64.h b/unix/boot/bootlib/kproto64.h
new file mode 100644
index 00000000..5335919c
--- /dev/null
+++ b/unix/boot/bootlib/kproto64.h
@@ -0,0 +1,80 @@
+/* _bytmov.c */
+extern void bytmov_(short *a, long *aoff, short *b, long *boff, long *nbytes);
+/* envinit.c */
+extern void loadpkgenv(char *pkg);
+extern void _envinit(void);
+extern void loadenv(char *osfn);
+/* index.c */
+/* osaccess.c */
+extern int os_access(char *fname, int mode, int type);
+/* osamovb.c */
+extern void os_amovb(char *a, char *b, int nbytes);
+/* oschdir.c */
+extern int os_chdir(char *dir);
+/* osclose.c */
+extern void os_close(int fd);
+/* oscmd.c */
+extern int os_cmd(char *cmd);
+/* oscreatedir.c */
+extern int os_createdir(char *dirname, int mode);
+/* oscrfile.c */
+extern int os_createfile(char *fname, int mode, int type);
+/* osdelete.c */
+extern int os_delete(char *fname);
+/* osdir.c */
+extern int os_diropen(char *dirname);
+extern int os_dirclose(int chan);
+extern int os_gfdir(int chan, char *fname, int maxch);
+/* osfcopy.c */
+extern int os_fcopy(char *oldfile, char *newfile);
+/* osfdate.c */
+extern long os_fdate(char *fname);
+/* osfiletype.c */
+extern int os_filetype(char *fname);
+/* osfn2vfn.c */
+extern char *osfn2vfn(char *osfn);
+/* osfpathname.c */
+extern int os_fpathname(char *vfn, char *osfn, int maxch);
+/* osgetenv.c */
+extern char *os_getenv(char *envvar);
+extern char *_os_getenv(char *envvar, char *outstr, int maxch);
+/* osgetowner.c */
+extern void os_getowner(char *fname, int *uid, int *gid);
+/* osopen.c */
+extern int os_open(char *vfn, int mode, int type);
+/* osputenv.c */
+extern void os_putenv(char *name, char *value);
+/* osread.c */
+extern int os_read(int fd, char *buf, int nbytes);
+/* ossetfmode.c */
+extern int os_setfmode(char *fname, int mode);
+/* ossetowner.c */
+extern int os_setowner(char *fname, int uid, int gid);
+/* ossettime.c */
+extern int os_setmtime(char *fname, long mtime);
+/* osstrpak.c */
+extern char *os_strpak(short *sppstr, char *cstr, int maxch);
+/* osstrupk.c */
+extern short *os_strupk(char *str, short *outstr, int maxch);
+/* ossubdir.c */
+extern char *os_subdir(char *dir, char *subdir);
+/* ossymlink.c */
+extern int os_symlink(char *fname, char *valbuf, int maxch);
+/* ossysfile.c */
+extern int os_sysfile(char *sysfile, char *fname, int maxch);
+/* ostime.c */
+extern long os_utime(long iraf_time);
+extern long os_itime(long unix_time);
+/* oswrite.c */
+extern int os_write(int fd, char *buf, int nbytes);
+/* rindex.c */
+/* tape.c */
+extern int tape_open(char *fname, int mode);
+extern int tape_close(int fd);
+extern int tape_read(int fd, char *buf, int maxbytes);
+extern int tape_write(int fd, char *buf, int nbytes);
+/* vfn2osfn.c */
+extern char *vfn2osfn(char *vfn, int new);
+extern int kigets_(void);
+extern void kisend_(void);
+extern void kirece_(void);
diff --git a/unix/boot/bootlib/mkpkg b/unix/boot/bootlib/mkpkg
new file mode 100644
index 00000000..5b4f9ba1
--- /dev/null
+++ b/unix/boot/bootlib/mkpkg
@@ -0,0 +1,49 @@
+# Update the BOOTLIB library. The Makefile is used to bootstrap the library,
+# but once MKPKG is up it is easier to maintain the library with MKPKG.
+
+$checkout libboot.a hlib$
+$update libboot.a
+$checkin libboot.a hlib$
+$exit
+
+libboot.a:
+ $set XFLAGS = "-c $(HSI_XF)"
+ $iffile (as$bytmov.s) as$bytmov.s $else _bytmov.c $endif
+ osamovb.c
+
+ index.c
+ rindex.c
+ envinit.c
+
+ osaccess.c bootlib.h
+ oschdir.c bootlib.h
+ osclose.c bootlib.h
+ oscmd.c bootlib.h
+ oscreatedir.c bootlib.h
+ oscrfile.c bootlib.h
+ osdelete.c bootlib.h
+ osdir.c bootlib.h
+ osfcopy.c bootlib.h
+ osfdate.c bootlib.h
+ osfiletype.c
+ osfpathname.c bootlib.h
+ osgetenv.c bootlib.h
+ osgetowner.c bootlib.h
+ osopen.c
+ osputenv.c bootlib.h
+ osread.c
+ ossetfmode.c bootlib.h
+ ossetowner.c bootlib.h
+ ossettime.c bootlib.h
+ osstrpak.c
+ osstrupk.c
+ ossymlink.c
+ ossubdir.c bootlib.h
+ ossysfile.c bootlib.h
+ ostime.c
+ oswrite.c bootlib.h
+
+ vfn2osfn.c bootlib.h
+ osfn2vfn.c bootlib.h
+ tape.c
+ ;
diff --git a/unix/boot/bootlib/mkpkg.sh b/unix/boot/bootlib/mkpkg.sh
new file mode 100644
index 00000000..6f37c67e
--- /dev/null
+++ b/unix/boot/bootlib/mkpkg.sh
@@ -0,0 +1,16 @@
+# Make the bootstrap utilities library (bootlib).
+
+if test -f ../../as/bytmov.s; then\
+ $CC -c $HSI_CF ../../as/bytmov.s -o bytmov.o;\
+else\
+ $CC -c $HSI_CF _bytmov.c;\
+fi
+
+# $CC -c $HSI_CF [a-z]*.c
+for i in [a-z]*.c ;\
+do $CC -c $HSI_CF $i ;\
+done
+
+ar rv libboot.a *.o; rm *.o
+$RANLIB libboot.a
+mv -f libboot.a ../../bin
diff --git a/unix/boot/bootlib/osaccess.c b/unix/boot/bootlib/osaccess.c
new file mode 100644
index 00000000..0c6861e7
--- /dev/null
+++ b/unix/boot/bootlib/osaccess.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <string.h>
+#include "bootlib.h"
+
+/* OS_ACCESS -- Determine if file is accessible with the given access mode
+ * and type. Returns YES (1) or NO (0).
+ */
+int
+os_access (
+ char *fname,
+ int mode,
+ int type
+)
+{
+ PKCHAR osfn[SZ_PATHNAME+1];
+ XINT status, xmode=mode, xtype=type;
+
+ extern int ZFACSS();
+
+
+ strcpy ((char *)osfn, vfn2osfn(fname,0));
+ ZFACSS (osfn, &xmode, &xtype, &status);
+
+ return (status);
+}
diff --git a/unix/boot/bootlib/osamovb.c b/unix/boot/bootlib/osamovb.c
new file mode 100644
index 00000000..71b1d2d0
--- /dev/null
+++ b/unix/boot/bootlib/osamovb.c
@@ -0,0 +1,34 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#define import_spp
+#define import_knames
+#include <iraf.h>
+
+
+/* OS_AMOVB -- Memory to memory copy using BYTMOV.
+ */
+void
+os_amovb (
+ char *a,
+ char *b,
+ int nbytes
+)
+{
+ XCHAR *a_wp, *b_wp;
+ XINT a_off, b_off;
+
+ extern void BYTMOV();
+
+
+ a_wp = (XCHAR *)a;
+ b_wp = (XCHAR *)b;
+
+ /* The following offsets can be something other than one if the
+ * buffers are not word aligned.
+ */
+ a_off = a - (char *)a_wp + 1;
+ b_off = b - (char *)b_wp + 1;
+
+ BYTMOV (a_wp, &a_off, b_wp, &b_off, &nbytes);
+}
diff --git a/unix/boot/bootlib/oschdir.c b/unix/boot/bootlib/oschdir.c
new file mode 100644
index 00000000..497f1576
--- /dev/null
+++ b/unix/boot/bootlib/oschdir.c
@@ -0,0 +1,43 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "bootlib.h"
+
+
+extern int os_fpathname (char *vfn, char *osfn, int maxch);
+
+
+
+/* OS_CHDIR -- Change the current default directory. Note that the kernel
+ * procedure ZFCHDR should only be called with the full pathname of a
+ * directory.
+ */
+int
+os_chdir (char *dir)
+{
+ XCHAR dpath[SZ_PATHNAME+1];
+ XCHAR osdir[SZ_PATHNAME+1];
+ XINT sz_dpath, sz_osdir, status, x_maxch=SZ_PATHNAME;
+
+ extern int ZFXDIR(), ZFGCWD(), ZFSUBD(), ZFCHDR();
+
+
+ sz_dpath = os_fpathname (dir, (char *)dpath, SZ_PATHNAME);
+ os_strupk ((char *)dpath, osdir, SZ_PATHNAME);
+ ZFXDIR (osdir, osdir, &x_maxch, &sz_osdir);
+
+ if (sz_osdir <= 0) {
+ /* Dir is a subdirectory, not a full pathname. Note that this
+ * only works for an immediate subdirectory, and does not work
+ * for paths relative to the cwd.
+ */
+ ZFGCWD (osdir, &x_maxch, &sz_osdir);
+ os_strupk ((char *)osdir, osdir, SZ_PATHNAME);
+ os_strupk (dir, dpath, SZ_PATHNAME);
+ ZFSUBD (osdir, &x_maxch, dpath, &sz_osdir);
+ os_strpak (osdir, (char *)dpath, SZ_PATHNAME);
+ }
+
+ ZFCHDR (dpath, &status);
+ return (status);
+}
diff --git a/unix/boot/bootlib/osclose.c b/unix/boot/bootlib/osclose.c
new file mode 100644
index 00000000..f9be512c
--- /dev/null
+++ b/unix/boot/bootlib/osclose.c
@@ -0,0 +1,29 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <unistd.h> /* for close() */
+#include "bootlib.h"
+
+
+/* OS_CLOSE -- Close a file created (opened) by OSCREATE. If writing to a
+ * text file flush any incomplete (non newline terminated) output line.
+ */
+void
+os_close (int fd)
+{
+ XINT junk, xfd=fd;
+ XINT nchars;
+
+ extern int ZPUTTX(), ZCLSTX();
+
+
+ if (osfiletype == BINARY_FILE)
+ close (fd);
+ else {
+ if (txop > text) {
+ nchars = txop - text;
+ ZPUTTX (&xfd, text, &nchars, &junk);
+ }
+ ZCLSTX (&xfd, &junk);
+ }
+}
diff --git a/unix/boot/bootlib/oscmd.c b/unix/boot/bootlib/oscmd.c
new file mode 100644
index 00000000..0f9c9755
--- /dev/null
+++ b/unix/boot/bootlib/oscmd.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <string.h>
+#include "bootlib.h"
+
+#define SZ_CMD 2048
+
+/* OS_CMD -- Send a command to the host system.
+ */
+int
+os_cmd (char *cmd)
+{
+ PKCHAR x_cmd[SZ_CMD+1];
+ PKCHAR nullstr[1];
+ XINT status;
+ extern int ZOSCMD();
+
+
+ strncpy ((char *)x_cmd, cmd, SZ_CMD);
+ nullstr[0] = 0;
+
+ /* Terminate the parent process if the OS command is interrupted.
+ */
+ ZOSCMD (x_cmd, nullstr, nullstr, nullstr, &status);
+ return (status);
+}
diff --git a/unix/boot/bootlib/oscreatedir.c b/unix/boot/bootlib/oscreatedir.c
new file mode 100644
index 00000000..517d0eed
--- /dev/null
+++ b/unix/boot/bootlib/oscreatedir.c
@@ -0,0 +1,18 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <sys/stat.h> /* for mkdir() */
+#include "bootlib.h"
+
+/* OS_CREATEDIR -- Create a new subdirectory.
+ */
+int
+os_createdir (
+ char *dirname,
+ int mode
+)
+{
+ if (bdebug)
+ fprintf (stderr, "createdir '%s'\n", dirname);
+ return (mkdir (vfn2osfn(dirname,1), mode));
+}
diff --git a/unix/boot/bootlib/oscrfile.c b/unix/boot/bootlib/oscrfile.c
new file mode 100644
index 00000000..28eec304
--- /dev/null
+++ b/unix/boot/bootlib/oscrfile.c
@@ -0,0 +1,36 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <fcntl.h>
+#include "bootlib.h"
+
+
+/* OS_CREATEFILE -- Open a new file for writing. Create the file with the
+ * given mode bits.
+ */
+int
+os_createfile (
+ char *fname,
+ int mode,
+ int type
+)
+{
+ static XINT xmode = NEW_FILE;
+ PKCHAR *osfn = (PKCHAR *) vfn2osfn (fname, 1);
+ XINT chan;
+ extern int ZOPNTX();
+
+
+ if (bdebug)
+ fprintf (stderr, "create %s file `%s' -> `%s'\n",
+ type == TEXT_FILE ? "text" : "binary", fname, (char *)osfn);
+ osfiletype = type;
+
+ if (type == BINARY_FILE)
+ return (creat ((char *)osfn, mode));
+ else {
+ ZOPNTX (osfn, &xmode, &chan);
+ txop = text;
+ return (chan == XERR ? ERR : chan);
+ }
+}
diff --git a/unix/boot/bootlib/osdelete.c b/unix/boot/bootlib/osdelete.c
new file mode 100644
index 00000000..a56a72e6
--- /dev/null
+++ b/unix/boot/bootlib/osdelete.c
@@ -0,0 +1,19 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "bootlib.h"
+
+
+/* OS_DELETE -- Delete a file.
+ */
+int
+os_delete (char *fname)
+{
+ XINT status;
+
+ extern int ZFDELE();
+
+
+ ZFDELE ((PKCHAR *)vfn2osfn (fname, 0), &status);
+ return (status);
+}
diff --git a/unix/boot/bootlib/osdir.c b/unix/boot/bootlib/osdir.c
new file mode 100644
index 00000000..d3807302
--- /dev/null
+++ b/unix/boot/bootlib/osdir.c
@@ -0,0 +1,93 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <string.h>
+#include "bootlib.h"
+
+
+/*
+ * OS_DIR -- A package for accessing a directory as a list of files.
+ */
+
+#ifndef NOVOS
+
+/* OS_DIROPEN -- Open the directory.
+ */
+int
+os_diropen (char *dirname)
+{
+ PKCHAR osfn[SZ_PATHNAME+1];
+ XINT chan;
+
+ extern int ZOPDIR();
+
+
+ strcpy ((char *)osfn, dirname);
+ ZOPDIR (osfn, &chan);
+
+ return (chan);
+}
+
+
+/* OS_DIRCLOSE -- Close the directory.
+ */
+int
+os_dirclose (int chan)
+{
+ XINT x_chan=chan, status;
+
+ extern int ZCLDIR();
+
+
+ ZCLDIR (&x_chan, &status);
+ return (status);
+}
+
+
+/* OS_GFDIR -- Get the next filename from the directory.
+ */
+int
+os_gfdir (
+ int chan,
+ char *fname,
+ int maxch
+)
+{
+ PKCHAR osfn[SZ_PATHNAME+1];
+ XINT x_chan=chan, x_maxch=maxch, status;
+
+ extern int ZGFDIR();
+
+ for (;;) {
+ ZGFDIR (&x_chan, osfn, &x_maxch, &status);
+ if (status > 0) {
+ /* Omit the self referential directory files "." and ".."
+ * or recursion may result.
+ */
+ if (strcmp ((char *)osfn, ".") == 0)
+ continue;
+ if (strcmp ((char *)osfn, "..") == 0)
+ continue;
+
+ strncpy (fname, osfn2vfn ((char *)osfn), maxch);
+ return (status);
+
+ } else {
+ /* End of directory.
+ */
+ *fname = EOS;
+ return (0);
+ }
+ }
+}
+
+#else
+/* NOVOS bootsrap. Just stub these out until we re-boostrap using the
+ * VOS libs, which provide zopdir.
+ */
+
+int os_dirclose (int chan) { return (-1); }
+int os_diropen (char *dirname) { return (-1); }
+int os_gfdir (int chan, char *fname, int maxch) { return (0); }
+
+#endif
diff --git a/unix/boot/bootlib/osfcopy.c b/unix/boot/bootlib/osfcopy.c
new file mode 100644
index 00000000..037d6eff
--- /dev/null
+++ b/unix/boot/bootlib/osfcopy.c
@@ -0,0 +1,84 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "bootlib.h"
+
+extern int os_access (char *fname, int mode, int type);
+
+
+/* OS_FCOPY -- Copy a file. Used by RTAR to resolve links.
+ */
+int
+os_fcopy (
+ char *oldfile,
+ char *newfile
+)
+{
+ XCHAR buf[SZ_FBUF];
+ XINT status, junk, maxch = SZ_FBUF, mode = 0, in, out, n, nw;
+
+ extern int ZOPNTX(), ZGETTX(), ZCLSTX(), ZPUTTX();
+
+
+ if (os_access (oldfile,0,0) == NO)
+ return (ERR);
+
+ if (os_access (oldfile, 0, TEXT_FILE) == YES) {
+ if (bdebug)
+ fprintf (stderr, "copy text file '%s' -> '%s'\n",
+ oldfile, newfile);
+
+ mode = READ_ONLY;
+ ZOPNTX ((PKCHAR *)vfn2osfn(oldfile,0), &mode, &in);
+ if (in == XERR)
+ return (ERR);
+
+ mode = NEW_FILE;
+ ZOPNTX ((PKCHAR *)vfn2osfn(newfile,1), &mode, &out);
+ if (out == XERR) {
+ ZCLSTX (&in, &status);
+ return (ERR);
+ }
+
+ while (ZGETTX (&in, buf, &maxch, &n), n != XEOF) {
+ if (n != XERR)
+ ZPUTTX (&out, buf, &n, &status);
+ if (n == XERR || status == XERR) {
+ ZCLSTX (&in, &junk);
+ ZCLSTX (&out, &junk);
+ return (ERR);
+ }
+ }
+
+ ZCLSTX (&in, &status);
+ ZCLSTX (&out, &status);
+
+ return (status);
+
+ } else {
+ if (bdebug)
+ fprintf (stderr, "copy binary file `%s' -> `%s'\n",
+ oldfile, newfile);
+
+ if ((in = open (vfn2osfn(oldfile,0), 0)) == ERR)
+ return (ERR);
+ if ((out = creat (vfn2osfn(newfile,1), 0644)) == ERR) {
+ close (in);
+ return (ERR);
+ }
+
+ while ((n = read (in, (char *)buf, SZ_FBUF)) > 0)
+ nw = write (out, (char *)buf, n);
+
+ close (in);
+ close (out);
+ if (n < 0)
+ return (ERR);
+ }
+
+ return (ERR);
+}
diff --git a/unix/boot/bootlib/osfdate.c b/unix/boot/bootlib/osfdate.c
new file mode 100644
index 00000000..900b2a9d
--- /dev/null
+++ b/unix/boot/bootlib/osfdate.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "bootlib.h"
+
+
+/* FDATE -- Get the date of last modification of a file. [MACHDEP]
+ */
+long
+os_fdate (char *fname)
+{
+ struct stat buf;
+
+ if (stat (vfn2osfn(fname,0), &buf) == ERR)
+ return (0);
+ else
+ return (buf.st_mtime);
+}
diff --git a/unix/boot/bootlib/osfiletype.c b/unix/boot/bootlib/osfiletype.c
new file mode 100644
index 00000000..d211cc99
--- /dev/null
+++ b/unix/boot/bootlib/osfiletype.c
@@ -0,0 +1,116 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#define import_spp
+#include <iraf.h>
+
+/*
+ * OS_FILETYPE -- Determine whether the named file is a text file, a binary
+ * file, or a directory. The filename extensions used to speed up the test
+ * are portable provided osfn2vfn() is called to map the OSFN before we are
+ * called.
+ */
+
+char *binextn[] = { /* Known binary file extensions */
+ ".o",
+ ".e",
+ ".a",
+ ".so",
+ ".pyc",
+ NULL
+};
+
+char *srcextn[] = { /* Known source file extensions */
+ ".x",
+ ".h",
+ ".f",
+ ".f77",
+ ".f90",
+ ".s",
+ ".c",
+ ".cpp",
+ ".hlp",
+ ".mip",
+ ".imh",
+ ".pix",
+ ".gki",
+ ".vdm",
+ ".fits",
+ ".fit",
+ ".ftz",
+ ".pl",
+ ".gif",
+ ".jpeg",
+ ".jpg",
+ ".tiff",
+ ".tif",
+ ".png",
+ ".gz",
+ ".tar",
+ ".jar",
+ ".java",
+ ".py",
+ ".pdf",
+ ".ps",
+ ".hqx",
+ ".std",
+ NULL
+};
+
+extern int os_access (char *fname, int mode, int type);
+
+
+
+/* OS_FILETYPE -- Determine the type of a file. If the file has one of the
+ * known source file extensions we assume it is a text file; if it has a well
+ * known binary file extension we assume it is a binary file; otherwise we call
+ * os_access to determine the file type.
+ */
+int
+os_filetype (
+ char *fname /* name of file to be examined */
+)
+{
+ register char *ip, *ep;
+ register int ch, i;
+ char *extn;
+
+
+ /* Get filename extension.
+ */
+ extn = NULL;
+ for (ip=fname; (ch = *ip); ip++)
+ if (ch == '.')
+ extn = ip;
+
+ /* If the filename has a extension, check the list of known text and
+ * binary file extensions to see if we can make a quick determination
+ * of the file type.
+ */
+ if (extn) {
+ ch = *(extn + 1);
+
+ /* Known source file extension? */
+ for (i=0; (ep = srcextn[i]); i++)
+ if (*(ep+1) == ch)
+ if (strcasecmp (ep, extn) == 0)
+ return (TEXT_FILE);
+
+ /* Known binary file extension? */
+ for (i=0; (ep = binextn[i]); i++)
+ if (*(ep+1) == ch)
+ if (strcasecmp (ep, extn) == 0)
+ return (BINARY_FILE);
+ }
+
+ /* Call ACCESS to determine the file type.
+ */
+ if (os_access (fname, READ_ONLY, DIRECTORY_FILE) == YES)
+ return (DIRECTORY_FILE);
+ else if (os_access (fname, 0, TEXT_FILE) == YES)
+ return (TEXT_FILE);
+ else
+ return (BINARY_FILE);
+}
diff --git a/unix/boot/bootlib/osfn2vfn.c b/unix/boot/bootlib/osfn2vfn.c
new file mode 100644
index 00000000..c16ccf03
--- /dev/null
+++ b/unix/boot/bootlib/osfn2vfn.c
@@ -0,0 +1,81 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#define NOLIBCNAMES
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_knames
+#include <iraf.h>
+#include "bootlib.h"
+
+
+static char vfn[SZ_PATHNAME+1];
+
+#ifdef NOVOS
+
+/* OSFN2VFN -- Convert a local-directory OS filename into a virtual filename.
+ * On UNIX this is a no-op since escape sequence encoding is not needed and
+ * the IRAF file extensions are the same as UNIX.
+ */
+char *
+osfn2vfn (
+ char *osfn /* input OS filename */
+)
+{
+ strcpy (vfn, osfn); /* [MACHDEP */
+ return (vfn);
+}
+
+#else
+
+/* OSFN2VFN -- Convert a local-directory OS filename into a virtual filename.
+ * Undo the escape sequence encoding and map the OS filename extension into
+ * the IRAF one. No attempt is made to map OS directory names into IRAF
+ * logical directory names; this is a local directory operation only.
+ */
+char *osfn2vfn (osfn)
+char *osfn; /* input OS filename */
+{
+ XCHAR x_osfn[SZ_PATHNAME+1];
+ XCHAR x_vfn[SZ_PATHNAME+1];
+ XINT x_maxch = SZ_PATHNAME;
+ XINT x_mode, vp, nchars;
+
+ extern void _envinit();
+
+
+ _envinit();
+
+ os_strupk ("./", x_vfn, SZ_PATHNAME);
+ x_mode = VFN_UNMAP;
+ iferr (vp = VFNOPEN (x_vfn, (integer *)&x_mode)) {
+ vp = 0;
+ goto err_;
+ }
+
+ strcpy ((char *)x_osfn, osfn);
+ iferr (nchars = VFNUNMAP ((integer *)&vp, x_osfn, x_vfn,
+ (integer *)&x_maxch))
+ goto err_;
+ if (nchars < 0)
+ goto err_;
+
+ x_mode = VFN_NOUPDATE;
+ VFNCLOSE ((integer *)&vp, (integer *)&x_mode);
+
+ os_strpak (x_vfn, vfn, SZ_PATHNAME);
+ return (vfn);
+
+err_:
+ fprintf (stderr, "cannot unmap filename `%s'\n", osfn);
+ if (vp > 0)
+ VFNCLOSE ((integer *)&vp, (integer *)&x_mode);
+
+ strcpy (vfn, osfn);
+ return (vfn);
+}
+
+#endif
diff --git a/unix/boot/bootlib/osfpathname.c b/unix/boot/bootlib/osfpathname.c
new file mode 100644
index 00000000..17fdba61
--- /dev/null
+++ b/unix/boot/bootlib/osfpathname.c
@@ -0,0 +1,41 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "bootlib.h"
+
+
+/* OS_FPATHNAME -- Map a VFN (virtual filename) into a pathname (filename
+ * specification which is independent of the current directory).
+ */
+int
+os_fpathname (
+ char *vfn, /* virtual filename */
+ char *osfn, /* OS filename */
+ int maxch
+)
+{
+ XCHAR x_vfn[SZ_PATHNAME+1];
+ XCHAR x_osfn[SZ_PATHNAME+1];
+ XINT x_maxch = SZ_PATHNAME, x_nchars;
+
+ extern int ZFGCWD(), ZFSUBD(), ZFPATH();
+
+
+ if (vfn[0])
+ os_strupk (vfn2osfn(vfn,0), x_vfn, x_maxch);
+ else
+ x_vfn[0] = 0;
+
+ if (vfn[0] == '.' && (vfn[1] == EOS || vfn[2] == EOS)) {
+ ZFGCWD (x_osfn, &x_maxch, &x_nchars);
+ os_strupk ((char *)x_osfn, x_osfn, x_maxch);
+ if (vfn[1] == '.') {
+ os_strupk (vfn, x_vfn, x_maxch);
+ ZFSUBD (x_osfn, &x_maxch, x_vfn, &x_nchars);
+ }
+ } else
+ ZFPATH (x_vfn, x_osfn, &x_maxch, &x_nchars);
+
+ os_strpak (x_osfn, osfn, maxch);
+ return (x_nchars);
+}
diff --git a/unix/boot/bootlib/osgetenv.c b/unix/boot/bootlib/osgetenv.c
new file mode 100644
index 00000000..3ccfb403
--- /dev/null
+++ b/unix/boot/bootlib/osgetenv.c
@@ -0,0 +1,127 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <string.h>
+#define import_xnames
+#include "bootlib.h"
+
+
+char *_os_getenv();
+
+
+/* OS_GETENV -- Return the value of the named environment variable. Null is
+ * returned if the named variable is not found.
+ */
+char *
+os_getenv (char *envvar)
+{
+ static char irafdir[SZ_PATHNAME+1] = "";
+ static char hostdir[SZ_PATHNAME+1] = "";
+ static char valstr[SZ_COMMAND+1];
+ static char errmsg[] = "environment variable `%s' not found\n";
+ extern char *os_subdir();
+ char *vp;
+
+
+ /* Try the standard environment first. */
+ memset (valstr, 0, SZ_COMMAND+1);
+ if ( (vp = _os_getenv (envvar, valstr, SZ_COMMAND)) )
+ return (vp);
+
+ /* The following maps certain well-known IRAF logical directories
+ * even if there is no regular (VOS) environment facility.
+ */
+ if (irafdir[0] == EOS)
+ if (_os_getenv ("iraf", irafdir, SZ_PATHNAME) == NULL) {
+ fprintf (stderr, errmsg, "iraf");
+ return (NULL);
+ }
+ if (hostdir[0] == EOS)
+ if (_os_getenv ("host", hostdir, SZ_PATHNAME) == NULL) {
+ fprintf (stderr, errmsg, "host");
+ return (NULL);
+ }
+
+ /* Map the names of the well known IRAF logical directories which
+ * are defined portably in terms of iraf$ or host$.
+ */
+ if ( strcmp (envvar, "lib") == 0) /* iraf/. */
+ strcpy (valstr, os_subdir (irafdir, "lib"));
+ else if (strcmp (envvar, "bin") == 0)
+ strcpy (valstr, os_subdir (irafdir, "bin"));
+ else if (strcmp (envvar, "dev") == 0)
+ strcpy (valstr, os_subdir (irafdir, "dev"));
+ else if (strcmp (envvar, "pkg") == 0)
+ strcpy (valstr, os_subdir (irafdir, "pkg"));
+ else if (strcmp (envvar, "sys") == 0)
+ strcpy (valstr, os_subdir (irafdir, "sys"));
+ else if (strcmp (envvar, "math") == 0)
+ strcpy (valstr, os_subdir (irafdir, "math"));
+ else if (strcmp (envvar, "hlib") == 0) /* host/. */
+ strcpy (valstr, os_subdir (hostdir, "hlib"));
+ else if (strcmp (envvar, "as") == 0)
+ strcpy (valstr, os_subdir (hostdir, "as"));
+ else
+ return (NULL);
+
+ return (valstr);
+}
+
+
+#ifdef NOVOS
+/* _OS_GETENV -- Fetch the value of the named environment variable from the
+ * host environment.
+ */
+char *
+_os_getenv (
+ char *envvar, /* name of environment variable */
+ char *outstr, /* receives value */
+ int maxch
+)
+{
+ PKCHAR symbol[SZ_FNAME+1];
+ PKCHAR value[SZ_COMMAND+1];
+ XINT x_maxch = SZ_COMMAND, status=1;
+
+ strcpy ((char *)symbol, envvar);
+ ZGTENV (symbol, value, &x_maxch, &status);
+
+ if (status < 0) {
+ outstr[0] = EOS;
+ return (NULL);
+ } else {
+ strncpy (outstr, (char *)value, maxch);
+ outstr[maxch] = EOS;
+ return (outstr);
+ }
+}
+
+#else
+/* _OS_GETENV -- Fetch the value of the named environment variable from the
+ * host environment.
+ */
+char *
+_os_getenv (
+ char *envvar, /* name of environment variable */
+ char *outstr, /* receives value */
+ int maxch
+)
+{
+ XCHAR x_symbol[SZ_FNAME+1];
+ XCHAR x_value[SZ_COMMAND+1];
+ XINT x_maxch = SZ_COMMAND, status=1;
+ extern XINT ENVFIND();
+
+
+ os_strupk (envvar, x_symbol, SZ_FNAME);
+ status = ENVFIND (x_symbol, x_value, &x_maxch);
+
+ if (status <= 0) {
+ outstr[0] = EOS;
+ return (NULL);
+ } else {
+ os_strpak (x_value, outstr, maxch);
+ return (outstr);
+ }
+}
+#endif
diff --git a/unix/boot/bootlib/osgetowner.c b/unix/boot/bootlib/osgetowner.c
new file mode 100644
index 00000000..489997c1
--- /dev/null
+++ b/unix/boot/bootlib/osgetowner.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "bootlib.h"
+
+
+/* OS_GETOWNER -- Get the user and group identifications for a file. This is
+ * not a required function and is expected to rarely work when transporting
+ * files to a host at a different site. Nonetheless it is useful when moving
+ * files between compatible hosts at a single site, so we make use of it in
+ * case it works. It is sufficient to merely set uid and gid to 0 and return.
+ */
+void
+os_getowner (
+ char *fname,
+ int *uid,
+ int *gid
+)
+{
+ struct stat fi;
+
+ if (stat (vfn2osfn(fname,0), &fi) != -1) {
+ *uid = fi.st_uid;
+ *gid = fi.st_gid;
+ }
+}
diff --git a/unix/boot/bootlib/osopen.c b/unix/boot/bootlib/osopen.c
new file mode 100644
index 00000000..42b3cdeb
--- /dev/null
+++ b/unix/boot/bootlib/osopen.c
@@ -0,0 +1,29 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <fcntl.h>
+#include "bootlib.h"
+
+extern int os_createfile (char *fname, int mode, int type);
+
+
+/* OS_OPEN -- Open or create a host system file for reading or writing (text
+ * and binary disk files only).
+ */
+int
+os_open (
+ char *vfn, /* file to be opened */
+ int mode, /* access mode 0=R, 1=W, 2=RW */
+ int type /* file type */
+)
+{
+ extern char *vfn2osfn();
+
+ if (mode == 0) {
+ osfiletype = BINARY_FILE;
+ return (open (vfn2osfn (vfn, 0), 0));
+ } else if (mode == 1) {
+ return (os_createfile (vfn, mode, type));
+ } else
+ return (-1);
+}
diff --git a/unix/boot/bootlib/osproto.h b/unix/boot/bootlib/osproto.h
new file mode 100644
index 00000000..0be822d7
--- /dev/null
+++ b/unix/boot/bootlib/osproto.h
@@ -0,0 +1,136 @@
+extern int zdvall_(short *aliases, int *allflg, int *status);
+extern int zdvown_(short *device, short *owner, int *maxch, int *status);
+extern int zawset_(int *best_size, int *new_size, int *old_size, int *max_size);
+extern int zcall0_(int *proc);
+extern int zcall1_(int *proc, void *arg1);
+extern int zcall2_(int *proc, void *arg1, void *arg2);
+extern int zcall3_(int *proc, void *arg1, void *arg2, void *arg3);
+extern int zcall4_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4);
+extern int zcall5_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5);
+extern int zcall6_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6);
+extern int zcall7_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7);
+extern int zcall8_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8);
+extern int zcall9_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, void *arg9);
+extern int zcalla_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, void *arg9, void *arg10);
+extern void zdojmp_(int *jmpbuf, int *status);
+extern int zfacss_(short *fname, int *mode, int *type, int *status);
+extern int zfaloc_(short *fname, int *nbytes, int *status);
+extern int zfchdr_(short *newdir, int *status);
+extern int zfdele_(short *fname, int *status);
+extern int zfgcwd_(short *outstr, int *maxch, int *status);
+extern int zfinfo_(short *fname, int *finfo_struct, int *status);
+extern int zopnbf_(short *osfn, int *mode, int *chan);
+extern int zclsbf_(int *fd, int *status);
+extern int zardbf_(int *chan, short *buf, int *maxbytes, int *offset);
+extern int zawrbf_(int *chan, short *buf, int *nbytes, int *offset);
+extern int zawtbf_(int *fd, int *status);
+extern int zsttbf_(int *fd, int *param, int *lvalue);
+extern int zopnks_(short *x_server, int *mode, int *chan);
+extern int zclsks_(int *chan, int *status);
+extern int zardks_(int *chan, short *buf, int *totbytes, int *loffset);
+extern int zawrks_(int *chan, short *buf, int *totbytes, int *loffset);
+extern int zawtks_(int *chan, int *status);
+extern int zsttks_(int *chan, int *param, int *lvalue);
+extern int zopnlp_(short *printer, int *mode, int *chan);
+extern int zclslp_(int *chan, int *status);
+extern int zardlp_(int *chan, short *buf, int *maxbytes, int *offset);
+extern int zawrlp_(int *chan, short *buf, int *nbytes, int *offset);
+extern int zawtlp_(int *chan, int *status);
+extern int zsttlp_(int *chan, int *param, int *lvalue);
+extern int zzopmt_(short *device, int *acmode, short *devcap, int *devpos, int *newfile, int *chan);
+extern int zzclmt_(int *chan, int *devpos, int *o_status);
+extern int zzrdmt_(int *chan, short *buf, int *maxbytes, int *offset);
+extern int zzwrmt_(int *chan, short *buf, int *nbytes, int *offset);
+extern int zzwtmt_(int *chan, int *devpos, int *o_status);
+extern int zzstmt_(int *chan, int *param, int *lvalue);
+extern int zzrwmt_(short *device, short *devcap, int *o_status);
+extern int zopnnd_(short *pk_osfn, int *mode, int *chan);
+extern int zclsnd_(int *fd, int *status);
+extern int zardnd_(int *chan, short *buf, int *maxbytes, int *offset);
+extern int zawrnd_(int *chan, short *buf, int *nbytes, int *offset);
+extern int zawtnd_(int *fd, int *status);
+extern int zsttnd_(int *fd, int *param, int *lvalue);
+extern int zopnpl_(short *plotter, int *mode, int *chan);
+extern int zclspl_(int *chan, int *status);
+extern int zardpl_(int *chan, short *buf, int *maxbytes, int *offset);
+extern int zawrpl_(int *chan, short *buf, int *nbytes, int *offset);
+extern int zawtpl_(int *chan, int *status);
+extern int zsttpl_(int *chan, int *param, int *lvalue);
+extern int zopcpr_(short *osfn, int *inchan, int *outchan, int *pid);
+extern int zclcpr_(int *pid, int *exit_status);
+extern int zardpr_(int *chan, short *buf, int *maxbytes, int *loffset);
+extern int zawrpr_(int *chan, short *buf, int *nbytes, int *loffset);
+extern int zawtpr_(int *chan, int *status);
+extern int zsttpr_(int *chan, int *param, int *lvalue);
+extern int zopnsf_(short *osfn, int *mode, int *chan);
+extern int zclssf_(int *fd, int *status);
+extern int zardsf_(int *chan, short *buf, int *maxbytes, int *offset);
+extern int zawrsf_(int *chan, short *buf, int *nbytes, int *offset);
+extern int zawtsf_(int *fd, int *status);
+extern int zsttsf_(int *fd, int *param, int *lvalue);
+extern int zopntx_(short *osfn, int *mode, int *chan);
+extern int zclstx_(int *fd, int *status);
+extern int zflstx_(int *fd, int *status);
+extern int zgettx_(int *fd, short *buf, int *maxchars, int *status);
+extern int znottx_(int *fd, int *offset);
+extern int zputtx_(int *fd, short *buf, int *nchars, int *status);
+extern int zsektx_(int *fd, int *znottx_offset, int *status);
+extern int zstttx_(int *fd, int *param, int *value);
+extern int zopnty_(short *osfn, int *mode, int *chan);
+extern int zclsty_(int *fd, int *status);
+extern int zflsty_(int *fd, int *status);
+extern int zgetty_(int *fd, short *buf, int *maxchars, int *status);
+extern int znotty_(int *fd, int *offset);
+extern int zputty_(int *fd, short *buf, int *nchars, int *status);
+extern int zsekty_(int *fd, int *znotty_offset, int *status);
+extern int zsttty_(int *fd, int *param, int *value);
+extern int zfmkcp_(short *osfn, short *new_osfn, int *status);
+extern int zfmkdr_(short *newdir, int *status);
+extern int zfnbrk_(short *vfn, int *uroot_offset, int *uextn_offset);
+extern int zfpath_(short *osfn, short *pathname, int *maxch, int *nchars);
+extern int zfpoll_(int *pfds, int *nfds, int *timeout, int *npoll, int *status);
+extern int zfprot_(short *fname, int *action, int *status);
+extern int zfrnam_(short *oldname, short *newname, int *status);
+extern int zfrmdr_(short *dir, int *status);
+extern int zfsubd_(short *osdir, int *maxch, short *subdir, int *nchars);
+extern int zfunc0_(int *proc);
+extern int zfunc1_(int *proc, void *arg1);
+extern int zfunc2_(int *proc, void *arg1, void *arg2);
+extern int zfunc3_(int *proc, void *arg1, void *arg2, void *arg3);
+extern int zfunc4_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4);
+extern int zfunc5_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5);
+extern int zfunc6_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6);
+extern int zfunc7_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7);
+extern int zfunc8_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8);
+extern int zfunc9_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, void *arg9);
+extern int zfunca_(int *proc, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8, void *arg9, void *arg10);
+extern int zfutim_(short *fname, int *atime, int *mtime, int *status);
+extern int zfxdir_(short *osfn, short *osdir, int *maxch, int *nchars);
+extern int zgcmdl_(short *cmd, int *maxch, int *status);
+extern int zghost_(short *outstr, int *maxch);
+extern int zgmtco_(int *gmtcor);
+extern int zgtenv_(short *envvar, short *outstr, int *maxch, int *status);
+extern int zgtime_(int *clock_time, int *cpu_time);
+extern int zgtpid_(int *pid);
+extern int zintpr_(int *pid, int *exception, int *status);
+extern int zlocpr_(PFI proc, int *o_epa);
+extern int zlocva_(short *variable, int *location);
+extern int zmaloc_(int *buf, int *nbytes, int *status);
+extern int zmfree_(int *buf, int *status);
+extern int zopdir_(short *fname, int *chan);
+extern int zcldir_(int *chan, int *status);
+extern int zgfdir_(int *chan, short *outstr, int *maxch, int *status);
+extern int zopdpr_(short *osfn, short *bkgfile, short *queue, int *jobcode);
+extern int zcldpr_(int *jobcode, int *killflag, int *exit_status);
+extern int zoscmd_(short *oscmd, short *stdin_file, short *stdout_file, short *stderr_file, int *status);
+extern int zpanic_(int *errcode, short *errmsg);
+extern int zraloc_(int *buf, int *nbytes, int *status);
+extern int zwmsec_(int *msec);
+extern int zxwhen_(int *sig_code, int *epa, int *old_epa);
+extern int zxgmes_(int *os_exception, short *errmsg, int *maxch);
+extern int zzepro_(void);
+extern int zzpstr_(short *s1, short *s2);
+extern int zzlstr_(short *s1, short *s2);
+extern int zzsetk_(char *ospn, char *osbfn, int prtype, int isatty, int in, int out);
+extern int zzstrt_(void);
+extern int zzstop_(void);
diff --git a/unix/boot/bootlib/osputenv.c b/unix/boot/bootlib/osputenv.c
new file mode 100644
index 00000000..40599a85
--- /dev/null
+++ b/unix/boot/bootlib/osputenv.c
@@ -0,0 +1,72 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#define import_xnames
+#include "bootlib.h"
+
+#define SZ_VALUE SZ_COMMAND
+
+#ifdef NOVOS
+/* OS_PUTENV -- Set the value of the named environment variable.
+ */
+void
+os_putenv (
+ char *name,
+ char *value
+)
+{
+ char buf[SZ_VALUE], *env;
+
+ sprintf (buf, "%s=%s", name, value);
+ if ( (env = (char *) malloc (strlen(buf) + 1)) ) {
+ strcpy (env, buf);
+#ifdef ultrix
+ putenv (env); /* must keep env around. */
+#else
+#ifdef vax
+ setenv (name, value, 1);
+#else
+ putenv (env); /* must keep env around. */
+#endif
+#endif
+ }
+}
+
+#else
+/* OS_PUTENV -- Set the value of the named environment variable.
+ */
+void
+os_putenv (
+ char *name,
+ char *value
+)
+{
+ XCHAR x_name[SZ_FNAME+1];
+ XCHAR x_value[SZ_VALUE+1];
+ char buf[SZ_VALUE], *env;
+ extern void ENVRESET();
+
+
+ /* Set the VOS environment. */
+ os_strupk (name, x_name, SZ_FNAME);
+ os_strupk (value, x_value, SZ_VALUE);
+ ENVRESET (x_name, x_value);
+
+ /* Set the HOST environment. */
+ sprintf (buf, "%s=%s", name, value);
+ if ( (env = (char *) malloc (strlen(buf) + 1)) ) {
+ strcpy (env, buf);
+#ifdef ultrix
+ putenv (env);
+#else
+#ifdef vax
+ setenv (name, value, 1);
+#else
+ putenv (env); /* must keep env around. */
+#endif
+#endif
+ }
+}
+#endif
diff --git a/unix/boot/bootlib/osread.c b/unix/boot/bootlib/osread.c
new file mode 100644
index 00000000..b7d731d2
--- /dev/null
+++ b/unix/boot/bootlib/osread.c
@@ -0,0 +1,18 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <unistd.h>
+
+
+/* OS_READ -- Read from a disk file. We can use the UNIX procedures for
+ * reading both binary and text files.
+ */
+int
+os_read (
+ int fd, /* input file */
+ char *buf, /* output buffer */
+ int nbytes /* max bytes to read */
+)
+{
+ return (read (fd, buf, nbytes));
+}
diff --git a/unix/boot/bootlib/ossetfmode.c b/unix/boot/bootlib/ossetfmode.c
new file mode 100644
index 00000000..be2f7c5f
--- /dev/null
+++ b/unix/boot/bootlib/ossetfmode.c
@@ -0,0 +1,18 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <sys/stat.h>
+#include "bootlib.h"
+
+
+/* OS_SETFMODE -- Set the file mode bits. This is an important function on
+ * any system and should be implemented.
+ */
+int
+os_setfmode (
+ char *fname,
+ int mode
+)
+{
+ return (chmod (vfn2osfn(fname,0), mode));
+}
diff --git a/unix/boot/bootlib/ossetowner.c b/unix/boot/bootlib/ossetowner.c
new file mode 100644
index 00000000..e6d78261
--- /dev/null
+++ b/unix/boot/bootlib/ossetowner.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <unistd.h>
+#include "bootlib.h"
+
+/* OS_SETOWNER -- Set the user and group identifications for the file. This is
+ * not a required function and is expected to rarely work when transporting
+ * files to a host at a different site. Nonetheless it is useful when moving
+ * files between compatible hosts at a single site, so we make use of it in
+ * case it works.
+ */
+int
+os_setowner (
+ char *fname,
+ int uid,
+ int gid
+)
+{
+ return (chown (vfn2osfn(fname,0), uid, gid));
+}
diff --git a/unix/boot/bootlib/ossettime.c b/unix/boot/bootlib/ossettime.c
new file mode 100644
index 00000000..4c7d8694
--- /dev/null
+++ b/unix/boot/bootlib/ossettime.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <unistd.h>
+#include "bootlib.h"
+
+
+/* OS_SETMTIME -- Set the modification (update) time of a file. Should only
+ * be called when the named file is closed. This is a desirable but
+ * nonessential function to implement.
+ */
+int
+os_setmtime (
+ char *fname,
+ long mtime
+)
+{
+ struct timeval tvp[2];
+
+ tvp[0].tv_sec = tvp[1].tv_sec = mtime;
+ tvp[0].tv_usec = tvp[1].tv_usec = 0L;
+
+ return (utimes (vfn2osfn(fname,0), tvp));
+}
diff --git a/unix/boot/bootlib/osstrpak.c b/unix/boot/bootlib/osstrpak.c
new file mode 100644
index 00000000..01b6cf1a
--- /dev/null
+++ b/unix/boot/bootlib/osstrpak.c
@@ -0,0 +1,34 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#define import_spp
+#include <iraf.h>
+
+
+/* OS_STRPAK -- Pack an SPP string (type XCHAR) into a C string in a user
+ * supplied buffer. Return a pointer to the output buffer.
+ *
+ * N.B.: This routine should be used in preference to STRPAK in C code
+ * since the output string is of type char*, rather than XCHAR*.
+ */
+char *
+os_strpak (
+ XCHAR *sppstr, /* SPP string */
+ char *cstr, /* C string */
+ int maxch /* max chars out, excl EOS */
+)
+{
+ register XCHAR *ip = sppstr;
+ register char *op = cstr;
+ register int n = maxch;
+
+
+ while ( (*op++ = *ip++) ) {
+ if (--n <= 0) {
+ *op = EOS;
+ break;
+ }
+ }
+
+ return (cstr);
+}
diff --git a/unix/boot/bootlib/osstrupk.c b/unix/boot/bootlib/osstrupk.c
new file mode 100644
index 00000000..e0617089
--- /dev/null
+++ b/unix/boot/bootlib/osstrupk.c
@@ -0,0 +1,44 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+
+#include <string.h>
+#define import_spp
+#include <iraf.h>
+
+/* OS_STRUPK -- Unpack a C string into an SPP string. This procedure should
+ * be called from C in preference to the SPP procedure STRUPK because the
+ * input string is declared to be of type char, rather than as an XCHAR
+ * array containing packed chars as in STRUPK. The output string is however
+ * of type XCHAR since it is expected to be passed to an SPP procedure. A
+ * pointer to the output string is returned as the function value for use
+ * in argument lists.
+ */
+XCHAR *
+os_strupk (
+ char *str, /* C string */
+ XCHAR *outstr, /* SPP string */
+ int maxch /* max chars out, excl EOS */
+)
+{
+ register char *ip = str;
+ register XCHAR *op = outstr;
+ register int n = maxch;
+
+
+ /* Is is necessary to determine the length of the string in order to
+ * be able to unpack the string in place, i.e., from right to left.
+ */
+ if (maxch) {
+ if (sizeof(char) != sizeof(XCHAR) || str != (char *)outstr) {
+ n = min (n, strlen(ip));
+ op[n] = XEOS;
+
+ while (--n >= 0)
+ op[n] = ip[n];
+ }
+ }
+
+ return (outstr);
+}
diff --git a/unix/boot/bootlib/ossubdir.c b/unix/boot/bootlib/ossubdir.c
new file mode 100644
index 00000000..4330aaad
--- /dev/null
+++ b/unix/boot/bootlib/ossubdir.c
@@ -0,0 +1,31 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "bootlib.h"
+
+
+/* OS_SUBDIR -- Fold a subdirectory name into a directory pathname and return
+ * a pointer to the pathname of the subdirectory.
+ */
+char *
+os_subdir (
+ char *dir, /* OS pathname of directory */
+ char *subdir /* name of subdirectory */
+)
+{
+ static XCHAR x_path[SZ_PATHNAME+1];
+ XCHAR x_subdir[SZ_FNAME+1];
+ XINT x_maxch = SZ_PATHNAME, x_nchars;
+ extern int ZFSUBD();
+
+
+ os_strupk (dir, x_path, SZ_PATHNAME);
+ os_strupk (subdir, x_subdir, SZ_FNAME);
+
+ ZFSUBD (x_path, &x_maxch, x_subdir, &x_nchars);
+
+ if (x_nchars > 0)
+ return (os_strpak (x_path, (char *)x_path, SZ_PATHNAME));
+ else
+ return (NULL);
+}
diff --git a/unix/boot/bootlib/ossymlink.c b/unix/boot/bootlib/ossymlink.c
new file mode 100644
index 00000000..991b8359
--- /dev/null
+++ b/unix/boot/bootlib/ossymlink.c
@@ -0,0 +1,35 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <unistd.h>
+#include <iraf.h>
+
+#ifndef VMS
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+/* OS_SYMLINK -- Determine if a file is a symbolic link.
+ */
+int
+os_symlink (
+ char *fname, /* file to be tested */
+ char *valbuf, /* buffer to receive link path, else NULL */
+ int maxch
+)
+{
+#ifndef VMS
+ struct stat fi;
+ int n;
+
+ if (lstat (fname, &fi) == 0)
+ if ((fi.st_mode & S_IFMT) == S_IFLNK) {
+ if (valbuf && maxch)
+ if ((n = readlink (fname, valbuf, maxch)) > 0)
+ valbuf[n] = '\0';
+ return (1);
+ }
+#endif
+
+ return (0);
+}
diff --git a/unix/boot/bootlib/ossysfile.c b/unix/boot/bootlib/ossysfile.c
new file mode 100644
index 00000000..2d4f23be
--- /dev/null
+++ b/unix/boot/bootlib/ossysfile.c
@@ -0,0 +1,113 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <string.h>
+#include "bootlib.h"
+
+/* Uncomment the following if the kernel for this machine does not need
+ * or provide its own custom irafpath function, used if it can not be easily
+ * determine in advance what directories need to be searched.
+ */
+/* #define STANDALONE */
+
+#ifdef STANDALONE
+#define irafpath os_irafpath
+#endif
+
+char *irafpath();
+char *os_getenv();
+extern int os_access (char *fname, int mode, int type);
+
+
+/* OS_SYSFILE -- Return the pathname of a system library file. The library
+ * search order is
+ *
+ * IRAFULIB libraries, if any
+ * HSI system libraries (lib, hlib, hbin, etc.)
+ * pkglibs applications libraries, if any
+ *
+ * Hence, the IRAFULIB mechanism may be used to make use of custom copies
+ * of system files (libraries or global include files), whereas the `pkglibs'
+ * mechanism is provided to extend the system library search path to include
+ * applications specified libraries. These are intended to be the global
+ * libraries of installed layered packages, rather than private user libraries
+ * (the IRAFULIB mechanism is better for the latter).
+ */
+int
+os_sysfile (
+ char *sysfile, /* filename from include statement */
+ char *fname, /* receives filename */
+ int maxch
+)
+{
+ register char *ip, *op;
+ char *files, *ip_save;
+
+
+ /* Search the standard system libraries and exit if the named
+ * file is found.
+ */
+ strncpy (fname, irafpath(sysfile), maxch);
+ fname[maxch-1] = EOS;
+ if (strcmp (fname, sysfile) != 0)
+ return (strlen (fname));
+
+ /* Search the designated package libraries, if any.
+ */
+ if ( (files = os_getenv ("pkglibs")) ) {
+ for (ip=files; *ip; ) {
+ /* Get the next library name from the list. */
+ while (isspace(*ip) || *ip == ',')
+ ip++;
+ for (op=fname; *ip && !isspace(*ip) && *ip != ','; op++)
+ *op = *ip++;
+ *op = EOS;
+
+ /* Append the target filename. */
+ for (ip_save=ip, (ip=sysfile); (*op++ = *ip++); )
+ ;
+ ip = ip_save;
+
+ /* Exit if the file exists. */
+ if (os_access (fname, 0, 0))
+ return (strlen (fname));
+ }
+ }
+
+ return (ERR);
+}
+
+
+#ifdef STANDALONE
+static char *libs[] = { "iraf$lib/", "host$hlib/", "" };
+
+/* OS_IRAFPATH -- Portable version of the kernel irafpath() function, used
+ * if only the standard directories LIB and HLIB need to be searched.
+ */
+char *
+os_irafpath (sysfile)
+char *sysfile; /* filename from include statement */
+{
+ register char *ip, *op;
+ register int n;
+ static char outfname[SZ_PATHNAME+1];
+ char fname[SZ_PATHNAME+1];
+ int i;
+
+ strcpy (outfname, sysfile);
+
+ for (i=0; libs[i][0] != EOS; i++) {
+ strcpy (fname, libs[i]);
+ strcat (fname, sysfile);
+ if (os_access (fname, 0,0) == YES) {
+ n = SZ_PATHNAME;
+ for (ip=fname, op=outfname; --n >= 0 && (*op = *ip++); op++)
+ ;
+ *op = EOS;
+ break;
+ }
+ }
+
+ return (outfname);
+}
+#endif
diff --git a/unix/boot/bootlib/ostime.c b/unix/boot/bootlib/ostime.c
new file mode 100644
index 00000000..8ae97df7
--- /dev/null
+++ b/unix/boot/bootlib/ostime.c
@@ -0,0 +1,113 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <sys/types.h>
+#ifdef SYSV
+#include <time.h>
+#else
+#include <sys/time.h>
+#include <sys/timeb.h>
+#endif
+
+#ifdef MACOSX
+#include <time.h>
+#endif
+
+#define SECONDS_1970_TO_1980 315532800L
+static long os_timezone();
+
+
+/* OS_UTIME -- Convert IRAF time (local standard, epoch 1980) to UNIX time
+ * (greenwich mean time, epoch 1970). [MACHDEP]
+ *
+ * NOTE: If this is difficult to implement on your system, you can probably
+ * forget about the correction to Greenwich (e.g., 7 hours) and that for
+ * daylight savings time (1 hour), and file times will come out a bit off
+ * but it probably won't matter.
+ */
+long
+os_utime (long iraf_time)
+{
+ struct tm *localtime();
+ time_t time_var, lst;
+#ifdef AUX
+ long lstl;
+#endif
+
+ lst = (time_t)iraf_time;
+
+ /* Add minutes westward from GMT */
+ time_var = lst + os_timezone();
+
+ /* Correct for daylight savings time, if in effect */
+#ifdef AUX
+ lstl = (long)lst;
+ if (localtime(&lstl)->tm_isdst)
+#else
+ if (localtime(&lst)->tm_isdst)
+#endif
+ time_var += 60L * 60L;
+
+ return ((long)time_var + SECONDS_1970_TO_1980);
+}
+
+
+/* OS_ITIME -- Convert UNIX time (gmt, epoch 1970) to IRAF time (lst, epoch
+ * 1980). [MACHDEP]
+ */
+long
+os_itime (long unix_time)
+{
+ struct tm *localtime();
+ time_t time_var, gmt;
+#ifdef AUX
+ long gmtl;
+#endif
+
+ gmt = (time_t)unix_time;
+
+ /* Subtract minutes westward from GMT */
+ time_var = gmt - os_timezone();
+
+ /* Correct for daylight savings time, if in effect */
+#ifdef AUX
+ gmtl = (long)gmt;
+ if (localtime(&gmtl)->tm_isdst)
+#else
+ if (localtime(&gmt)->tm_isdst)
+#endif
+ time_var -= 60L * 60L;
+
+ return ((long)time_var - SECONDS_1970_TO_1980);
+}
+
+
+/* OS_GTIMEZONE -- Get the local timezone, measured in seconds westward
+ * from Greenwich, ignoring daylight savings time if in effect.
+ */
+static long
+os_timezone()
+{
+#ifdef CYGWIN
+ extern long _timezone;
+ return (_timezone);
+#else
+#if defined(SOLARIS) && defined(X86)
+ extern long timezone;
+ return (timezone);
+
+#else
+#if defined(SYSV) || defined(MACOSX)
+ struct tm *tm;
+ time_t clock;
+ clock = time(NULL);
+ tm = gmtime (&clock);
+ return (-(tm->tm_gmtoff));
+#else
+ struct timeb time_info;
+ ftime (&time_info);
+ return (time_info.timezone * 60);
+#endif
+#endif
+#endif
+}
diff --git a/unix/boot/bootlib/oswrite.c b/unix/boot/bootlib/oswrite.c
new file mode 100644
index 00000000..3c59f8cd
--- /dev/null
+++ b/unix/boot/bootlib/oswrite.c
@@ -0,0 +1,49 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <unistd.h>
+#include "bootlib.h"
+
+/* OS_WRITE -- Write to the output file. If the output file is a text file
+ * we must convert the binary input (text) stream to the record structured
+ * stream required by the host.
+ */
+int
+os_write (
+ int fd, /* output file */
+ char *buf, /* data to be written */
+ int nbytes /* num bytes to be written */
+)
+{
+ register char *ip;
+ register XCHAR *op, *otop;
+ register int ch, n;
+ XINT nchars, status, xfd=fd;
+ extern int ZPUTTX();
+
+
+ if (osfiletype == BINARY_FILE)
+ return (write (fd, buf, nbytes));
+
+ n = nbytes;
+ ip = buf;
+ op = txop;
+ otop = &text[SZ_FBUF];
+
+ /* Accumulate an output line of text and pass it on to the system when
+ * newline is seen or when the output buffer fills (unlikely).
+ */
+ while (--n >= 0) {
+ *op++ = ch = *ip++;
+ if (ch == '\n' || op >= otop) {
+ nchars = op - text;
+ ZPUTTX (&xfd, text, &nchars, &status);
+ op = txop = text;
+ if (status == XERR)
+ return (ERR);
+ }
+ }
+
+ txop = op;
+ return (nbytes);
+}
diff --git a/unix/boot/bootlib/rindex.c b/unix/boot/bootlib/rindex.c
new file mode 100644
index 00000000..9a2a99f2
--- /dev/null
+++ b/unix/boot/bootlib/rindex.c
@@ -0,0 +1,33 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#ifdef LINUX
+#define NOINDEX
+#endif
+#ifdef MACOSX
+/* The following effectively disables the local version. */
+#define rindex strrindex
+#endif
+
+#ifndef NOINDEX
+
+/* RINDEX -- Return pointer to the last occurrence of a character in a string,
+ * or null if the char is not found.
+ */
+char *
+rindex (str, ch)
+char *str;
+register int ch;
+{
+ register char *ip;
+ register int cch;
+ char *last;
+
+ for (ip=str, last=0; (cch = *ip); ip++)
+ if (cch == ch)
+ last = ip;
+
+ return (last);
+}
+
+#endif
diff --git a/unix/boot/bootlib/tape.c b/unix/boot/bootlib/tape.c
new file mode 100644
index 00000000..6d949f72
--- /dev/null
+++ b/unix/boot/bootlib/tape.c
@@ -0,0 +1,271 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#define NOKNET
+#define import_spp
+#define import_finfo
+#define import_knames
+#include <iraf.h>
+
+/*
+ * TAPE.C -- Generalized binary file i/o to a tape drive or other devices.
+ *
+ * fd = tape_open (fname, mode)
+ * tape_close (fd)
+ * nb = tape_read (fd, buf, maxbytes)
+ * nb = tape_write (fd, buf, nbytes)
+ *
+ * Only one "tape" file can be open at a time (unless all open files are of
+ * the same type). Since we call ZZRDMT and ZZWRMT directly, only blocked
+ * output is permitted (there is no internal buffering). Only sequential
+ * output is permitted to disk (there is no seek entry point).
+ *
+ * NOTE - For the IRAF V2.10 version of this utility, only host device names
+ * are permitted. The IRAF device names "mta", "mtb", etc are not supported
+ * as the tapefile file is not read.
+ */
+
+#define TF_STDIN 0
+#define TF_STDOUT 1
+#define TF_BINARY 2
+#define TF_TAPE 3
+
+#define R 0
+#define W 1
+#define RW 2
+
+/* Tape position structure (V2.10). */
+struct mtpos {
+ int filno; /* current file (1=first) */
+ int recno; /* current record (1=first) */
+ int nfiles; /* number of files on tape */
+ int tapeused; /* total tape used (Kb) */
+ int pflags; /* i/o status bitflags (output) */
+};
+
+/* MTPOS bitflags. */
+#define MF_ERR 0001 /* i/o error occurred in last operation */
+#define MF_EOF 0002 /* a tape mark was seen in the last operation */
+#define MF_EOT 0004 /* end of tape seen in the last operation */
+#define MF_EOR 0010 /* a record advance occurred in the last operation */
+
+static int ftype;
+static XINT acmode;
+static int ateof;
+static XLONG offset = 0;
+
+static int os_mtname (char *fname, char *osdev);
+
+extern int ZZOPMT(), ZOPNBF(), ZCLSBF(), ZZCLMT();
+extern int ZARDBF(), ZAWTBF(), ZZRDMT(), ZZWTMT(), ZAWRBF(), ZZWRMT();
+
+
+
+/* TAPE_OPEN -- Open the named file, which need not actually be a tape device.
+ */
+int
+tape_open (
+ char *fname, /* file or device to be opened */
+ int mode /* access mode */
+)
+{
+ PKCHAR osfn[SZ_PATHNAME+1];
+ XINT chan;
+ extern char *vfn2osfn();
+
+
+ if (strcmp (fname, "stdin") == 0) {
+ ftype = TF_STDIN;
+ if (mode != R)
+ chan = ERR;
+ else
+ chan = 1; /* arbitrary */
+
+ } else if (strcmp (fname, "stdout") == 0) {
+ ftype = TF_STDOUT;
+ if (mode != W)
+ chan = ERR;
+ else
+ chan = 1; /* arbitrary */
+
+ } else if (os_mtname (fname, (char *)osfn)) {
+ /* Open a magtape device. Only host device names are permitted.
+ * Try to open without moving the tape (newfile=0).
+ */
+ register int *op;
+ struct mtpos devpos;
+ int nwords = sizeof(devpos) / sizeof(int);
+ XINT newfile = 0;
+ char *tapecap = ":np";
+
+ for (op = (int *)&devpos; --nwords >= 0; )
+ *op++ = 0;
+ ftype = TF_TAPE;
+ if (mode == R)
+ acmode = READ_ONLY;
+ else
+ acmode = WRITE_ONLY;
+
+ ZZOPMT (osfn, &acmode, (PKCHAR *)tapecap, (XINT *)&devpos,
+ &newfile, &chan);
+
+ } else {
+ /* Open a binary disk file.
+ */
+ ftype = TF_BINARY;
+ offset = 1;
+
+ strcpy ((char *)osfn, vfn2osfn (fname, 0));
+ if (mode == R)
+ acmode = READ_ONLY;
+ else if (mode == W)
+ acmode = NEW_FILE;
+ else
+ acmode = READ_WRITE;
+
+ ZOPNBF (osfn, &acmode, &chan);
+ }
+
+ ateof = 0;
+
+ return (chan == XERR ? ERR : chan);
+}
+
+
+/* TAPE_CLOSE -- Close a file opened with tape_open.
+ */
+int
+tape_close (int fd)
+{
+ struct mtpos devpos;
+ XINT x_fd=fd, status;
+
+ if (ftype == TF_BINARY)
+ ZCLSBF (&x_fd, &status);
+ else if (ftype == TF_TAPE)
+ ZZCLMT (&x_fd, (XINT *)&devpos, &status);
+ else
+ status = XOK;
+
+ return (status == XERR ? ERR : OK);
+}
+
+
+/* TAPE_READ -- Read from a file opened with tape_open.
+ */
+int
+tape_read (
+ int fd, /* input file */
+ char *buf, /* output buffer */
+ int maxbytes /* max bytes to read */
+)
+{
+ struct mtpos devpos;
+ XINT x_fd=fd, x_maxbytes=maxbytes, status;
+
+ if (ateof)
+ return (0);
+
+ if (ftype == TF_STDIN) {
+ status = read (0, buf, maxbytes);
+ } else if (ftype == TF_BINARY) {
+ ZARDBF (&x_fd, (XCHAR *)buf, &x_maxbytes, &offset);
+ ZAWTBF (&x_fd, &status);
+ if (status > 0)
+ offset += status;
+ } else if (ftype == TF_TAPE){
+ ZZRDMT (&x_fd, (XCHAR *)buf, &x_maxbytes, &offset);
+ ZZWTMT (&x_fd, (XINT *)&devpos, &status);
+ if (devpos.pflags & MF_EOF)
+ ateof++;
+ } else
+ status = XERR;
+
+ return (status == XERR ? ERR : status);
+}
+
+
+/* TAPE_WRITE -- Write to a file opened with tape_open.
+ */
+int
+tape_write (
+ int fd, /* output file */
+ char *buf, /* input bufferr */
+ int nbytes /* nbytes to write */
+)
+{
+ struct mtpos devpos;
+ XINT x_fd=fd, x_nbytes=nbytes, status;
+
+ if (ftype == TF_STDOUT) {
+ status = write (1, buf, nbytes);
+ } else if (ftype == TF_BINARY) {
+ ZAWRBF (&x_fd, (XCHAR *)buf, &x_nbytes, &offset);
+ ZAWTBF (&x_fd, &status);
+ if (status > 0)
+ offset += status;
+ } else if (ftype == TF_TAPE) {
+ ZZWRMT (&x_fd, (XCHAR *)buf, &x_nbytes, &offset);
+ ZZWTMT (&x_fd, (XINT *)&devpos, &status);
+ } else
+ status = XERR;
+
+ return (status == XERR ? ERR : status);
+}
+
+
+/* OS_MTNAME -- Parse a filename to determine if the file is a magtape
+ * device or something else. A nonzero return indicates that the device
+ * is a tape.
+ */
+static int
+os_mtname (
+ char *fname, /* filename e.g., "foo.tar" or "mua0:". */
+ char *osdev /* receives host system drive name */
+)
+{
+#ifdef VMS
+ register char *ip;
+ char drive[SZ_FNAME+1];
+#endif
+
+ /* Ignore any "mt." prefix. This is for backwards compatibility,
+ * to permit old-style names like "mt.MUA0:".
+ */
+ if (!strncmp (fname, "mt.", 3) || !strncmp (fname, "MT.", 3))
+ fname += 3;
+
+#ifdef VMS
+ /* Resolve a possible logical device name. */
+ if (strchr (fname, '['))
+ strcpy (drive, fname);
+ else
+ _tranlog (fname, drive);
+
+ /* If the resolved name ends with a colon it is a device name,
+ * which we assume to be a tape device.
+ */
+ for (ip=drive; *ip; ip++)
+ ;
+ if (*(ip-1) == ':') {
+ strcpy (osdev, drive);
+ return (1);
+ }
+#else
+ /* For unix systems we assume anything beginning with /dev is a
+ * tape device.
+ */
+ if (strncmp (fname, "/dev/", 5) == 0) {
+ strcpy (osdev, fname);
+ return (1);
+ }
+#endif
+
+ strcpy (osdev, fname);
+ return (0);
+}
diff --git a/unix/boot/bootlib/vfn2osfn.c b/unix/boot/bootlib/vfn2osfn.c
new file mode 100644
index 00000000..c93d2090
--- /dev/null
+++ b/unix/boot/bootlib/vfn2osfn.c
@@ -0,0 +1,147 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#define NOLIBCNAMES
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_knames
+#include <iraf.h>
+
+#define FINIT
+#include "bootlib.h"
+
+static PKCHAR pk_osfn[SZ_PATHNAME+1];
+static char *osfn = (char *)pk_osfn;
+extern char *os_getenv();
+
+
+#ifdef NOVOS
+
+/* VFN2OSFN -- Map an IRAF virtual filename into an OS filename. This is
+ * a simplified version for UNIX which does not use the VOS. This version
+ * should also be almost sufficient to compile the system libraries when
+ * starting from scratch on a new machine, since the filenames in the system
+ * directories are simple and the full generality of the FIO filename mapping
+ * code is not required (extension mapping is about all that is required).
+ * Only the well-known system logical directories are recognized in this
+ * version, however ZGTENV is called to replace logical directories, and
+ * this in turn references the host system environment, so one can bootstrap
+ * things by using the host environment facilities.
+ */
+char *
+vfn2osfn (
+ char *vfn, /* input IRAF virtual filename */
+ int new /* new file */
+)
+{
+ register char *ip, *op;
+ char fname[SZ_PATHNAME+1], *ldir;
+
+ /* Recursively expand logical directories, but don't do anything
+ * about subdirectories, extensions, etc. This is all that is
+ * needed for UNIX.
+ */
+ for (ip=vfn, op=fname; (*op = *ip++); op++)
+ if (*op == '$') {
+ *op = EOS;
+ if ( (ldir = os_getenv (fname)) )
+ strcpy (fname, ldir);
+ strcat (fname, ip);
+ return (vfn2osfn (fname, 0));
+ }
+
+ /* Copy filename to the output string. Fix up the "//" sequences
+ * that occur because IRAF likes the / at the end of logical directory
+ * names.
+ */
+ for (ip=fname, op=osfn; (*op = *ip++); op++)
+ if (*op == '/' && op > osfn && *(op-1) == '/')
+ --op;
+
+ return (osfn);
+}
+
+
+#else
+
+/* VFN2OSFN -- Map an IRAF virtual filename into an OS filename. This is
+ * the portable version using the VOS (libsys.a+libvops.a+libos.a) to do the
+ * mapping. The system libraries must have been built before we can do this,
+ * of course.
+ */
+char *
+vfn2osfn (
+ char *vfn, /* input IRAF virtual filename */
+ int new /* new file */
+)
+{
+ register char *ip;
+ register XCHAR *op;
+ register int n = SZ_PATHNAME;
+ XINT vp, mode, maxch = SZ_PATHNAME;
+ PKCHAR upkvfn[SZ_PATHNAME+1];
+ int err;
+
+ extern void _envinit();
+
+
+
+ /* Copy the input filename into local storage before calling envinit,
+ * below, to avoid any chance of overwriting the input string in a
+ * recursive call to vfn2osfn by envinit.
+ */
+ for (ip=vfn, op=upkvfn; --n >= 0 && (*op++ = *ip++) != (XCHAR)EOS; )
+ ;
+ *(op-1) = XEOS;
+ mode = new ? VFN_WRITE : VFN_READ;
+
+ /* Nasty beast that can call vsn2osfn recursively. */
+ _envinit();
+
+ err = 0;
+ iferr (vp = VFNOPEN (upkvfn, (integer *)&mode)) {
+ fprintf (stderr, "Warning: cannot open vfn `%s' for %s\n",
+ vfn, mode == VFN_WRITE ? "writing" : "reading");
+ err++;
+ }
+
+ if (new) {
+ if (!err)
+ iferr (VFNADD ((integer *)&vp, pk_osfn, (integer *)&maxch))
+ fprintf (stderr, "Warning: cannot add filename `%s'\n",vfn);
+ } else {
+ if (!err)
+ iferr (VFNMAP ((integer *)&vp, pk_osfn, (integer *)&maxch))
+ fprintf (stderr, "Warning: cannot map filename `%s'\n",vfn);
+ }
+
+ mode = (mode == VFN_WRITE) ? VFN_UPDATE : VFN_NOUPDATE;
+ if (!err) {
+ iferr (VFNCLOSE ((integer *)&vp, (integer *)&mode))
+ fprintf (stderr, "Warning: error closing mapping file\n");
+ } else
+ *osfn = EOS;
+
+ return (osfn);
+}
+
+
+/*
+ * KISTUB -- Stub out selected KI (kernel network interface) routines. This
+ * is done when VOS filename mapping is in use to avoid linking in a lot of
+ * objects that will never be used, since the HSI does not use networking.
+ */
+int KI_GETHOSTS() { return (0); }
+void KI_SEND(){}
+void KI_RECEIVE(){}
+#endif
+
+#ifdef SUNOS
+/* Stub out the following too, since there is no floating point in the HSI. */
+ieee_flags(){}
+ieee_handler(){}
+abrupt_underflow_(){}
+#endif