diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 1996-07-24 16:16:11 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 1996-07-24 16:16:11 +0000 |
commit | 9fe0ebe622331e4ca8b324440857ac3415cf231e (patch) | |
tree | da7d517118e7d40dfef8b4943e368ecbd43475cb /usr.bin/vi/common | |
parent | 4e78eb09c86098d70b62e357fffcf4c3d379074f (diff) |
bring vi/ex up to 1.71
Diffstat (limited to 'usr.bin/vi/common')
-rw-r--r-- | usr.bin/vi/common/api.c | 2 | ||||
-rw-r--r-- | usr.bin/vi/common/common.h | 4 | ||||
-rw-r--r-- | usr.bin/vi/common/exf.c | 84 | ||||
-rw-r--r-- | usr.bin/vi/common/gs.h | 16 | ||||
-rw-r--r-- | usr.bin/vi/common/key.c | 8 | ||||
-rw-r--r-- | usr.bin/vi/common/key.h | 8 | ||||
-rw-r--r-- | usr.bin/vi/common/mem.h | 2 | ||||
-rw-r--r-- | usr.bin/vi/common/msg.c | 14 | ||||
-rw-r--r-- | usr.bin/vi/common/options.c | 5 | ||||
-rw-r--r-- | usr.bin/vi/common/options_f.c | 29 | ||||
-rw-r--r-- | usr.bin/vi/common/recover.c | 16 | ||||
-rw-r--r-- | usr.bin/vi/common/screen.h | 39 | ||||
-rw-r--r-- | usr.bin/vi/common/search.c | 90 | ||||
-rw-r--r-- | usr.bin/vi/common/signal.c | 569 |
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); -} |