Browse Source

Add tty line support

Not always is desirable to create a pseudo terminal, and some times
we want to open a terminal emulator over a tty line. With this new
patch is possible to do someting like:

	$ st -l /dev/ttyS0 115200

Without this option was needed to launch another terminal emulator
over st (for example minicom, picocom, cu, ...).
Roberto E. Vargas Caballero 10 years ago
parent
commit
215bdb2da3
3 changed files with 91 additions and 13 deletions
  1. 1 0
      config.def.h
  2. 36 1
      st.1
  3. 54 12
      st.c

+ 1 - 0
config.def.h

@@ -9,6 +9,7 @@ static char font[] = "Liberation Mono:pixelsize=12:antialias=false:autohint=fals
 static int borderpx = 2;
 static int borderpx = 2;
 static char shell[] = "/bin/sh";
 static char shell[] = "/bin/sh";
 static char *utmp = NULL;
 static char *utmp = NULL;
+static char stty_args[] = "stty raw -echo -iexten echonl";
 
 
 /* identification sequence returned in DA and DECID */
 /* identification sequence returned in DA and DECID */
 static char vtiden[] = "\033[?6c";
 static char vtiden[] = "\033[?6c";

+ 36 - 1
st.1

@@ -15,11 +15,36 @@ st \- simple terminal
 .IR file ]
 .IR file ]
 .RB [ \-t 
 .RB [ \-t 
 .IR title ]
 .IR title ]
+.RB [ \-l
+.IR line ]
 .RB [ \-w 
 .RB [ \-w 
 .IR windowid ]
 .IR windowid ]
 .RB [ \-v ]
 .RB [ \-v ]
 .RB [ \-e
 .RB [ \-e
 .IR command ...]
 .IR command ...]
+.RI [ commands ...]
+.PP
+.B st
+.RB [ \-a ]
+.RB [ \-c
+.IR class ]
+.RB [ \-f
+.IR font ]
+.RB [ \-g
+.IR geometry ]
+.RB [ \-i ]
+.RB [ \-o
+.IR file ]
+.RB [ \-t
+.IR title ]
+.RB [ \-l
+.IR line ]
+.RB [ \-w
+.IR windowid ]
+.RB [ \-v ]
+.RB [ \-l
+.IR line ]
+.RI [ stty_args ...]
 .SH DESCRIPTION
 .SH DESCRIPTION
 .B st
 .B st
 is a simple terminal emulator.
 is a simple terminal emulator.
@@ -58,6 +83,11 @@ defines the window title (default 'st').
 embeds st within the window identified by 
 embeds st within the window identified by 
 .I windowid
 .I windowid
 .TP
 .TP
+.BI \-l " line"
+use a tty line instead of a pseudo terminal.
+When this flag is used
+remaining arguments are used as flags for stty.
+.TP
 .B \-v
 .B \-v
 prints version information to stderr, then exits.
 prints version information to stderr, then exits.
 .TP
 .TP
@@ -67,6 +97,9 @@ st executes
 instead of the shell.  If this is used it
 instead of the shell.  If this is used it
 .B must be the last option
 .B must be the last option
 on the command line, as in xterm / rxvt.
 on the command line, as in xterm / rxvt.
+This option is only intended for compability,
+and all the remaining arguments are used as a command
+even without it.
 .SH SHORTCUTS
 .SH SHORTCUTS
 .TP
 .TP
 .B Ctrl-Print Screen
 .B Ctrl-Print Screen
@@ -110,7 +143,9 @@ See the LICENSE file for the authors.
 .SH LICENSE
 .SH LICENSE
 See the LICENSE file for the terms of redistribution.
 See the LICENSE file for the terms of redistribution.
 .SH SEE ALSO
 .SH SEE ALSO
-.BR tabbed (1)
+.BR tabbed (1),
+.BR utmp (1),
+.BR stty (1)
 .SH BUGS
 .SH BUGS
 See the TODO file in the distribution.
 See the TODO file in the distribution.
 
 

+ 54 - 12
st.c

@@ -352,6 +352,7 @@ static void draw(void);
 static void redraw(void);
 static void redraw(void);
 static void drawregion(int, int, int, int);
 static void drawregion(int, int, int, int);
 static void execsh(void);
 static void execsh(void);
+static void stty(void);
 static void sigchld(int);
 static void sigchld(int);
 static void run(void);
 static void run(void);
 
 
@@ -508,6 +509,7 @@ static char *opt_title = NULL;
 static char *opt_embed = NULL;
 static char *opt_embed = NULL;
 static char *opt_class = NULL;
 static char *opt_class = NULL;
 static char *opt_font = NULL;
 static char *opt_font = NULL;
+static char *opt_line = NULL;
 static int oldbutton = 3; /* button event on startup: 3 = release */
 static int oldbutton = 3; /* button event on startup: 3 = release */
 
 
 static char *usedfont = NULL;
 static char *usedfont = NULL;
@@ -1253,11 +1255,55 @@ sigchld(int a) {
 	exit(EXIT_SUCCESS);
 	exit(EXIT_SUCCESS);
 }
 }
 
 
+
+void
+stty(void)
+{
+	char cmd[_POSIX_ARG_MAX], **p, *q, *s;
+	size_t n, siz;
+
+	if((n = strlen(stty_args)) > sizeof(cmd)-1)
+		die("incorrect stty parameters\n");
+	memcpy(cmd, stty_args, n);
+	q = cmd + n;
+	siz = sizeof(cmd) - n;
+	for(p = opt_cmd; p && (s = *p); ++p) {
+		if((n = strlen(s)) > siz-1)
+			die("stty parameter length too long\n");
+		*q++ = ' ';
+		q = memcpy(q, s, n);
+		q += n;
+		siz-= n + 1;
+	}
+	*q = '\0';
+	system(cmd);
+}
+
 void
 void
 ttynew(void) {
 ttynew(void) {
 	int m, s;
 	int m, s;
 	struct winsize w = {term.row, term.col, 0, 0};
 	struct winsize w = {term.row, term.col, 0, 0};
 
 
+	if(opt_io) {
+		term.mode |= MODE_PRINT;
+		iofd = (!strcmp(opt_io, "-")) ?
+			  STDOUT_FILENO :
+			  open(opt_io, O_WRONLY | O_CREAT, 0666);
+		if(iofd < 0) {
+			fprintf(stderr, "Error opening %s:%s\n",
+				opt_io, strerror(errno));
+		}
+	}
+
+	if (opt_line) {
+		if((cmdfd = open(opt_line, O_RDWR)) < 0)
+			die("open line failed: %s\n", strerror(errno));
+		close(STDIN_FILENO);
+		dup(cmdfd);
+		stty();
+		return;
+	}
+
 	/* seems to work fine on linux, openbsd and freebsd */
 	/* seems to work fine on linux, openbsd and freebsd */
 	if(openpty(&m, &s, NULL, NULL, &w) < 0)
 	if(openpty(&m, &s, NULL, NULL, &w) < 0)
 		die("openpty failed: %s\n", strerror(errno));
 		die("openpty failed: %s\n", strerror(errno));
@@ -1267,6 +1313,7 @@ ttynew(void) {
 		die("fork failed\n");
 		die("fork failed\n");
 		break;
 		break;
 	case 0:
 	case 0:
+		close(iofd);
 		setsid(); /* create a new process group */
 		setsid(); /* create a new process group */
 		dup2(s, STDIN_FILENO);
 		dup2(s, STDIN_FILENO);
 		dup2(s, STDOUT_FILENO);
 		dup2(s, STDOUT_FILENO);
@@ -1281,16 +1328,6 @@ ttynew(void) {
 		close(s);
 		close(s);
 		cmdfd = m;
 		cmdfd = m;
 		signal(SIGCHLD, sigchld);
 		signal(SIGCHLD, sigchld);
-		if(opt_io) {
-			term.mode |= MODE_PRINT;
-			iofd = (!strcmp(opt_io, "-")) ?
-				  STDOUT_FILENO :
-				  open(opt_io, O_WRONLY | O_CREAT, 0666);
-			if(iofd < 0) {
-				fprintf(stderr, "Error opening %s:%s\n",
-					opt_io, strerror(errno));
-			}
-		}
 		break;
 		break;
 	}
 	}
 }
 }
@@ -4009,9 +4046,11 @@ run(void) {
 
 
 void
 void
 usage(void) {
 usage(void) {
-	die("%s " VERSION " (c) 2010-2015 st engineers\n" \
+	die("%s " VERSION " (c) 2010-2015 st engineers\n"
 	"usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
 	"usage: st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
-	"          [-i] [-t title] [-w windowid] [-e command ...] [command ...]\n",
+	"          [-i] [-t title] [-w windowid] [-e command ...] [command ...]\n"
+	"       st [-a] [-v] [-c class] [-f font] [-g geometry] [-o file]\n"
+	"          [-i] [-t title] [-w windowid] [-l line] [stty_args ...]\n",
 	argv0);
 	argv0);
 }
 }
 
 
@@ -4047,6 +4086,9 @@ main(int argc, char *argv[]) {
 	case 'o':
 	case 'o':
 		opt_io = EARGF(usage());
 		opt_io = EARGF(usage());
 		break;
 		break;
+	case 'l':
+		opt_line = EARGF(usage());
+		break;
 	case 't':
 	case 't':
 		opt_title = EARGF(usage());
 		opt_title = EARGF(usage());
 		break;
 		break;