/*----------------------------------------------------------------------+*/ SPC_Channel_Ptr SPC_Lookup_Channel(int cid, SPC_Connection_Ptr connection) /*----------------------------------------------------------------------+*/ { SPC_Channel_Ptr spc; if(!cid) return(NULL); _DtSvcProcessLock(); for(spc=spc_activation_list; spc; spc=spc->next) /* This test is here because: a. Only remote channels have cid's b. It is possible for multiple remote servers to have the same cid (which is simply the address of the channel), so we need to distinguish among remote channels, but c. channels on the remote daemon have cid's, but a null connection. */ if((spc->cid == cid) && (!spc->connection || (spc->connection == connection))) { _DtSvcProcessUnlock(); return(spc); } _DtSvcProcessUnlock(); return(NULL); }
char * Dt11GetMessage( char *filename, int set, int n, char *s) { char *msg; static int first = 1; static nl_catd nlmsg_fd; static char *nlmsg_filename = NULL; _DtSvcProcessLock(); if ( NULL == nlmsg_filename || 0 != strcmp(nlmsg_filename, filename) ) { nlmsg_fd = catopen(filename, NL_CAT_LOCALE); if (nlmsg_filename) { free(nlmsg_filename); nlmsg_filename = NULL; } nlmsg_filename = strdup(filename); } msg=catgets(nlmsg_fd,set,n,s); _DtSvcProcessUnlock(); return (msg); }
/*----------------------------------------------------------------------+*/ int SPC_Write_Chars(int fd, XeString charptr, int request_len) /*----------------------------------------------------------------------+*/ { int numchars, numwritten; int numtowrite=request_len; numwritten=0; while(numwritten<request_len) { do numchars=write(fd, charptr, numtowrite); while(numchars == ERROR && errno == EINTR); #ifdef DEBUG _DtSvcProcessLock(); if(SPC_Print_Protocol) fprintf(SPC_Print_Protocol, "SPC_Write_Chars -- wrote: %d of %d, expected: %d, errno: %d\n", numchars, request_len, numtowrite, errno); _DtSvcProcessUnlock(); #endif if(numchars == ERROR) return(ERROR); charptr += numchars; numwritten += numchars; numtowrite -= numchars; } return(numwritten); }
int SUNWDtHelpdlopen() { void *libDtHelpHandle = NULL; _DtSvcProcessLock(); pmySUNWProcList = (SUNWHelpProcList *)malloc(sizeof(SUNWHelpProcList)); libDtHelpHandle = dlopen("libDtHelp.so.2.1", RTLD_LAZY | RTLD_GLOBAL); if (libDtHelpHandle == NULL) { char *my_err_msg; my_err_msg = dlerror(); printf("%s\n", my_err_msg); _DtSvcProcessUnlock(); return(FALSE); } pmySUNWProcList->DtCreateHelpDialogSym = (SUNWWidgetProc) dlsym(libDtHelpHandle, "DtCreateHelpDialog"); pmySUNWProcList->DtCreateHelpQuickDialogSym = (SUNWWidgetProc) dlsym(libDtHelpHandle, "DtCreateHelpQuickDialog"); pmySUNWProcList->DtHelpQuickDialogGetChildSym = (SUNWWidgetProc) dlsym(libDtHelpHandle, "DtHelpQuickDialogGetChild"); pmySUNWProcList->DtHelpReturnSelectedWidgetIdSym = (SUNWIntProc) dlsym(libDtHelpHandle, "DtHelpReturnSelectedWidgetId"); _DtSvcProcessUnlock(); return(TRUE); }
/*-----------------------------------------------------------------------+*/ static SbInputId SPC_RemoveInput(int source, SPC_Callback_Condition condition) /*-----------------------------------------------------------------------+*/ { SPC_Callback_Struct *structptr = NULL; _DtSvcProcessLock(); if (SPC_Fd_Mapping == NULL) { SPC_Fd_Mapping = (SPC_Callback_Struct **) XeMalloc (FD_SETSIZE * sizeof (SPC_Callback_Struct *)); memset(SPC_Fd_Mapping, 0, FD_SETSIZE * sizeof(SPC_Callback_Struct *)); } structptr=SPC_LOOKUP_FD_MAPPING(source); _DtSvcProcessUnlock(); switch(condition) { case SPC_Input: case SPC_Terminator: case SPC_Client: return structptr->read_id; case SPC_Exception: return structptr->except_id; } return 0; }
/*----------------------------------------------------------------------+*/ void SPC_Free_Protocol_Ptr(protocol_request_ptr prot) /*----------------------------------------------------------------------+*/ { _DtSvcProcessLock(); prot->next = free_protocol_requests; free_protocol_requests = prot; _DtSvcProcessUnlock(); }
/*----------------------------------------------------------------------+*/ void SPC_Close_Connection(SPC_Connection_Ptr connection) /*----------------------------------------------------------------------+*/ { SPC_Channel_Ptr channel; SPC_Channel_Ptr next; SPC_Connection_Ptr trail, ptr; /* We have to be careful here. SPC_Input_Handler may call the users termination handler, which in turn might close the channel, which may deallocate the channel. Therefore, we grab the next channel from the list while we are still alive. */ _DtSvcProcessLock(); channel=spc_activation_list; connection->connected = FALSE; while(channel) { next=channel->next; if(channel->connection == connection) { if(!IS_SPCIO_DELAY_CLOSE(channel->IOMode)) SPC_Channel_Terminated(channel); channel->connection = NULL; } channel=next; } SPC_XtRemoveInput(&connection->termination_id, SPC_Terminator); spc_close(connection->sid); connection->sid = (-1); if (connection->hostinfo) XeFree(connection->hostinfo); /* Remove the connection from the connection list */ if(connection_list == connection) connection_list = connection->next; else { trail = connection_list; while(trail) { ptr = trail->next; if(ptr == connection) { trail->next = ptr->next; break; } trail=ptr; } if(!trail) { /* Here if no such connection found. */ } } free((char *)connection); _DtSvcProcessUnlock(); }
/*----------------------------------------------------------------------+*/ void SPC_Add_Connection(SPC_Connection_Ptr connection) /*----------------------------------------------------------------------+*/ { /* Add a connection to the connection_list */ _DtSvcProcessLock(); connection->next = connection_list; connection_list = connection; _DtSvcProcessUnlock(); }
/*-----------------------------------------------------------------------+*/ void SPC_XtBreak(void) /*-----------------------------------------------------------------------+*/ { _DtSvcProcessLock(); if(!spc_xe_termination_flag) { spc_xe_termination_flag = TRUE; if (SbBreakMainLoop_hookfn == NULL) (void) fprintf (stderr, "Error: SbBreakMainLoop = NULL\n"); else (*SbBreakMainLoop_hookfn)(); } _DtSvcProcessUnlock(); }
/*----------------------------------------------------------------------+*/ SPC_Channel_Ptr SPC_Find_PID(int pid) /*----------------------------------------------------------------------+*/ { /* Attempt to return a channel which currently handles process number PID */ SPC_Channel_Ptr spc; _DtSvcProcessLock(); for (spc = spc_activation_list; spc != NULL; spc = spc->next) { if (spc->pid == pid) break; } _DtSvcProcessUnlock(); return spc; /* NULL when not found */ }
void _DtInitializeCommandInvoker( Display *display, char *toolClass, /* ignored */ char *appClass, /* ignored */ DtSvcMessageProc reloadDBHandler, /* OBSOLETE -- ignored */ XtAppContext appContext) { static int beenCalled = 0; _DtSvcAppLock(appContext); /* * Prevent repeat calls */ _DtSvcProcessLock(); if ( beenCalled ) { _DtSvcProcessUnlock(); return; } beenCalled++; cmd_Globals.app_context = appContext; SbAddInput_hookfn = _DtCmdSPCAddInputHandler; SbRemoveInput_hookfn = XtRemoveInput; SbAddException_hookfn = _DtCmdSPCAddExceptionHandler; SbRemoveException_hookfn = XtRemoveInput; _DtCmdBuildPathList (); _DtCmdInitializeErrorMessages (); /* * Must get the name of the invoking host, so that requests * can be checked for remote execution. */ if ((DtGetShortHostname(_cmdClientHost, MAXHOSTNAMELEN)) == -1) { _DtCmdLogErrorMessage ("Cannot determine the local host name.\n"); } _DtCmdGetResources (display); _DtSvcProcessUnlock(); _DtSvcAppUnlock(appContext); }
Widget _DtHelpQuickDialogGetChild( Widget widget, unsigned char child ) { int status; _DtSvcProcessLock(); status = pmySUNWProcList || SUNWDtHelpdlopen(); _DtSvcProcessUnlock(); if (!status) return(NULL); return ((*pmySUNWProcList->DtHelpQuickDialogGetChildSym)(widget, child)); }
/*----------------------------------------------------------------------+*/ SPC_Connection_Ptr SPC_Alloc_Connection(void) /*----------------------------------------------------------------------+*/ { SPC_Connection_Ptr conn; _DtSvcProcessLock(); conn=(SPC_Connection_Ptr) XeMalloc(sizeof(SPC_Connection)); /* Zero the connection */ memset(conn, 0, sizeof(SPC_Connection)); conn->queued_remote_data = Xe_make_queue(FALSE); conn->termination_id = (-1); /* Init the socket id to "-1" because "0" is a valid file descriptor. */ conn->sid = (-1); _DtSvcProcessUnlock(); return(conn); }
Widget _DtCreateHelpQuickDialog( Widget parent, char *name, ArgList al, Cardinal ac) { int status; _DtSvcProcessLock(); status = pmySUNWProcList || SUNWDtHelpdlopen(); _DtSvcProcessUnlock(); if (!status) return(NULL); return ((*pmySUNWProcList->DtCreateHelpQuickDialogSym)(parent, name, al, ac)); }
int _DtHelpReturnSelectedWidgetId( Widget parent, Cursor cursor, Widget *widget) { int status; _DtSvcProcessLock(); status = pmySUNWProcList || SUNWDtHelpdlopen(); _DtSvcProcessUnlock(); if (!status) return(NULL); return ((*pmySUNWProcList->DtHelpReturnSelectedWidgetIdSym)(parent, cursor, widget)); }
/*----------------------------------------------------------------------+*/ void SPC_Conditional_Packet_Handler(void * UNUSED_PARM(client_data), int * source, SPCInputId * UNUSED_PARM(id)) /*----------------------------------------------------------------------+*/ { SPC_Channel_Ptr channel; channel = XeSPCHandleTerminator(*source); /* Okay, blast out of our wait */ _DtSvcProcessLock(); if( (channel==SPC_ERROR || !IS_ACTIVE(channel)) && break_on_termination) SPC_XtBreak(); _DtSvcProcessUnlock(); /* return(TRUE); */ }
/*----------------------------------------------------------------------+*/ protocol_request_ptr SPC_New_Protocol_Ptr (SPC_Channel_Ptr channel, XeChar req, int len) /*----------------------------------------------------------------------+*/ { protocol_request_ptr prot; _DtSvcProcessLock(); if(free_protocol_requests) { prot = free_protocol_requests; free_protocol_requests = free_protocol_requests->next; } else { prot = (protocol_request_ptr)XeMalloc(sizeof(protocol_request)); prot->dataptr = SPC_New_Buffered_Data_Ptr(); } SPC_Reset_Protocol_Ptr(prot, channel, req, len); _DtSvcProcessUnlock(); return(prot); }
/*----------------------------------------------------------------------+*/ SPC_Connection_Ptr SPC_Lookup_Connection(XeString hostname) /*----------------------------------------------------------------------+*/ { /* Search for an existing connection to a server */ SPC_Connection_Ptr conn; _DtSvcProcessLock(); for (conn = connection_list; conn != NULL; conn = conn->next) { /* Look for a connection with the same hostname */ if (!strcmp(conn->hostname, hostname)) { _DtSvcProcessUnlock(); return(conn); } } _DtSvcProcessUnlock(); return(FALSE); }
/*----------------------------------------------------------------------+*/ int SPC_Initialize(void) /*----------------------------------------------------------------------+*/ { XeString home; _DtSvcProcessLock(); if(SPC_Initialized) { _DtSvcProcessUnlock(); return(TRUE); } spc_init_fds(); if (!SPC_ResetTerminator()) { _DtSvcProcessUnlock(); return(SPC_ERROR); } if(!SPC_Init_Local_Host_Info()) { _DtSvcProcessUnlock(); return(SPC_ERROR); } if(SPC_Setup_Synchronous_Terminator()==SPC_ERROR) { _DtSvcProcessUnlock(); return(SPC_ERROR); } if(home=getenv("HOME")) { spc_user_environment_file=(XeString) XeMalloc(strlen(home)+ strlen(SPCD_ENV_HOME_DIRECTORY)+strlen(SPCD_ENV_FILE)+3); sprintf(spc_user_environment_file, "%s/%s/%s", home, SPCD_ENV_HOME_DIRECTORY, SPCD_ENV_FILE); } SPC_Initialized=TRUE; _DtSvcProcessUnlock(); return(TRUE); }
/*----------------------------------------------------------------------+*/ SPC_Connection_Ptr SPC_Lookup_Connection_Fd(int fd) /*----------------------------------------------------------------------+*/ { /* Search for an existing connection to a server, using fd (file descriptor) as a key */ SPC_Connection_Ptr conn; _DtSvcProcessLock(); for (conn = connection_list; conn != NULL; conn = conn->next) { /* Look for a connection with the same hostname */ if (conn->sid==fd) { _DtSvcProcessUnlock(); return(conn); } } _DtSvcProcessUnlock(); return(FALSE); }
void Dt_nlInit( void ) { char * bc; static Boolean first = True; _DtSvcProcessLock(); if (!first) { _DtSvcProcessUnlock(); return; } first = False; _DtSvcProcessUnlock(); if (MB_CUR_MAX > 1) _DtNl_is_multibyte = True; else _DtNl_is_multibyte = False; }
/*-----------------------------------------------------------------------+*/ static int SPC_Select(void ) /*-----------------------------------------------------------------------+*/ { break_on_termination=TRUE; _DtSvcProcessLock(); spc_xe_termination_flag= FALSE; /* Use a function pointer so we don't have explict dependancy */ /* on libXe.a */ /* ---------------------------------------------------------- */ if (SbMainLoopUntil_hookfn == NULL) (void) fprintf (stderr, "Error: SbMainLoopUntil = NULL\n"); else (*SbMainLoopUntil_hookfn)(&spc_xe_termination_flag); _DtSvcProcessUnlock(); break_on_termination=FALSE; return(TRUE); }
/*----------------------------------------------------------------------+*/ int SPC_ResetTerminator(void) /*----------------------------------------------------------------------+*/ { struct sigaction svect; _DtSvcProcessLock(); if (SPC_who_am_i == SPC_I_AM_A_DAEMON) { svect.sa_handler = SPC_Child_Terminated; sigemptyset(&svect.sa_mask); svect.sa_flags = 0; if(sigaction(SIGCHLD, &svect, (struct sigaction *)NULL)==ERROR) { SPC_Error(SPC_No_Signal_Handler); return(SPC_ERROR); } } _DtSvcProcessUnlock(); return (TRUE); }
/*----------------------------------------------------------------------+*/ SPC_Setup_Synchronous_Terminator(void) /*----------------------------------------------------------------------+*/ { int pipes[2]; _DtSvcProcessLock(); if(write_terminator) { _DtSvcProcessUnlock(); return(TRUE); } if(pipe(pipes)<0) { SPC_Error(SPC_No_Pipe); _DtSvcProcessUnlock(); return(SPC_ERROR); } if((write_terminator=SPC_Alloc_Connection())==SPC_ERROR) { _DtSvcProcessUnlock(); return(SPC_ERROR); } SPC_Add_Connection(write_terminator); if((read_terminator=SPC_Alloc_Connection())==SPC_ERROR) { _DtSvcProcessUnlock(); return(SPC_ERROR); } SPC_Add_Connection(read_terminator); write_terminator->sid=pipes[WRITE_SIDE]; write_terminator->connected=TRUE; read_terminator->sid=pipes[READ_SIDE]; read_terminator->connected=TRUE; SPC_XtAddInput(NULL, &read_terminator->termination_id, read_terminator->sid, SPC_Conditional_Packet_Handler, SPC_Terminator); _DtSvcProcessUnlock(); return(TRUE); }
/*-----------------------------------------------------------------------+*/ static int SPC_AddInput(int source, SPC_Callback_Condition condition, SbInputId id) /*-----------------------------------------------------------------------+*/ { SPC_Callback_Struct *structptr = NULL; _DtSvcProcessLock(); if (SPC_Fd_Mapping == NULL) { SPC_Fd_Mapping = (SPC_Callback_Struct **) XeMalloc (FD_SETSIZE * sizeof (SPC_Callback_Struct *)); memset(SPC_Fd_Mapping, 0, FD_SETSIZE * sizeof(SPC_Callback_Struct *)); } structptr=SPC_LOOKUP_FD_MAPPING(source); if(!structptr) { structptr=(SPC_Callback_Struct *) XeMalloc(sizeof(SPC_Callback_Struct)); SPC_LOOKUP_FD_MAPPING(source)=structptr; } _DtSvcProcessUnlock(); switch (condition) { case SPC_Input: case SPC_Terminator: case SPC_Client: structptr->read_id = id; break; case SPC_Exception: structptr->except_id = id; break; default: break; } return(source); }
/*----------------------------------------------------------------------+*/ spc_dup2(int from, int to) /*----------------------------------------------------------------------+*/ { int retval; /* Dup file descriptors. If a null descriptor, then use /dev/null */ static int devnull = NULL; if (from == to) return(TRUE); if (from == -1) { _DtSvcProcessLock(); if (!devnull) devnull = open("/dev/null", 0); /* Use /dev/null when no source file descriptor */ from = devnull; _DtSvcProcessUnlock(); } /* Now do the dup2 */ retval=dup2(from, to); return(retval); }
/****************************************************************************** * * _DtEnvGetTargetCache() * * For a specified targetHost, find existing cache information and * optionally create a cache for a targetHost if one doesn't exist. * * The define MAX_HOSTS_CACHED controls how many targetHosts can * be cached. */ static cacheForTargetHost *_DtEnvGetTargetCache( char *targetHost, int createIfNeeded) { static int cacheHitGen = 0; static int hitIdxStart; int i, hitidx, hitval; /* * Handle obvious. */ if (!targetHost) { return( (cacheForTargetHost *) NULL ); } _DtSvcProcessLock(); /* * Look for targetHost in current cache pool. */ for ( i = 0; i < MAX_HOSTS_CACHED; i++ ) { if ( cachePoolG[i].remoteHost ) { if ( !strcmp( targetHost, cachePoolG[i].remoteHost ) ) { cachePoolG[i].cacheHit++; break; } } } if ( i != MAX_HOSTS_CACHED ) { /* * targetHost is in a cache slot already. */ _DtSvcProcessUnlock(); return( &cachePoolG[i] ); } else if ( !createIfNeeded ) { /* * No cache slot for, and we shouldn't create one either. */ _DtSvcProcessUnlock(); return( (cacheForTargetHost *) NULL ); } else { /* * Find an empty cache slot or take over a rarely used slot. */ hitIdxStart = (hitIdxStart + 7) % MAX_HOSTS_CACHED; hitidx = hitIdxStart; hitval = cachePoolG[hitidx].cacheHit; for ( i = 0; i < MAX_HOSTS_CACHED; i++ ) { if ( ! cachePoolG[i].remoteHost ) { /* * Empty slot - take it. */ hitidx = i; break; } else if ( cachePoolG[i].cacheHit < hitval ) { hitidx = i; hitval = cachePoolG[i].cacheHit; } } if ( cachePoolG[hitidx].remoteHost ) { /* * Cache was in use, clean first. */ _DtEnvCleanCacheSlot( &cachePoolG[hitidx] ); cachePoolG[hitidx].remoteHost = strdup( targetHost ); /* * Since all the slots are full, occasionally reset everyones * cacheHit counters. This gives new targetHosts a chance * to compete with targetHosts that were popular long ago. */ if ( cacheHitGen++ > 50 ) { for ( i = 0; i < MAX_HOSTS_CACHED; i++ ) { cachePoolG[i].cacheHit = 1; } cacheHitGen = 1; } } _DtSvcProcessUnlock(); return( &cachePoolG[hitidx] ); } }
char *_DtEnv_tt_host_netfile_file( const char *host, const char *filename) { static int first_time = 1; static int fragListAvail = CACHE_FILEFRAG_SIZE_START; static int fragListCnt = 0; static cachedNetfileFrag *fragList; static int cacheGen = 0; static int hitIdxStart = 0; char *newfile; int hitval, hitIdx, i; cachedNetfileFrag *tmpCffP; char *tmpStr; int newCount = fragListCnt; _DtSvcProcessLock(); if (first_time) { fragList = (cachedNetfileFrag *) calloc( fragListAvail, sizeof(cachedNetfileFrag) ); first_time = 0; } /* * Take care of the obvious. */ if (!filename) { _DtSvcProcessUnlock(); return( (char *) NULL ); } if (!host) { /* * Return a tt_free-able un-mapped copy. */ tmpStr = tt_malloc( strlen(filename) + 1 ); strcpy( tmpStr, filename ); _DtSvcProcessUnlock(); return(tmpStr); } /* * Look for existing answer in cache. * * While at it, also look for least used entry just in case. */ if (fragListCnt) hitIdxStart = (hitIdxStart + 7) % fragListCnt; else hitIdxStart = 0; hitIdx = hitIdxStart; hitval = fragList[hitIdx].cacheHit; tmpCffP = fragList; /* walk rather than index */ for ( i = 0; i < fragListCnt; i++ ) { if (tmpCffP->cacheHit && !strcmp( filename, tmpCffP->pathFragOrig ) ) { if (!strcmp( host, tmpCffP->targetHost ) ) { break; } } /* * Save index of least used entry */ if (tmpCffP->cacheHit < hitval) { hitIdx = i; hitval = tmpCffP->cacheHit; } tmpCffP++; } /* * Decide what was found. */ if ( i != fragListCnt ) { /* * Found a cached entry. */ hitIdx = i; if ( fragList[hitIdx].cacheHit++ > CACHE_FILEFRAG_REMAP_AFTER ) { /* * This looks like an old entry, so re-compute it. */ freeAndNull( fragList[hitIdx].targetHost ); freeAndNull( fragList[hitIdx].pathFragOrig ); ttfreeAndNull( fragList[hitIdx].pathFragMapped ); fragList[hitIdx].cacheHit = 0; /* 0 means remap below */ } } else { /* * Did not find a cache entry, so scrounge around for * a new entry. */ if ( fragListCnt < fragListAvail ) { /* * Use next already-malloc'ed cacheEntry. */ hitIdx = fragListCnt; newCount = fragListCnt + 1; } else if ( fragListCnt < CACHE_FILEFRAG_SIZE_MAX ) { /* * Can grow fragList[] */ fragListAvail += CACHE_FILEFRAG_SIZE_BUMP; fragList = (cachedNetfileFrag *) realloc( (char *) fragList, sizeof(cachedNetfileFrag) * fragListAvail); /* * Zero out new memory. */ memset( fragList + (fragListAvail-CACHE_FILEFRAG_SIZE_BUMP), 0, CACHE_FILEFRAG_SIZE_BUMP*sizeof(cachedNetfileFrag) ); hitIdx = fragListCnt; newCount = fragListCnt + 1; } else { /* * Last resort - bump out the least used entry. */ freeAndNull( fragList[hitIdx].targetHost ); freeAndNull( fragList[hitIdx].pathFragOrig ); ttfreeAndNull( fragList[hitIdx].pathFragMapped ); /* * Since the cache is 100% full, ocassionally reset * everyone's cacheHit rate so entries that were only * popular long ago don't get locked in. */ if ( cacheGen++ > CACHE_FILEFRAG_RESET_PRI ) { cacheGen = 0; tmpCffP = fragList; for ( i = 0; i < fragListCnt; i++ ) { tmpCffP->cacheHit = 1; tmpCffP++; } } } fragList[hitIdx].cacheHit = 0; /* 0 means remap below */ } if ( ! fragList[hitIdx].cacheHit ) { /* * Need to perform mapping. */ newfile = tt_host_netfile_file( host, filename ); #ifdef _DTENV_SUPPORT_MAPERROR_CACHING fragList[hitIdx].targetHost = strdup ( host ); fragList[hitIdx].pathFragOrig = strdup( filename ); fragList[hitIdx].cacheHit = 1; fragList[hitIdx].pathFragMapped = newfile; fragListCnt = newCount; #else if ( tt_ptr_error(newfile) == TT_OK ) { fragList[hitIdx].targetHost = strdup ( host ); fragList[hitIdx].pathFragOrig = strdup( filename ); fragList[hitIdx].cacheHit = 1; fragList[hitIdx].pathFragMapped = newfile; /* * Only change the count if we are successful in adding * a new entry. */ fragListCnt = newCount; } else { /* * Don't cache errors. Leave this cache slot empty * and it will be rediscovered and used in the future. */ fragList[hitIdx].cacheHit = 0; /* * Do not change the fragListCount since we are not saving * error entries. */ } #endif /* _DTENV_SUPPORT_MAPERROR_CACHING */ } /* * Dig out answer and return it. */ #ifdef _DTENV_SUPPORT_MAPERROR_CACHING if ( tt_ptr_error(newfile) == TT_OK ) #else if ( fragList[hitIdx].cacheHit ) #endif /* _DTENV_SUPPORT_MAPERROR_CACHING */ { /* * Return a tt_free-able copy of the answer. */ tmpStr = tt_malloc( strlen(fragList[hitIdx].pathFragMapped) + 1 ); strcpy( tmpStr, fragList[hitIdx].pathFragMapped ); _DtSvcProcessUnlock(); return(tmpStr); } else { /* * See XXX comment. * * Since newfile is an error code, return as is. */ _DtSvcProcessUnlock(); return(newfile); } }
/* This is the right way according to the Spec 1170 */ void SPC_Child_Terminated(int i) /*----------------------------------------------------------------------+*/ { /* This catches signals for sub-process termination */ int type, cause, status; pid_t wait_pid, pid; SPC_Channel_Ptr channel; protocol_request req, *prot; buffered_data data, *pdata; int length; int indx; int saved_errno = errno; prot = (&req); pdata = (&data); prot->dataptr=pdata; wait_pid = -1; while(pid = waitpid(wait_pid, &status, WNOHANG)) { if((pid == -1 && errno == ECHILD) || pid == 0) { /* no more children. Return */ errno = saved_errno; return; } /* Okay, we got the process ID of a terminated child. Find the channel associated with this PID. */ channel=SPC_Find_PID(pid); #ifdef DEBUG fprintf(stderr, (XeString)"got SIGCHLD, pid: %d, channel: %p\n", pid, channel); #endif if(!channel) { continue; } _DtSvcProcessLock(); /* * Look for this process in the pid list. If found, mark it * as done. */ if (SPC_pid_list != NULL) { for (indx=0; SPC_pid_list[indx] != NULL; indx++) if (SPC_pid_list[indx] == pid) { SPC_pid_list[indx] = SPCD_DEAD_PROCESS; break; } } _DtSvcProcessUnlock(); /* We have the channel. Mark it as being closed. */ channel->status = status; /* If we this channel is set up for synchronous termination, write the protocol request to record that this guy died. Otherwise, call the termination handler directly. */ if(IS_SPCIO_SYNC_TERM(channel->IOMode)) { /* This code is basically what SPC_Write_Protocol_Request does. It is replicated here because a call to SPC_W_P_R would have to be re-enterant if we called it here, and SPC_W_P_R is not re-enterant at this time. */ SPC_Reset_Protocol_Ptr(prot, channel, APPLICATION_DIED, 0); pdata->len=WRITE_APPLICATION_DIED(pdata, status); length=WRITE_HEADER(pdata, channel->cid, prot->request_type, pdata->len, 0); pdata->data[length]=(XeChar)' '; length=pdata->len+REQUEST_HEADER_LENGTH; if(write(write_terminator->sid, pdata->data, length)==ERROR) SPC_Error(SPC_Internal_Error); pdata->offset=REQUEST_HEADER_LENGTH; print_protocol_request((XeString) (XeString)" <-- INTERNAL APPLICATION_DIED", prot); } else { SPC_Change_State(channel, NULL, -1, 0); if(channel->Terminate_Handler) { XeSPCGetProcessStatus(channel, &type, &cause); (* channel->Terminate_Handler) (channel, channel->pid, type, cause, channel->Terminate_Data); } } /* Loop around & get another PID */ } errno = saved_errno; }
/*----------------------------------------------------------------------+*/ int exec_proc_local_channel_object(SPC_Channel_Ptr channel) /*----------------------------------------------------------------------+*/ { sigset_t newsigmask, oldsigmask; pid_t pid; int result; XeString *envp; XeString dir = XeString_NULL; int retval; int i, reuse_pid = 0; call_parent_method(channel, exec_proc, (channel), result); if(result==SPC_ERROR) return(SPC_ERROR); /* Check to see if the channel pathname points to a valid executable. We do this by using the _path_search function. If the channel has a PATH variable set in its local environment, use it, otherwise use the "global" environment. We can accomplish this by using the spc_getenv call in the _path_search call. If the channel doesn't have a PATH variable, then spc_getenv will return NULL, which indicates use of the global environment. */ if(!_path_search(SPC_Getenv("PATH", channel->envp), channel->path, executable_predicate)) { SPC_Error(SPC_Cannot_Exec, channel->path); return(SPC_ERROR); } /* If we were passed a host:dir to cd to, make sure it exists. */ /* We want to do this before we fork the child. */ if((channel->context_dir) && (channel->context_dir[0])) { struct stat stat_info; Boolean ok = FALSE; _DtSvcProcessLock(); if (SPC_client_version_number < SPC_PROTOCOL_VERSION_CDE_BASE) dir = get_path_from_context(channel->context_dir); else { /* * context_dir is actually a "netfile" so it needs to * be converted to a "real" path. */ dir = (char *) tt_netfile_file (channel->context_dir); if (tt_ptr_error (dir) != TT_OK) dir = NULL; } _DtSvcProcessUnlock(); if (dir == NULL) /* can't make connection ... */; else if (stat(dir,&stat_info) != 0) /* directory not there */; else if ((stat_info.st_mode & S_IFDIR) == 0) /* path is not a directory ... */; else ok = TRUE; if (!ok && IS_SPCIO_FORCE_CONTEXT(channel->IOMode)) { if (dir != NULL && (strcmp (dir, channel->context_dir) != 0)) SPC_Error(SPC_cannot_Chdir, dir); SPC_Error(SPC_cannot_Chdir, channel->context_dir); XeFree(dir); dir = XeString_NULL; return(SPC_ERROR); } } if(mempf0(channel, pre_fork)==SPC_ERROR) return(SPC_ERROR); /* When using HP NLIO (xj0input) we have a problem. Namely, */ /* the xj0 processs uses signal() to deal with SIGCLD which */ /* is incompatible with sigaction/sigprogmask/etc. Even */ /* though xj0 resets the signal handler, since the signal */ /* routines are incompatible, our original handler gets lost. */ /* Hence, we need to reset it. We do it here everytime we */ /* fork a child just to be on the safe side. */ SPC_ResetTerminator(); sigemptyset(&newsigmask); sigemptyset(&oldsigmask); sigaddset(&newsigmask, SIGCHLD); if (sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask) == ERROR) return(SPC_ERROR); pid = channel->pid = fork(); /* * Must save this pid so that when the daemon's timer goes off, * if there has been no activity and there are no sub-processes * running, the daemon can exit. */ i = 0; _DtSvcProcessLock(); if (SPC_pid_list == NULL) /* * Create the first block plus the NULL terminator. */ SPC_pid_list = (pid_t *) malloc (2 * sizeof (pid_t)); else { /* * If a dead pid entry exists, reuse it; otherwise, must create * room for the new pid. */ for (i = 0; SPC_pid_list[i] != NULL; i++) if (SPC_pid_list[i] == SPCD_DEAD_PROCESS) { SPC_pid_list[i] = pid; reuse_pid = 1; break; } if (!reuse_pid) SPC_pid_list = (pid_t *) realloc (SPC_pid_list, (i+2) * sizeof (pid_t)); } if (!reuse_pid) { SPC_pid_list[i] = pid; SPC_pid_list[i+1] = NULL; } _DtSvcProcessUnlock(); if (pid) { XeFree(dir); /* Did we really fork? */ if (pid == ERROR) { SPC_Error(SPC_Cannot_Fork); retval = SPC_ERROR; } else { /* Do any set up for the parent process here */ mempf1(channel, post_fork, pid); retval = TRUE; } /* Reinstate the old signal mask (unblock SIGCLD). */ sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL); return(retval); } else { /* Child process: connect wires, make environment and exec sub-process */ sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL); /* Make sure the child is the process group leader. In the case of ptys, we also want to break the current terminal affiliation. We want to be the process group leader so XeSPCKillProcess (which does a kill(-pid, 9)) will kill all processes associated with us. For PTY's, we need to break the terminal affiliation so the next open (which will be a pty) will cause us to become affiliated with the pty. We do this so when the parent process closes the master side of the pty, the slave side processes get SIGHUP. If they ignore SIGHUP, they will never die. So it goes... */ if(IS_SPCIO_PTY(channel->IOMode)) setsid(); else { pid_t tmppid = getpid(); if(setpgid(tmppid, tmppid) == -1) fprintf(stderr, (XeString)"setpgid failed, errno: %d\n", errno); } /* Connect wires to sub-process standard files */ result=mempf1(channel, post_fork, pid); if(result!=SPC_ERROR) { int indx = -1; int i; char **ppch; /* * Before adding in the list of environment variables * from the environment variable files, must search * the list for LANG definitions. If found, the * last definition must be putenv'ed to assure the * multi-byte parsing code is using the correct locale. */ for (i = 0, ppch = channel->envp; *ppch; *ppch++, i++) if (!strncmp (*ppch, "LANG=", 5)) indx = i; if (indx != -1) resolve_variable_reference (&channel->envp[indx]); _DtSvcProcessLock(); if (!setlocale (LC_CTYPE, "")) /* * setlocale failed - log a message but execute * the command anyway. */ if (SPC_Print_Protocol != NULL) (void) fprintf(SPC_Print_Protocol, "+++> Failed to 'setlocale'; LANG = %s\n", getenv("LANG")); /* Mix in the stashed environment */ for(envp=channel->envp; *envp; envp++) resolve_variable_reference(&*envp); if (SPC_mount_point_env_var != NULL) /* * The mount point environment variable was * inherited by the daemon or was given to the * daemon via the command line. In either case * this subprocess must inherit the daemon's * value. */ (void) putenv (SPC_mount_point_env_var); _DtSvcProcessUnlock(); /* Connect to the context directory */ /* We have already validated this guy exists */ if(dir) Xechdir(dir); } XeFree(dir); if(result!=SPC_ERROR) { /* Execute */ /* Compiler barfs without cast ? */ #if defined(__hpux_8_0) || defined(__aix) result=execvp(channel->path, channel->argv); #else result=execvp(channel->path, channel->argv); #endif /* If we return from exec, it failed */ SPC_Error(SPC_Cannot_Exec, channel->path); } /* We want to get rid of this child image (carefully) */ _exit(42); } }