app_term.c
author viric@llimona
Mon, 24 Sep 2007 13:59:40 +0200
changeset 38 f1e581c862d5
parent 29 91286c3ecebc
child 41 954941c6e40a
permissions -rw-r--r--
Improved help. Moving to 0.2.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
     1
#include <sys/types.h>
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
     2
#include <unistd.h>
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
     3
#include <errno.h>
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
     4
#include <fcntl.h>
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
     5
#include <string.h>
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
     6
#include <sys/select.h>
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
     7
#include <sys/ioctl.h>
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
     8
#include <termios.h>
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
     9
#include <pty.h>
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    10
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    11
#include "main.h"
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    12
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    13
enum
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    14
{
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    15
    STDIN,
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    16
    STDOUT,
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    17
    STDERR
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    18
};
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    19
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    20
static void set_close_on_exec(int fd)
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    21
{
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    22
    int res;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    23
    res = fcntl(fd, F_SETFD, FD_CLOEXEC);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    24
    if (res == -1)
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    25
        error("Set close-on-exec failed");
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    26
}
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    27
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    28
static void give_terminal(int parent[], int child[])
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    29
{
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    30
    struct termios tios;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    31
    struct winsize wsize;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    32
    int res;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    33
    int master, slave;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    34
28
b73712b8370d use the termios calls to stdout instead of stdin.
viric@llimona
parents: 26
diff changeset
    35
    res = tcgetattr(1, &tios);
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    36
    if (res == -1)
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    37
        error("tcgetatttr");
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    38
28
b73712b8370d use the termios calls to stdout instead of stdin.
viric@llimona
parents: 26
diff changeset
    39
    res = ioctl(1, TIOCGWINSZ, &wsize);
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    40
    if (res == -1)
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    41
        error("ioctl TIOCGWINSZ");
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    42
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    43
    res = openpty(&master, &slave, 0, &tios, &wsize);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    44
    if (res == -1)
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    45
        error("openpty");
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    46
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    47
    parent[STDIN]  = master;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    48
    parent[STDOUT] = master;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    49
    parent[STDERR] = master;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    50
    child[STDIN]  = slave;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    51
    child[STDOUT] = slave;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    52
    child[STDERR] = slave;
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    53
    set_close_on_exec(master);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    54
    set_close_on_exec(slave);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    55
}
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    56
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    57
static void give_pipes(int parent[], int child[])
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    58
{
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    59
    int p_stdin[2]; /* from us to mpg321 */
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    60
    int p_stdout[2]; /* from mpg321 to us */
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    61
    int p_stderr[2]; /* from mpg321 to us, its stderr */
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    62
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    63
    pipe(p_stdin);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    64
    pipe(p_stdout);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    65
    pipe(p_stderr);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    66
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    67
    parent[STDIN]  = p_stdin[1];
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    68
    parent[STDOUT] = p_stdout[0];
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    69
    parent[STDERR] = p_stderr[0];
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    70
    child[STDIN]   = p_stdin[0];
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    71
    child[STDOUT]  = p_stdout[1];
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    72
    child[STDERR]  = p_stderr[1];
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    73
    set_close_on_exec(parent[STDIN]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    74
    set_close_on_exec(parent[STDOUT]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    75
    set_close_on_exec(parent[STDERR]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    76
    set_close_on_exec(child[STDIN]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    77
    set_close_on_exec(child[STDOUT]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    78
    set_close_on_exec(child[STDERR]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    79
}
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    80
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    81
int fork_app(char * const command[])
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    82
{
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    83
    int p_parent[3];
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    84
    int p_child[3];
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    85
    int pid;
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    86
    int res;
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    87
29
91286c3ecebc Added getopt, and some things got based on parameters.
viric@llimona
parents: 28
diff changeset
    88
    if (command_line.s_param.run_in_subterminal)
26
96920c3707b3 Unix sockets version works! Well, signals don't. :)
viric@llimona
parents: 25
diff changeset
    89
        give_terminal(p_parent, p_child);
96920c3707b3 Unix sockets version works! Well, signals don't. :)
viric@llimona
parents: 25
diff changeset
    90
    else
96920c3707b3 Unix sockets version works! Well, signals don't. :)
viric@llimona
parents: 25
diff changeset
    91
        give_pipes(p_parent, p_child);
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    92
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    93
    /* globals */
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    94
    app_stdin  = p_parent[STDIN];  /* For us to write */
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    95
    app_stdout = p_parent[STDOUT]; /* For us to read */
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
    96
    app_stderr = p_parent[STDERR]; /* For us to read */
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    97
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    98
    pid = fork();
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
    99
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   100
    switch(pid)
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   101
    {
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   102
        case 0: /* child */
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   103
            res = dup2(p_child[STDIN], 0);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   104
            if (res == -1) error("Dup2 stdin");
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   105
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   106
            res = dup2(p_child[STDOUT], 1);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   107
            if (res == -1) error("Dup2 stdout");
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   108
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   109
            res = dup2(p_child[STDERR], 2);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   110
            if (res == -1) error("Dup2 stderr");
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   111
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   112
            execvp(command[0], command);
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   113
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   114
            error("Cannot execvp %s", command[0]);
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   115
        case -1:
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   116
            error("Failed fork");
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   117
        default: /* parent */
25
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   118
            close(p_child[STDIN]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   119
            close(p_child[STDOUT]);
5b5ca60e3646 First try on openpty.
viric@llimona
parents: 23
diff changeset
   120
            close(p_child[STDERR]);
23
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   121
    }
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   122
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   123
    return pid;
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   124
}
b3e6c6ffc69c Moving the client out.
viric@llimona
parents:
diff changeset
   125