Merge pull request #4 from mrunalp/opt_parsing
Separate tty/non-tty and add opt parsing
This commit is contained in:
commit
817b22b5f3
1 changed files with 106 additions and 77 deletions
183
conmon/conmon.c
183
conmon/conmon.c
|
@ -1,4 +1,5 @@
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -58,7 +59,9 @@ static void tty_restore(void)
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
const char *cid;
|
int opt;
|
||||||
|
bool terminal = FALSE;
|
||||||
|
const char *cid = NULL;
|
||||||
char cmd[CMD_SIZE];
|
char cmd[CMD_SIZE];
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
_cleanup_free_ char *contents;
|
_cleanup_free_ char *contents;
|
||||||
|
@ -74,12 +77,29 @@ int main(int argc, char *argv[])
|
||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
struct epoll_event evlist[MAX_EVENTS];
|
struct epoll_event evlist[MAX_EVENTS];
|
||||||
|
|
||||||
if (argc < 2) {
|
while ((opt = getopt(argc, argv, "tc:")) != -1) {
|
||||||
nexit("Run as: conmon <id>");
|
switch(opt) {
|
||||||
|
case 't':
|
||||||
|
terminal = TRUE;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
cid = optarg;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
if (optopt == 'c')
|
||||||
|
nexit("Option -%c requires an argument.", optopt);
|
||||||
|
else if (isprint (optopt))
|
||||||
|
nexit("Unknown option `-%c'.", optopt);
|
||||||
|
else
|
||||||
|
nexit("Unknown option character `\\x%x'.\n", optopt);
|
||||||
|
default:
|
||||||
|
nexit("Usage: %s [-c container_id] [-t]", argv[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the container id */
|
if (cid == NULL) {
|
||||||
cid = argv[1];
|
nexit("Container ID not passed");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set self as subreaper so we can wait for container process
|
* Set self as subreaper so we can wait for container process
|
||||||
|
@ -90,28 +110,35 @@ int main(int argc, char *argv[])
|
||||||
pexit("Failed to set as subreaper");
|
pexit("Failed to set as subreaper");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the master pty */
|
if (terminal) {
|
||||||
mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
|
/* Open the master pty */
|
||||||
if (mfd < 0)
|
mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
|
||||||
pexit("Failed to open console master pty");
|
if (mfd < 0)
|
||||||
|
pexit("Failed to open console master pty");
|
||||||
|
|
||||||
/* Grant access to the slave pty */
|
/* Grant access to the slave pty */
|
||||||
if (grantpt(mfd) == -1)
|
if (grantpt(mfd) == -1)
|
||||||
pexit("Failed to grant access to slave pty");
|
pexit("Failed to grant access to slave pty");
|
||||||
|
|
||||||
/* Unlock the slave pty */
|
/* Unlock the slave pty */
|
||||||
if (unlockpt(mfd) == -1) { /* Unlock slave pty */
|
if (unlockpt(mfd) == -1) { /* Unlock slave pty */
|
||||||
pexit("Failed to unlock the slave pty");
|
pexit("Failed to unlock the slave pty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the slave pty name */
|
||||||
|
ret = ptsname_r(mfd, slname, BUF_SIZE);
|
||||||
|
if (ret != 0) {
|
||||||
|
pexit("Failed to get the slave pty name");
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the slave pty name */
|
|
||||||
ret = ptsname_r(mfd, slname, BUF_SIZE);
|
|
||||||
if (ret != 0) {
|
|
||||||
pexit("Failed to get the slave pty name");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the container */
|
/* Create the container */
|
||||||
snprintf(cmd, CMD_SIZE, "runc create %s --pid-file pidfile --console %s", cid, slname);
|
if (terminal) {
|
||||||
|
snprintf(cmd, CMD_SIZE, "runc create %s --pid-file pidfile --console %s", cid, slname);
|
||||||
|
} else {
|
||||||
|
snprintf(cmd, CMD_SIZE, "runc create %s --pid-file pidfile", cid);
|
||||||
|
}
|
||||||
ret = system(cmd);
|
ret = system(cmd);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
nexit("Failed to create container");
|
nexit("Failed to create container");
|
||||||
|
@ -128,73 +155,75 @@ int main(int argc, char *argv[])
|
||||||
cpid = atoi(contents);
|
cpid = atoi(contents);
|
||||||
printf("container PID: %d\n", cpid);
|
printf("container PID: %d\n", cpid);
|
||||||
|
|
||||||
/* Save exiting termios settings */
|
if (terminal) {
|
||||||
if (tcgetattr(STDIN_FILENO, &tty_orig) == -1)
|
/* Save exiting termios settings */
|
||||||
pexit("tcegetattr");
|
if (tcgetattr(STDIN_FILENO, &tty_orig) == -1)
|
||||||
|
pexit("tcegetattr");
|
||||||
|
|
||||||
/* Settings for raw mode */
|
/* Settings for raw mode */
|
||||||
t.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN);
|
t.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN);
|
||||||
t.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR | INPCK |
|
t.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR | INPCK |
|
||||||
ISTRIP | IXON | IXOFF | IGNPAR | PARMRK);
|
ISTRIP | IXON | IXOFF | IGNPAR | PARMRK);
|
||||||
t.c_oflag &= ~OPOST;
|
t.c_oflag &= ~OPOST;
|
||||||
t.c_cc[VMIN] = 1;
|
t.c_cc[VMIN] = 1;
|
||||||
t.c_cc[VTIME] = 0;
|
t.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
/* Set terminal to raw mode */
|
/* Set terminal to raw mode */
|
||||||
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) == -1)
|
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) == -1)
|
||||||
pexit("tcsetattr");
|
pexit("tcsetattr");
|
||||||
|
|
||||||
/* Setup terminal restore on exit */
|
/* Setup terminal restore on exit */
|
||||||
if (atexit(tty_restore) != 0)
|
if (atexit(tty_restore) != 0)
|
||||||
pexit("atexit");
|
pexit("atexit");
|
||||||
|
|
||||||
epfd = epoll_create(5);
|
epfd = epoll_create(5);
|
||||||
if (epfd < 0)
|
if (epfd < 0)
|
||||||
pexit("epoll_create");
|
pexit("epoll_create");
|
||||||
ev.events = EPOLLIN;
|
ev.events = EPOLLIN;
|
||||||
ev.data.fd = STDIN_FILENO;
|
ev.data.fd = STDIN_FILENO;
|
||||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) < 0) {
|
if (epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) < 0) {
|
||||||
pexit("Failed to add stdin to epoll");
|
pexit("Failed to add stdin to epoll");
|
||||||
}
|
}
|
||||||
ev.data.fd = mfd;
|
ev.data.fd = mfd;
|
||||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, mfd, &ev) < 0) {
|
if (epoll_ctl(epfd, EPOLL_CTL_ADD, mfd, &ev) < 0) {
|
||||||
pexit("Failed to add console master fd to epoll");
|
pexit("Failed to add console master fd to epoll");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy data back and forth between STDIN and master fd */
|
/* Copy data back and forth between STDIN and master fd */
|
||||||
while (true) {
|
while (true) {
|
||||||
int ready = epoll_wait(epfd, evlist, MAX_EVENTS, -1);
|
int ready = epoll_wait(epfd, evlist, MAX_EVENTS, -1);
|
||||||
for (int i = 0; i < ready; i++) {
|
for (int i = 0; i < ready; i++) {
|
||||||
if (evlist[i].events & EPOLLIN) {
|
if (evlist[i].events & EPOLLIN) {
|
||||||
if (evlist[i].data.fd == STDIN_FILENO) {
|
if (evlist[i].data.fd == STDIN_FILENO) {
|
||||||
num_read = read(STDIN_FILENO, buf, BUF_SIZE);
|
num_read = read(STDIN_FILENO, buf, BUF_SIZE);
|
||||||
if (num_read <= 0)
|
if (num_read <= 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (write(mfd, buf, num_read) != num_read) {
|
if (write(mfd, buf, num_read) != num_read) {
|
||||||
nwarn("partial/failed write (masterFd)");
|
nwarn("partial/failed write (masterFd)");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (evlist[i].data.fd == mfd) {
|
} else if (evlist[i].data.fd == mfd) {
|
||||||
num_read = read(mfd, buf, BUF_SIZE);
|
num_read = read(mfd, buf, BUF_SIZE);
|
||||||
if (num_read <= 0)
|
if (num_read <= 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (write(STDOUT_FILENO, buf, num_read) != num_read) {
|
if (write(STDOUT_FILENO, buf, num_read) != num_read) {
|
||||||
nwarn("partial/failed write (STDOUT_FILENO)");
|
nwarn("partial/failed write (STDOUT_FILENO)");
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (evlist[i].events & (EPOLLHUP | EPOLLERR)) {
|
||||||
|
printf("closing fd %d\n", evlist[i].data.fd);
|
||||||
|
if (close(evlist[i].data.fd) < 0)
|
||||||
|
pexit("close");
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (evlist[i].events & (EPOLLHUP | EPOLLERR)) {
|
|
||||||
printf("closing fd %d\n", evlist[i].data.fd);
|
|
||||||
if (close(evlist[i].data.fd) < 0)
|
|
||||||
pexit("close");
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
tty_restore();
|
tty_restore();
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait for the container process and record its exit code */
|
/* Wait for the container process and record its exit code */
|
||||||
while ((pid = waitpid(-1, &status, 0)) > 0) {
|
while ((pid = waitpid(-1, &status, 0)) > 0) {
|
||||||
|
|
Loading…
Reference in a new issue