/* @(#)sp_utils.c 17.1.1.1 (ESO-IPG) 01/25/02 17:26:44 */ /*--------------------------------------------------------------------- * $Date: 93/07/12 19:02:02 $ $Revision: 2.5.6.1 $ *--------------------------------------------------------------------- * Copyright (c) 1992, Visual Edge Software Ltd. * * ALL RIGHTS RESERVED. Permission to use, copy, modify, and * distribute this software and its documentation for any purpose * and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Visual Edge Software not be * used in advertising or publicity pertaining to distribution of * the software without specific, written prior permission. The year * included in the notice is the year of the creation of the work. *--------------------------------------------------------------------- * File_Description_Section *--------------------------------------------------------------------*/ /*--- include files ---*/ #include "uxproto.h" #include "version.h" #include "subproc.h" #include "sp_spmd.h" #include "sp_pty.h" /*--- macro symbolic constants ---*/ /*--- macro functions ---*/ /*--- types ---*/ /*--- external functions ---*/ /*--- external variables ---*/ /*--- global variables ---*/ /*--- file global variables ---*/ M_FILE_VERSION("$Header") /*--- forward declaration of static functions ---*/ static void InitializeSubprocMgr UXPROTO((void)); /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: NONE * RETURN: void * EXT REFS: globals used * EXT EFFECTS: globals or other things altered * ASSUMPTIONS: the fields of the structure are accessed by #define * REVISIONS: 04/01/93 fix3810 creation dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ static void InitializeSubprocMgr() { #ifdef _PTY_DRIVER UX_PREPARE_COMMAND = UxPtyPrepareCommand; UX_SET_PARENT_SIDE = UxGetPtty; UX_SETUP_PARENT_COMMUNICATION = UxSetPseudo; UX_START_CHILD = UxPtyStartChild; UX_SET_CHILD_SIDE = UxSetTty; UX_SETUP_CHILD_COMMUNICATION = UxPtyChildCommSetup; UX_SPMD_EXEC_SUBPROCESS = UxPtyExecSubprocess; UX_CLOSE_COMMUNICATION = UxPtyExitHandler; #endif #ifdef _STREAM_DRIVER UX_PREPARE_COMMAND = UxStreamPrepareCommand; UX_SET_PARENT_SIDE = UxGetStream; UX_SETUP_PARENT_COMMUNICATION = NULL; UX_START_CHILD = UxStreamStartChild; UX_SET_CHILD_SIDE = UxSetStream; UX_SETUP_CHILD_COMMUNICATION = UxStreamChildCommSetup; UX_EXEC_SUBPROCESS = UxStreamExecSubprocess; UX_CLOSE_COMMUNICATION = UxStreamExitHandler; #endif } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: NONE * RETURN: int - index of new process in processes array * EXT REFS: UxSpmd, UxSpArray * EXT EFFECTS: UxSpArray * ASSUMPTIONS: * REVISIONS: 05/01/93 fix3810 clean-up dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ int UxGetSp() { /* declare register as int because of PS/2 compiler */ /* where the default register declarations are of type const */ register int i; InitializeSubprocMgr(); /* Start the Sub-Process Manager Daemon * if it hasn't already been started. */ if ((UxSpmd.spmd_pid <= 0) && (UxSpmdCreateDaemon() == ERROR)) { error_msg("Subprocess Manager Daemon cannot be started"); return(ERROR); } /* look for a free slot in the array */ for(i = 0; i < MAX_SUBPROC; i++) { if( UxSpArray[i] == (SubprocInfo_t *)0) break; } if(i == MAX_SUBPROC) { char *msg, *fmt; fmt = CGETS( MS_MISC_MAX_PROCS, DS_MS_MISC_MAX_PROCS); msg = UxMalloc(strlen(fmt) + 16 + 1); sprintf(msg,fmt,MAX_SUBPROC); error_msg(msg); UxFree(msg); return(ERROR); } else { if(! (UxSpArray[i] = (SubprocInfo_t *)UxCalloc(1, sizeof(SubprocInfo_t))) ) { UxInternalError(__FILE__, __LINE__, CGETS( MS_MISC_CALLOC_ERR,DS_MS_MISC_CALLOC_ERR)); return ERROR; } else { UxSpArray[i]->handle = -1; UxSpArray[i]->pid = -1; UxSpArray[i]->subprocStatus = UNDEFINED; return i; } } } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: handle index - index to subproc struct * RETURN: ERROR/NO_ERROR * EXT REFS: UxSpArray * EXT EFFECTS: globals or other things altered * ASSUMPTIONS: * REVISIONS: 05/01/93 fix3810 clean-up 11/03/93 fix3989 tested for MAX_SUBPROC - 1 dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ int UxCheckIndex(index) handle index; { if ((index < 0) || (index > (MAX_SUBPROC - 1))) { UxError( CGETS( MS_MISC_INV_HNDL, DS_MS_MISC_INV_HNDL)); return(ERROR); } if( !(UxSpArray[index]) ) { UxError( CGETS( MS_MISC_NOT_HNDL, DS_MS_MISC_NOT_HNDL)); return(ERROR); } return(NO_ERROR); } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: char *msg1, *msg2; message to print. * RETURN: void * EXT REFS: globals_used * EXT EFFECTS: globals or other things altered * ASSUMPTIONS: * REVISIONS: 05/01/93 fix3810 cleanup * dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ void UxSyserr(msg1, msg2) char *msg1; char *msg2; { int error; extern int errno, sys_nerr; #if !defined(__linux__) extern char *sys_errlist[]; #endif char buffer[BUFSIZ]; *buffer = '\0'; error = errno; if (msg1 && *msg1) { (void) strcat(buffer, msg1); (void) strcat(buffer, ": "); if (msg2 && *msg2) { (void) strcat(buffer, msg2); (void) strcat(buffer, ": "); } } if(error > 0 && error < sys_nerr) { (void) strcat(buffer, sys_errlist[errno]); (void) strcat(buffer, "\n"); } else { (void) strcat(buffer, CGETS( MS_MISC_SYS_ERR, DS_MS_MISC_SYS_ERR)); } UxStandardError(buffer); } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: int pid - process id int status - status of the process * RETURN: void * EXT REFS: UxSpArray * EXT EFFECTS: UxSpArray * ASSUMPTIONS: * REVISIONS: 05/01/93 fix3810 clean-up 02/04/93 fix4074 set subprocStatus flag dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ void UxOnExitRunExitCb(pid, status) int pid; int status; { int i; if (pid != -1) { for (i=0; ipid == pid) { UxSpArray[i]->subprocStatus = EXITING; if (UxSpArray[i]->exit_cb) { (*UxSpArray[i]->exit_cb)(pid, status, i); } UxSpExit(UxSpArray[i]); if (UxSpArray[i]->subprocStatus!=DELAYED_EXIT) { UxSpArray[i]->pid = -1; UxSpArray[i]->subprocStatus = UNDEFINED; } break; } } } } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: char *process, *command_line -- args * RETURN: char **args - returns pointer to the argument array * EXT REFS: globals_used * EXT EFFECTS: globals or other things altered * ASSUMPTIONS: * REVISIONS: 05/01/93 fix3810 clean-up dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ char **UxBuildArgs(process, command_line) char *process, *command_line; { static char *Buffer = NULL; static char **Argv = (char **) 0; register char *From; register char *To; register char **ArgvPtr; register int Quote; int i; if (! command_line) command_line = ""; /* allocate storage for string to be mucked with and copy it over... */ if (Buffer) Buffer = (char*)UxRealloc(Buffer, strlen(command_line) + 1); else Buffer = UxMalloc(strlen(command_line) + 1); (void) strcpy(Buffer, command_line); /* Allocate storage for Argv. We don't need to be exact. We just don't * want to underestimate the number of arguments (or we trash memory), * and we don't want to grossly overestimate the amount of memory. If * we count all groups of spaces as separators we will be close -- we * will overcount any that are quoted. */ /* The first one is for the command being executed... */ for (i = 1, From = Buffer; *From; ) { /* count this as a potential argument... */ (void) i++; /* skip over characters... */ while (*From && ((*From != ' ') && (*From != '\t'))) (void) From++; /* skip over white space... */ while (*From && ((*From == ' ') || (*From == '\t'))) (void) From++; } /* leave an extra one for null terminating the array... */ if (Argv) Argv = (char **) UxRealloc((char *) Argv, (i + 1) * sizeof(char *)); else Argv = (char **) UxMalloc((i + 1) * sizeof(char *)); /* initialize the world... */ ArgvPtr = Argv; From = Buffer; To = Buffer; Quote = 0; *ArgvPtr++ = process; *ArgvPtr = To; /* ** skip over leading blanks */ while (*From && ((*From == ' ') || (*From == '\t'))) (void) From++; if (*From == '\0') { *ArgvPtr = (char *) 0; return (Argv); } while (*From) { #ifdef DEBUGPARSE printf ("char='%c' ", *From); #endif /* DEBUGPARSE */ switch (*From) { case '\'' : case '"' : /* ** if we are not quoting, start doing so */ if (Quote == 0) { #ifdef DEBUGPARSE printf ("quoting on\n"); #endif /* DEBUGPARSE */ Quote = *From++; break; } /* ** if we are done quoting, do so */ if (Quote == *From) { #ifdef DEBUGPARSE printf ("quoting off\n"); #endif /* DEBUGPARSE */ Quote = 0; From++; break; } /* ** else, it is a valid character */ #ifdef DEBUGPARSE printf ("copied\n"); #endif /* DEBUGPARSE */ *To++ = *From++; break; case ' ' : case '\t' : if (Quote) { #ifdef DEBUGPARSE printf ("quoted tab/space\n"); #endif /* DEBUGPARSE */ *To++ = *From++; break; } /* ** put in a null and advance ArgvPtr */ #ifdef DEBUGPARSE printf ("seperator\n"); #endif /* DEBUGPARSE */ while ((*From == ' ') || (*From == '\t')) (void) From++; *To++ = '\0'; /* if we are done, return the string. This takes care * of the problem of command lines terminated by spaces. */ if (*From == '\0') { *(++ArgvPtr) = (char *) 0; return (Argv); } *(++ArgvPtr) = To; break; case '\\' : /* ** quote the next character directly */ (void) From++; if (*From) { #ifdef DEBUGPARSE printf ("quoting '%c'\n", *From); #endif /* DEBUGPARSE */ *To++ = *From++; } break; default : #ifdef DEBUGPARSE printf ("copied\n"); #endif /* DEBUGPARSE */ *To++ = *From++; break; } } *To = '\0'; *(++ArgvPtr) = (char *) 0; return (Argv); } #ifdef DEBUG /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: char **tmp - arg list * RETURN: NONE * EXT REFS: globals_used * EXT EFFECTS: globals or other things altered * ASSUMPTIONS: * REVISIONS: 05/01/93 fix3810 clean-up dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ int UxPrintArgs(tmp) char **tmp; { int i; printf("Argument list\n"); for(i = 0; tmp[i]; i++) printf("Arg %d: %s\n", i, tmp[i]); printf("\n"); } #endif /* DEBUG */ /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: subproc *sp - process that exits * RETURN: void * EXT REFS: globals_used * EXT EFFECTS: UxSpArray via sp * ASSUMPTIONS: * REVISIONS: 13/06/89 creation 05/01/93 fix3810 clean-up dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ void UxSpExit (sp) SubprocInfo_t *sp; { if(sp->handle != -1) { (void)close(sp->handle); sp->handle = -1; } } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: subproc *sp -- subprocess object * RETURN: void * EXT REFS: globals_used * EXT EFFECTS: UxSpArray via sp * ASSUMPTIONS: * REVISIONS: 19/12/91 fix3288 05/01/93 fix3810 clean-up dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ void UxSpCheck(sp) SubprocInfo_t *sp; { if(!sp) return; if ((kill(sp->pid, 0) == -1) && (errno != EPERM)) { sp->pid = -1; UxSpExit (sp); } } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: subproc *sp - subproc object * RETURN: void * EXT REFS: globals_used * EXT EFFECTS: globals or other things altered * ASSUMPTIONS: * REVISIONS: 05/01/93 fix3810 cleanup * dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ void UxOutputHandler(sp) SubprocInfo_t *sp; { if(!sp) { error_msg(CGETS( MS_MISC_INV_SPRC_STRUCT, DS_MS_MISC_INV_SPRC_STRUCT)); return; } if(! sp->output_fnt ) { error_msg(CGETS( MS_MISC_INV_OUT_FNCTN, DS_MS_MISC_INV_OUT_FNCTN)); return; } (*sp->output_fnt) (sp->handle, sp->user_data); } /*---------------------------------------------------------------------- * NAME: * DESCRIPTION: * PARAMETERS: none * RETURN: nothing * EXT REFS: UxSpArray * EXT EFFECTS: UxSpArray * ASSUMPTIONS: * REVISIONS: 23/04/93 fix4181 handle Ctrl-C in design time dd/mm/yy fix# fix_description *--------------------------------------------------------------------*/ void UxKillAllSubprocs() { int i; for(i = 0; i < MAX_SUBPROC; i++) { if( (UxSpArray[i] != (SubprocInfo_t *)0) && (UxSpArray[i]->subprocStatus != EXITING)) { UxDeleteSubproc (i); } } }