summaryrefslogtreecommitdiffstats
path: root/src/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tty.c')
-rw-r--r--src/tty.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/tty.c b/src/tty.c
new file mode 100644
index 0000000..a3c460e
--- /dev/null
+++ b/src/tty.c
@@ -0,0 +1,137 @@
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "config.h"
+
+static int setup_slave(int fd)
+{
+ struct termios tio;
+
+ tcgetattr(fd, &tio);
+
+ /* disable "\n" -> "\r\n" */
+ tio.c_oflag &= ~ONLCR;
+
+ return tcsetattr(fd, TCSANOW, &tio);
+}
+
+int tty_master(struct lt_config_app *cfg)
+{
+ int mfd;
+
+ if ((mfd = getpt()) < 0) {
+ perror("getpt failed");
+ return -1;
+ }
+
+ if (unlockpt(mfd)) {
+ perror("unlockpt failed");
+ return -1;
+ }
+
+ PRINT_VERBOSE(cfg, 1, "pty master opened succesfully\n");
+ return mfd;
+}
+
+int tty_init(struct lt_config_app *cfg, int master)
+{
+ int i, slave, num_files = getdtablesize();
+ char *sname;
+ jmp_buf env;
+
+ if (setjmp(env)) {
+ tty_restore(cfg);
+ return -1;
+ }
+
+ sname = (char*) ptsname(master);
+ if (!sname)
+ longjmp(env, 1);
+
+ PRINT_VERBOSE(cfg, 1, "closing all opened descriptors\n");
+ for(i = 0; i < num_files; i++)
+ close(i);
+
+ /* get new session before we open new controling tty */
+ if (-1 == setsid()) {
+ perror("setsid failed");
+ return -1;
+ }
+
+ slave = open(sname, O_RDWR);
+ if (slave != 0)
+ longjmp(env, 1);
+
+ /* set controling tty */
+ if (ioctl(0, TIOCSCTTY, 1))
+ longjmp(env, 1);
+
+ if (setup_slave(0))
+ longjmp(env, 1);
+
+ dup(0);
+ dup(0);
+ return 0;
+}
+
+int tty_restore(struct lt_config_app *cfg)
+{
+ int i, num_files = getdtablesize();
+
+ for(i = 0; i < num_files; i++)
+ close(i);
+
+ open("/dev/tty", O_RDWR);
+ dup(0);
+ dup(0);
+
+ return 0;
+}
+
+int tty_process(struct lt_config_app *cfg, int master)
+{
+#define BUFSIZE 4096
+ char buf[BUFSIZE];
+ ssize_t ret;
+ static int fd = 0;
+
+ if (!fd) {
+ fd = open(cfg->output_tty_file, O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (fd < 0) {
+ perror("failed to open OUTPUT_TTY file,"
+ " output is not logged");
+ return -1;
+ }
+ PRINT_VERBOSE(cfg, 1, "opened tty output file %s\n",
+ cfg->output_tty_file);
+ }
+
+ ret = read(master, buf, BUFSIZE);
+ /* Most likely the other side closed */
+ if (ret <= 0) {
+ PRINT_VERBOSE(cfg, 1,
+ "failed to read tty, closing [ errno %d '%s']\n",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ if (fd < 0)
+ return -1;
+
+ if (write(fd, buf, ret) <= 0) {
+ perror("failed to write to OUTPUT_TTY file");
+ return -1;
+ }
+
+ return 0;
+}