static pid_t FakeFork (void) { static Boolean debugInit = True; static int debugForkFailures = 0; char *c; if (isDebugFSet('f', 10)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ _DtTermProcessLock(); if (debugInit) { if (c = getenv("dttermDebugForkFailures")) { debugForkFailures = strtol(c, (char **) 0, 0); debugInit = 0; } } if (debugForkFailures > 0) { /* decrement the number of failures... */ (void) debugForkFailures--; /* set our error return... */ errno = EAGAIN; /* and error out... */ _DtTermProcessUnlock(); return(-1); } _DtTermProcessUnlock(); } /* just do a fork()... */ return(fork()); }
void _DtTermPrimInitRepTypes(void) { static Boolean first = True; _DtTermProcessLock(); if (first) { /* register our resource converters... */ #ifdef NotDefined (void) XtSetTypeConverter(XmRString, DtRDtTermTerminalSize, CvtStringToTerminalSize, NULL, 0, XtCacheNone, CvtStringToTerminalSizeDestroy); #endif /* NotDefined */ (void) XtSetTypeConverter(XmRString, DtRDtTermTerminalSizeList, CvtStringToTerminalSizeList, NULL, 0, XtCacheNone, CvtStringToTerminalSizeListDestroy); (void) XmRepTypeRegister(DtRDtTermEmulationMode, TermEmulationModeStrings, NULL, (unsigned char ) XtNumber(TermEmulationModeStrings)); (void) XmRepTypeRegister(DtRDtTermCharCursorStyle, CharCursorStyleStrings, NULL, (unsigned char ) XtNumber(CharCursorStyleStrings)); _DtTermPrimEmulationMode = XmRepTypeGetId(DtRDtTermEmulationMode); _DtTermPrimCharCursorStyle = XmRepTypeGetId(DtRDtTermCharCursorStyle); first = False; } _DtTermProcessUnlock(); return; }
_termSubprocId _DtTermPrimAddSubproc(Widget w, pid_t pid, _termSubprocProc proc, XtPointer client_data) { subprocInfo *subprocTmp; /* malloc a new entry... */ subprocTmp = (subprocInfo *) XtCalloc(1, sizeof(subprocInfo)); /* fill in the structures... */ subprocTmp->pid = pid; subprocTmp->w = w; subprocTmp->proc = proc; subprocTmp->client_data = client_data; subprocTmp->signal_id = XtAppAddSignal(XtWidgetToApplicationContext(w), InvokeCallbacks, subprocTmp); /* insert it after the head of the list... */ _DtTermProcessLock(); subprocTmp->prev = subprocHead; subprocTmp->next = subprocHead->next; subprocHead->next = subprocTmp; if (subprocTmp->next) { subprocTmp->next->prev = subprocTmp; } _DtTermProcessUnlock(); /* return the pointer... */ return((_termSubprocId) subprocTmp); }
void _DtTermPrimPtyGetDefaultModes() { int tty = -1; int refTty = -1; #if defined (USE_CSWIDTH) struct strioctl i_str; #endif /* (USE_CSWIDTH) */ _DtTermProcessLock(); if (!refValid) { /* see if we can get a reference tty to get our base reference from... */ if ((tty = open("/dev/tty", O_RDONLY, 0)) >= 0) { if (!tcgetattr(tty, &refTio)) { /* we got a valid reference tty... */ DebugF('p', 3, fprintf(stderr, ">>_DtTermPrimPtyGetDefaultModes() valid reference \"/dev/tty\"\n")); refTty = tty; refValid = 1; } } if (!refValid) { for (refTty = 0; refTty < 3; refTty++) { if (!tcgetattr(refTty, &refTio)) { DebugF('p', 3, fprintf(stderr, ">>_DtTermPrimPtyGetDefaultModes() valid reference \fd %d\n", refTty)); refValid = 1; break; } } } #if defined (USE_CSWIDTH) if (refValid && (MB_CUR_MAX > 1)) { /* ** we are in a wide character locale, get the current ** width settings... */ i_str.ic_cmd = EUC_WGET; i_str.ic_timout = 0; i_str.ic_len = sizeof(struct eucioc); i_str.ic_dp = (char *)&refWp; (void)ioctl(refTty, I_STR, &i_str); } #endif /* (USE_CSWIDTH) */ /* all done... */ /* close off the "/dev/tty" fd... */ if (tty >= 0) { (void) close(tty); } } _DtTermProcessUnlock(); }
static void DeleteLogFileEntry ( FILE *logFile ) { logInfo *logInfoTmp; sigset_t newSigs; sigset_t oldSigs; /* find the entry... */ _DtTermProcessLock(); for (logInfoTmp = logInfoHead->next; logInfoTmp; logInfoTmp = logInfoTmp->next) { if (logInfoTmp->logFile == logFile) { break; } } /* did we find anything... */ if (!logInfoTmp) { /* not found... */ _DtTermProcessUnlock(); return; } /* delete entry from the list... */ /* block all signals... */ (void) sigfillset(&newSigs); (void) sigemptyset(&oldSigs); (void) sigprocmask(SIG_BLOCK, &newSigs, &oldSigs); /* remove it... */ logInfoTmp->prev->next = logInfoTmp->next; if (logInfoTmp->next) { logInfoTmp->next->prev = logInfoTmp->prev; } /* restore signals... */ (void) sigprocmask(SIG_SETMASK, &oldSigs, (sigset_t *) 0); /* free up the data... */ (void) XtFree((char *) logInfoTmp); _DtTermProcessUnlock(); }
static void suidInit() { _DtTermProcessLock(); if (first) { uid_user = getuid(); uid_root = geteuid(); gid_user = getgid(); gid_root = getegid(); first = False; } _DtTermProcessUnlock(); }
void _DtTermPrimWriteLog(DtTermPrimitiveWidget tw, char *buffer, int cnt) { DtTermPrimData tpd = tw->term.tpd; if (cnt > 0) { _DtTermProcessLock(); (void) fwrite(buffer, cnt, 1, tpd->logStream); if ((errno == EPIPE) && ferror(tpd->logStream)) { ForceCloseLog(tw); } _DtTermProcessUnlock(); } }
void _DtTermPrimSubprocRemoveSubproc(Widget w, _termSubprocId id) { subprocInfo *subprocTmp = (subprocInfo *) id; /* remove the entry from the linked list... */ /* there will always be a head, so we can always update it... */ _DtTermProcessLock(); subprocTmp->w = NULL; subprocTmp->prev->next = subprocTmp->next; if (subprocTmp->next) { subprocTmp->next->prev = subprocTmp->prev; } _DtTermProcessUnlock(); XtRemoveSignal(subprocTmp->signal_id); /* free our storage... */ (void) XtFree((char *) subprocTmp); }
void _DtTermPrimLogFileCleanup ( void ) { logInfo *logInfoTmp; DebugF('s', 10, fprintf(stderr, ">>_DtTermPrimLogFileCleanup() starting\n")); /* flush all the log files... */ _DtTermProcessLock(); for (logInfoTmp = logInfoHead->next; logInfoTmp; logInfoTmp = logInfoTmp->next) { DebugF('s', 10, fprintf(stderr, ">>flushing logfile 0x%lx\n", logInfoTmp->logFile)); (void) fflush(logInfoTmp->logFile); } _DtTermProcessUnlock(); DebugF('s', 10, fprintf(stderr, ">>_DtTermPrimLogFileCleanup() finished\n")); }
static void AddLogFileEntry ( FILE *logFile ) { logInfo *logInfoTmp; sigset_t newSigs; sigset_t oldSigs; /* malloc a new entry... */ logInfoTmp = (logInfo *) XtMalloc(sizeof(logInfo)); (void) memset(logInfoTmp, '\0', sizeof(logInfo)); /* fill in the structure... */ logInfoTmp->logFile = logFile; /* insert it after the head of the list... */ /* block all signals... */ (void) sigfillset(&newSigs); (void) sigemptyset(&oldSigs); (void) sigprocmask(SIG_BLOCK, &newSigs, &oldSigs); /* insert the entry into the list... */ _DtTermProcessLock(); logInfoTmp->prev = logInfoHead; logInfoTmp->next = logInfoHead->next; logInfoHead->next = logInfoTmp; if (logInfoTmp->next) { logInfoTmp->next->prev = logInfoTmp; } _DtTermProcessUnlock(); /* restore signals... */ (void) sigprocmask(SIG_SETMASK, &oldSigs, (sigset_t *) 0); }
/* ** Parse the character, tell the calling routine if we are not ** in the start state. */ Boolean _DtTermPrimParse ( Widget w, unsigned char *parseChar, int parseCharLen ) { ParserContext context = GetParserContext(w); StateEntry thisEntry; StateEntry thisPreParseEntry; #ifdef NOCODE /* ** This decision should be made somewhere else. */ if (tp->t_modes.disp_func == 1) { in_disp_func(); return(False); } #endif /* NOCODE */ if (parseCharLen == 1) { *context->inputChar = *parseChar; } else { (void) memmove(context->inputChar, parseChar, parseCharLen); } context->inputCharLen = parseCharLen; if (isDebugFSet('p', 1)) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ static unsigned char debugChar; static Boolean first = True; char *c; if (parseCharLen == 1) { _DtTermProcessLock(); if (first) { if (!(c = getenv("dttermDebugParseChar"))) { c = "0x03"; } debugChar = strtol(c, (char **) 0, 0); first = False; } _DtTermProcessUnlock(); if (*parseChar == debugChar) { ParseTrap(); return 0; } } } /* ** Determine which state entry to use. */ thisPreParseEntry = context->stateTable->statePreParseEntry; thisEntry = context->stateTable->stateEntry; /* first run through the preParse entry... */ if (thisPreParseEntry && (parseCharLen == 1)) { while ((*parseChar < thisPreParseEntry->lower) || (*parseChar > thisPreParseEntry->upper)) { thisPreParseEntry++; } /* if we hit the end, ignore it... */ if ((0x00 == thisPreParseEntry->lower) && (0xff == thisPreParseEntry->upper)) { thisPreParseEntry = (StateEntry) 0; } } /* if we hit a valid preParseEntry, then let's execute it and * return... */ if (thisPreParseEntry) { /* ** Now change states. If the next state is NULL, stay in the ** current state. This is for parse entries that do not break us ** out of the current parse thread. If we need to bail out of the ** current parse thread, then we have a new state specified and ** will switch to it. We do this before we execute the function ** incase the function needs to change the state as well... */ if (thisPreParseEntry->nextState) { context->stateTable = thisPreParseEntry->nextState; } /* ** Execute the action associated with the entry. */ if (thisPreParseEntry->action) { (*thisPreParseEntry->action)(w); } return(!context->stateTable->startState); } /* HACK ALERT!!!! * * We need two different search algorithms - the first to deal * with single byte characters, the second to deal with multi-byte * characters. For now, we will match multi-byte character with * the parse entry that covers 0..255. If we find that this will * not work for everything, we may need to rethink this. */ if (parseCharLen == 1) { while ((*parseChar < thisEntry->lower) || (*parseChar > thisEntry->upper)) { thisEntry++; } } else { while ((0x00 != thisEntry->lower) || (0xff != thisEntry->upper)) { thisEntry++; } } /* ** Now change states. We do this before we execute the function incase ** the function needs to change the state as well... */ context->stateTable = thisEntry->nextState; /* ** Execute the action associated with the entry. */ if (thisEntry->action) { (*thisEntry->action)(w); } return(!context->stateTable->startState); }
void _DtTermPrimPtyInit ( int pty, char *modeString, char *csWidthString ) { struct termios tio; #if defined (USE_CSWIDTH) struct strioctl i_str; eucioc_t wp; #endif /* (USE_CSWIDTH) */ #if defined (USE_SETCSMAP) /* ** set thing up so we can use setcsmap() ** for the time being, this is IBM specific */ char path[MAXPATHLEN]; int oldStdin = -1; #endif /* (USE_SETCSMAP) */ #ifdef NOTDEF #ifdef USE_STREAMS if (ioctl(pty, I_PUSH, "ptem") < 0) { (void) perror("I_PUSH ptem"); } if (ioctl(pty, I_PUSH, "ldterm") < 0) { (void) perror("I_PUSH ldterm"); } if (ioctl(pty, I_PUSH, "ttcompat") < 0) { (void) perror("I_PUSH ttcompat"); } #endif /* USE_STREAMS */ #endif /* NOTDEF */ if (refValid) { /* we will start from the reference tty... */ /* we already got the termios structure. No need to get again... */ DebugF('p', 3, fprintf(stderr, ">>_DtTermPrimPtyInit() using refTio\n")); tio = refTio; #if defined (USE_CSWIDTH) /* ** use the cs width information from the reference... */ wp = refWp; #endif /* (USE_CSWIDTH) */ /* DKS: are there any other terminal states we need to get?... */ } else { /* let's set a reasonable default... */ DebugF('p', 3, fprintf(stderr, ">>_DtTermPrimPtyInit() generating default termio\n")); (void) memset(&tio, '\0', sizeof(tio)); tio.c_iflag = ICRNL | IXON | IXOFF; tio.c_oflag = OPOST | ONLCR | TAB3; tio.c_cflag = B9600 | CS8 | CREAD | PARENB | HUPCL; tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE; /* DKS: this is termio specific. Do we need it?... tio.c_line = 0; */ tio.c_cc[VINTR] = 0x7f; /* DEL */ tio.c_cc[VQUIT] = '\\' & 0x3f; /* '^\' */ tio.c_cc[VERASE] = '#'; /* '#' */ tio.c_cc[VKILL] = '@'; /* '@' */ tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */ tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */ #ifdef VSWITCH tio.c_cc[VSWITCH] = '@' & 0x3f; /* '^@' */ #endif /* VSWITCH */ #if defined (USE_CSWIDTH) /* ** get the cs width information from the resource */ parseCSWidth(csWidthString, &wp); #endif /* (USE_CSWIDTH) */ } /* now, let's clean up certain flags... */ /* input: nl->nl, don't ignore cr, cr->nl * turn on IXOFF pacing so that we can do paste without * overflowing the buffer... */ tio.c_iflag &= ~(INLCR | IGNCR); tio.c_iflag |= ICRNL | IXOFF; /* output: cr->cr, nl is not return, no delays, nl->cr/nl */ tio.c_oflag &= ~(OCRNL | ONLRET | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY); tio.c_oflag |= ONLCR; /* baud rate is 9600 (nice default), turn off clocal and turn on * hupcl so that the last close will SIGHUP processes running on * the tty... */ tio.c_cflag &= ~(CBAUD | CLOCAL); tio.c_cflag |= B9600 | HUPCL; /* enable signals, canonical processing (erase, kill, etc), echo... */ tio.c_lflag |= ISIG | ICANON | ECHO | IEXTEN | ECHOCTL | ECHOKE; /* reset EOL to the default value (ksh mucks this up sometimes)... */ tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */ /* reset EOF to the default value (ksh and csh muck with this)... */ tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */ /* ** Now its time to handle the ttyModes ** Decide if the user supplied a ttyModes resource, if so then ** parse it and if it was a legal mode string, pass the parse result */ #define TMODE(ind,var) if (_DtTermPrimTtyModeList[ind].set) var = _DtTermPrimTtyModeList[ind].value; _DtTermProcessLock(); if (modeString) { if (parseTtyModes(modeString, _DtTermPrimTtyModeList) < 0) { /* ** NOTE: should we prepend the program name to this string? */ fprintf(stderr, "Bad tty modes \"%s\"\n", modeString); } else { TMODE (XTTYMODE_intr, tio.c_cc[VINTR]); TMODE (XTTYMODE_quit, tio.c_cc[VQUIT]); TMODE (XTTYMODE_erase, tio.c_cc[VERASE]); TMODE (XTTYMODE_kill, tio.c_cc[VKILL]); TMODE (XTTYMODE_eof, tio.c_cc[VEOF]); TMODE (XTTYMODE_eol, tio.c_cc[VEOL]); #if defined(HP_ARCHITECTURE) TMODE (XTTYMODE_swtch, tio.c_cc[VSWTCH]); TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]); #if OSMAJORVERSION > 9 /* HP-UX 10.0 supports the new, extended c_cc[] array... */ TMODE (XTTYMODE_start, tio.c_cc[VSTART]); TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]); TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]); #ifdef NOTDEF /* the following two parameters are not supported by * HP-UX 10.0. */ TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]); TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]); #endif /* NOTDEF */ TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]); TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]); #else /* OSMAJORVERSION > 9 */ { /* With HP-UX 9.0 (and earlier) we need to set dsuspc * via the ltchars array. In addition, we have no support * for rprnt, flush, weras, and lnext... */ struct ltchars ltc; if (!ioctl(pty, TIOCGLTC, <c)) { TMODE (XTTYMODE_dsusp, ltc.t_dsuspc); (void) ioctl(pty, TIOCSLTC, <c); } } #endif /* OSMAJORVERSION > 9 */ #elif defined(IBM_ARCHITECTURE) TMODE (XTTYMODE_start, tio.c_cc[VSTRT]); TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]); TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]); TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]); TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]); TMODE (XTTYMODE_flush, tio.c_cc[VDISCRD]); TMODE (XTTYMODE_weras, tio.c_cc[VWERSE]); TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]); #elif defined(SUN_ARCHITECTURE) TMODE (XTTYMODE_swtch, tio.c_cc[VSWTCH]); TMODE (XTTYMODE_start, tio.c_cc[VSTART]); TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]); TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]); TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]); TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]); TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]); TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]); TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]); #elif defined(ALPHA_ARCHITECTURE) TMODE (XTTYMODE_start, tio.c_cc[VSTART]); TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]); TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]); TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]); TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]); TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]); TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]); TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]); #endif } #undef TMODE } _DtTermProcessUnlock(); (void) tcsetattr(pty, TCSADRAIN, &tio); #if defined (USE_CSWIDTH) if (MB_CUR_MAX > 1) { /* ** we are in a wide character locale, set the cs ** width settings... */ i_str.ic_cmd = EUC_WSET; i_str.ic_timout = 0; i_str.ic_len = sizeof(struct eucioc); i_str.ic_dp = (char *)℘ (void)ioctl(pty, I_STR, &i_str); } #endif /* (USE_CSWIDTH) */ #if defined (USE_SETCSMAP) /* ** NOTE: ** Setcsmap() only operates on STDIN, so we have to do some ** munging around to map the pty to STDIN in order to get ** the desired result. This may seem wasteful, but it ** makes it easier to encapsulate the OS dependencies in ** this function. */ if (pty != 0) { oldStdin = fcntl(0, F_DUPFD, 1); (void) close(0); (void) dup(pty); } sprintf(path, "%s%s", CSMAP_DIR, nl_langinfo(CODESET)); if(access(path, E_ACC|R_ACC) == 0) { setcsmap(path); } if (pty != 0) { (void) close(0); if (oldStdin >= 0) { (void) dup(oldStdin); (void) close(oldStdin); } } #endif /* (USE_SETCSMAP) */ }
void _DtTermPrimStartLog(Widget w) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; DtTermPrimData tpd = tw->term.tpd; char *cp; int i; if ( tw->term.log_on || tw->term.logInhibit ) { return; } if (!tw->term.logFile || !*tw->term.logFile) { tw->term.logFile = "DttermLogXXXXX"; } if (!strcmp(tw->term.logFile + strlen(tw->term.logFile) - 5, "XXXXX")) { /* make a local copy in case we are going to change it... */ cp = XtMalloc(strlen(tw->term.logFile) + 1); (void) strcpy(cp, tw->term.logFile); (void) mktemp(cp); if (cp && *cp) { tw->term.logFile = cp; } else { (void) XtFree(cp); return; } } if ('|' == *tw->term.logFile ) { /* ** pipe logfile into command */ int p[2]; _DtTermProcessLock(); if (pipe(p) < 0 || (i = fork()) < 0) { _DtTermProcessUnlock(); return; } if (i == 0) { /* ** child */ _DtTermProcessUnlock(); /* Remove suid root capability... */ (void) _DtTermPrimRemoveSuidRoot(); (void) close(p[1]); (void) close(0); (void) dup(p[0]); (void) close(p[0]); /* ** set close on exec flag on all other fd's */ for (i = 3; i < _NFILE; i++) { (void) fcntl(i, F_SETFD, 1); } /* ** reset signals */ (void) signal(SIGHUP, SIG_DFL); (void) signal(SIGCHLD, SIG_DFL); #ifdef BBA _bA_dump(); #endif /* BBA */ (void) execl(DEFAULT_SHELL, DEFAULT_SHELL_ARGV0, "-c", &tw->term.logFile[1], 0); (void) fprintf(stderr, " Can't exec \"%s\"\n", &tw->term.logFile[1]); (void) exit(1); } _DtTermProcessUnlock(); (void) close(p[0]); tpd->logStream = fdopen(p[1], "w"); (void) AddLogFileEntry(tpd->logStream); (void) signal(SIGPIPE, SIG_IGN); } else { if (access(tw->term.logFile, F_OK) == 0) { if (access(tw->term.logFile, W_OK) < 0) { return; } } else if (cp = strrchr(tw->term.logFile, '/')) { *cp = 0; i = access(tw->term.logFile, W_OK); *cp = '/'; if (i < 0) { return; } } else if (access(".", W_OK) < 0) { return; } if ((tpd->logStream = fopen(tw->term.logFile, "a")) == NULL) { return; } (void) AddLogFileEntry(tpd->logStream); (void) chown(tw->term.logFile, getuid(), getgid()); } tw->term.log_on = True ; }
void _DtTermPrimCursorOn(Widget w) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; struct termData *tpd = tw->term.tpd; XPoint point; static Boolean alreadyActive = False; short chunkWidth; enhValues enhancements; unsigned long valueMask = 0L; XGCValues values; TermEnhInfoRec enhInfo; int cursorRow; /* if we are being called cyclically (by _DtTermPrimScrollWait -> * _DtTermPrimExposeText -> _DtTermPrimCursorOn), just return... */ _DtTermProcessLock(); if (alreadyActive) { /*DKS!!! vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ fprintf(stderr, "tell Dave _DtTermPrimCursorOn has alreadyActive == True\n"); /*DKS!!! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ _DtTermProcessUnlock(); return; } /* this is where we will actually perform a pending scroll and * text refresh... */ if (tw->term.jumpScroll && tpd->scroll.jump.scrolled) { /* make sure we don't end up in an infinite loop... */ alreadyActive = True; Debug('t', fprintf(stderr, ">>_DtTermPrimCursorOn() calling _DtTermPrimScrollWait()\n")); (void) _DtTermPrimScrollWait(w); alreadyActive = False; } _DtTermProcessUnlock(); #ifdef DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF if ( _DtTermPrimSelectIsAboveSelection(w,tpd->cursorRow, tpd->cursorColumn)) { _DtTermPrimSelectDisown(w) ; } #endif /* DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF */ /* update the input method spot location... */ if ((tpd->IMCursorColumn != tpd->cursorColumn) || (tpd->IMCursorRow != tpd->cursorRow)) { tpd->IMCursorColumn = tpd->cursorColumn; tpd->IMCursorRow = tpd->cursorRow; point.x = tpd->cursorColumn * tpd->cellWidth + tpd->offsetX; point.y = tpd->cursorRow * tpd->cellHeight + tpd->offsetY + tpd->ascent; DebugF('F', 1, fprintf(stderr, "%s() %s calling %s\n", "_DtTermPrimCursorOn", "dont care", "XmImVaSetValues()")); (void) XmImVaSetValues(w, XmNspotLocation, &point, NULL); } #ifdef NOT_NEEDED if (!tw->term.hasFocus) { (void) fprintf(stderr, "%s() %s calling %s\n", "_DtTermPrimCursorOn", "!hasFocus", "XmImUnsetFocus()"); (void) XmImUnsetFocus(w); } #endif /* NOT_NEEDED */ /* update the scrollbar and position indicator... */ (void) _DtTermPrimCursorUpdate(w); /* if the cursor is not visible, we are done now... */ if (!tpd->cursorVisible) { return; } /* set up the GC... */ if (!tpd->cursorGC.gc) { tpd->cursorGC.foreground = tw->primitive.foreground ^ tw->core.background_pixel; values.foreground = tpd->cursorGC.foreground; values.function = GXxor; tpd->cursorGC.gc = XCreateGC(XtDisplay(w), XtWindow(w), GCForeground | GCFunction, &values); } /* update the cursor's foreground and background... */ /* if we are past the lastUsedRow, or the column > width, use color * pair 0... */ /* reasonable defaults... */ enhInfo.fg = tw->primitive.foreground; enhInfo.bg = tw->core.background_pixel; if (!((tpd->lastUsedRow <= tpd->topRow + tpd->cursorRow) || (_DtTermPrimBufferGetLineWidth(tpd->termBuffer, tpd->topRow + tpd->cursorRow) <= MIN(tpd->cursorColumn, tw->term.columns - 1)))) { /* get the current enhancement to determine the color pair to use... */ (void) _DtTermPrimBufferGetEnhancement(tpd->termBuffer, /* TermBuffer */ tpd->topRow + tpd->cursorRow, /* row */ MIN(tpd->cursorColumn, tw->term.columns - 1), /* col */ &enhancements, /* enhancements */ &chunkWidth, /* width */ countNew); /* countWhich */ /* set our font and color from the enhancements... */ if (ENH_PROC(tpd->termBuffer)) { (void) (*(ENH_PROC(tpd->termBuffer)))(w, enhancements, &enhInfo); } } /* set the GC... */ if (tpd->cursorGC.foreground != enhInfo.fg ^ enhInfo.bg) { tpd->cursorGC.foreground = enhInfo.fg ^ enhInfo.bg; values.foreground = enhInfo.fg ^ enhInfo.bg; valueMask |= GCForeground; } if (valueMask) { (void) XChangeGC(XtDisplay(w), tpd->cursorGC.gc, valueMask, &values); } if (tpd->cursorState != CURSORoff) { return; } tpd->cursorState = CURSORon; (void) cursorToggle(w); if (tw->term.hasFocus) { /* add a timeout... */ if (tw->term.blinkRate > 0) { tpd->cursorTimeoutId = XtAppAddTimeOut(XtWidgetToApplicationContext(w), tw->term.blinkRate, (XtTimerCallbackProc) timeoutCallback, (XtPointer) w); } } }
pid_t _DtTermPrimSubprocExec(Widget w, char *ptyName, Boolean consoleMode, char *cwd, char *cmd, char **argv, Boolean loginShell) { DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w; static char *defaultCmd = (char *) 0; int i; int pty; pid_t pid; char *c; int err; #ifdef MOVE_FDS int saveFd[3]; #else /* MOVE_FDS */ int savedStderr; #endif /* MOVE_FDS */ Boolean argvFree = False; struct sigaction sa; sigset_t ss; char buffer[BUFSIZ]; Widget parent; char *namebuf; struct passwd * pw; _Xgetpwparams pw_buf; _Xgetloginparams login_buf; #ifdef ALPHA_ARCHITECTURE /* merge code from xterm, ignore so that TIOCSWINSZ doesn't block */ signal(SIGTTOU, SIG_IGN); #endif /* ALPHA_ARCHITECTURE */ /* build a default exec command and argv list if one wasn't supplied... */ /* cmd... */ /* the command will be taken as follows: * - from the passed in cmd, * - from $SHELL, * - from the /etc/passwd entry for the /etc/utmp entry for this * terminal, * - from the /etc/passwd entry for this userid, or * - /bin/sh. */ if (!cmd || !*cmd) { if (!defaultCmd) { /* from $SHELL... */ c = getenv("SHELL"); /* if not valid, try the /etc/passwd entry for the username * associated with the /etc/utmp entry for this tty... */ if (!c || !*c) { /* get the /etc/passwd entry for the username associated with * /etc/utmp... */ if ((namebuf = _XGetlogin(login_buf)) != NULL) { /* get the user's passwd entry... */ pw = _XGetpwnam(namebuf, pw_buf); /* if we weren't able to come up with one for the * username... */ if (pw != NULL) c = pw->pw_shell; } } /* if not valid, try the /etc/passwd entry for the username * associate with the real uid... */ if (!c || !*c) { /* if we weren't able to come up with one for the userid... */ pw = _XGetpwuid(getuid(), pw_buf); if (pw != NULL) { c = pw->pw_shell; } } /* if not valid, use /bin/sh... */ if (!c || !*c) { c = DEFAULT_SHELL; } /* malloc space for this string. It will be free'ed in the * destroy function... */ defaultCmd = XtMalloc(strlen(c) + 1); (void) strcpy(defaultCmd, c); } cmd = defaultCmd; } if (!argv) { /* base it on cmd... */ argv = (char **) XtMalloc(2 * sizeof(char *)); /* if loginShell is set, then pre-pend a '-' to argv[0]. That's * also why we allocate an extra byte in argv[0]... */ argv[0] = XtMalloc(strlen(cmd) + 2); *argv[0] = '\0'; if (loginShell) { /* pre-pend an '-' for loginShell... */ (void) strcat(argv[0], "-"); if (c = strrchr(cmd, '/')) { strcat(argv[0], ++c); } else { strcat(argv[0], cmd); } } else { (void) strcat(argv[0], cmd); } /* null term the list... */ argv[1] = (char *) 0; /* we will need to free it up later... */ argvFree = True; } #ifdef OLDCODE /* this is left around from when we were using vfork().... */ /* open the pty slave so that we can set the modes. * * NOTE: this code depends on support for the O_NOCTTY ioctl. This * ioctl allows us to open the device without becoming the * session group leader for it. If that can't be done, it may * be necessary to rethink the way we open the pty slave... */ if ((pty = open(ptyName, O_RDWR | O_NOCTTY, 0)) < 0) { (void) perror(ptyName); return((pid_t) -1); } #endif /* OLDCODE */ #ifdef MOVE_FDS /* move fd[0:2] out of the way for now... */ for (i = 0; i <= 2; i++) { saveFd[i] = fcntl(i, F_DUPFD, 3); (void) close(i); } #else /* MOVE_FDS */ savedStderr = fcntl(2, F_DUPFD, 3); #endif /* MOVE_FDS */ /* set close on exec flags on all files... */ for (i = 0; i < _NFILE; i++) { (void) fcntl(i, F_SETFD, 1); } /* fork. We can't use vfork() since we need to do lots of stuff * below... */ if (isDebugSet('T')) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ (void) timeStamp("about to fork()"); } _DtTermProcessLock(); for (i = 0; ((pid = FakeFork()) < 0) && (i < 10); i++) { /* if we are out of process slots, then let's sleep a bit and * try again... */ if (errno != EAGAIN) { break; } /* give it a chance to clear up... */ (void) sleep((unsigned long) 2); } if (pid < 0) { (void) perror("fork()"); #ifdef OLDCODE /* this is left around from when we were using vfork().... */ (void) close(pty); #endif /* OLDCODE */ return((pid_t) - 1); } else if (pid == 0) { /* child... */ _DtTermProcessUnlock(); #if defined(ALPHA_ARCHITECTURE) || defined(CSRG_BASED) || defined(LINUX_ARCHITECTURE) /* establish a new session for child */ setsid(); #else /* do a setpgrp() so that we can... */ (void) setpgrp(); #endif /* ALPHA_ARCHITECTURE */ #if defined(LINUX_ARCHITECTURE) /* set the ownership and mode of the pty... */ (void) _DtTermPrimSetupPty(ptyName, pty); #endif /* open the pty slave as our controlling terminal... */ pty = open(ptyName, O_RDWR, 0); if (pty < 0) { (void) perror(ptyName); (void) _exit(1); } #if defined(ALPHA_ARCHITECTURE) || defined(CSRG_BASED) || defined(LINUX_ARCHITECTURE) /* BSD needs to do this to acquire pty as controlling terminal */ if (ioctl(pty, TIOCSCTTY, (char *)NULL) < 0) { (void) close(pty); (void) perror("Error acquiring pty slave as controlling terminal"); /* exit the subprocess */ _exit(1); } /* Do it when no controlling terminal doesn't work for OSF/1 */ _DtTermPrimPtyGetDefaultModes(); #endif /* ALPHA_ARCHITECTURE */ #if !defined(LINUX_ARCHITECTURE) /* set the ownership and mode of the pty... */ (void) _DtTermPrimSetupPty(ptyName, pty); #endif /* LINUX_ARCHITECTURE */ /* apply the ttyModes... */ _DtTermPrimPtyInit(pty, tw->term.ttyModes, tw->term.csWidth); /* set the window size... */ _DtTermPrimPtySetWindowSize(pty, tw->term.columns * tw->term.widthInc + (2 * (tw->primitive.shadow_thickness + tw->primitive.highlight_thickness + tw->term.marginWidth)), tw->term.rows * tw->term.heightInc + (2 * (tw->primitive.shadow_thickness + tw->primitive.highlight_thickness + tw->term.marginHeight)), tw->term.rows, tw->term.columns); /* if we are in console mode, turn it on... */ if (consoleMode) { _DtTermPrimPtyConsoleModeEnable(pty); } #ifdef MOVE_FDS /* that should have open'ed into fd 0. Dup it into fd's 1 and 2... */ (void) dup(pty); (void) dup(pty); #else /* MOVE_FDS */ /* dup pty into fd's 0, 1, and 2... */ for (i = 0; i < 3; i++) { if (i != pty) { (void) close(i); (void) dup(pty); } } if (pty >= 3) { (void) close(pty); } #endif /* MOVE_FDS */ /* reset any alarms... */ (void) alarm(0); /* reset all signal handlers... */ sa.sa_handler = SIG_DFL; (void) sigemptyset(&sa.sa_mask); sa.sa_flags = 0; for (i = 1; i < NSIG; i++) { (void) sigaction(i, &sa, (struct sigaction *) 0); } /* unblock all signals... */ (void) sigemptyset(&ss); (void) sigprocmask(SIG_SETMASK, &ss, (sigset_t *) 0); /* ** Restore the original (pre-DT) environment, removing any ** DT-specific environment variables that were added before ** we... */ #if defined(HPVUE) #if (OSMINORVERSION > 01) (void) VuEnvControl(VUE_ENV_RESTORE_PRE_VUE); #endif /* (OSMINORVERSION > 01) */ #else /* (HPVUE) */ (void) _DtEnvControl(DT_ENV_RESTORE_PRE_DT); #endif /* (HPVUE) */ /* ** set a few environment variables of our own... */ for (parent = w; !XtIsShell(parent); parent = XtParent(parent)) ; (void) sprintf(buffer, "%ld", XtWindow(parent)); _DtTermPrimPutEnv("WINDOWID=", buffer); _DtTermPrimPutEnv("DISPLAY=", XDisplayString(XtDisplay(w))); if (((DtTermPrimitiveWidget)w)->term.emulationId) { _DtTermPrimPutEnv("TERMINAL_EMULATOR=", ((DtTermPrimitiveWidget)w)->term.emulationId); } /* set our utmp entry... */ (void) _DtTermPrimUtmpEntryCreate(w, getpid(), ((DtTermPrimitiveWidget)w)->term.tpd->utmpId); if (isDebugSet('T')) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ (void) timeStamp("about to execvp()"); } /* turn off suid forever... */ _DtTermPrimRemoveSuidRoot(); /* change to the requested directory... */ if (cwd && *cwd) { (void) chdir(cwd); } #ifdef BBA _bA_dump(); #endif /* BBA */ _DtEnvControl(DT_ENV_RESTORE_PRE_DT); (void) execvp(cmd, argv); /* if we got to this point we error'ed out. Let's write out the * error... */ err = errno; /* restore stderr... */ (void) close(2); (void) dup(savedStderr); /* restore errno... */ errno = err; (void) perror(cmd); /* and we need to exit the subprocess... */ _exit(1); } /* parent... */ _DtTermProcessUnlock(); if (isDebugSet('T')) { #ifdef BBA #pragma BBA_IGNORE #endif /*BBA*/ (void) timeStamp("parent resuming"); } #ifdef MOVE_FDS /* DKS: we should check this out and see if it is necessary... */ (void) close(0); (void) close(1); (void) close(2); /* move fd[0:2] back in place... */ for (i = 0; i <= 2; i++) { if (saveFd[i] >= 0) { (void) fcntl(saveFd[i], F_DUPFD, i); (void) close(saveFd[i]); } } #else /* MOVE_FDS */ (void) close(savedStderr); #endif /* MOVE_FDS */ /* clean up malloc'ed memory... */ if (argvFree) { (void) XtFree(argv[0]); (void) XtFree((char *) argv); } #ifdef OLDCODE /* since we no longer open it in the parent, we probably don't want * to close it either... */ (void) close(pty); #endif /* OLDCODE */ /* assume that our child set up a utmp entry (since we have no way * for it to report to us) and add it to the list to cleanup)... */ _DtTermPrimUtmpAddEntry(((DtTermPrimitiveWidget)w)->term.tpd->utmpId); return(pid); }