[daip] problems with AIPS installation

Eric Greisen egreisen at aoc.nrao.edu
Mon Jun 23 19:17:15 EDT 2003


RedHat 9 involves several new things that make AIPS not compile
properly.  I would recommend using the gnu 3.2+ or 3.3 compiler
provided with RedHat 9 rather than 2.95.3 which is responsible for
several of the error messages in the link edits.  Unfortunately,
software "errors" (they were once legitimate...) are responsible for
the failures.  I have fixed 31DEC03 which you could install instead of
the frozen version.  Alternatively, you could fix the errors:

The changes are:

11284.  April 13, 2003         errno.h                    Eric
        The standard unix error code should be obtained by
            #include <errno.h>
        not with the obsolete
            extern int errno
        RedHat 9 can detect that the latter was used!
        Changed numerous versions of ZPRMPT.C and a variety of other
        routines.
        Moved nowhere.

11285.  April 14, 2003       ZERRO2, ZACTV9               Eric
        Another change is to complain about direct references to
        sys_errlist and sys_nerr.  Changed ZERRO2 and ZACTV9 to call
        strerror - the thread safe version strerror_r is not available
        on Solaris.
        Moved nowhere.
13-APR-2003 20:22:07 20030413 TST APLLINUX ZPRMPT.C      direct access to errno
13-APR-2003 20:48:22 20030413 TST APLUNIX  ZTPMI2.C      errno
14-APR-2003 17:20:33 20030414 TST APLUNIX  ZERRO2.C      sys_errlist
14-APR-2003 17:20:34 20030414 TST APLUNIX  ZACTV9.C      sys_errlist

These routines follow:

#define Z_prmpt__
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <NOTST/GNU/history.h>

#define HAVE_STRING_H                   /* Needed inside readline.h   */
#include <NOTST/GNU/readline.h>
#include <AIPSPROTO.H>

                                        /* Local signal-handler.      */
#if __STDC__
   static void zprmpt_sigs(int sig)
#else
   static void zprmpt_sigs(sig)
   int sig;
#endif
{
   extern int _rl_meta_flag;
   extern int kill ();                  /* Arg...some OS's...really!  */
   extern void rl_prep_terminal ();

   kill (getpid (), SIGTSTP);
   rl_prep_terminal (_rl_meta_flag);
}

#if __STDC__
   void zprmpt_(char ipc[1], char buff[80], int *ierr)
#else
   void zprmpt_(ipc, buff, ierr)
   char ipc[1], buff[80];
   int *ierr;
#endif
/*--------------------------------------------------------------------*/
/*! prompt user and read 80 characters from CRT screen                */
/*# Terminal                                                          */
/*--------------------------------------------------------------------*/
/*;  Copyright (C) 1995-1997, 2003                                    */
/*;  Associated Universities, Inc. Washington DC, USA.                */
/*;                                                                   */
/*;  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 Massachusetts Ave, Cambridge,     */
/*;  MA 02139, USA.                                                   */
/*;                                                                   */
/*;  Correspondence concerning AIPS should be addressed as follows:   */
/*;         Internet email: aipsmail at nrao.edu.                        */
/*;         Postal address: AIPS Project Office                       */
/*;                         National Radio Astronomy Observatory      */
/*;                         520 Edgemont Road                         */
/*;                         Charlottesville, VA 22903-2475 USA        */
/*--------------------------------------------------------------------*/
/* ZPRMPT prompts user on CRT screen and reads a line of user input   */
/* via the GNU readline (+history) library.  The input line is placed */
/* in a buffer and either truncated to 80 characters or space-padded  */
/* to 80 characters prior to return.  Non-empty lines are added to a  */
/* history list for possible later access/reuse via the               */
/* history-manipulation key-bindings (a la Bash/Ksh/Emacs--or even    */
/* vi).  If the user is not on an interactive tty, say by giving AIPS */
/* input via a shell-script "here document," then the old             */
/* (non-readline) behavior is used and the input line is not added to */
/* the history.  Use of the readline library can be disabled by       */
/* starting AIPS with the "norl" option.                              */
/*                                                                    */
/* Input:                                                             */
/*    IPC    C*1    prompt character                                  */
/* Output:                                                            */
/*    BUFF   C*80   line of user input.                               */
/*    IERR   I      Error return code: 0 => ok                        */
/*                     1 => read/write error (not implemented/set)    */
/*                                                                    */
/* UNIX GNU-readline version (with terminal-reset signal-handler).    */
/*                                                                    */
/* JAU 26 Jul 95: Jeff Uphoff, NRAO.  Added GNU readline support.     */
/* JAU 29 Aug 95: Jeff Uphoff, NRAO.  Overhaul of several portions.   */
/* JAU 22 Sep 95: Jeff Uphoff, NRAO.  Added check for userno prompt.  */
/* JAU 25 Jun 97: Jeff Uphoff, NRAO.  Fix prompt bug.                 */
/*--------------------------------------------------------------------*/
{
   char *rlenv = NULL;
   char *temp = NULL;
   register int i, ttyp;
/*--------------------------------------------------------------------*/
   *ierr = 0;

   buff[0] = '\0';                      /* Initialize buffer.         */

                                        /* Check if readline disabled */
   if (!(ttyp = isatty (0)) ||          /* or if not interactive tty. */
         (((rlenv = getenv ("READLINE")) != NULL) &&
         !strcmp (rlenv, "NO"))) {

      char pc = ipc[0];                 /* OK, fall back to old       */
                                        /* prompting and input-       */
                                        /* handling behavior.         */
      if(!(temp = (char *)malloc (81))) {
         perror ("ZPRMPT: malloc failed");
         exit (errno);                  /* This is *very* bad!        */
      }
      putchar (pc);                     /* Display prompt.            */

                                        /* Use old input method.      */
      if (fgets (temp, 81, stdin) == NULL) {
         free (temp);
         temp = NULL;
      }
      ttyp = 0;                         /* We'll fake this for later. */

   } else {                             /* Use GNU readline for input */
      char prompt[2];

      if (ipc[0] == '?')                /* Check if userno. prompt.   */
         rl_bind_key ('\t', NULL);      /* If so, disable TAB's.      */

      zignal_ (SIGTTIN, zprmpt_sigs);   /* All of these signal-       */
      zignal_ (SIGTTOU, zprmpt_sigs);   /* handling shenanigans are   */
                                        /* due to general insanity.   */

      prompt[0] = ipc[0];               /* Ensure prompt sanity.      */
      prompt[1] = '\0';
      temp = readline (prompt);         /* Use readline to prompt     */
                                        /* user and return pointer    */
                                        /* to line of user input.     */
                                        /* readline() does the        */
                                        /* malloc() for us, but we    */
                                        /* must free() the pointer.   */

      zignal_ (SIGTTIN, SIG_DFL);       /* More fun with signals.     */
      zignal_ (SIGTTOU, SIG_DFL);
   }

   if (temp == NULL)                    /* NULL pointer means EOF at  */
      sprintf (buff, "EXIT");           /* *beginning* of user input. */

   else {                               /* Non-NULL means good input. */

      if (*temp && ttyp)                /* If not blank (and          */
         add_history (temp);            /* interactive), put in hist. */
                                        /* unless readline disabled   */
                                        /* (the reason for "faking"   */
                                        /* ttyp = 0 earlier).         */

                                        /* readline() strips the new- */
                                        /* line for us.  We need to   */
                                        /* find the first null and    */
                                        /* then pad the output buffer */
                                        /* with trailing spaces.      */
                                        /* The 80-column limit is     */
                                        /* historical...              */
      for (i = 0; i < 80 && temp[i] != '\0'; i++)
         buff[i] = temp[i];             /* Copy up to first null.     */
      for (i = i; i < 80; i++)
         buff[i] = ' ';                 /* Pad remainder with spaces. */
      if (temp)
         free (temp);                   /* Free the readline pointer. */
   }
   return;
}

/*
 * Local Variables:
 * c-basic-offset: 3
 * comment-column: 40
 * indent-tabs-mode: nil
 * End:
 */

#define Z_tpmi2__
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <AIPSPROTO.H>

#if __STDC__
   void ztpmi2_(char *oper, int *fcb, char *buff, int *nbytes, int *ierr)
#else
   void ztpmi2_(oper, fcb, buff, nbytes, ierr)
   char oper[], buff[];
   int *fcb, *nbytes, *ierr;
#endif
/*--------------------------------------------------------------------*/
/*! read/write from/to a tape device                                  */
/*# IO-basic Tape                                                     */
/*--------------------------------------------------------------------*/
/*;  Copyright (C) 1995, 1997, 2003                                   */
/*;  Associated Universities, Inc. Washington DC, USA.                */
/*;                                                                   */
/*;  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 Massachusetts Ave, Cambridge,     */
/*;  MA 02139, USA.                                                   */
/*;                                                                   */
/*;  Correspondence concerning AIPS should be addressed as follows:   */
/*;         Internet email: aipsmail at nrao.edu.                        */
/*;         Postal address: AIPS Project Office                       */
/*;                         National Radio Astronomy Observatory      */
/*;                         520 Edgemont Road                         */
/*;                         Charlottesville, VA 22903-2475 USA        */
/*--------------------------------------------------------------------*/
/*  Read/write "nbytes" 8-bit bytes of data from/to a tape device     */
/*  using "map" I/O (i.e., double buffered, asynchronous I/O).        */
/*  Inputs:                                                           */
/*     oper     C*4    Operation code "READ" or "WRIT"                */
/*     fcb      I(*)   File control block for opened tape drive       */
/*     buff     I(*)   I/O buffer                                     */
/*     nbytes   I      Number of 8-bit bytes to be transferred        */
/*  Output:                                                           */
/*     ierr     I      Error return code: 0 => no error               */
/*                        2 => bad opcode                             */
/*                        3 => I/O error (left for ZTPWA2 now)        */
/*  Generic UNIX version - sysnchronous I/O actually, reports IO error*/
/*  but not End Of File                                               */
/*  Modified for real-time VLA calling olread when fd < 0             */
/*--------------------------------------------------------------------*/
{
                                        /* Offsets to entries in the  */
                                        /* file control blocks        */
   extern int Z_fcbfd, Z_fcbreq, Z_fcberr, Z_fcbxfr, Z_fcbsiz,
      Z_fcbsp1, Z_fcbsp2, Z_fcbsp3, Z_fcbsp4;

   int fd, n8 = 8, ifd, ntry, otry, jerr;
   register int i;
   float secs = 100.0;
   char op[5], msgbuf[80], pathname[MAXAPATH] = "ON-LINE";
/*--------------------------------------------------------------------*/
   *ierr = 0;
   pathname[7] = '\0';
                                        /* Form null terminated       */
                                        /* opcode.                    */
   for (i = 0; i < 4; i++)
      op[i] = oper[i];
   op[4] = '\0';
                                        /* Get file descriptor from   */
                                        /* the file control block as  */
                                        /* stored there by ZTPOP2.    */
   fd = *(fcb + Z_fcbfd);
                                        /* Record byte request in the */
                                        /* file control block.        */
   *(fcb + Z_fcbreq) = *nbytes;
                                        /* Also, zero error status &  */
                                        /* transfer count entries.    */
   *(fcb + Z_fcberr) = 0;
   *(fcb + Z_fcbxfr) = 0;
                                        /* Zero byte request just     */
                                        /* initiates double buffered  */
                                        /* I/O.                       */
   if (*(fcb + Z_fcbreq) != 0) {
                                        /* Perform the I/O and record */
                                        /* the # of bytes transferred */
                                        /* in *(fcb + Z_fcbxfr).      */
                                        /* Record the system error    */
                                        /* code (if any) in           */
                                        /* *(fcb + Z_fcberr).         */
      if (strcmp (op, "READ") == 0) {
                                        /* fake fd<0 ==> use Wes'     */
                                        /* on-line device.            */
         if (fd < 0) {
            for (ntry=0; ntry<100; ntry++) {
               *(fcb + Z_fcbxfr) = olread_(&fd, buff, *(fcb + Z_fcbreq));
                                        /* error - close and re-open  */
               if (*(fcb + Z_fcbxfr) == 0) {
                  sprintf (msgbuf, "ZTPMI2: End-of-data: try to reopen");
                  zmsgwr_ (msgbuf, &n8);
                  olclose_(&fd);
                  for (otry=0; otry<100; otry++) {
                     ifd = -99;
                     zdela2_ (&secs, &jerr) ;
                     fd = olopen_(&ifd, pathname, strlen(pathname));
                     sprintf (msgbuf, "ZTPMI2: olopen %d", fd);
                     zmsgwr_ (msgbuf, &n8);
                                        /* open fails */
                     if (fd == -99 || fd >= 0) {
                        sprintf (msgbuf,
                           "ZTPOP2: FAILS TO OPEN ON-LINE - RETRY");
                        if (otry == 99) {
                           sprintf (msgbuf,
                              "ZTPOP2: FAILS TO OPEN ON-LINE - QUIT");
                           ntry = 101;
                           }
                        zmsgwr_ (msgbuf, &n8);
                        }
                     else {
                        *(fcb + Z_fcbfd) = fd;
                        otry = 1000;
                        }
                     }
                  }
               else {
                  ntry=1000;
                  }
               }
            }
         else {
            *(fcb + Z_fcbxfr) = read(fd, buff, *(fcb + Z_fcbreq));
            }
         if (*(fcb + Z_fcbxfr) == -1) {
            *(fcb + Z_fcberr) = errno;
            }
         }
      else if (strcmp (op, "WRIT") == 0) {
         if ((*(fcb + Z_fcbxfr) =
            write (fd, buff, *(fcb + Z_fcbreq))) == -1) {
            *(fcb + Z_fcberr) = errno;
            }
         }
                                        /* Bad opcode.                */
      else {
         *ierr = 2;
         }
      }
                                        /* Exit.                      */
   return;
}

#define Z_erro2__
#include <stdio.h>
#include <string.h>

#if __STDC__
   void zerro2_(int *syserr, int *elen, char *errmsg)
#else
   void zerro2_(syserr, elen, errmsg)
   int *syserr, *elen;
   char errmsg[];
#endif
/*--------------------------------------------------------------------*/
/*! return system error message for given system error code           */
/*# Service                                                           */
/*--------------------------------------------------------------------*/
/*;  Copyright (C) 1995, 1997-1998, 2003                              */
/*;  Associated Universities, Inc. Washington DC, USA.                */
/*;                                                                   */
/*;  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 Massachusetts Ave, Cambridge,     */
/*;  MA 02139, USA.                                                   */
/*;                                                                   */
/*;  Correspondence concerning AIPS should be addressed as follows:   */
/*;         Internet email: aipsmail at nrao.edu.                        */
/*;         Postal address: AIPS Project Office                       */
/*;                         National Radio Astronomy Observatory      */
/*;                         520 Edgemont Road                         */
/*;                         Charlottesville, VA 22903-2475 USA        */
/*--------------------------------------------------------------------*/
/*  This routine gets the text of the system error message            */
/*  corresponding to a system error code.  Called by ZERROR.          */
/*  Inputs:                                                           */
/*     syserr   I         System error code                           */
/*  In/Out:                                                           */
/*     elen     I         In:  length of errmsg variable in bytes     */
/*                        Out: 1-relative position of last non-blank  */
/*                             character in error message text        */
/*                             corresponding to syserr (if any,       */
/*                             otherwise, zero)                       */
/*     errmsg   C*(elen)  Text of system error message                */
/*  Generic UNIX version.                                             */
/*--------------------------------------------------------------------*/
{
   register int i;
   int elnb;
/*--------------------------------------------------------------------*/
                                        /* Get system error message   */
   if (*syserr >= 0) {
      sprintf (errmsg, "ERRNO = %d (%s)", *syserr, strerror(*syserr));
      for (i = 0; i < *elen && errmsg[i] != '\0'; i++);
                                        /* Blank fill remainder       */
      elnb = i;
      for (i = elnb; i < *elen; i++)
         errmsg[i] = ' ';
      *elen = elnb;
      }
                                        /* no message in list         */
   else
      *elen = 0;

   return;
}

#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#endif

#include <unistd.h>
                                       /* If <unistd.h> can not be   */
                                       /* found you do not have a    */
                                       /* POSIX.1 compliant system   */
                                       /* and ZACTV9 requires local  */
                                       /* development.               */
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <signal.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>

                                       /* We use our own prototypes   */
                                       /* for string functions if we  */
                                       /* are not using an ANSI C     */
                                       /* compiler so that we don't   */
                                       /* have to worry about the use */
                                       /* of <strings.h> on older BSD */
                                       /* systems.                    */
#ifdef __STDC__
#include <string.h>
#else
extern int strcmp();
extern char *strcpy();
extern int strlen();
#endif

                                       /* The malloc prototype may    */
                                       /* also be stored in           */
                                       /* unpredictable headers if    */
                                       /* not using ANSI C.           */
#ifdef __STDC__
#include <stdlib.h>
#else
extern char *malloc();
#endif
#include <AIPSPROTO.H>

#define PMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
#define CMODE (O_WRONLY | O_CREAT | O_TRUNC | O_EXCL)

extern int msg_fd;                    /* Message terminal file        */
                                      /* descriptor (shared by all    */
                                      /* AIPS processes in this       */
                                      /* session) if messages are not */
                                      /* directed to the controlling  */
                                      /* terminal (-1 if they are)    */

#if __STDC__
   void zactv9_(int *flen, char fulnam[], int *plen, char cpname[],
      int *idbg, pid_t *pid, int *syserr, int *ierr)
#else
   void zactv9_(flen, fulnam, plen, cpname, idbg, pid, syserr, ierr)
   int *flen, *plen, *idbg, *pid, *syserr, *ierr;
   char fulnam[], cpname[];
#endif
/*--------------------------------------------------------------------*/
/*! starts requested load module under requested process name         */
/*# Z2 System                                                         */
/*--------------------------------------------------------------------*/
/*;  Copyright (C) 1995, 1997, 2003                                   */
/*;  Associated Universities, Inc. Washington DC, USA.                */
/*;                                                                   */
/*;  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 Massachusetts Ave, Cambridge,     */
/*;  MA 02139, USA.                                                   */
/*;                                                                   */
/*;  Correspondence concerning AIPS should be addressed as follows:   */
/*;         Internet email: aipsmail at nrao.edu.                        */
/*;         Postal address: AIPS Project Office                       */
/*;                         National Radio Astronomy Observatory      */
/*;                         520 Edgemont Road                         */
/*;                         Charlottesville, VA 22903-2475 USA        */
/*--------------------------------------------------------------------*/
/*  ZACTV9 will execute the load module "fulnam" as a process/sub-    */
/*  process called "cpname" which consists of the program name with a */
/*  POPS number suffix x (e.g., AIPSx, BATERx, AIPSCx, AIPSBx, QMNGRx */
/*  or <taskname>x).  AIPSx an BATERx are initiated as processes that */
/*  replace the process that invokes ZACTV9 (i.e., without first      */
/*  forking a subprocess).  This means that in the case of AIPSx and  */
/*  BATERx, there is no return from ZACTV9.  The startup programs     */
/*  ZSTRTA and ZSTRTB invoke ZACTV9 (via ZACTV8) as part of the       */
/*  process of initiating an interative AIPS or BATER session.        */
/*  ZACTV9 is only called by ZACTV8. Note that the AIPS daemon        */
/*  DAIPx is treated exactly as AIPSx.                                */
/*                                                                    */
/*  Inputs:                                                           */
/*     FLEN     I          Length in characters of "fulnam"           */
/*     FULNAM   C*(flen)   Full path name of the required executable  */
/*                         module                                     */
/*     PLEN     I          Length in characters of "cpname"           */
/*     CPNAME   C*(plen)   Desired process name (6 characters or      */
/*                         less = program name + POPS number)         */
/*     IDBG     I          1 => start in DEBUGger if possible         */
/*                         0 => use no DEBUGger if possible           */
/*                         Ignore on CPNAME='AIPSn','BATERn'          */
/*  In/Out:                                                           */
/*     PID      I(4)       Process identification information:        */
/*                         In:  *(pid + 0) user number for systems    */
/*                                         use it (= 0 otherwise and  */
/*                                         on all AIPSB invocations)  */
/*                         Out: *(pid + 1) process ID number from     */
/*                                         "fork" or "vfork"          */
/*                              *(pid + 2) not used                   */
/*                              *(pid + 3) not used                   */
/*  Output:                                                           */
/*     SYSERR   I          System error code (i.e., errno) if error   */
/*     IERR     I          Error return code: 0 => no error           */
/*                             1 => error                             */
/*  Generic UNIX version.                                             */
/*  If the OS is does not comply with POSIX.1 then ZACTV9 will issue  */
/*  a message and return an error code.                               */
/*--------------------------------------------------------------------*/
                                       /* If _POSIX_VERSION is not    */
                                       /* defined then we do not have */
                                       /* a POSIX.1 system.           */
#ifndef _POSIX_VERSION
{
   printf("ZACTV9 REQUIRES LOCAL DEVELOPMENT\n");
   *ierr = 1;
   return;
}
/*--------------------------------------------------------------------*/
#else
{
   char *pathname;                     /* pathname of executable.     */
   char *dirname;                      /* directory name of           */
   char procname[7];                   /* desired process name.       */
   char rootname[6];                   /* root name of desired        */
                                       /* process (ie. process name   */
                                       /* without the POPS number.    */
   char *debugger;                     /* pathname of debugger.       */
   struct sigaction newaction;         /* Signal action for INT       */
   struct sigaction saved;             /* Previous signal action for  */
                                       /* INT                         */
   char lockname[_POSIX_PATH_MAX];     /* Name of lock file           */
   int  lockfile;                      /* lock file file descriptor   */
   pid_t child;                        /* PID of child process        */
   pid_t grandchild;                   /* PID of grandchild process   */
   int p[2];                           /* File descriptors for pipe   */
   int i, j, n8 = 8;
   char msg[80];
/*--------------------------------------------------------------------*/
   *syserr = 0;
   if (*plen > 6) {
      *ierr = 2;
      return;
      }
                                       /* Convert pathname of         */
                                       /* executable to null-         */
                                       /* terminated form:            */
   pathname = malloc (*flen+1);
   dirname = malloc (*flen+1);
   for (i = 0; i != *flen && fulnam[i] != ' '; i++) {
                                       /* Invariant: for all k,       */
                                       /* 0 <= k < i,                 */
                                       /* pathname[k] = fulnam[k] and */
                                       /* dirname[k] = fulnam[k]      */
      pathname[i] = fulnam[i];
      dirname[i] = fulnam[i];
      if (fulnam[i] == '/') j = i;
      }
   pathname[i] = '\0';
   dirname[j] = '\0';

                                       /* Convert desired process     */
                                       /* name to null-terminated     */
                                       /* form and save rootname:     */
   for (i = 0; i != *plen && cpname[i] != ' '; i++) {
                                       /* Invariant: for all j,       */
                                       /* 0 <= j < i,                 */
                                       /* procname[j] = cpname[j] and */
                                       /* rootname[j] = cpname[j].    */
      procname[i] = cpname[i];
      rootname[i] = cpname[i];
      }
   procname[i] = '\0';
   rootname[i-1] = '\0';

                                       /* Extract the pathname of the */
                                       /* debugger:                   */
   debugger = NULL;
   if (strcmp (rootname, "AIPS") == 0 ||
       strcmp (rootname, "DAIP") == 0) {
      if (getenv ("AIPSDBUGR") != NULL) {
         debugger = malloc (strlen (getenv ("AIPSDBUGR")) + 1);
         strcpy (debugger, getenv ("AIPSDBUGR"));
         }
      }
   else if (strcmp (rootname, "BATER") == 0) {
      if (getenv ("BATERDBUGR") != NULL) {
         debugger = malloc (strlen (getenv ("BATERDBUGR")) + 1);
         strcpy (debugger, getenv ("BATERDBUGR"));
         }
      }
   else if (*idbg == 1) {
      if (getenv ("DBUGR") != NULL) {
         debugger = malloc (strlen (getenv ("DBUGR")) + 1);
         strcpy (debugger, getenv ("DBUGR"));
         }
      }


                                       /* Check that the executable   */
                                       /* exists and that this        */
                                       /* process can execute it.     */
   if (access (pathname, F_OK) != 0) {
      *syserr = errno;
      *ierr = 1;
      sprintf(msg, "ZACTV9: CANNOT FIND %s", pathname);
      zmsgwr_ (msg, &n8);
      if (errno >= 0) {
         sprintf (msg, "ERRNO = %d (%s)", errno, strerror(errno));
         zmsgwr_ (msg, &n8);
         }
      return;
      }
   if (access (pathname, X_OK) != 0) {
      *syserr = errno;
      *ierr = 1;
      sprintf(msg, "ZACTV9: NO EXECUTE PERMISSION FOR %s", pathname);
      zmsgwr_ (msg, &n8);
      if (errno >= 0) {
         sprintf (msg, "ERRNO = %d (%s)", errno, strerror(errno));
         zmsgwr_ (msg, &n8);
         }
      return;
      }

   if (debugger != NULL) {
                                       /* Debug mode startup.         */

                                       /* Ignore interrupt signals    */
      newaction.sa_handler = SIG_IGN;
      sigemptyset(&newaction.sa_mask);
      newaction.sa_flags =0;
      if (sigaction (SIGINT, &newaction, &saved) == -1) {
         *syserr = errno;
         *ierr = 1;
         sprintf(msg, "ZACTV9: CANNOT INSTALL SIGINT HANDLER");
         zmsgwr_ (msg, &n8);
         if (errno >= 0) {
            sprintf (msg, "ERRNO = %d (%s)", errno, strerror(errno));
            zmsgwr_ (msg, &n8);
            }
         return;
         }

                                       /* Check that debugger exists  */
                                       /* and is executable:          */
      if (access (debugger, F_OK) == -1) {
         *syserr = errno;
         *ierr = 1;
         sprintf(msg, "ZACTV9: CANNOT FIND %s", debugger);
         zmsgwr_ (msg, &n8);
         if (errno >= 0) {
            sprintf (msg, "ERRNO = %d (%s)", errno, strerror(errno));
            zmsgwr_ (msg, &n8);
            }
         goto restore;
         }
      if (access (debugger, X_OK) == -1) {
         *syserr = errno;
         *ierr = 1;
         sprintf("ZACTV9: NO EXECUTE PERMISSION FOR %s", debugger);
         zmsgwr_ (msg, &n8);
         if (errno >= 0) {
            sprintf (msg, "ERRNO = %d (%s)", errno, strerror(errno));
            zmsgwr_ (msg, &n8);
            }
         goto restore;
         }
                                       /* We need to start the       */
                                       /* program through a link     */
                                       /* otherwise the POPS number  */
                                       /* doesn't propagate through  */
                                       /* the debugger and ZWHOMI    */
                                       /* will fail                  */
      if (chdir (dirname) == -1) {
         *syserr = errno;
         *ierr = 1;
         sprintf(msg, "ZACTV9: CAN NOT CHANGE DIRECTORY TO %s",
            dirname);
         zmsgwr_ (msg, &n8);
         if (errno >= 0) {
            sprintf (msg, "ERRNO = %d (%s)", errno, strerror(errno));
            zmsgwr_ (msg, &n8);
            }
         goto restore;
         }
      unlink(procname);
      if (link (pathname, procname) == -1) {
         *syserr = errno;
         *ierr = 1;
         sprintf(msg, "ZACTV9: CAN NOT CREATE LINK TO %s", procname);
         zmsgwr_ (msg, &n8);
         if (errno >= 0) {
            sprintf (msg, "ERRNO = %d (%s)", errno, strerror(errno));
            zmsgwr_ (msg, &n8);
            }
         goto restore;
         }

      if (strcmp (rootname, "AIPS") == 0 ||
          strcmp (rootname, "BATER") == 0 ||
          strcmp (rootname, "DAIP") == 0) {
                                       /* Execute new program in this */
                                       /* process:                    */

         pid[1] = (int)getpid ();
         sprintf (lockname, "/tmp/%s.%d", procname, pid[1]);

                                       /* Create lock file:           */
         if ((lockfile = open (lockname, CMODE, PMODE)) == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT CREATE LOCK FILE %s",
               lockname);
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            goto restore;
            }
         close (lockfile);

         if (execl (debugger, debugger, procname, NULL) == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT START DEBUGGER");
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            goto restore;
            }
         }
      else {                           /* Not AIPS or BATER           */
         if ((pid[1] = fork()) == 0) { /* Child process               */

                                       /* Close all open file         */
                                       /* descriptors except for      */
                                       /* anything that might be the  */
                                       /* message terminal:           */
            for (i = 0; i != sysconf(_SC_OPEN_MAX); i++) {
               if ((i != msg_fd) && (i > 2)) {
                  close (i);
                  }
               }


            if (execl (debugger, debugger, procname, NULL) == -1) {
               sprintf(msg, "ZACTV9: CANNOT START %s", procname);
               zmsgwr_ (msg, &n8);
               if (errno >= 0) {
                  sprintf (msg, "ERRNO = %d (%s)", errno,
                     strerror(errno));
                  zmsgwr_ (msg, &n8);
                  }
               exit (1);
               }

            exit (0);
            }
         else if (pid[1] == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT SPAWN CHILD PROCESS");
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            goto restore;
            }
         else {                        /* Still parent                */
                                       /* Create lock file:           */
               sprintf(lockname, "/tmp/%s.%d", procname, pid[1]);
               zmsgwr_ (msg, &n8);
               if ((lockfile = open (lockname, CMODE, PMODE)) == -1) {
                  sprintf(msg, "ZACTV9: CANNOT CREATE LOCK FILE");
                  zmsgwr_ (msg, &n8);
                  if (errno >= 0) {
                     sprintf (msg, "ERRNO = %d (%s)", errno,
                        strerror(errno));
                     zmsgwr_ (msg, &n8);
                     }
                  exit (1);
                  }
               close (lockfile);

                                       /* Wait for child:             */
            waitpid (pid[1], &i, 0);
            }


restore:
         free (debugger);
         unlink (procname);
                                       /* Restore signal handling:    */
         if (sigaction (SIGINT, &saved, &newaction) == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT RESTORE SIGNAL HANDLERS");
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            return;
            }
         }
      }
   else {                            /* Non-debug mode            */
      if (strcmp (rootname, "AIPS") == 0 ||
          strcmp (rootname, "BATER") == 0 ||
          strcmp (rootname, "DAIP") == 0) {
                                       /* Execute new program in this */
                                       /* process:                    */

         pid[1] = (int)getpid ();
         sprintf(lockname, "/tmp/%s.%d", procname, pid[1]);

                                       /* Create lock file:           */
         if ((lockfile = open (lockname, CMODE, PMODE)) == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT CREATE LOCK FILE %s",
               lockname);
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            return;
            }
         close (lockfile);

         if (execl (pathname, procname, NULL) == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT START %s", procname);
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            return;
            }
         }
      else {                           /* Not AIPS or BATER           */
                                       /* Spawn new process as a      */
                                       /* grandchild to prevent an    */
                                       /* accumulation of zombies;    */
                                       /* the pid of the grandchild   */
                                       /* will be returned through a  */
                                       /* pipe:                       */

         if (pipe(p) == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT CREATE PIPE TO CHILD");
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            return;
            }

         if ((child = fork()) == 0) {  /* Child process               */
            close(p[0]);

                                       /* Close all open file         */
                                       /* descriptors (apart from the */
                                       /* pipe and anything that      */
                                       /* might be the message        */
                                       /* terminal):                  */
            for (i = 0; i != sysconf(_SC_OPEN_MAX); i++) {
               if ((i != p[1]) && (i != msg_fd) && (i > 2)) {
                  close (i);
                  }
               }

            if ((grandchild = fork()) == 0) {
                                       /* Grandchild process          */

                                       /* No need to close file       */
                                       /* descriptors since they were */
                                       /* already closed in the       */
                                       /* immediate parent.           */

               if (execl (pathname, procname, NULL) == -1) {
                  sprintf(msg, "ZACTV9: CANNOT START %s", procname);
                  zmsgwr_ (msg, &n8);
                  if (errno >= 0) {
                     sprintf (msg, "ERRNO = %d (%s)", errno,
                        strerror(errno));
                     zmsgwr_ (msg, &n8);
                     }
                  exit (1);
                  }
               }
            else if (grandchild == -1) {
               sprintf(msg, "ZACTV9: CANNOT SPAWN GRANDCHILD");
               zmsgwr_ (msg, &n8);
               if (errno >= 0) {
                  sprintf (msg, "ERRNO = %d (%s)", errno,
                     strerror(errno));
                  zmsgwr_ (msg, &n8);
                  }
               exit (1);
               }
            else {                     /* Still child                 */
                                       /* Create lock file:           */
               sprintf(lockname, "/tmp/%s.%d", procname, grandchild);
               if ((lockfile = open (lockname, CMODE, PMODE)) == -1) {
                  sprintf(msg, "ZACTV9: CANNOT CREATE LOCK FILE");
                  zmsgwr_ (msg, &n8);
                  if (errno >= 0) {
                     sprintf (msg, "ERRNO = %d (%s)", errno,
                        strerror(errno));
                     zmsgwr_ (msg, &n8);
                     }
                  exit (1);
                  }
               close (lockfile);

                                       /* Return grandchild pid to    */
                                       /* parent process:             */
               if (write (p[1], &grandchild, sizeof(pid_t)) == -1) {
                  sprintf(msg, "ZACTV9: CANNOT SEND PID TO PARENT");
                  zmsgwr_ (msg, &n8);
                  if (errno >= 0) {
                     sprintf (msg, "ERRNO = %d (%s)", errno,
                        strerror(errno));
                     zmsgwr_ (msg, &n8);
                     }
                  exit (1);
                  }
               close (p[1]);

               exit (0);
               }
            }
         else if (child == -1) {
            *syserr = errno;
            *ierr = 1;
            sprintf(msg, "ZACTV9: CANNOT SPAWN CHILD PROCESS");
            zmsgwr_ (msg, &n8);
            if (errno >= 0) {
               sprintf (msg, "ERRNO = %d (%s)", errno,
                  strerror(errno));
               zmsgwr_ (msg, &n8);
               }
            return;
            }
         else {                        /* Still parent                */
            close(p[1]);

                                       /* Read grandchild pid         */
            if (read (p[0], &grandchild, sizeof(pid_t)) == -1) {
               *syserr = errno;
               *ierr = 1;
               sprintf(msg, "ZACTV9: CANNOT READ PID");
               zmsgwr_ (msg, &n8);
               if (errno >= 0) {
                  sprintf (msg, "ERRNO = %d (%s)", errno,
                     strerror(errno));
                  zmsgwr_ (msg, &n8);
                  }
               return;
               }
            close(p[0]);
            pid[1] = (int)grandchild;

                                       /* Wait for child:             */
            waitpid (child, &i, 0);
            }
         }
      }
   free (pathname);
   free (dirname);
   }

#endif



More information about the Daip mailing list