hackedteam/vector-default

View on GitHub
pe.old/CONTRIB/CYGTERMD/PTY.C

Summary

Maintainability
Test Coverage
/*
 * pty.c - pseudo-terminal handling
 */

#define _XOPEN_SOURCE
#include <features.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <pwd.h>

#include "pty.h"
#include "malloc.h"

static char ptyname[FILENAME_MAX];
int master = -1;

void pty_preinit(void)
{
    /*
     * Allocate the pty.
     */
    master = open("/dev/ptmx", O_RDWR);
    if (master < 0) {
    perror("/dev/ptmx: open");
    exit(1);
    }

    if (grantpt(master) < 0) {
    perror("grantpt");
    exit(1);
    }
    
    if (unlockpt(master) < 0) {
    perror("unlockpt");
    exit(1);
    }
}

void pty_resize(int w, int h)
{
    struct winsize sz;

    assert(master >= 0);

    sz.ws_row = h;
    sz.ws_col = w;
    sz.ws_xpixel = sz.ws_ypixel = 0;
    ioctl(master, TIOCSWINSZ, &sz);
}

int run_program_in_pty(const struct shell_data *shdata,
                       char *directory, char **program_args)
{
    int slave, pid;
    char *fallback_args[2];

    assert(master >= 0);

    ptyname[FILENAME_MAX-1] = '\0';
    strncpy(ptyname, ptsname(master), FILENAME_MAX-1);

#if 0
    {
    struct winsize ws;
    struct termios ts;

    /*
     * FIXME: think up some good defaults here
     */

    if (!ioctl(0, TIOCGWINSZ, &ws))
        ioctl(master, TIOCSWINSZ, &ws);
    if (!tcgetattr(0, &ts))
        tcsetattr(master, TCSANOW, &ts);
    }
#endif

    slave = open(ptyname, O_RDWR | O_NOCTTY);
    if (slave < 0) {
    perror("slave pty: open");
    return 1;
    }

    /*
     * Fork and execute the command.
     */
    pid = fork();
    if (pid < 0) {
    perror("fork");
    return 1;
    }

    if (pid == 0) {
    int i, fd;

    /*
     * We are the child.
     */
    close(master);

    fcntl(slave, F_SETFD, 0);    /* don't close on exec */
    dup2(slave, 0);
    dup2(slave, 1);
    if (slave != 0 && slave != 1)
        close(slave);
    dup2(1, 2);
    setsid();
    setpgrp();
        i = 0;
#ifdef TIOCNOTTY
        if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
            ioctl(fd, TIOCNOTTY, &i);
            close(fd);
        }
#endif
#ifdef TIOCSCTTY
        ioctl(0, TIOCSCTTY, &i);
#endif
    tcsetpgrp(0, getpgrp());

    for (i = 0; i < shdata->nenvvars; i++)
            putenv(shdata->envvars[i]);
    if (shdata->termtype)
            putenv(shdata->termtype);

        if (directory)
            chdir(directory);

    /*
     * Use the provided shell program name, if the user gave
     * one. Failing that, use $SHELL; failing that, look up
     * the user's default shell in the password file; failing
     * _that_, revert to the bog-standard /bin/sh.
     */
    if (!program_args) {
            char *shell;
            
        shell = getenv("SHELL");
            if (!shell) {
                const char *login;
                uid_t uid;
                struct passwd *pwd;

                /*
                 * For maximum generality in the face of multiple
                 * /etc/passwd entries with different login names and
                 * shells but a shared uid, we start by using
                 * getpwnam(getlogin()) if it's available - but we
                 * insist that its uid must match our real one, or we
                 * give up and fall back to getpwuid(getuid()).
                 */
                uid = getuid();
                login = getlogin();
                if (login && (pwd = getpwnam(login)) && pwd->pw_uid == uid)
                    shell = pwd->pw_shell;
                else if ((pwd = getpwuid(uid)))
                    shell = pwd->pw_shell;
            }
            if (!shell)
                shell = "/bin/sh";

            fallback_args[0] = shell;
            fallback_args[1] = NULL;
            program_args = fallback_args;
        }

        execv(program_args[0], program_args);

    /*
     * If we're here, exec has gone badly foom.
     */
    perror("exec");
    exit(127);
    }

    close(slave);

    return master;
}