/* @(#)preph.c 17.1.1.1 (ESO-DMD) 01/25/02 17:37:40 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) 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 ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*+++++++++++++++++++ MIDAS monitor routines PREPH +++++++++++++++++++++++++++ .LANGUAGE C .IDENTIFICATION Module PREPH .AUTHOR K. Banse ESO - Garching .ENVIRONMENT VMS and UNIX .KEYWORDS MIDAS monitor, process control .COMMENTS holds INPREPA, START_IT, RUN_IT, STOP_IT, DCLOP, ASSIO, DCLDEM, HTERM, CNTRLC, EXH, intmonit .VERSION [1.00] 870710: initial vers. built from FORTRAN v. 4.30 as of 870311 010917 last modif ----------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include /* for symbolic signal names */ static char keyfile[200]; /* full name of MID_WORK:FORGRxy.KEY */ static char Userterm[20]; static char prefix[8]; #if vms static int ttchan, mbchan; /* old MONIT.TTCHAN, MONIT.MBCHAN */ static char mbx[12]; static char vmsbuf[200]; static int Cintr = 1; void START_IT(); #endif /* */ void intmonit() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE interrupt routine for Cntrl/C in the monitor .ALGORITHM clean up all the stuff from Midas procedures .RETURNS nothing -----------------------------------------------------------------------*/ { #if vms Cintr = 1; #endif MONIT.CTRLC = 1; /* indicate the interrupt */ osscatch(SIGINT,intmonit); /* reenable CntrlC catching */ } /* */ void INPREPA() /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE link to the keyword file as a shared data structure set initial values for SYSCOM create subprocess FORGRxy and set up everything what's needed for communicating with that subprocess .ALGORITHM create + map global section for keyword file + hold it until PREPA exits .RETURNS nothing ---------------------------------------------------------------------------*/ { int iwa, mm, kk, stat, fastmem; register int nr; char cbuf[20]; extern char DATA_PATH[328]; fastmem = myINIT(0); /* clean FCT and do other stuff like in SCSPRO */ /* init global data */ MONIT.LEVEL = 0; MONIT.COUNT = 0; MONIT.INTERRUPT = 0; MONIT.PAUSLEVL = -1; MONIT.TOPLEVL = 0; MONIT.CROSS_COUNT = 0; MONIT.COMPILED = 0; ERRORS.STATUS = 0; /* init low level error status */ ERRORS.SYS = 0; /* and for the Monitor */ MONIT.CTRLC = 0; for (nr=0; nr INITCOM will use update_cmd_list() */ (void) strcpy(BATCH[0].CMND,"IF"); /* same order as in COMPILE !! */ (void) strcpy(BATCH[1].CMND,"ELSE"); (void) strcpy(BATCH[2].CMND,"ELSEIF"); (void) strcpy(BATCH[3].CMND,"ENDIF"); (void) strcpy(BATCH[4].CMND,"DO"); (void) strcpy(BATCH[5].CMND,"ENDDO"); (void) strcpy(PROC.FORMAT,"4.4 18.8 18.8 "); /* init interactive FORMAT */ FRAMACC('I',KAUX.OUT,0,&iwa); /* init structure FRAME */ /* set error_continue, error_log and error_display flag for the monitor */ ERRO_CONT = 1; /* continue always */ ERRO_LOG = 0; /* log nothing */ ERRO_DISP = 0; /* display nothing */ ERRO_INDX = -1; /* clear error message pointers */ ERRO_OFF = 0; /* initialize CONTEXT structure */ kk = MAX_CONTXT * 8; CGN_FILL(CONTXT.NAME,' ',kk); /* clear context names */ CONTXT.NAME[kk] = '\0'; /* make sure we have an end marker */ CONTXT.STACK = 0; CONTXT.BASE = 0; for (nr=0; nr 160 char.\n\r"); ospexit(1); } #if vms if (keyfile[kk-1] != FSY_DISKEND) { if (keyfile[kk-1] != FSY_DIREND) { keyfile[kk++] = FSY_DIREND; keyfile[kk] = '\0'; } } #else if (keyfile[kk-1] != FSY_DIREND) { keyfile[kk++] = FSY_DIREND; keyfile[kk] = '\0'; } #endif (void) strcpy(FRONT.STARTUP,keyfile); /* save name of startup directory */ (void) strcpy(CPATH[0].STR,keyfile); /* also in CPATH[0] */ (void) strcpy(EPATH[0].STR,keyfile); /* also in EPATH[0] */ for (nr=1; nr<4; nr++) { CPATH[nr].STR[0] = '\0'; /* mark the end */ EPATH[nr].STR[0] = '\0'; /* mark the end */ } /* get foreground keys in */ if (FRONT.ENV == '*') /* Unix command line input */ stat = MID_MOVKEY("IM","*"); else { (void) strcpy(&keyfile[kk],"FORGR .KEY"); keyfile[kk+5] = FRONT.DAZUNIT[0]; keyfile[kk+6] = FRONT.DAZUNIT[1]; stat = MID_MOVKEY("IM",keyfile); } if (stat != ERR_NORMAL) ospexit(1); stat = MID_LOG('I',FRONT.DAZUNIT,2); /* open the logfile */ if (stat != ERR_NORMAL) { (void) strcpy(cbuf,"INPREPA/MID_LOG:"); MID_ERROR("MIDAS",cbuf,stat,1); } (void) strcpy(prefix,"FORGR "); /* will be used in DCLOP() */ prefix[5] = FRONT.DAZUNIT[0]; prefix[6] = FRONT.DAZUNIT[1]; /* save offsets for keys P1,...,P8 + Q1, Q2, Q3 */ MONIT.POFF[0] = OFF_P1; MONIT.POFF[1] = OFF_P2; MONIT.POFF[2] = OFF_P3; MONIT.POFF[3] = OFF_P4; MONIT.POFF[4] = OFF_P5; MONIT.POFF[5] = OFF_P6; MONIT.POFF[6] = OFF_P7; MONIT.POFF[7] = OFF_P8; MONIT.POFF[8] = OFF_Q1; MONIT.POFF[9] = OFF_Q2; MONIT.POFF[10] = OFF_Q3; KIWORDS[OFF_OUTFLG] = 99; /* init keyword OUT$FLAG */ KIWORDS[OFF_OUTFLG+2] = -1; (void) strcpy(&KCWORDS[OFF_OUTNAM]," yyy"); KIWORDS[OFF_MODE+6] = 0; /* reset overall program level */ KIWORDS[OFF_MONPAR+2] = KEY_MAXENT; /* store no. of global + local keys */ KIWORDS[OFF_MONPAR+3] = LOC_MAXENT; KIWORDS[OFF_MONPAR+18] = fastmem; /* save FASTMEM option */ if (fastmem != 0) KIWORDS[OFF_MONPAR+19] = 2000; /* set MP(20) = 4000 */ CGN_FILL(&KCWORDS[OFF_DPATH],' ',319); /* initialize keyword DATA_PATH */ for (nr=0; nr<320; nr+=80) KCWORDS[OFF_DPATH+nr] = '^'; KCWORDS[OFF_DPATH+319] = '\0'; (void) strcpy(DATA_PATH,&KCWORDS[OFF_DPATH]); /* copy also to DATA_PATH */ PIPE.CONT[0] = '\0'; /* clear PIPE(line) structure */ PIPE.EXE[0] = '\0'; PIPE.PROC[0] = '\0'; PIPE.INSTRUM[0] = '\0'; for (nr=0; nr<5; nr++) /* clear REDIRECT structure */ REDIRECT[nr].OUTFLAG[0] = 99; /* clear default definitions + open file internal.cod */ (void) PARDEFS('I'," "); (void) INTERNAL("OPEN","COD",&mm); /***************** VMS ***********************/ #if vms START_IT(); /* start up foreground process */ #endif /***********************************************/ /* set up terminal and use TermWindows (only in interactive mode...) */ cbuf[0] = ' '; (void) OSY_TRNLOG("TERMWIN",cbuf,3,&kk); if ( ((cbuf[0] == 'y') || (cbuf[0] == 'Y')) && (KIWORDS[OFF_MODE+2] != 1) ) KIWORDS[OFF_AUX+7] = 1; /* turn TW on */ else KIWORDS[OFF_AUX+7] = 0; /* turn TW off */ DSC_FLAG = 'Y'; /* use new descr. format w. integrated Help Text */ osscatch(SIGINT,intmonit); /* set up Control/C interrupt handler */ } /* */ #if vms void START_IT() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE create subprocess FORGRxy and set up everything what's needed for communicating with that subprocess .ALGORITHM use lots of system service calls .RETURNS nothing -----------------------------------------------------------------------*/ { char eqn[2][20], cbuf[200]; int stat, mm, pid; int DCLDEM(), HTERM(), EXH(); /* external functions */ stat = OSY_DCLEXH(EXH); /* declare exit handler */ if (stat != ERR_NORMAL) { printf("problems with exit handler/event_flag clearing...\n\r"); ospexit(1); } /* Create mailboxes for DCL commands to foreground processes */ (void) strcpy(mbx,"FORGR _IN"); mbx[5] = FRONT.DAZUNIT[0]; mbx[6] = FRONT.DAZUNIT[1]; stat = OSY_CREMBX(mbx,&mbchan); if (stat != ERR_NORMAL) { (void) printf("problems with mailbox creation...\n\r"); ospexit(1); } stat = OSY_TRNLOG(mbx,&eqn[0][0],20,&mm); /* get equivalence name */ if (stat != ERR_NORMAL) { (void) printf("could not translate mailbox %s ...\n\r",mbx); ospexit(1); } else eqn[0][mm] = '\0'; MONIT.PROCESS = 0; /* Enable AST for subprocess's first DCL input request */ stat = OSY_ENAST(mbchan,"READATT",DCLDEM,0); if (stat != ERR_NORMAL) { (void) printf("could not enable AST for mailbox, status = %x \n\r",stat); ospexit(1); } /* Create subprocess */ mbx[7] = '\0'; /* that's already the process name */ stat = OSY_SPAWN(&eqn[0][0],mbx,Userterm,&pid,HTERM,&mm); MONIT.PID = pid; if (stat != ERR_NORMAL) { (void) printf("could not spawn subprocess - delete old FORGRxy process\n\r"); ospexit(1); } /* Hibernate until something happens */ stat = OSY_HIBER(); if (stat != ERR_NORMAL) { (void) printf("problems with hibernating call, status = %x \n\r",stat); ospexit(1); } /* --- we only get here after having been woken up by the subprocess --- */ sect_1000: if (MONIT.PROCESS != 1 ) /* has the subprocess died? */ { (void) printf(" subprocess %s has died...\n\r",mbx); ospexit(1); } /* Make subprocess assignments at user level */ (void) strcpy(vmsbuf,Userterm); ASSIO(vmsbuf,vmsbuf); } /* */ void RUN_IT(image) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE run given image in a subprocess .ALGORITHM enable CNTRL/C AST to terminate a foreground process .RETURNS nothing ---------------------------------------------------------------------*/ char *image /*IN: image to be executed in the subprocess */; { char *dclpntr; int stat, mm, kk; int DCLDEM(), CNTRLC(); /* Enable CTRL/C AST only for interactive foreground process */ if (Cintr > 0) { if (KIWORDS[OFF_MODE+2] != 1) { mm = 0; stat = OSY_ENAST(ttchan,"CNTRLC",CNTRLC,0); if (stat != ERR_NORMAL) { (void) printf("could not enable AST for CNTRL_C, status = %x\n\r",stat); ospexit(1); } } MONIT.CTRLC = 0; /* just for compatibility */ Cintr = 0; } /* check, that subprocess has not died */ if (MONIT.PROCESS < 0) { (void) printf("RUN_IT: subprocess %s has died...\n\r",mbx); ospexit(1); } /* image name or host opsys command? */ if (*image == '$') { MONIT.PROCESS = 2; /* host opsys command: set flag */ dclpntr = image; if (CGN_INDEXC(dclpntr,'@') > 0) KAUX.DCLINP = 1; } else { MONIT.PROCESS = 3; /* image: set flag + construct RUN command */ dclpntr = vmsbuf; if (MONIT.MDEBUG[MONIT.LEVEL] != 0) { if (MONIT.MDEBUG[MONIT.LEVEL] == 2) { (void) strcpy(dclpntr,"$RUN/DEBUG "); /* with debugger */ (void) strcpy(dclpntr+11,image); } else /* get the current time first */ { (void) sprintf(vmsbuf,"before %s",image); SCTPUT(vmsbuf); OSY_ASCTIM(vmsbuf); SCTPUT(vmsbuf); (void) strcpy(dclpntr,"$RUN/NODEBUG "); /* without debugger */ (void) strcpy(dclpntr+13,image); MONIT.PROCESS = 9; } } else { (void) strcpy(dclpntr,"$RUN/NODEBUG "); /* without debugger */ (void) strcpy(dclpntr+13,image); } /* write keywords out + command string into mailbox */ fixout(1,MONIT.LEVEL); /* close any ASCII out file */ (void) MID_LOG('O',LINE.STR,2); /* close logfile */ (void) MID_MOVKEY("O",vmsbuf); /* write keywords out */ } DCLOP(dclpntr); /* Enable AST for PREPA -> PROCESS mailbox read demand */ stat = OSY_ENAST(mbchan,"READATT",DCLDEM,0); if (stat != ERR_NORMAL) { (void) printf("could not enable AST for READATT, status = %x\n\r",stat); ospexit(1); } /* hibernate until something happens */ stat = OSY_HIBER(); if (stat != ERR_NORMAL) { (void) printf("problems with hibernating call, status = %x\n\r",stat); ospexit(1); } /* --- we only get here after having been woken up by the subprocess --- */ sect_1000: if (MONIT.PROCESS >= 3) { (void) strcpy(vmsbuf,FRONT.STARTUP); /* get name of startup directory */ kk = strlen(vmsbuf); (void) strcpy(&vmsbuf[kk],"FORGR .KEY"); vmsbuf[kk+5] = FRONT.DAZUNIT[0]; vmsbuf[kk+6] = FRONT.DAZUNIT[1]; (void) MID_MOVKEY("IM",vmsbuf); /* get keywords back */ (void) MID_LOG('I',FRONT.DAZUNIT,2); /* open logfile again */ if (MONIT.PROCESS == 9) /* get current time after execution */ { (void) sprintf(vmsbuf,"after %s",image); SCTPUT(vmsbuf); OSY_ASCTIM(vmsbuf); SCTPUT(vmsbuf); } } } /* */ STOP_IT() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE kill foreground subprocess; .ALGORITHM PID is stored in MONIT.PID - use system service calls .RETURNS nothing ----------------------------------------------------------------*/ { int stat; /* flush terminal I/O + delete process */ (void) OSY_CANCEL(ttchan); if (MONIT.PROCESS != -1) { stat = OSY_DELPRC(&MONIT.PID); /* try to abort foreground process */ if (stat != ERR_NORMAL) (void) printf("problems with process deletion, status = %x\n\r",stat); MONIT.PROCESS = -1; } } /* */ ASSIO(indev,outdev) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE assign the standard I/O streams for subprocess .ALGORITHM use DCLOP to pass "$ASSIGN commands" to the subprocess .RETURNS nothing --------------------------------------------------------------------*/ char *indev /*IN: point to input device (with '\0') */; char *outdev /*OUT: output device (with '\0') */; { int mm; char work[60]; DCLOP("$SET NOVERIFY"); /* Switch off verify in subprocess */ DCLOP("$SET NOON"); /* Prevent error exit */ (void) strcpy(work,"$ASSIGN "); (void) strcpy(&work[8],indev); mm = strlen(work); (void) strcpy(&work[mm]," SYS$COMMAND"); /* $ASSIGN indev SYS$COMMAND */ DCLOP(work); (void) strcpy(&work[mm]," SYS$INPUT"); /* $ASSIGN indev SYS$INPUT */ DCLOP(work); (void) strcpy(&work[mm]," FOR$READ"); /* $ASSIGN indev FOR$READ */ DCLOP(work); (void) strcpy(&work[mm]," DBG$INPUT"); /* $ASSIGN indev DBG$INPUT */ DCLOP(work); (void) strcpy(&work[mm]," TT"); /* $ASSIGN indev SYS$COMMAND */ DCLOP(work); (void) strcpy(&work[8],outdev); mm = strlen(work); (void) strcpy(&work[mm]," SYS$OUTPUT"); /* $ASSIGN outdev SYS$OUTPUT */ DCLOP(work); } /* */ DCLDEM() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE service AST when subprocess requests next DCL command .ALGORITHM wake up main process .RETURNS nothing ---------------------------------------------------------------*/ { int stat; /* If first time, set subprocess status = created */ if (MONIT.PROCESS == 0) MONIT.PROCESS = 1; /* Wake the main process */ stat = OSY_WAKE(); if (stat != ERR_NORMAL) ospexit(1); /* for host (DCL) commands we may have to reset SYS$INPUT... */ if (KAUX.DCLINP == 1) { KAUX.DCLINP = 0; (void) strcpy(vmsbuf,"$ASSIGN "); (void) strcpy(&vmsbuf[8],Userterm); (void) strcat(vmsbuf," SYS$INPUT"); DCLOP(vmsbuf); } } /* */ HTERM() /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE service AST when subprocess terminates .ALGORITHM wake up main process .RETURNS nothing ------------------------------------------------------------------*/ { int stat; /* Set the process status flag */ MONIT.PROCESS = -1; /* Wake the main process if hibernating */ stat = OSY_WAKE(); if (stat != ERR_NORMAL) ospexit(1); } /* */ EXH(stat) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE kill subprocesses on forced exit of main process .ALGORITHM will be called as EXH(stat) when main process crashes use OSY_DELPRC .RETURNS nothing ------------------------------------------------------------------*/ int *stat /* IN: status of exit */; { /* Last chance to get rid of subprocesses */ if (MONIT.PROCESS != -1) { *stat = OSY_DELPRC(&MONIT.PID); MONIT.PROCESS = -1; } if (KIWORDS[OFF_AUX+7] == 1) ostraw(0); } /* */ DCLOP(dcl) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE pass DCL input to subprocess via mailbox .ALGORITHM get mailbox from keyword CHANNEL + use system service calls .RETURNS nothing -------------------------------------------------------------------------*/ char *dcl /* IN: pointer to host command (terminated by '\0') */; { int stat; /* Write DCL command to mailbox */ stat = OSY_WRCHAN(mbchan,dcl,(int)strlen(dcl)); if (stat != ERR_NORMAL) { if (strncmp(dcl,"$RUN",4) == 0) { char string[160]; int nr, m; for (nr=0; nr<4; nr++) { if (EPATH[nr].STR[0] == '\0') break; m = CGN_COPY(string,EPATH[nr].STR); (void) strcpy(&string[m],dcl); stat = OSY_WRCHAN(mbchan,string,(int)strlen(string)); if (stat == ERR_NORMAL) return; } } printf("problems with OSY_WRCHAN of %s ...\n\r",dcl); } } /* */ CNTRLC() /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE AST routine for CTRL/C .ALGORITHM reset any procedure level, clear local keys + force exit of image in subproce .RETURNS nothing -----------------------------------------------------------------------*/ { int stat; /* proceed unless subprocess isn't running a job */ (void) strcpy(vmsbuf,"FORGR "); vmsbuf[5] = FRONT.DAZUNIT[0]; vmsbuf[6] = FRONT.DAZUNIT[1]; stat = OSY_FORCEX(vmsbuf); if (stat != ERR_NORMAL) ospexit(1); MONIT.CTRLC = 1; /* indicate the interrupt */ Cintr = 1; } /* */ #else /* Unix part */ void RUN_IT(image) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE run given image in a subprocess .ALGORITHM enable CNTRL/C AST to terminate a foreground process .RETURNS nothing ---------------------------------------------------------------------*/ char *image /*IN: image to be executed in the subprocess */; { int kk, exec_stat; char cbuf[200]; /* image name or host opsys command? */ if (*image == '$') { MONIT.PROCESS = 2; /* host opsys command: set flag */ exec_stat = DCLOP(image); } else { MONIT.PROCESS = 3; /* image name: set flag + prepare execution of image */ if (MONIT.MDEBUG[MONIT.LEVEL] != 0) { if (MONIT.MDEBUG[MONIT.LEVEL] == 2) /* we use the debugger */ { kk = OFF_SYS + 20; /* points to keyword MID$SYS */ (void) strncpy(cbuf,&KCWORDS[kk],10); /* copy name of debugger */ cbuf[10] = ' '; kk = CGN_INDEXC(cbuf,' '); (void) strcpy(&cbuf[kk+1],image); image = cbuf; } else /* get the current time first */ { (void) sprintf(cbuf,"before %s",image); SCTPUT(cbuf); OSY_ASCTIM(cbuf); SCTPUT(cbuf); MONIT.PROCESS = 9; } } /* close logfile + write keywords out */ fixout(1,MONIT.LEVEL); /* close any ASCII out file */ (void) MID_LOG('O',LINE.STR,2); /* close logfile */ (void) MID_MOVKEY("O",cbuf); /* write keywords out */ exec_stat = DCLOP(image); /* on return from subprocess move keyword stuff back in */ if (FRONT.ENV == '*') /* from Unix command line */ (void) MID_MOVKEY("IM","*"); /* get keywords back in */ else (void) MID_MOVKEY("IM",keyfile); /* inside Midas */ (void) MID_LOG('I',FRONT.DAZUNIT,2); /* open logfile again */ if (MONIT.PROCESS == 9) /* get current time after execution */ { (void) sprintf(cbuf,"after %s",image); SCTPUT(cbuf); OSY_ASCTIM(cbuf); SCTPUT(cbuf); } } if (exec_stat != ERR_NORMAL) /* now we can also log */ { /* errors from the execution */ if (exec_stat == ERR_OPSSYS) { char *mypr, *osmsg(); mypr = osmsg(); (void) sprintf(KAUX.OUT,"(ERR) Problems in executing %s",image); SCTPUT(KAUX.OUT); SCTPUT(mypr); kk = 888; } else /* ERR_INPINV for timeout */ { (void) sprintf(KAUX.OUT,"(ERR) %s timed out (%d seconds)", image,MONIT.MAXTIME); SCTPUT(KAUX.OUT); kk = 998; } KIWORDS[OFF_PRSTAT] = kk; /* store status and error source */ KIWORDS[OFF_PRSTAT+1] = 100; /* into key PROGSTAT */ } } /* */ int DCLOP(dcl) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE start up subprocess to run executable .ALGORITHM use system service .RETURNS nothing -------------------------------------------------------------------------*/ char *dcl /* IN: pointer to host command (terminated by '\0') */; { int pid, maxtime, stat; maxtime = MONIT.MXT[MONIT.LEVEL]; if ((maxtime > 0) && (MONIT.LEVEL > 0)) { long int oshtime(); maxtime = (int) (MONIT.ENDT[MONIT.LEVEL] - oshtime()); if (maxtime < 1) return (ERR_INPINV); } stat = OSY_SPAWN(0,dcl,prefix,maxtime,&pid); if (MONIT.PROCESS == 2) { KIWORDS[OFF_AUX+16] = stat; /* host return status => AUX_MODE(17) */ stat = ERR_NORMAL; } else { if ( (stat != ERR_NORMAL) && (oserror == ENOENT) ) { char string[160]; int nr, m; for (nr=0; nr<4; nr++) { if (EPATH[nr].STR[0] != '\0') { m = CGN_COPY(string,EPATH[nr].STR); (void) strcpy(&string[m],dcl); if ((stat = OSY_SPAWN(0,string,prefix,maxtime,&pid)) == ERR_NORMAL) break; } } } } MONIT.PID = pid; return (stat); } #endif