I am currently writing regress tests for mg which use an mg startup file's
capabilities to process mg commands to test mg's internal functions. In
order to facilitate mg fitting into the OpenBSD regress test framework and
be able to run via a cron job I have amended mg to be able to run with a
pty. The diff below adds a 'batch' mode to mg via the '-b' command line
option which will initialise a pty, run the specified file of mg commands
and then exit.
There are other things to do to get mg fully integrated into the regress
framework, but this diff is independant of them and offers a solution to
no tty being available when being executed vi cron.
Comments/oks/criticisms?
Mark
Index: def.h
===================================================================
RCS file: /cvs/src/usr.bin/mg/def.h,v
retrieving revision 1.168
diff -u -p -r1.168 def.h
--- def.h 1 Mar 2021 10:51:14 -0000 1.168
+++ def.h 18 Mar 2021 15:58:39 -0000
@@ -750,6 +750,7 @@ extern int doaudiblebell;
extern int dovisiblebell;
extern int dblspace;
extern int allbro;
+extern int batch;
extern char cinfo[];
extern char *keystrings[];
extern char pat[NPAT];
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/main.c,v
retrieving revision 1.88
diff -u -p -r1.88 main.c
--- main.c 23 Feb 2021 08:10:51 -0000 1.88
+++ main.c 18 Mar 2021 15:58:40 -0000
@@ -14,7 +14,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>
+#include <util.h>
#include "def.h"
#include "kbd.h"
@@ -33,6 +35,7 @@ int doaudiblebell; /* audible bell
t
int dovisiblebell; /* visible bell toggle */
int dblspace; /* sentence end #spaces */
int allbro; /* all buffs read-only */
+int batch; /* for regress tests */
struct buffer *curbp; /* current buffer */
struct buffer *bheadp; /* BUFFER list head */
struct mgwin *curwp; /* current window */
@@ -40,6 +43,7 @@ struct mgwin *wheadp; /* MGWIN listhea
char pat[NPAT]; /* pattern */
static void edinit(struct buffer *);
+static void pty_init(void);
static __dead void usage(void);
extern char *__progname;
@@ -48,8 +52,8 @@ extern void closetags(void);
static __dead void
usage()
{
- fprintf(stderr, "usage: %s [-nR] [-f mode] [-u file] [+number] "
- "[file ...]\n",
+ fprintf(stderr, "usage: %s [-nR] [-b file] [-f mode] [-u file] "
+ " [+number] [file ...]\n",
__progname);
exit(1);
}
@@ -58,6 +62,7 @@ int
main(int argc, char **argv)
{
char *cp, *conffile = NULL, *init_fcn_name = NULL;
+ char *batchfile = NULL;
PF init_fcn = NULL;
int o, i, nfiles;
int nobackups = 0;
@@ -67,8 +72,12 @@ main(int argc, char **argv)
NULL) == -1)
err(1, "pledge");
- while ((o = getopt(argc, argv, "nRf:u:")) != -1)
+ while ((o = getopt(argc, argv, "nRb:f:u:")) != -1)
switch (o) {
+ case 'b':
+ batch = 1;
+ batchfile = optarg;
+ break;
case 'R':
allbro = 1;
break;
@@ -87,6 +96,20 @@ main(int argc, char **argv)
default:
usage();
}
+
+ if (batch && (conffile != NULL)) {
+ fprintf(stderr, "%s: -b and -u are mutually exclusive.\n",
+ __progname);
+ exit(1);
+ } else if (batch) {
+ pty_init();
+ conffile = batchfile;
+ }
+ if (conffile != NULL && access(conffile, R_OK) != 0) {
+ fprintf(stderr, "%s: Missing file: %s\n", __progname,
conffile);
+ exit(1);
+ }
+
argc -= optind;
argv += optind;
@@ -136,6 +159,9 @@ main(int argc, char **argv)
if ((cp = startupfile(NULL, conffile)) != NULL)
(void)load(cp);
+ if (batch)
+ return (0);
+
/*
* Now ensure any default buffer modes from the startup file are
* given to any files opened when parsing the startup file.
@@ -249,6 +275,26 @@ edinit(struct buffer *bp)
wp->w_linep = wp->w_dotp = bp->b_headp;
wp->w_ntrows = nrow - 2; /* 2 = mode, echo. */
wp->w_rflag = WFMODE | WFFULL; /* Full. */
+}
+
+/*
+ * Create pty for batch mode.
+ */
+static void
+pty_init(void)
+{
+ struct winsize ws;
+ int master;
+ int slave;
+
+ memset(&ws, 0, sizeof(ws));
+ ws.ws_col = 80,
+ ws.ws_row = 24;
+
+ openpty(&master, &slave, NULL, NULL, &ws);
+ login_tty(slave);
+
+ return;
}
/*
Index: mg.1
===================================================================
RCS file: /cvs/src/usr.bin/mg/mg.1,v
retrieving revision 1.120
diff -u -p -r1.120 mg.1
--- mg.1 23 Feb 2021 18:45:33 -0000 1.120
+++ mg.1 18 Mar 2021 15:58:40 -0000
@@ -10,6 +10,7 @@
.Sh SYNOPSIS
.Nm mg
.Op Fl nR
+.Op Fl b Ar file
.Op Fl f Ar mode
.Op Fl u Ar file
.Op + Ns Ar number
@@ -35,6 +36,12 @@ sign and the number).
If a negative number is specified, the line number counts
backwards from the end of the file i.e. +-1 will be the last
line of the file, +-2 will be second last, and so on.
+.It Fl b Ar file
+Turn on batch mode and execute the
+.Nm
+commands found in the specified
+.Ar file
+and then terminate.
.It Fl f Ar mode
Run the mode command for all buffers created from
arguments on the command line, including the
Index: tty.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/tty.c,v
retrieving revision 1.38
diff -u -p -r1.38 tty.c
--- tty.c 1 Mar 2021 10:51:14 -0000 1.38
+++ tty.c 18 Mar 2021 15:58:40 -0000
@@ -34,6 +34,7 @@
#include <signal.h>
#include <stdio.h>
#include <term.h>
+#include <unistd.h>
#include "def.h"
@@ -64,9 +65,15 @@ winchhandler(int sig)
void
ttinit(void)
{
+ char *tty;
int errret;
- if (setupterm(NULL, 1, &errret))
+ if (batch == 1)
+ tty = "pty";
+ else
+ tty = NULL;
+
+ if (setupterm(tty, STDOUT_FILENO, &errret))
panic("Terminal setup failed");
signal(SIGWINCH, winchhandler);
Index: ttyio.c
===================================================================
RCS file: /cvs/src/usr.bin/mg/ttyio.c,v
retrieving revision 1.39
diff -u -p -r1.39 ttyio.c
--- ttyio.c 1 Mar 2021 10:51:14 -0000 1.39
+++ ttyio.c 18 Mar 2021 15:58:40 -0000
@@ -140,7 +140,7 @@ ttflush(void)
ssize_t written;
char *buf = obuf;
- if (nobuf == 0)
+ if (nobuf == 0 || batch == 1)
return;
while ((written = write(fileno(stdout), buf, nobuf)) != nobuf) {