summaryrefslogtreecommitdiff
path: root/usr.bin/vi/common
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>1996-07-24 16:16:11 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>1996-07-24 16:16:11 +0000
commit9fe0ebe622331e4ca8b324440857ac3415cf231e (patch)
treeda7d517118e7d40dfef8b4943e368ecbd43475cb /usr.bin/vi/common
parent4e78eb09c86098d70b62e357fffcf4c3d379074f (diff)
bring vi/ex up to 1.71
Diffstat (limited to 'usr.bin/vi/common')
-rw-r--r--usr.bin/vi/common/api.c2
-rw-r--r--usr.bin/vi/common/common.h4
-rw-r--r--usr.bin/vi/common/exf.c84
-rw-r--r--usr.bin/vi/common/gs.h16
-rw-r--r--usr.bin/vi/common/key.c8
-rw-r--r--usr.bin/vi/common/key.h8
-rw-r--r--usr.bin/vi/common/mem.h2
-rw-r--r--usr.bin/vi/common/msg.c14
-rw-r--r--usr.bin/vi/common/options.c5
-rw-r--r--usr.bin/vi/common/options_f.c29
-rw-r--r--usr.bin/vi/common/recover.c16
-rw-r--r--usr.bin/vi/common/screen.h39
-rw-r--r--usr.bin/vi/common/search.c90
-rw-r--r--usr.bin/vi/common/signal.c569
14 files changed, 188 insertions, 698 deletions
diff --git a/usr.bin/vi/common/api.c b/usr.bin/vi/common/api.c
index bf90d1c717e..a4c5a2a73ed 100644
--- a/usr.bin/vi/common/api.c
+++ b/usr.bin/vi/common/api.c
@@ -12,7 +12,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)api.c 8.18 (Berkeley) 4/27/96";
+static const char sccsid[] = "@(#)api.c 8.19 (Berkeley) 6/8/96";
#endif /* not lint */
#include <sys/types.h>
diff --git a/usr.bin/vi/common/common.h b/usr.bin/vi/common/common.h
index 9b785073adc..555db960d7a 100644
--- a/usr.bin/vi/common/common.h
+++ b/usr.bin/vi/common/common.h
@@ -6,7 +6,7 @@
*
* See the LICENSE file for redistribution information.
*
- * @(#)common.h 10.11 (Berkeley) 4/10/96
+ * @(#)common.h 10.12 (Berkeley) 5/24/96
*/
/*
@@ -51,7 +51,7 @@ typedef struct _text TEXT;
typedef enum { C_NOTSET, C_CARATSET, C_NOCHANGE, C_ZEROSET } carat_t;
/* Busy message types. */
-typedef enum { BUSY_ON, BUSY_OFF, BUSY_UPDATE } busy_t;
+typedef enum { BUSY_ON = 1, BUSY_OFF, BUSY_UPDATE } busy_t;
/*
* Routines that return a confirmation return:
diff --git a/usr.bin/vi/common/exf.c b/usr.bin/vi/common/exf.c
index dac9714fe86..97b5e9ee4dc 100644
--- a/usr.bin/vi/common/exf.c
+++ b/usr.bin/vi/common/exf.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)exf.c 10.35 (Berkeley) 5/16/96";
+static const char sccsid[] = "@(#)exf.c 10.42 (Berkeley) 6/19/96";
#endif /* not lint */
#include <sys/param.h>
@@ -395,6 +395,9 @@ file_init(sp, frp, rcv_name, flags)
/* Set the initial cursor position, queue initial command. */
file_cinit(sp);
+ /* Change the name of the icon/window. */
+ (void)sp->gp->scr_rename(sp);
+
/* Redraw the screen from scratch, schedule a welcome message. */
F_SET(sp, SC_SCR_REFORMAT | SC_STATUS);
@@ -662,9 +665,11 @@ file_write(sp, fm, tm, name, flags)
FILE *fp;
FREF *frp;
MARK from, to;
+ size_t len;
u_long nlno, nch;
int fd, nf, noname, oflags, rval;
- char *p;
+ char *p, *s, *t, buf[MAXPATHLEN + 64];
+ const char *msgstr;
/*
* Writing '%', or naming the current file explicitly, has the
@@ -838,13 +843,14 @@ file_write(sp, fm, tm, name, flags)
F_CLR(frp, FR_NAMECHANGE);
/*
- * If wrote the entire file clear the modified bit. If the file was
- * written back to the original file name and the file is a temporary,
- * set the "no exit" bit. This permits the user to write the file and
- * use it in the context of the file system, but still keeps them from
- * losing their changes by exiting.
+ * If wrote the entire file, and it wasn't by appending it to a file,
+ * clear the modified bit. If the file was written to the original
+ * file name and the file is a temporary, set the "no exit" bit. This
+ * permits the user to write the file and use it in the context of the
+ * filesystem, but still keeps them from discarding their changes by
+ * exiting.
*/
- if (LF_ISSET(FS_ALL)) {
+ if (LF_ISSET(FS_ALL) && !LF_ISSET(FS_APPEND)) {
F_CLR(sp->ep, F_MODIFIED);
if (F_ISSET(frp, FR_TMPFILE))
if (noname)
@@ -856,14 +862,40 @@ file_write(sp, fm, tm, name, flags)
p = msg_print(sp, name, &nf);
switch (mtype) {
case NEWFILE:
- msgq(sp, M_INFO, "256|%s: new file: %lu lines, %lu characters",
- p, nlno, nch);
+ msgstr = msg_cat(sp,
+ "256|%s: new file: %lu lines, %lu characters", NULL);
+ len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
break;
case OLDFILE:
- msgq(sp, M_INFO, "257|%s: %s%lu lines, %lu characters",
- p, LF_ISSET(FS_APPEND) ? "appended: " : "", nlno, nch);
+ msgstr = msg_cat(sp, LF_ISSET(FS_APPEND) ?
+ "315|%s: appended: %lu lines, %lu characters" :
+ "257|%s: %lu lines, %lu characters", NULL);
+ len = snprintf(buf, sizeof(buf), msgstr, p, nlno, nch);
break;
+ default:
+ abort();
+ }
+
+ /*
+ * There's a nasty problem with long path names. Cscope and tags files
+ * can result in long paths and vi will request a continuation key from
+ * the user. Unfortunately, the user has typed ahead, and chaos will
+ * result. If we assume that the characters in the filenames only take
+ * a single screen column each, we can trim the filename.
+ */
+ s = buf;
+ if (len >= sp->cols) {
+ for (s = buf, t = buf + strlen(p); s < t &&
+ (*s != '/' || len >= sp->cols - 3); ++s, --len);
+ if (s == t)
+ s = buf;
+ else {
+ *--s = '.'; /* Leading ellipses. */
+ *--s = '.';
+ *--s = '.';
+ }
}
+ msgq(sp, M_INFO, s);
if (nf)
FREE_SPACE(sp, p, 0);
return (0);
@@ -1069,16 +1101,25 @@ file_comment(sp)
char *p;
for (lno = 1; !db_get(sp, lno, 0, &p, &len) && len == 0; ++lno);
- if (p == NULL || len <= 1 || p[0] != '/' || p[1] != '*')
+ if (p == NULL)
return;
- F_SET(sp, SC_SCR_TOP);
- do {
- for (; len; --len, ++p)
- if (p[0] == '*' && len > 1 && p[1] == '/') {
+ if (p[0] == '#') {
+ F_SET(sp, SC_SCR_TOP);
+ while (!db_get(sp, ++lno, 0, &p, &len))
+ if (len < 1 || p[0] != '#') {
sp->lno = lno;
return;
}
- } while (!db_get(sp, ++lno, 0, &p, &len));
+ } else if (len >= 1 && p[0] == '/' && p[1] == '*') {
+ F_SET(sp, SC_SCR_TOP);
+ do {
+ for (; len > 1; --len, ++p)
+ if (p[0] == '*' && p[1] == '/') {
+ sp->lno = lno;
+ return;
+ }
+ } while (!db_get(sp, ++lno, 0, &p, &len));
+ }
}
/*
@@ -1346,8 +1387,11 @@ file_lock(sp, name, fdp, fd, iswrite)
* as returning EACCESS and EAGAIN; add EWOULDBLOCK for good measure,
* and assume they are the former. There's no portable way to do this.
*/
- return (errno == EACCES || errno == EAGAIN || errno == EWOULDBLOCK ?
- LOCK_UNAVAIL : LOCK_FAILED);
+ return (errno == EACCES || errno == EAGAIN
+#ifdef EWOULDBLOCK
+ || errno == EWOULDBLOCK
+#endif
+ ? LOCK_UNAVAIL : LOCK_FAILED);
}
#endif
#if !defined(HAVE_LOCK_FLOCK) && !defined(HAVE_LOCK_FCNTL)
diff --git a/usr.bin/vi/common/gs.h b/usr.bin/vi/common/gs.h
index 37805d53c31..afb2721788c 100644
--- a/usr.bin/vi/common/gs.h
+++ b/usr.bin/vi/common/gs.h
@@ -6,7 +6,7 @@
*
* See the LICENSE file for redistribution information.
*
- * @(#)gs.h 10.29 (Berkeley) 4/15/96
+ * @(#)gs.h 10.32 (Berkeley) 6/18/96
*/
#define TEMPORARY_FILE_STRING "/tmp" /* Default temporary file name. */
@@ -38,15 +38,15 @@ struct _fref {
u_int16_t flags;
};
-/* Action argument to scr_exadjust(). */
+/* Action arguments to scr_exadjust(). */
typedef enum { EX_TERM_CE, EX_TERM_SCROLL } exadj_t;
-/* Screen attribute argument to scr_attr(). */
-typedef enum { SA_INVERSE } scr_attr_t;
+/* Screen attribute arguments to scr_attr(). */
+typedef enum { SA_ALTERNATE, SA_INVERSE } scr_attr_t;
-/* Key type argument to scr_keyval(). */
+/* Key type arguments to scr_keyval(). */
typedef enum { KEY_VEOF, KEY_VERASE, KEY_VKILL, KEY_VWERASE } scr_keyval_t;
-
+
/*
* GS:
*
@@ -65,8 +65,8 @@ struct _gs {
void *tcl_interp; /* Tcl_Interp *: Tcl interpreter. */
void *cl_private; /* Curses support private area. */
+ void *ip_private; /* IP support private area. */
void *tk_private; /* Tk/Tcl support private area. */
- void *xaw_private; /* XAW support private area. */
/* File references. */
CIRCLEQ_HEAD(_frefh, _fref) frefq;
@@ -156,7 +156,7 @@ struct _gs {
/* Beep/bell/flash the terminal. */
int (*scr_bell) __P((SCR *));
/* Display a busy message. */
- void (*scr_busy) __P((SCR *, char const *, busy_t));
+ void (*scr_busy) __P((SCR *, const char *, busy_t));
/* Clear to the end of the line. */
int (*scr_clrtoeol) __P((SCR *));
/* Return the cursor location. */
diff --git a/usr.bin/vi/common/key.c b/usr.bin/vi/common/key.c
index 0ff6da0d8d3..474efe2da5e 100644
--- a/usr.bin/vi/common/key.c
+++ b/usr.bin/vi/common/key.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)key.c 10.30 (Berkeley) 4/3/96";
+static const char sccsid[] = "@(#)key.c 10.32 (Berkeley) 6/30/96";
#endif /* not lint */
#include <sys/types.h>
@@ -790,12 +790,12 @@ v_event_err(sp, evp)
case E_TIMEOUT:
msgq(sp, M_ERR, "286|Unexpected timeout event");
break;
+ case E_WRESIZE:
+ msgq(sp, M_ERR, "316|Unexpected resize event");
+ break;
case E_WRITE:
msgq(sp, M_ERR, "287|Unexpected write event");
break;
- case E_WRITEQUIT:
- msgq(sp, M_ERR, "288|Unexpected write-and-quit event");
- break;
/*
* Theoretically, none of these can occur, as they're handled at the
diff --git a/usr.bin/vi/common/key.h b/usr.bin/vi/common/key.h
index 61b0ac87903..76fb64f8e1e 100644
--- a/usr.bin/vi/common/key.h
+++ b/usr.bin/vi/common/key.h
@@ -6,7 +6,7 @@
*
* See the LICENSE file for redistribution information.
*
- * @(#)key.h 10.14 (Berkeley) 4/10/96
+ * @(#)key.h 10.18 (Berkeley) 6/30/96
*/
/*
@@ -48,8 +48,8 @@ typedef enum {
E_SIGTERM, /* SIGTERM. */
E_STRING, /* Input string: e_csp, e_len set. */
E_TIMEOUT, /* Timeout. */
- E_WRITE, /* Write. */
- E_WRITEQUIT /* Write and quit. */
+ E_WRESIZE, /* Window resize. */
+ E_WRITE /* Write. */
} e_event_t;
/*
@@ -185,7 +185,7 @@ extern KEYLIST keylist[];
#define EC_MAPINPUT 0x004 /* Apply the input map. */
#define EC_MAPNODIGIT 0x008 /* Return to a digit. */
#define EC_QUOTED 0x010 /* Try to quote next character */
-#define EC_RAW 0x020 /* Any next character. */
+#define EC_RAW 0x020 /* Any next character. XXX: not used. */
#define EC_TIMEOUT 0x040 /* Timeout to next character. */
/* Flags describing text input special cases. */
diff --git a/usr.bin/vi/common/mem.h b/usr.bin/vi/common/mem.h
index 9eb99dd4c94..af42e6bcd1d 100644
--- a/usr.bin/vi/common/mem.h
+++ b/usr.bin/vi/common/mem.h
@@ -99,7 +99,7 @@
/* Free a GET_SPACE returned buffer. */
#define FREE_SPACE(sp, bp, blen) { \
GS *L__gp = (sp) == NULL ? NULL : (sp)->gp; \
- if (L__gp != NULL && (CHAR_T *)bp == (CHAR_T *)L__gp->tmp_bp) \
+ if (L__gp != NULL && bp == L__gp->tmp_bp) \
F_CLR(L__gp, G_TMP_INUSE); \
else \
free(bp); \
diff --git a/usr.bin/vi/common/msg.c b/usr.bin/vi/common/msg.c
index 27b87b91014..9327b6d2b4d 100644
--- a/usr.bin/vi/common/msg.c
+++ b/usr.bin/vi/common/msg.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)msg.c 10.36 (Berkeley) 5/15/96";
+static const char sccsid[] = "@(#)msg.c 10.39 (Berkeley) 6/20/96";
#endif /* not lint */
#include <sys/param.h>
@@ -381,7 +381,7 @@ msgq_str(sp, mtype, str, fmt)
}
/*
- * msgq_rpt --
+ * mod_rpt --
* Report on the lines that changed.
*
* !!!
@@ -398,10 +398,10 @@ msgq_str(sp, mtype, str, fmt)
* the command 2d}, from the 'b' would report that two lines were deleted,
* not one.
*
- * PUBLIC: void msgq_rpt __P((SCR *));
+ * PUBLIC: void mod_rpt __P((SCR *));
*/
void
-msgq_rpt(sp)
+mod_rpt(sp)
SCR *sp;
{
static char * const action[] = {
@@ -672,9 +672,9 @@ msg_open(sp, file)
char *p, *t, buf[MAXPATHLEN];
if ((p = strrchr(file, '/')) != NULL && p[1] == '\0' &&
- ((t = getenv("LANG")) != NULL && t[0] != '\0' ||
- (t = getenv("LC_MESSAGES")) != NULL && t[0] != '\0')) {
- (void)snprintf(buf, sizeof(buf), "%svi_%s", file, t);
+ ((t = getenv("LC_MESSAGES")) != NULL && t[0] != '\0' ||
+ (t = getenv("LANG")) != NULL && t[0] != '\0')) {
+ (void)snprintf(buf, sizeof(buf), "%s%s", file, t);
p = buf;
} else
p = file;
diff --git a/usr.bin/vi/common/options.c b/usr.bin/vi/common/options.c
index 609a0433dfd..891e7333edb 100644
--- a/usr.bin/vi/common/options.c
+++ b/usr.bin/vi/common/options.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)options.c 10.43 (Berkeley) 5/16/96";
+static const char sccsid[] = "@(#)options.c 10.46 (Berkeley) 6/26/96";
#endif /* not lint */
#include <sys/types.h>
@@ -214,6 +214,8 @@ OPTLIST const optlist[] = {
{"warn", NULL, OPT_1BOOL, 0},
/* O_WINDOW 4BSD */
{"window", f_window, OPT_NUM, 0},
+/* O_WINDOWNAME 4BSD */
+ {"windowname", f_windowname, OPT_0BOOL, 0},
/* O_WRAPLEN 4.4BSD */
{"wraplen", NULL, OPT_NUM, 0},
/* O_WRAPMARGIN 4BSD */
@@ -254,6 +256,7 @@ static OABBREV const abbrev[] = {
{"sh", O_SHELL}, /* 4BSD */
{"slow", O_SLOWOPEN}, /* 4BSD */
{"sm", O_SHOWMATCH}, /* 4BSD */
+ {"smd", O_SHOWMODE}, /* 4BSD */
{"sw", O_SHIFTWIDTH}, /* 4BSD */
{"tag", O_TAGS}, /* 4BSD (undocumented) */
{"tl", O_TAGLENGTH}, /* 4BSD */
diff --git a/usr.bin/vi/common/options_f.c b/usr.bin/vi/common/options_f.c
index e45df04a528..039ed0dbf7a 100644
--- a/usr.bin/vi/common/options_f.c
+++ b/usr.bin/vi/common/options_f.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)options_f.c 10.23 (Berkeley) 5/4/96";
+static const char sccsid[] = "@(#)options_f.c 10.24 (Berkeley) 6/26/96";
#endif /* not lint */
#include <sys/types.h>
@@ -365,3 +365,30 @@ f_window(sp, op, str, valp)
*valp = 1;
return (0);
}
+
+/*
+ * PUBLIC: int f_windowname __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_windowname(sp, op, str, valp)
+ SCR *sp;
+ OPTION *op;
+ char *str;
+ u_long *valp;
+{
+ /*
+ * XXX
+ * The cl_rename routine depends on the O_WINDOWNAME value being
+ * already set, because it's a destructive action, and it wants
+ * to make sure we have permission. This doesn't apply to other
+ * screen types where the naming won't be destructive, so we don't
+ * want to move the check up out of the screen code.
+ */
+ if (*valp)
+ O_CLR(sp, O_WINDOWNAME);
+ else
+ O_SET(sp, O_WINDOWNAME);
+
+ (void)sp->gp->scr_rename(sp);
+ return (0);
+}
diff --git a/usr.bin/vi/common/recover.c b/usr.bin/vi/common/recover.c
index 38c33c0668d..10702cc384f 100644
--- a/usr.bin/vi/common/recover.c
+++ b/usr.bin/vi/common/recover.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)recover.c 10.18 (Berkeley) 5/15/96";
+static const char sccsid[] = "@(#)recover.c 10.20 (Berkeley) 6/20/96";
#endif /* not lint */
#include <sys/param.h>
@@ -35,6 +35,7 @@ static const char sccsid[] = "@(#)recover.c 10.18 (Berkeley) 5/15/96";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include "common.h"
@@ -333,6 +334,7 @@ rcv_mailfile(sp, issync, cp_path)
char *cp_path;
{
EXF *ep;
+ GS *gp;
struct passwd *pw;
size_t len;
time_t now;
@@ -351,6 +353,7 @@ rcv_mailfile(sp, issync, cp_path)
#endif
char host[MAXHOSTNAMELEN];
+ gp = sp->gp;
if ((pw = getpwuid(uid = getuid())) == NULL) {
msgq(sp, M_ERR,
"062|Information on user id %u not found", uid);
@@ -403,22 +406,23 @@ rcv_mailfile(sp, issync, cp_path)
VI_FHEADER, t, /* Non-standard. */
VI_PHEADER, cp_path, /* Non-standard. */
"Reply-To: root",
- "From: root (Vi recovery program)",
+ "From: root (Nvi recovery program)",
"To: ", pw->pw_name,
- "Subject: Vi saved the file ", p,
+ "Subject: Nvi saved the file ", p,
"Precedence: bulk"); /* For vacation(1). */
if (len > sizeof(buf) - 1)
goto lerr;
if (write(fd, buf, len) != len)
goto werr;
- len = snprintf(buf, sizeof(buf), "%s%.24s%s%s%s%s%s%s%s%s%s%s%s\n\n",
+ len = snprintf(buf, sizeof(buf),
+ "%s%.24s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n",
"On ", ctime(&now), ", the user ", pw->pw_name,
" was editing a file named ", t, " on the machine ",
host, ", when it was saved for recovery. ",
"You can recover most, if not all, of the changes ",
- "to this file using the -r option to ex or vi:\n\n",
- "\tvi -r ", t);
+ "to this file using the -r option to ", gp->progname, ":\n\n\t",
+ gp->progname, " -r ", t);
if (len > sizeof(buf) - 1) {
lerr: msgq(sp, M_ERR, "064|Recovery file buffer overrun");
goto err;
diff --git a/usr.bin/vi/common/screen.h b/usr.bin/vi/common/screen.h
index b66833189b8..141d50703b6 100644
--- a/usr.bin/vi/common/screen.h
+++ b/usr.bin/vi/common/screen.h
@@ -6,7 +6,7 @@
*
* See the LICENSE file for redistribution information.
*
- * @(#)screen.h 10.19 (Berkeley) 5/15/96
+ * @(#)screen.h 10.22 (Berkeley) 6/30/96
*/
/*
@@ -88,7 +88,6 @@ struct _scr {
SM_REPLACE } showmode;
void *ex_private; /* Ex private area. */
- void *sex_private; /* Ex screen private area. */
void *vi_private; /* Vi private area. */
/* PARTIALLY OR COMPLETELY COPIED FROM PREVIOUS SCREEN. */
@@ -110,19 +109,20 @@ struct _scr {
#define SEARCH_EOL 0x0002 /* Offset past EOL is okay. */
#define SEARCH_FILE 0x0004 /* Search the entire file. */
#define SEARCH_INCR 0x0008 /* Search incrementally. */
-#define SEARCH_MSG 0x0010 /* Display search warning messages. */
+#define SEARCH_MSG 0x0010 /* Display search messages. */
#define SEARCH_PARSE 0x0020 /* Parse the search pattern. */
#define SEARCH_SET 0x0040 /* Set search direction. */
#define SEARCH_TAG 0x0080 /* Search for a tag pattern. */
+#define SEARCH_WMSG 0x0100 /* Display search-wrapped messages. */
/* Ex/vi: RE information. */
dir_t searchdir; /* Last file search direction. */
- char *re; /* Search RE (uncompiled form). */
- regex_t re_c; /* Search RE (compiled form). */
- size_t re_len; /* Search RE length. */
- char *subre; /* Substitute RE (uncompiled form.) */
- regex_t subre_c; /* Substitute RE (compiled form.) */
- size_t subre_len; /* Substitute RE length. */
+ regex_t re_c; /* Search RE: compiled form. */
+ char *re; /* Search RE: uncompiled form. */
+ size_t re_len; /* Search RE: uncompiled length. */
+ regex_t subre_c; /* Substitute RE: compiled form. */
+ char *subre; /* Substitute RE: uncompiled form. */
+ size_t subre_len; /* Substitute RE: uncompiled length). */
char *repl; /* Substitute replacement. */
size_t repl_len; /* Substitute replacement length.*/
size_t *newl; /* Newline offset array. */
@@ -186,15 +186,16 @@ struct _scr {
#define SC_ARGRECOVER 0x00004000 /* Argument list is recovery files. */
#define SC_AT_SET 0x00008000 /* Last at buffer set. */
#define SC_COMEDIT 0x00010000 /* Colon command-line edit window. */
-#define SC_EX_DONTWAIT 0x00020000 /* Ex: don't wait for the user. */
-#define SC_EX_GLOBAL 0x00040000 /* Ex: executing a global command. */
-#define SC_EX_SILENT 0x00080000 /* Ex: batch script. */
-#define SC_READONLY 0x00100000 /* Persistent readonly state. */
-#define SC_RE_SEARCH 0x00200000 /* Search RE has been compiled. */
-#define SC_RE_SUBST 0x00400000 /* Substitute RE has been compiled. */
-#define SC_SCRIPT 0x00800000 /* Shell script window. */
-#define SC_STATUS 0x01000000 /* Schedule welcome message. */
-#define SC_TINPUT 0x02000000 /* Doing text input. */
-#define SC_TINPUT_INFO 0x04000000 /* Doing text input on info line. */
+#define SC_EX_GLOBAL 0x00020000 /* Ex: executing a global command. */
+#define SC_EX_SILENT 0x00040000 /* Ex: batch script. */
+#define SC_EX_WAIT_NO 0x00080000 /* Ex: don't wait for the user. */
+#define SC_EX_WAIT_YES 0x00100000 /* Ex: do wait for the user. */
+#define SC_READONLY 0x00200000 /* Persistent readonly state. */
+#define SC_RE_SEARCH 0x00400000 /* Search RE has been compiled. */
+#define SC_RE_SUBST 0x00800000 /* Substitute RE has been compiled. */
+#define SC_SCRIPT 0x01000000 /* Shell script window. */
+#define SC_STATUS 0x02000000 /* Schedule welcome message. */
+#define SC_TINPUT 0x04000000 /* Doing text input. */
+#define SC_TINPUT_INFO 0x08000000 /* Doing text input on info line. */
u_int32_t flags;
};
diff --git a/usr.bin/vi/common/search.c b/usr.bin/vi/common/search.c
index 5823f250ff4..3fd2719778f 100644
--- a/usr.bin/vi/common/search.c
+++ b/usr.bin/vi/common/search.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)search.c 10.24 (Berkeley) 5/26/96";
+static const char sccsid[] = "@(#)search.c 10.25 (Berkeley) 6/30/96";
#endif /* not lint */
#include <sys/types.h>
@@ -30,17 +30,18 @@ static const char sccsid[] = "@(#)search.c 10.24 (Berkeley) 5/26/96";
typedef enum { S_EMPTY, S_EOF, S_NOPREV, S_NOTFOUND, S_SOF, S_WRAP } smsg_t;
static void search_msg __P((SCR *, smsg_t));
-static int search_setup __P((SCR *, dir_t, char *, char **, u_int));
+static int search_init __P((SCR *, dir_t, char *, size_t, char **, u_int));
/*
- * search_setup --
+ * search_init --
* Set up a search.
*/
static int
-search_setup(sp, dir, ptrn, epp, flags)
+search_init(sp, dir, ptrn, plen, epp, flags)
SCR *sp;
dir_t dir;
char *ptrn, **epp;
+ size_t plen;
u_int flags;
{
recno_t lno;
@@ -60,16 +61,16 @@ search_setup(sp, dir, ptrn, epp, flags)
if (LF_ISSET(SEARCH_PARSE)) { /* Parse the string. */
/*
- * Use the saved pattern if no pattern supplied, or if only
- * the delimiter character supplied.
+ * Use the saved pattern if no pattern specified, or if only
+ * one or two delimiter characters specified.
*
* !!!
- * Only the pattern itself was saved, historically vi didn't
- * reuse addressing or delta information.
+ * Historically, only the pattern itself was saved, vi didn't
+ * preserve addressing or delta information.
*/
if (ptrn == NULL)
goto prev;
- if (ptrn[1] == '\0') {
+ if (plen == 1) {
if (epp != NULL)
*epp = ptrn + 1;
goto prev;
@@ -83,9 +84,9 @@ prev: if (sp->re == NULL) {
search_msg(sp, S_NOPREV);
return (1);
}
- /* Compile the search pattern if necessary. */
- if (!F_ISSET(sp, SC_RE_SEARCH) &&
- re_compile(sp, sp->re, NULL, NULL, &sp->re_c,
+ /* Re-compile the search pattern if necessary. */
+ if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
+ sp->re, sp->re_len, NULL, NULL, &sp->re_c,
RE_C_SEARCH |
(LF_ISSET(SEARCH_MSG) ? 0 : RE_C_SILENT)))
return (1);
@@ -104,21 +105,24 @@ prev: if (sp->re == NULL) {
* Only discard an escape character if it escapes a delimiter.
*/
for (delim = *ptrn, p = t = ++ptrn;; *t++ = *p++) {
- if (p[0] == '\0' || p[0] == delim) {
- if (p[0] == delim)
+ if (--plen == 0 || p[0] == delim) {
+ if (plen != 0)
++p;
- *t = '\0';
break;
}
- if (p[1] == delim && p[0] == '\\')
+ if (plen > 1 && p[0] == '\\' && p[1] == delim) {
++p;
+ --plen;
+ }
}
if (epp != NULL)
*epp = p;
+
+ plen = t - ptrn;
}
/* Compile the RE. */
- if (re_compile(sp, ptrn, &sp->re, &sp->re_len, &sp->re_c,
+ if (re_compile(sp, ptrn, plen, &sp->re, &sp->re_len, &sp->re_c,
RE_C_SEARCH |
(LF_ISSET(SEARCH_MSG) ? 0 : RE_C_SILENT) |
(LF_ISSET(SEARCH_TAG) ? RE_C_TAG : 0) |
@@ -136,13 +140,15 @@ prev: if (sp->re == NULL) {
* f_search --
* Do a forward search.
*
- * PUBLIC: int f_search __P((SCR *, MARK *, MARK *, char *, char **, u_int));
+ * PUBLIC: int f_search __P((SCR *,
+ * PUBLIC: MARK *, MARK *, char *, size_t, char **, u_int));
*/
int
-f_search(sp, fm, rm, ptrn, eptrn, flags)
+f_search(sp, fm, rm, ptrn, plen, eptrn, flags)
SCR *sp;
MARK *fm, *rm;
char *ptrn, **eptrn;
+ size_t plen;
u_int flags;
{
busy_t btype;
@@ -152,7 +158,7 @@ f_search(sp, fm, rm, ptrn, eptrn, flags)
int cnt, eval, rval, wrapped;
char *l;
- if (search_setup(sp, FORWARD, ptrn, eptrn, flags))
+ if (search_init(sp, FORWARD, ptrn, plen, eptrn, flags))
return (1);
if (LF_ISSET(SEARCH_FILE)) {
@@ -245,32 +251,8 @@ f_search(sp, fm, rm, ptrn, eptrn, flags)
break;
}
- /*
- * XXX
- * Warn if the search wrapped. This message is only displayed
- * if we're in interactive mode and there are no keys in the
- * queue. The problem is that the command is going to succeed,
- * and the message isn't an error, it's merely informational.
- * So, if we're reading the .exrc file, displaying it causes
- * the screen to pause before entering the file, which is bad.
- * Or, if a macro causes it to be repeatedly displayed, e.g.,
- * the pattern only occurs once in the file and wrapscan is set,
- * you lose, particularly if the macro does something like:
- * :map K /pattern/^MjK
- * Each new search will display the message and the /pattern/
- * will immediately overwrite it, with strange results. The
- * System V vi displays the "wrapped" message multiple times,
- * but it's overwritten each time, so it's not as noticeable.
- * Since we don't discard messages, it's a real problem.
- *
- * XXX
- * The test for SC_SCR_EX or SC_SCR_VI feels wrong to me. I
- * didn't originally intend for that bit to reflect that the
- * user has "gone interactive", but that's the only solution
- * I see.
- */
- if (wrapped && LF_ISSET(SEARCH_MSG) &&
- F_ISSET(sp, SC_SCR_EX | SC_SCR_VI) && !KEYS_WAITING(sp))
+ /* Warn if the search wrapped. */
+ if (wrapped && LF_ISSET(SEARCH_WMSG))
search_msg(sp, S_WRAP);
#if defined(DEBUG) && 0
@@ -302,13 +284,15 @@ f_search(sp, fm, rm, ptrn, eptrn, flags)
* b_search --
* Do a backward search.
*
- * PUBLIC: int b_search __P((SCR *, MARK *, MARK *, char *, char **, u_int));
+ * PUBLIC: int b_search __P((SCR *,
+ * PUBLIC: MARK *, MARK *, char *, size_t, char **, u_int));
*/
int
-b_search(sp, fm, rm, ptrn, eptrn, flags)
+b_search(sp, fm, rm, ptrn, plen, eptrn, flags)
SCR *sp;
MARK *fm, *rm;
char *ptrn, **eptrn;
+ size_t plen;
u_int flags;
{
busy_t btype;
@@ -318,7 +302,7 @@ b_search(sp, fm, rm, ptrn, eptrn, flags)
int cnt, eval, rval, wrapped;
char *l;
- if (search_setup(sp, BACKWARD, ptrn, eptrn, flags))
+ if (search_init(sp, BACKWARD, ptrn, plen, eptrn, flags))
return (1);
/*
@@ -408,12 +392,8 @@ b_search(sp, fm, rm, ptrn, eptrn, flags)
if (coff != 0 && match[0].rm_so >= coff)
continue;
- /*
- * XXX
- * See the comment in f_search() for more information.
- */
- if (wrapped && LF_ISSET(SEARCH_MSG) &&
- F_ISSET(sp, SC_SCR_EX | SC_SCR_VI) && !KEYS_WAITING(sp))
+ /* Warn if the search wrapped. */
+ if (wrapped && LF_ISSET(SEARCH_WMSG))
search_msg(sp, S_WRAP);
#if defined(DEBUG) && 0
diff --git a/usr.bin/vi/common/signal.c b/usr.bin/vi/common/signal.c
deleted file mode 100644
index 47a5e5bca23..00000000000
--- a/usr.bin/vi/common/signal.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)signal.c 8.34 (Berkeley) 8/17/94";
-#endif /* not lint */
-
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "compat.h"
-#include <db.h>
-#include <regex.h>
-
-#include "vi.h"
-
-static void h_alrm __P((int));
-static void h_hup __P((int));
-static void h_int __P((int));
-static void h_term __P((int));
-static void h_winch __P((int));
-static void sig_sync __P((int, u_int));
-
-/*
- * There are seven normally asynchronous actions about which vi cares:
- * SIGALRM, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP and SIGWINCH.
- *
- * The assumptions:
- * 1: The DB routines are not reentrant.
- * 2: The curses routines may not be reentrant.
- *
- * SIGALRM, SIGHUP, SIGTERM
- * Used for file recovery. The DB routines can't be reentered, so
- * the vi routines that call DB block all three signals (see line.c).
- * This means that DB routines can be called at interrupt time.
- *
- * SIGALRM
- * Used to paint busy messages on the screen. The curses routines
- * can't be reentered, so this function of SIGALRM can only be used
- * in sections of code that do not use any curses functions (see
- * busy_on, busy_off in signal.c). This means that curses can be
- * called at interrupt time.
- *
- * SIGQUIT
- * Disabled by the signal initialization routines. Historically,
- * ^\ switched vi into ex mode, and we continue that practice.
- *
- * SIGWINCH:
- * The interrupt routine sets a global bit which is checked by the
- * key-read routine, so there are no reentrancy issues. This means
- * that the screen will not resize until vi runs out of keys, but
- * that doesn't seem like a problem.
- *
- * SIGINT and SIGTSTP are a much more difficult issue to resolve. Vi has
- * to permit the user to interrupt long-running operations. Generally, a
- * search, substitution or read/write is done on a large file, or, the user
- * creates a key mapping with an infinite loop. This problem will become
- * worse as more complex semantics are added to vi. There are four major
- * solutions on the table, each of which have minor permutations.
- *
- * 1: Run in raw mode.
- *
- * The up side is that there's no asynchronous behavior to worry about,
- * and obviously no reentrancy problems. The down side is that it's easy
- * to misinterpret characters (e.g. :w big_file^Mi^V^C is going to look
- * like an interrupt) and it's easy to get into places where we won't see
- * interrupt characters (e.g. ":map a ixx^[hxxaXXX" infinitely loops in
- * historic implementations of vi). Periodically reading the terminal
- * input buffer might solve the latter problem, but it's not going to be
- * pretty.
- *
- * Also, we're going to be checking for ^C's and ^Z's both, all over
- * the place -- I hate to litter the source code with that. For example,
- * the historic version of vi didn't permit you to suspend the screen if
- * you were on the colon command line. This isn't right. ^Z isn't a vi
- * command, it's a terminal event. (Dammit.)
- *
- * 2: Run in cbreak mode. There are two problems in this area. First, the
- * current curses implementations (both System V and Berkeley) don't give
- * you clean cbreak modes. For example, the IEXTEN bit is left on, turning
- * on DISCARD and LNEXT. To clarify, what vi WANTS is 8-bit clean, with
- * the exception that flow control and signals are turned on, and curses
- * cbreak mode doesn't give you this.
- *
- * We can either set raw mode and twiddle the tty, or cbreak mode and
- * twiddle the tty. I chose to use raw mode, on the grounds that raw
- * mode is better defined and I'm less likely to be surprised by a curses
- * implementation down the road. The twiddling consists of setting ISIG,
- * IXON/IXOFF, and disabling some of the interrupt characters (see the
- * comments in svi/svi_screen.c). This is all found in historic System
- * V (SVID 3) and POSIX 1003.1-1992, so it should be fairly portable.
- *
- * The second problem is that vi permits you to enter literal signal
- * characters, e.g. ^V^C. There are two possible solutions. First, you
- * can turn off signals when you get a ^V, but that means that a network
- * packet containing ^V and ^C will lose, since the ^C may take effect
- * before vi reads the ^V. (This is particularly problematic if you're
- * talking over a protocol that recognizes signals locally and sends OOB
- * packets when it sees them.) Second, you can turn the ^C into a literal
- * character in vi, but that means that there's a race between entering
- * ^V<character>^C, i.e. the sequence may end up being ^V^C<character>.
- * Also, the second solution doesn't work for flow control characters, as
- * they aren't delivered to the program as signals.
- *
- * Generally, this is what historic vi did. (It didn't have the curses
- * problems because it didn't use curses.) It entered signals following
- * ^V characters into the input stream, (which is why there's no way to
- * enter a literal flow control character).
- *
- * 3: Run in mostly raw mode; turn signals on when doing an operation the
- * user might want to interrupt, but leave them off most of the time.
- *
- * This works well for things like file reads and writes. This doesn't
- * work well for trying to detect infinite maps. The problem is that
- * you can write the code so that you don't have to turn on interrupts
- * per keystroke, but the code isn't pretty and it's hard to make sure
- * that an optimization doesn't cover up an infinite loop. This also
- * requires interaction or state between the vi parser and the key
- * reading routines, as an infinite loop may still be returning keys
- * to the parser.
- *
- * Also, if the user inserts an interrupt into the tty queue while the
- * interrupts are turned off, the key won't be treated as an interrupt,
- * and requiring the user to pound the keyboard to catch an interrupt
- * window is nasty.
- *
- * 4: Run in mostly raw mode, leaving signals on all of the time. Done
- * by setting raw mode, and twiddling the tty's termios ISIG bit.
- *
- * This works well for the interrupt cases, because the code only has
- * to check to see if the interrupt flag has been set, and can otherwise
- * ignore signals. It's also less likely that we'll miss a case, and we
- * don't have to worry about synchronizing between the vi parser and the
- * key read routines.
- *
- * The down side is that we have to turn signals off if the user wants
- * to enter a literal character (e.g. ^V^C). If the user enters the
- * combination fast enough, or as part of a single network packet,
- * the text input routines will treat it as a signal instead of as a
- * literal character. To some extent, we have this problem already,
- * since we turn off flow control so that the user can enter literal
- * XON/XOFF characters.
- *
- * This is probably the easiest to code, and provides the smoothest
- * programming interface.
- *
- * There are a couple of other problems to consider.
- *
- * First, System V's curses doesn't handle SIGTSTP correctly. If you use the
- * newterm() interface, the TSTP signal will leave you in raw mode, and the
- * final endwin() will leave you in the correct shell mode. If you use the
- * initscr() interface, the TSTP signal will return you to the correct shell
- * mode, but the final endwin() will leave you in raw mode. There you have
- * it: proof that drug testing is not making any significant headway in the
- * computer industry. The 4BSD curses is deficient in that it does not have
- * an interface to the terminal keypad. So, regardless, we have to do our
- * own SIGTSTP handling.
- *
- * The problem with this is that if we do our own SIGTSTP handling, in either
- * models #3 or #4, we're going to have to call curses routines at interrupt
- * time, which means that we might be reentering curses, which is something we
- * don't want to do.
- *
- * Second, SIGTSTP has its own little problems. It's broadcast to the entire
- * process group, not sent to a single process. The scenario goes something
- * like this: the shell execs the mail program, which execs vi. The user hits
- * ^Z, and all three programs get the signal, in some random order. The mail
- * program goes to sleep immediately (since it probably didn't have a SIGTSTP
- * handler in place). The shell gets a SIGCHLD, does a wait, and finds out
- * that the only child in its foreground process group (of which it's aware)
- * is asleep. It then optionally resets the terminal (because the modes aren't
- * how it left them), and starts prompting the user for input. The problem is
- * that somewhere in the middle of all of this, vi is resetting the terminal,
- * and getting ready to send a SIGTSTP to the process group in order to put
- * itself to sleep. There's a solution to all of this: when vi starts, it puts
- * itself into its own process group, and then only it (and possible child
- * processes) receive the SIGTSTP. This permits it to clean up the terminal
- * and switch back to the original process group, where it sends that process
- * group a SIGTSTP, putting everyone to sleep and waking the shell.
- *
- * Third, handing SIGTSTP asynchronously is further complicated by the child
- * processes vi may fork off. If vi calls ex, ex resets the terminal and
- * starts running some filter, and SIGTSTP stops them both, vi has to know
- * when it restarts that it can't repaint the screen until ex's child has
- * finished running. This is solveable, but it's annoying.
- *
- * Well, somebody had to make a decision, and this is the way it's going to be
- * (unless I get talked out of it). SIGINT is handled asynchronously, so
- * that we can pretty much guarantee that the user can interrupt any operation
- * at any time. SIGTSTP is handled synchronously, so that we don't have to
- * reenter curses and so that we don't have to play the process group games.
- * ^Z is recognized in the standard text input and command modes. (^Z should
- * also be recognized during operations that may potentially take a long time.
- * The simplest solution is probably to twiddle the tty, install a handler for
- * SIGTSTP, and then restore normal tty modes when the operation is complete.)
- */
-
-/*
- * sig_init --
- * Initialize signals.
- */
-int
-sig_init(sp)
- SCR *sp;
-{
- GS *gp;
- struct sigaction act;
-
- /* Initialize the signals. */
- gp = sp->gp;
- (void)sigemptyset(&gp->blockset);
-
- /*
- * Use sigaction(2), not signal(3), since we don't always want to
- * restart system calls. The example is when waiting for a command
- * mode keystroke and SIGWINCH arrives. Try to set the restart bit
- * (SA_RESTART) on SIGALRM anyway, it should result in a lot fewer
- * interruptions. We also block every other signal that we can block
- * when a signal arrives. This is because the signal functions call
- * other nvi functions, which aren't guaranteed to be reentrant.
- */
-
-#ifndef SA_RESTART
-#define SA_RESTART 0
-#endif
-#define SETSIG(signal, flags, handler) { \
- if (sigaddset(&gp->blockset, signal)) \
- goto err; \
- act.sa_handler = handler; \
- sigfillset(&act.sa_mask); \
- act.sa_flags = flags; \
- if (sigaction(signal, &act, NULL)) \
- goto err; \
-}
- SETSIG(SIGALRM, SA_RESTART, h_alrm);
- SETSIG(SIGHUP, 0, h_hup);
- SETSIG(SIGINT, 0, h_int);
- SETSIG(SIGTERM, 0, h_term);
- SETSIG(SIGWINCH, 0, h_winch);
- return (0);
-
-err: msgq(sp, M_SYSERR, "signal init");
- return (1);
-}
-
-/*
- * sig_end --
- * End signal setup.
- */
-void
-sig_end()
-{
- /*
- * POSIX 1003.1-1990 requires that fork (and, presumably, vfork) clear
- * pending alarms, and that the exec functions clear pending signals.
- * In addition, after an exec, the child continues to ignore signals
- * ignored in the parent, and the child's action for signals caught in
- * the parent is set to the default action. So, as we currently don't
- * ignore any signals, there's no cleanup to be done. This routine is
- * left here as a stub function.
- */
- return;
-}
-
-/*
- * busy_on --
- * Set a busy message timer.
- */
-int
-busy_on(sp, msg)
- SCR *sp;
- char const *msg;
-{
- struct itimerval value;
- struct timeval tod;
-
- /*
- * Give the oldest busy message precedence, since it's
- * the longer running operation.
- */
- if (sp->busy_msg != NULL)
- return (1);
-
- /* Get the current time of day, and create a target time. */
- if (gettimeofday(&tod, NULL))
- return (1);
-#define USER_PATIENCE_USECS (8 * 100000L)
- sp->busy_tod.tv_sec = tod.tv_sec;
- sp->busy_tod.tv_usec = tod.tv_usec + USER_PATIENCE_USECS;
-
- /* We depend on this being an atomic instruction. */
- sp->busy_msg = msg;
-
- /*
- * Busy messages turn around fast. Reset the timer regardless
- * of its current state.
- */
- value.it_value.tv_sec = 0;
- value.it_value.tv_usec = USER_PATIENCE_USECS;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- if (setitimer(ITIMER_REAL, &value, NULL))
- msgq(sp, M_SYSERR, "timer: setitimer");
- return (0);
-}
-
-/*
- * busy_off --
- * Turn off a busy message timer.
- */
-void
-busy_off(sp)
- SCR *sp;
-{
- /* We depend on this being an atomic instruction. */
- sp->busy_msg = NULL;
-}
-
-/*
- * rcv_on --
- * Turn on recovery timer.
- */
-int
-rcv_on(sp, ep)
- SCR *sp;
- EXF *ep;
-{
- struct itimerval value;
- struct timeval tod;
-
- /* Get the current time of day. */
- if (gettimeofday(&tod, NULL))
- return (1);
-
- /* Create target time of day. */
- ep->rcv_tod.tv_sec = tod.tv_sec + RCV_PERIOD;
- ep->rcv_tod.tv_usec = 0;
-
- /*
- * If there's a busy message happening, we're done, the
- * interrupt handler will start our timer as necessary.
- */
- if (sp->busy_msg != NULL)
- return (0);
-
- value.it_value.tv_sec = RCV_PERIOD;
- value.it_value.tv_usec = 0;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- if (setitimer(ITIMER_REAL, &value, NULL)) {
- msgq(sp, M_SYSERR, "timer: setitimer");
- return (1);
- }
- return (0);
-}
-
-/*
- * h_alrm --
- * Handle SIGALRM.
- *
- * There are two uses of the ITIMER_REAL timer (SIGALRM) in nvi. The first
- * is to push the recovery information out to disk at periodic intervals.
- * The second is to display a "busy" message if an operation takes more time
- * that users are willing to wait before seeing something happen. The SCR
- * structure has a wall clock timer structure for each of these. Since the
- * busy timer has a much faster timeout than the recovery timer, most of the
- * code ignores the recovery timer unless it's the only thing running.
- *
- * XXX
- * It would be nice to reimplement this with two timers, a la POSIX 1003.1,
- * but not many systems offer them yet.
- */
-static void
-h_alrm(signo)
- int signo;
-{
- struct itimerval value;
- struct timeval ntod, tod;
- SCR *sp;
- EXF *ep;
- int sverrno;
-
- sverrno = errno;
-
- /* XXX: Get the current time of day; if this fails, we're dead. */
- if (gettimeofday(&tod, NULL))
- goto ret;
-
- /*
- * Fire any timers that are past due, or any that are due
- * in a tenth of a second or less.
- */
- for (ntod.tv_sec = 0, sp = __global_list->dq.cqh_first;
- sp != (void *)&__global_list->dq; sp = sp->q.cqe_next) {
-
- /* Check the busy timer if the msg pointer is set. */
- if (sp->busy_msg == NULL)
- goto skip_busy;
- if (sp->busy_tod.tv_sec > tod.tv_sec ||
- sp->busy_tod.tv_sec == tod.tv_sec &&
- sp->busy_tod.tv_usec > tod.tv_usec &&
- sp->busy_tod.tv_usec - tod.tv_usec > 100000L) {
- if (ntod.tv_sec == 0 ||
- ntod.tv_sec > sp->busy_tod.tv_sec ||
- ntod.tv_sec == sp->busy_tod.tv_sec &&
- ntod.tv_usec > sp->busy_tod.tv_usec)
- ntod = sp->busy_tod;
- } else {
- (void)sp->s_busy(sp, sp->busy_msg);
- sp->busy_msg = NULL;
- }
-
- /*
- * Sync the file if the recovery timer has fired. If
- * the sync fails, we don't reschedule future sync's.
- */
-skip_busy: ep = sp->ep;
- if (ep->rcv_tod.tv_sec < tod.tv_sec ||
- ep->rcv_tod.tv_sec == tod.tv_sec &&
- ep->rcv_tod.tv_usec < tod.tv_usec + 100000L) {
- if (rcv_sync(sp, ep, 0))
- continue;
- ep->rcv_tod = tod;
- ep->rcv_tod.tv_sec += RCV_PERIOD;
- }
- if (ntod.tv_sec == 0 ||
- ntod.tv_sec > ep->rcv_tod.tv_sec ||
- ntod.tv_sec == ep->rcv_tod.tv_sec &&
- ntod.tv_usec > ep->rcv_tod.tv_usec)
- ntod = ep->rcv_tod;
- }
-
- if (ntod.tv_sec == 0)
- goto ret;
-
- /* XXX: Set the timer; if this fails, we're dead. */
- value.it_value.tv_sec = ntod.tv_sec - tod.tv_sec;
- value.it_value.tv_usec = ntod.tv_usec - tod.tv_usec;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- (void)setitimer(ITIMER_REAL, &value, NULL);
-
-ret: errno = sverrno;
-}
-
-/*
- * h_hup --
- * Handle SIGHUP.
- */
-static void
-h_hup(signo)
- int signo;
-{
- sig_sync(SIGHUP, RCV_EMAIL);
- /* NOTREACHED */
-}
-
-/*
- * h_int --
- * Handle SIGINT.
- *
- * XXX
- * This isn't right if windows are independent of each other.
- */
-static void
-h_int(signo)
- int signo;
-{
- F_SET(__global_list, G_SIGINT);
-}
-
-/*
- * h_term --
- * Handle SIGTERM.
- */
-static void
-h_term(signo)
- int signo;
-{
- sig_sync(SIGTERM, 0);
- /* NOTREACHED */
-}
-
-/*
- * h_winch --
- * Handle SIGWINCH.
- *
- * XXX
- * This isn't right if windows are independent of each other.
- */
-static void
-h_winch(signo)
- int signo;
-{
- F_SET(__global_list, G_SIGWINCH);
-}
-
-
-/*
- * sig_sync --
- *
- * Sync the files based on a signal.
- */
-static void
-sig_sync(signo, flags)
- int signo;
- u_int flags;
-{
- SCR *sp;
-
- /*
- * Walk the lists of screens, sync'ing the files; only sync
- * each file once.
- */
- for (sp = __global_list->dq.cqh_first;
- sp != (void *)&__global_list->dq; sp = sp->q.cqe_next)
- rcv_sync(sp, sp->ep, RCV_ENDSESSION | RCV_PRESERVE | flags);
- for (sp = __global_list->hq.cqh_first;
- sp != (void *)&__global_list->hq; sp = sp->q.cqe_next)
- rcv_sync(sp, sp->ep, RCV_ENDSESSION | RCV_PRESERVE | flags);
-
- /*
- * Die with the proper exit status. Don't bother using
- * sigaction(2) 'cause we want the default behavior.
- */
- (void)signal(signo, SIG_DFL);
- (void)kill(getpid(), signo);
- /* NOTREACHED */
-
- exit (1);
-}