Ejemplo n.º 1
0
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 ;
}
Ejemplo n.º 2
0
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);
}