This is an official patch to nn release 6.4 ------------------------------------------- PATCH #12 Priority: LOW This patch contains mainly updates to the documentation for the new features introduced in previous patches, but a number of minor bugs have been fixed and some new features related to the init files have been introduced. As usual, all changes are described in the updated RELEASE_NOTES file (read that for more details about this patch). Thanks to all who reported bugs and provided fixes. To apply this patch, use nn's :patch command, or run this command from the shell in the root of the nn source tree: patch -p0 < this-article Then run "make all" and "./inst u". ++Kim Storm =================================================================== *** ./LAST/SPLITNN1 Tue Apr 24 17:13:08 1990 --- SPLITNN1 Fri Nov 2 20:54:16 1990 *************** *** 1,6 **** --- 1,12 ---- # split nn.1 in 4 parts cd man + if [ ! -f nn.1 ] ; then + echo "nn.1 missing: cannot split it!" + exit 1 + fi + rm -f nn.1.[ABCD] + sed -n \ -e '/BEGINPART A/,/ENDPART A/w nn.1.A' \ -e '/BEGINPART B/,/ENDPART B/w nn.1.B' \ *** ./LAST/admin.c Fri Oct 5 19:07:02 1990 --- admin.c Thu Nov 1 20:40:38 1990 *************** *** 58,64 **** putchar(NL); if (exec_chdir_to != NULL) printf("\n\rDirectory: %s", exec_chdir_to); ! run_shell((char *)NULL, 0); } else printf("%c\n\n\r", c); } while (c == '!'); --- 58,64 ---- putchar(NL); if (exec_chdir_to != NULL) printf("\n\rDirectory: %s", exec_chdir_to); ! run_shell((char *)NULL, 0, 0); } else printf("%c\n\n\r", c); } while (c == '!'); *** ./LAST/answer.c Tue Sep 18 12:44:50 1990 --- answer.c Tue Nov 6 17:55:29 1990 *************** *** 422,431 **** if (distr == NULL) distr = "default"; var_options(&distr, "always\0ask\0same\0default\0", &opts); ! always = (opts & FLAG(0)); ! ask = (opts & FLAG(1)); ! same = (opts & FLAG(2)); ! dflt = (opts & FLAG(3)); if (*distr == NUL || dflt) distr = dd; --- 422,431 ---- if (distr == NULL) distr = "default"; var_options(&distr, "always\0ask\0same\0default\0", &opts); ! always = (opts & FLAG(1)); ! ask = (opts & FLAG(2)); ! same = (opts & FLAG(3)); ! dflt = (opts & FLAG(4)); if (*distr == NUL || dflt) distr = dd; *************** *** 893,899 **** if (display_group_list(*str == '/')) must_redraw = 2; else ! msg("No group list is avaialbe"); goto again_group; } if (*str == NUL) { --- 893,899 ---- if (display_group_list(*str == '/')) must_redraw = 2; else ! msg("No group list is available"); goto again_group; } if (*str == NUL) { *** ./LAST/aux.sh Fri Oct 5 19:07:02 1990 --- aux.sh Wed Oct 31 13:07:50 1990 *************** *** 208,217 **** ;; r*) ! ${AWK} 'END{printf "Edit original file: (y) "}' < /dev/null read act case "$act" in ! ""|"y*") cp $COPY $WORK ;; esac FIRST_ACTION=edit ;; --- 208,217 ---- ;; r*) ! ${AWK} 'END{printf "Undo all changes? (n) "}' < /dev/null read act case "$act" in ! "[yY]*") cp $COPY $WORK ;; esac FIRST_ACTION=edit ;; *** ./LAST/conf/m-i80386.h Sat Mar 31 23:12:49 1990 --- conf/m-i80386.h Sat Nov 3 00:27:14 1990 *************** *** 16,22 **** --- 16,24 ---- #undef NETWORK_BYTE_ORDER /* THEY ARE NOT */ + /* YOU LOSE -- I DON'T KNOW HOW TO DO THIS ON 80386 BASED SYSTEMS! + */ #define htonl(l) ... /* host long to network long */ #define ntohl(l) ... /* network long to host long */ *** ./LAST/db.c Fri Oct 5 19:07:04 1990 --- db.c Wed Nov 7 12:29:18 1990 *************** *** 979,985 **** fseek(index, get_index_offset(gh, art_num), 0); if (!db_read_offset(index, &data_offset)) ! return (off_t)(-1); fclose(index); --- 979,985 ---- fseek(index, get_index_offset(gh, art_num), 0); if (!db_read_offset(index, &data_offset)) ! data_offset = (off_t)(-1); fclose(index); *** ./LAST/doc/RELEASE_NOTES Fri Oct 5 19:07:07 1990 --- doc/RELEASE_NOTES Tue Nov 6 17:55:27 1990 *************** *** 1225,1231 **** --- 1225,1331 ---- From: olson%anchor.esd@sgi.com (Dave Olson) + fixes Fixed: Patch #11 [nntp.c global.c] + Prog: nn + Title: "line-1" can be bound in show mode but it is not defined. + From: Jaap Vermeulen + Fixed: Patch #12 [keymap.c] + + Prog: nn manual + Title: A ".nf" is missing + From: marcel@duteca.tudelft.nl (Marcel J.E. Mol) + Fixed: Patch #12 [nn.1] + + Prog: nn + Title: The var_options function uses (and returns) FLAG(0) which is illegal. + From: mmitchel@digi.lonestar.org (Mitch Mitchell) + Fixed: Patch #12 [answer.c variable.c] + + Prog: aux + Title: r)eedit should explain better what it does and have default (n). + From: coleman@CS.UCLA.EDU (Michael Coleman) + Fixed: Patch #12 [aux.sh] + + Prog: nn + Title: ":!shell command" doesn't allow spaces anymore? + From: dm@everexn.com (Dan McMullen) + Fixed: Patch #12 [init.c] + + Prog: nnmaster + Title: nntp problems should not be mailed to the sysop. + From: srp@cgl.ucsf.edu (Scott R. Presnell) + Fixed: Patch #12 [global.c master.c nnmaster.8] + + Default, they are still mailed to the sysop, but repeated + messages are ignored (also in the log). Warning mail can be + disabled with -M1 and all error mail can be disabled with -M0. + + Prog: m-i80386.h + Title: contain a single ' which annoys GCC (and ansi C). + From: Steven List + Fixed: Patch #12 [m-i80386.h] + + Prog: nn + Title: if newsgroups file is not found of nntp server, multiple + attempts to connect to the server will be done. + From: erf@progress.COM (Eric Feigenson) + John R MacMillan + Fixed: Patch #12 [nntp.c] + + This was really an NNTP bug, since the server returns a fatal error if + the newsgroups file doesn't exist (it reuses code from LIST ACTIVE + where it is a fatal error if the file is not found). + + Prog: nn + Title: Text search should work if rot13 decrypting is active + From: David Lesher + Fixed: Patch #12 [more.c] + + Prog: nn + Title: /RE will only highlight the first occurrence on a line. + From: david@wraith.cs.uow.edu.au (David E A Wilson) + fix + Fixed: Patch #12 [more.c] + + Prog: nn + Title: nn -g exits when the (j)ump option is used. + From: david@wraith.cs.uow.edu.au (David E A Wilson) + Fixed: Patch #12 [group.c] + Prog: xmakefile + Title: cvt-help and usercheck does not depend on config.h + From: Tom Dawes-Gamble + Fixed: Patch #12 [xmakefile] + + Prog: xmakefile + Title: EXTRA_LIB is missing for cvt-help and usercheck + From: Ray Davis + Fixed: Patch #12 [xmakefile] + + Prog: SPLITNN1 + Title: Some sed versions does not truncate existing files for the w command. + From: Ken Laprade + Fixed: Patch #12 [SPLITNN1] + + Prog: makefile + Title: make clean should remove nn.1 + From: Paul Pomes + Fixed: Patch #12 [xmakefile] + + Prog: nn + Title: In merged groups, confirm-junk-seen requires conf. for every group + From: itkin@mrspoc.Transact.COM (Steven M. List) + Fixed: Patch #12 [group.c newsrc.c] + + Prog: nn + Title: .rnlast was not ignored if new .newsrc is created + From: mason@freedom.msfc.nasa.gov (Jim Mason) + Fixed: Patch #12 [newsrc.c] + + Prog: nn + Title: Typo in "No group list is avaialbe" + From: itkin@guinan.transact.com (Steven List) + Fixed: Patch #12 [answer.c] + + New features since initial 6.4.0 release ---------------------------------------- *************** *** 1635,1637 **** --- 1735,1773 ---- rewritten even if the directory is read only. The backup folder is retained if the keep-backup-folder variable is set. A trace of the compression process is now shown if trace-folder-packing is set. + + Prog: nn + Title: Several new "on condition" constructs and other init file goodies. + From: KFS (following several requests for rather specific features). + Added: Patch #12 [init.c nn.1] + + Instead of a steady flow of requests for new controls in the init + file I decided to take a more generic approach and provide the + following new commands and conditionals in the init file. See + the manual for more details. + on [ test ] + on `shell command` str1 str2 ... + on `` str1 str2 ... + on !shell command + on $VAR [ str1 str2 ... ] + else + echo MESSAGE + error MESSAGE + exit [ n ] + stop + chain alternative-init-file + + Prog: nn + Title: nn can now enter the group that was active the last time nn was quit. + From: KFS on many requests + Added: Patch #12 [nn.c variable.c] + + There is a new variable 'enter-last-read-mode' to control this: + 0: never enter the last group read, + 1: ask to enter group if it has unread articles, else don't enter, + 2: ask to enter group even if no unread, + 3: enter unconditionally if unread articles, else don't enter, + 4: enter uncond even if no unread. + If there are no unread articles, nn will actually locate the next + group in the sequence starting with the remembered group. + *** ./LAST/execute.c Mon Jun 25 15:46:39 1990 --- execute.c Thu Nov 1 20:40:37 1990 *************** *** 11,16 **** --- 11,17 ---- export int shell_restrictions = 0; /* disable shell escapes */ + export char *init_shell = SHELL; export char *user_shell; export char *exec_chdir_to = NULL; *************** *** 90,102 **** if (cmd == NULL) return !first; if (*cmd == NUL) { ! if (first) run_shell((char *)NULL, 1); return 1; } strcpy(command, cmd); ! if (!run_shell(command, first)) return !first; first = 0; prompt_line = -1; } --- 91,103 ---- if (cmd == NULL) return !first; if (*cmd == NUL) { ! if (first) run_shell((char *)NULL, 1, 0); return 1; } strcpy(command, cmd); ! if (run_shell(command, first, 0) < 0) return !first; first = 0; prompt_line = -1; } *************** *** 110,126 **** (char *)NULL }; ! run_shell(command, clear) char *command; int clear; /* -2 => no command output (:!!command) - keep visual, output before command: -1 => none, 0 => CR/NL, 1 => clear */ { char cmdstring[512]; ! if (shell_check()) return 0; if (command != NULL) { ! if (!expand_file_name(cmdstring, command, 1)) return 0; exec_sh_args[1] = "-c"; exec_sh_args[2] = cmdstring; } else { --- 111,128 ---- (char *)NULL }; ! run_shell(command, clear, init_sh) char *command; int clear; /* -2 => no command output (:!!command) - keep visual, output before command: -1 => none, 0 => CR/NL, 1 => clear */ + int init_sh; /* 0 => use user_shell, else use init_shell */ { char cmdstring[512]; ! if (shell_check()) return -1; if (command != NULL) { ! if (!expand_file_name(cmdstring, command, 1)) return -1; exec_sh_args[1] = "-c"; exec_sh_args[2] = cmdstring; } else { *************** *** 136,143 **** putchar(NL); } ! execute(user_shell, exec_sh_args, clear == -2 ? 0 : 1); ! return 1; } #ifndef HAVE_JOBCONTROL --- 138,145 ---- putchar(NL); } ! return execute(init_sh ? init_shell : user_shell, ! exec_sh_args, clear == -2 ? 0 : 1); } #ifndef HAVE_JOBCONTROL *** ./LAST/global.c Fri Oct 5 19:07:09 1990 --- global.c Wed Oct 31 23:24:29 1990 *************** *** 48,53 **** --- 48,54 ---- export int process_id; export int who_am_i; export int dont_write_console = 0; + export int mail_errors_mode = 2; #ifdef HAVE_MULTIGROUP #ifndef NGROUPS *************** *** 671,676 **** --- 672,686 ---- FILE *f; char cmd[FILENAME*2]; + switch (mail_errors_mode) { + case 0: + return; + case 1: + if (!isfatal) return; + default: + break; + } + #ifdef FATAL_ERROR_MAIL_CMD strcpy(cmd, FATAL_ERROR_MAIL_CMD); #else *************** *** 736,750 **** char buf[512]; char *fmt; FILE *f; use_vararg; start_vararg; ! enter_log('R', va_args1toN); end_vararg; start_vararg; ! fmt = va_arg1(char *); ! vsprintf(buf, fmt, va_args2toN); end_vararg; if (who_am_i != I_AM_MASTER) --- 746,767 ---- char buf[512]; char *fmt; FILE *f; + static char *last_err = NULL; use_vararg; start_vararg; ! fmt = va_arg1(char *); ! vsprintf(buf, fmt, va_args2toN); end_vararg; + if (last_err != NULL) { + if (strcmp(last_err, buf) == 0) return; + free(last_err); + } + last_err = copy_str(buf); + start_vararg; ! enter_log('R', va_args1toN); end_vararg; if (who_am_i != I_AM_MASTER) *** ./LAST/group.c Fri Oct 5 19:07:10 1990 --- group.c Fri Nov 2 19:39:20 1990 *************** *** 188,193 **** --- 188,194 ---- extern flag_type parse_access_flags(); article_number o_entry_first; int o_only_unread; + import rc_merged_groups_hack; #define menu_return(cmd) { menu_cmd = (cmd); goto menu_exit; } *************** *** 357,364 **** --- 358,368 ---- if (n) sort_articles(0); n = 0; update_rc(gh); + rc_merged_groups_hack = 1; } while (mg_head != NULL && (gh = gh->merge_with) != NULL); + rc_merged_groups_hack = 0; + killed_articles = o_killed; entry_first_article = o_entry_first; only_unread_articles = o_only_unread; *************** *** 734,739 **** --- 738,747 ---- if (gh == orig_group || gh->unread_count <= 0) { msg("Cannot jump - no unread articles"); goto_return(ME_NO_REDRAW); + } + if (orig_group == NULL) { /* nn -g */ + first = -1; + goto enter_new_level; } jump_to_group = gh; goto_return(ME_QUIT); *** ./LAST/init.c Fri Oct 5 19:07:10 1990 --- init.c Fri Nov 2 23:29:58 1990 *************** *** 122,127 **** --- 122,129 ---- } #define START_SEQUENCE 555 + #define CHAIN_FILE 556 /* chain file */ + #define STOP_FILE 557 /* stop */ static load_init_file(name, seq_hook_ptr, only_seq) char *name; *************** *** 141,146 **** --- 143,149 ---- *cmd = NUL; name = cmdbuf; + chain_file: if (strchr(name, '/') == NULL) name = relative(nn_directory, name); *************** *** 154,160 **** return; } /* we use AC_REDRAW to avoid !-commands clear the screen */ ! if (parse_command(cmdbuf, AC_REDRAW, init) == START_SEQUENCE) { if (seq_hook_ptr) { *seq_hook_ptr = init; return; /* no close !! */ --- 157,174 ---- return; } /* we use AC_REDRAW to avoid !-commands clear the screen */ ! switch (parse_command(cmdbuf, AC_REDRAW, init)) { ! case CHAIN_FILE: ! fclose(init); ! name = argvec[argc]; /* ARGTAIL */ ! if (name == NULL) return; ! goto chain_file; ! ! case STOP_FILE: ! fclose(init); ! return; ! ! case START_SEQUENCE: if (seq_hook_ptr) { *seq_hook_ptr = init; return; /* no close !! */ *************** *** 311,316 **** --- 325,332 ---- if (index < 0) return 0; if (buf) { + if (index >= 1 && buf[0] == '!') return -1; /* :! is special */ + head = buf; tail = buf + index; alt = help_alt = alt_commands; *************** *** 745,751 **** --- 761,832 ---- { register char *cp; char buf[1024]; + static char *last_cmd_res = NULL; + int i; + + if (ARGTAIL == NULL || *ARGTAIL == NUL) goto on_err; + + cp = NULL; + switch (*ARGTAIL) { + case '#': /* on #... end: skipped (+hack for else) */ + goto skip_to_end; + + case '`': /* on `shell command` str1 str2 ... */ + { + FILE *p; + char *cmd = ARGTAIL + 1, *t; + + if ((cp = strrchr(cmd, '`')) == NULL) goto syntax_err; + if ((t = strip_str(cp + 1)) == NULL) goto syntax_err; + *cp = NUL; + ARGTAIL = t; + + if (cmd[0]) { + buf[0] = NUL; + if (p = popen(cmd, "r")) { + if (fgets(buf, 1024, p)) + buf[strlen(buf) - 1] = NUL; + pclose(p); + } + if (last_cmd_res != NULL && strcmp(last_cmd_res, buf)) { + free(last_cmd_res); + last_cmd_res = NULL; + } + if (buf[0] == NUL) goto skip_to_end; + last_cmd_res = copy_str(buf); + } + for (i = 1; argv(i) != NULL; i++) + if (strcmp(argv(i), last_cmd_res) == 0) return; + } + goto skip_to_end; + + case '$': /* on $VAR [ a b c ... ] */ + cp = argv(1); + if ((cp = getenv(cp+1)) == NULL) goto skip_to_end; + if (ARGTAIL == NULL) return; + for (i = 2; argv(i) != NULL; i++) + if (strcmp(argv(i), cp) == 0) return; + goto skip_to_end; + + case '!': /* on !shell-command */ + cp = ARGTAIL + 1; + break; + + case '[': /* on [ test ] */ + cp = ARGTAIL + strlen(ARGTAIL) - 1; + if (*cp != ']') goto syntax_err; + cp = ARGTAIL; + break; + + default: + break; + } + if (cp) { + if (run_shell(cp, -2, 1) == 0) return; + goto skip_to_end; + } + if (argv(1) == NULL) goto on_err; SWITCH ( argv(1) ) { *************** *** 833,841 **** --- 914,925 ---- goto on_err; } + skip_to_end: while (fgets_multi(buf, 1024, f) != NULL) { for (cp = buf; *cp && isascii(*cp) && isspace(*cp); cp++); + if (*cp != 'e') continue; if (strncmp(cp, "end", 3) == 0) return; + if (strncmp(cp, "else", 4) == 0) return; } init_message("end missing (on %s)", argv(1)); return; *************** *** 842,847 **** --- 926,935 ---- on_err: init_message("on `what'?"); + return; + + syntax_err: + init_message("syntax error: on %s", ARGTAIL); } parse_command(cmd, ok_val, initf) *************** *** 856,867 **** if (*ARGTAIL == '!') { if (ok_val == AC_UNCHANGED) { /* in macro */ if (ARGTAIL[1] == '!') /* !!cmd => guarantee no output! */ ! run_shell(ARGTAIL+2, -2); else ! run_shell(ARGTAIL+1, -1); return ok_val; } ! if (run_shell(ARGTAIL+1, ok_val == AC_PROMPT ? 1 : 0)) { any_key(0); return AC_REDRAW; } --- 944,955 ---- if (*ARGTAIL == '!') { if (ok_val == AC_UNCHANGED) { /* in macro */ if (ARGTAIL[1] == '!') /* !!cmd => guarantee no output! */ ! run_shell(ARGTAIL+2, -2, 1); else ! run_shell(ARGTAIL+1, -1, 1); return ok_val; } ! if (run_shell(ARGTAIL+1, ok_val == AC_PROMPT ? 1 : 0, in_init) >= 0) { any_key(0); return AC_REDRAW; } *************** *** 988,995 **** --- 1076,1111 ---- break; } + CASE( "else" ) { + ARGTAIL = "#"; /* skip to end */ + parse_on_to_end(initf); + break; + } + CASE( "end" ) { break; + } + + CASE( "echo" ) { + printf("\r%s\n\r", ARGTAIL); + break; + } + + CASE( "error" ) { + printf("\r%s\n\r", ARGTAIL); + nn_exit(1); + } + + CASE( "exit" ) { + nn_exit(ARGTAIL != NULL ? atoi(ARGTAIL) : 0); + } + + CASE( "chain" ) { + return CHAIN_FILE; + } + + CASE( "stop" ) { + return STOP_FILE; } CASE( "sequence" ) { *** ./LAST/keymap.c Thu Jul 19 18:12:15 1990 --- keymap.c Mon Oct 15 13:33:46 1990 *************** *** 478,484 **** "leave-article", K_LEAVE_ARTICLE, K_ONLY_MORE, "leave-next", K_LEAVE_NEXT, K_ONLY_MORE, "line+1", K_NEXT_LINE, 0, ! "line-1", K_PREV_LINE, 0, "line=@", K_GOTO_LINE, K_ONLY_MORE, "macro", K_MACRO, 0, --- 478,484 ---- "leave-article", K_LEAVE_ARTICLE, K_ONLY_MORE, "leave-next", K_LEAVE_NEXT, K_ONLY_MORE, "line+1", K_NEXT_LINE, 0, ! "line-1", K_PREV_LINE, K_ONLY_MENU, "line=@", K_GOTO_LINE, K_ONLY_MORE, "macro", K_MACRO, 0, *** ./LAST/macro.c Thu Jul 19 18:12:15 1990 --- macro.c Thu Nov 1 21:06:01 1990 *************** *** 6,11 **** --- 6,12 ---- #include "config.h" #include "keymap.h" + #include "menu.h" #include "term.h" export int in_menu_mode = 0; *************** *** 472,478 **** char buffer[128]; strcpy(buffer, m->m_string); if (macro_debug) { msg(":%s", buffer); user_delay(1); } ! parse_command(buffer, 0, (FILE *)NULL); m = m->m_next; } } --- 473,479 ---- char buffer[128]; strcpy(buffer, m->m_string); if (macro_debug) { msg(":%s", buffer); user_delay(1); } ! parse_command(buffer, AC_UNCHANGED, (FILE *)NULL); m = m->m_next; } } *** ./LAST/man/nn.1.A Tue Sep 18 12:45:02 1990 --- man/nn.1.A Wed Nov 7 12:29:49 1990 *************** *** 1111,1122 **** --- 1111,1163 ---- .LP Articles can optionally be saved in MAIL or MMDF compatible format by setting the \fBmail-format\fP and \fBmmdf-format\fP variables. + These variables only specify the format used when creating a new folder, + while appending to an existing folder will be done in the format of the + folder (unless \fBfolder-format-check\fP is false). .LP \fBRelated variables\fP: confirm-append, confirm-create, decode-header-file, decode-skip-prefix, default-save-file, folder-save-file, edit-patch-command, edit-print-command, edit-unshar-command, folder, + folder-format-check, mail-format, mmdf-format, patch-command, printer, quick-save, save-counter, save-counter-offset, save-report, suggest-default-save, unshar-command, unshar-header-file. + .SH FOLDER MAINTENANCE + When more than one article is saved in a folder, \fInn\fP is able to + split the folder, and each article in the folder can be treated like + a separate article. + .LP + This means that you can save, decode, reply, follow-up, etc. just as + with the original article. + .LP + You can also \fIcancel\fP (delete) individual articles in a folder + using the normal \fBC\fP {\fBcancel\fP} command described later. + When you quit from the folder, you will then be given the option to + remove the cancelled articles from the folder. + .LP + The original folder is saved in a file named `BackupFolder~' in the + \&.nn directory (see the \fBbackup-folder-path\fP variable) by + renaming or copying the old folder as appropriate. + When the folder + has been compressed, the backup folder will be removed unless the + variable \fBkeep-backup-folder\fP is set. + .LP + If all articles in a folder are cancelled, the folder will be removed + or truncated to zero length (whatever is allowed by directory and file + permissions). + In this case no backup folder is retained even when + \fBkeep-backup-folder\fP is set! + .LP + If the variable \fBtrace-folder-packing\fP is set, \fInn\fP will show + which articles are kept and which are removed as the folder is + rewritten. + .LP + Folders are rewritten in the format of the original folder, i.e. the + \fBmail-format\fP and \fBmmdf-format\fP variables are ignored. + .LP + \fBRelated variables\fP: + backup-folder-path, + keep-backup-folder, + trace-folder-packing. .\" ENDPART A *** ./LAST/man/nn.1.B Tue Sep 18 12:45:05 1990 --- man/nn.1.B Wed Nov 7 12:29:49 1990 *************** *** 29,34 **** --- 29,38 ---- .br ~/News/emacs, ~/News/nn, ~/src/shar/nn .TP + \fB~\fP\fIuser\fP\fB/\fP\fIfile\fP + The \fB~\fP\fIuser\fP part is replaced by the \fIuser\fP's home + directory as defined in the /etc/passwd file. + .TP \fB|\fP\fIcommand-line\fP Instead of writing to a file, the articles are piped to the given shell (/bin/sh) command-line. Each save or write command will create a *************** *** 154,159 **** --- 158,166 ---- \&\fBF\fP {\fBfollow\fP} Follow-up with an article in the same newsgroup (unless an alternative group is specified in the article header). + The distribution of the follow-up is normally the same as the original + article, but this can be modified via the \fBfollow-distribution\fP + variable. .TP \&\fBM\fP {\fBmail\fP} Mail a letter or *************** *** 185,190 **** --- 192,200 ---- expression (typically a single word) which will cause \fInn\fP to show a (much shorter) list containing only the lines matching the regular expression. + Normally, you will be prompted for the distribution of the article + with the default take from \fBdefault-distribution\fP, but this can be + changed via the \fBpost-distribution\fP variable. .LP Generally, \fInn\fP will construct a file with a suitable header, optionally include a copy of the article in the file with each non-empty line *************** *** 239,244 **** --- 249,255 ---- .LP \fBRelated variables\fP: append-signature-mail, append-signature-post, default-distribution, + follow-distribution, post-distribution, edit-response-check, editor, include-art-id, include-full-header, included-mark, mail-header, mail-record, mail-script, mailer, mailer-pipe-input, news-header, news-record, news-script, *************** *** 710,715 **** --- 721,727 ---- closed. In selection mode, you will be prompted for the identifier of the article to cancel. Normal users can only cancel their own articles. + See also the section on folder maintenance. .TP \&\fBY\fP {\fBoverview\fP} Provide an overview of the groups with unread articles. *************** *** 785,790 **** --- 797,805 ---- If a value is specified, it will be assigned to the local variable. To assign a new value to a boolean variable, the values \fBon\fP and \fBoff\fP must be used. + .TP + \fB:lock\fP \fIvariable\fP + Lock the specified \fIvariable\fP so it cannot be modified. .TP \fB:man\fP Call up the online manual. The manual is presented as a normal folder *** ./LAST/man/nn.1.C Fri Oct 5 19:07:12 1990 --- man/nn.1.C Wed Nov 7 12:29:49 1990 *************** *** 137,142 **** --- 137,156 ---- \fBset\fP \fIvariable key-name\fP .br .LP + A variable can be \fIlocked\fP which makes further modification of the + variable impossible: + .br + \fBlock\fP \fIvariable\fP + .br + This can be used in the \fIsetup\fP init file which is loaded + unconditionally to enforce local conventions or restrictions. For + example, to fix the \fBincluded-mark\fP variable to the string ">", + the following commands can be placed in the setup file: + .nf + \fBset\fP included-mark > + \fBlock\fP included-mark + .fi + .LP The current variable settings can be shown with the .B :set command: *************** *** 148,153 **** --- 162,168 ---- \fB:set all\fP This will give a listing of all variables. Modified variables will be marked with a `*' and \fIlocal\fP variables will be marked with a `>'. + A locked variable is marked with a `!'. .TP \fB:set /\fP\fIregexp\fP This will give a listing of all variables whose name matches the given *************** *** 241,246 **** --- 256,270 ---- contents of these files internally, so the backup variable can be set any time if not set on start-up. .TP + \fBbackup-folder-path\fP \fIfile\fP (string, default "BackupFolder~") + When removing deleted articles from a folder, this variable defines + the name of the file where a (temporary) copy of the original folder + is saved. If the \fIfile\fP name doesn't contain a `/', the file will + be located in the .nn directory. Otherwise the file name is used + directly as the relative or full path name of the backup file. + If possible, the old folder will be renamed to the backup folder name; + otherwise the old folder is copied to the backup folder. + .TP \fBbackup-suffix\fP \fIsuffix\fP (string, default ".bak") The suffix appended to file names to make the corresponding backup file name (see \fBbackup\fP). *************** *** 255,260 **** --- 279,292 ---- subjects, except in connection with auto-kill and auto-select where the individual kill file entries specifies this property. .TP + \fBcheck-group-access\fP (boolean, default false) + When set, \fInn\fP will perform a check on the readability of a + group's readability before showing the menu for that group. Normally, + this is not necessary since all users traditionally have access to all + news groups. Setting (and locking) this variable may be used to limit + access to a news group via the permissions and ownership of the + group's spool directory (this will only work for non-NNTP sites). + .TP \fBcollapse-subject\fP \fIoffset\fP (integer, default 25) When set (non-negative), subject lines which are too long to be presented in full on the menus will be "collapsed" by removing a *************** *** 376,386 **** valid uuencoded data. This allows \fInn\fP to automatically decode (multi-part) postings which are both uuencoded and packed with shar. .TP ! \fBdefault-distribution\fP \fIdistr\fP (string, default not set) The distribution to use as the default suggestion when posting ! articles using the \fBpost\fP command. If it is not set, the ! first component of the group name is used as the suggested ! distribution, e.g. `comp' when posting to comp.whatever. .TP \fBdefault-kill-select\fP \fI[1]days\fP (number, default 30) Specifies the default action for the \fBK\fP {\fBkill-select\fP} --- 408,418 ---- valid uuencoded data. This allows \fInn\fP to automatically decode (multi-part) postings which are both uuencoded and packed with shar. .TP ! \fBdefault-distribution\fP \fIdistr\fP (string, default "world") The distribution to use as the default suggestion when posting ! articles using the \fBfollow\fP and \fBpost\fP commands if the ! corresponding \fBfollow-distribution\fP or \fBpost-distribution\fP ! variable contains the \fBdefault\fP option. .TP \fBdefault-kill-select\fP \fI[1]days\fP (number, default 30) Specifies the default action for the \fBK\fP {\fBkill-select\fP} *************** *** 439,444 **** --- 471,490 ---- When saving an article to a file, header lines embedded in the body of the article are escaped using this string to make it possible for \fInn\fP to split the folder correctly afterwards. + Header lines are not escaped if this variable is not set. + .TP + \fBenter-last-read-mode\fP \fImode\fP (integer, default 1) + Normally, \fInn\fP will remember which group is active when you quit, + and offer to jump directly to this group when you start \fInn\fP the + next time. This variable is used to control this behaviour. The + following \fImode\fP values are recognized: + .nf + 0: Ignore the remembered group (r.g.). + 1: Enter r.g. if the group is unread (with user confirmation) + 2: Enter r.g. or first unread group after it in the sequence (w/conf). + 3: Enter r.g. if the group is unread (no confirmation) + 4: Enter r.g. or first unread group after it in the sequence (no conf). + .fi .TP \fBentry-report-limit\fP \fIarticles\fP (integer, default 300) Normally, \fInn\fP will just move the cursor to the upper left corner *************** *** 486,494 **** --- 532,587 ---- .I init file. .TP + \fBfolder-format-check\fP (boolean, default true) + When saving an article with a full or partial header in an existing + folder, \fInn\fP will check the format of the folder to be able to + append the article in the proper format. If this variable is not set, + folders are assumed to be in the format specified via the + \fBmmdf-format\fP and \fBmail-format\fP variables, and articles are + saved in that format without checking. Otherwise, the \fB*-format\fP + variables are only used to determine the format for \fInew\fP folders. + .TP \fBfolder-save-file\fP \fIfile\fP (string, default not set) The default save file used when saving articles \fIfrom\fP a folder. .TP + \fBfollow-distribution\fP \fIwords\fP (string, default see below) + This variable controls how the Distribution: header is constructed for + a follow-up to an original article. Its value is a list of + \fIwords\fP selected from the following list: + .sp 0.5v + [ [ \fBalways\fP ] \fBsame\fP ] [ \fBask\fP ] + [ \fBdefault\fP | \fIdistribution\fP ] + .sp 0.5v + This is interpreted in two steps: + .br + - First the default distribution is determined. If \fBsame\fP is + specified and the original article has a Distribution: header, that + header is used. Else if \fBdefault\fP is specified (or + \fIdistribution\fP is omitted), the value of + \fBdefault-distribution\fP is used. And finally, if only a + \fIdistribution\fP (any word) is specified that is used as the default. + .br + - Then if \fBask\fP is specified, the user will be asked to confirm + the default distribution or provide another distribution. However, if + \fBalways\fP (and \fBsame\fP) is specified, and the default was taken + from the original article's distribution, the original distribution is + used \fIwithout\fP confirmation. + .br + The default value of \fBfollow-distribution\fP is \fBalways\fP + \fBsame\fP \fBdefault\fP, i.e. use either the original distribution or + the \fBdefault-distribution\fP without confirmation in either case. + .TP + \fBfrom-line-parsing\fP \fIstrictness\fP (integer, default 2) + Specifies how strict \fInn\fP must parse a "From " line in a folder to + recognize it as a mail format message separator line. The following + strictness values determine whether a line starting with "From " will + be recognized as a separator line: + .nf + 0: Always. + 1: Line must have at least 8 fields. + 2: Line must contain a valid date and time (ctime style). + .fi + .TP \fBfsort\fP (boolean, default true) When set, folders are sorted alphabetically according to the subject (and age). *************** *** 550,555 **** --- 643,666 ---- program. Otherwise, the file containing the article will be given as the first (and only) argument to the \fBinews\fP command. .TP + \fBinitial-newsrc-file\fP \fIfile\fP (string, default '.defaultnewsrc') + Defines the name of a file which is used as the initial .newsrc file + for new users. The name may be a full path name, or as the default a + file name which will be looked for in a number of places: + in the standard news lib directory (where it can be shared with other + news readers), + in nn's lib directory, + and in the database directory. + Groups which are not present in the initial .newsrc file will be + automatically unsubscribed provided \fBnew-group-action\fP is set to a + value allowing unsubscribed groups to be omitted from .newsrc. + .TP + \fBkeep-backup-folder\fP (boolean, default false) + When set, the backup folder (see \fBbackup-folder-path\fP) created + when removing deleted articles from a folder is not removed. + Notice that a backup folder is not created if all articles are removed + from a folder! + .TP \fBkeep-unsubscribed\fP (boolean, default true) When set, unsubscribed groups are kept in .newsrc. If not set, \fInn\fP will automatically remove all unsubscribed from .newsrc if *************** *** 563,568 **** --- 674,681 ---- \fBkill-debug\fP (boolean, default false) When set, \fInn\fP will display a trace of the auto-kill/select process on entry to a group. + It is automatically turned off if `q' is entered as the answer to a + "hit any key" prompt during the debug output. .TP \fBkill-key\fP \fIkey\fP (key, default tty kill key) The key which deletes the current line *************** *** 606,611 **** --- 719,727 ---- \fBmail-format\fP (boolean, default false) When set, \fInn\fP will save articles in a format that is compatible with normal mail folders. + Unless \fBfolder-format-check\fP is false, it is only used to specify + the format used when new folders are created. + This variable is ignored if \fBmmdf-format\fP is set. .TP \fBmail-header\fP \fIheaders\fP (string, default not set) The \fIheaders\fP string specifies one or more extra header lines *************** *** 685,690 **** --- 801,808 ---- .TP \fBmmdf-format\fP (boolean, default false) When set, \fInn\fP will save articles in MMDF format. + Unless \fBfolder-format-check\fP is false, it is only used to specify + the format used when new folders are created. .TP \fBmonitor\fP (boolean, default false) When set, \fInn\fP will show *************** *** 808,813 **** --- 926,952 ---- \fBpatch-command\fP \fIshell-command\fP (string, default "patch -p0") This is the command which is invoked by the \fB:patch\fP command. .TP + \fBpost-distribution\fP \fIwords\fP (string, default see below) + This variable controls how the Distribution: header is constructed + when posting an original article. Its value is a list of + \fIwords\fP selected from the following list: + .sp 0.5v + [ \fBask\fP ] [ \fBdefault\fP | \fIdistribution\fP ] + .sp 0.5v + This is interpreted in two steps: + .br + - First the default distribution is determined. If \fBdefault\fP is + specified (or \fIdistribution\fP is omitted), the value of + \fBdefault-distribution\fP is used. Otherwise, the specified + \fIdistribution\fP (any word) is used as the default. + .br + - Then if \fBask\fP is specified, the user will be asked to confirm + the default distribution or provide another distribution. + .br + The default value of \fBpost-distribution\fP is \fBask\fP + \fBdefault\fP, i.e. use the \fBdefault-distribution\fP with + confirmation from the user. + .TP \fBpreview-continuation\fP \fIcond\fP (integer, default 12) This variable determines on what terms the following article should be automatically shown when previewing an article, and the *************** *** 1147,1152 **** --- 1286,1295 ---- This is useful on systems without a .I sysline (1) utility. + .TP + \fBtrace-folder-packing\fP (boolean, default true) + When set, a trace of the retained and deleted messages is printed when + a folder is rewritten. .TP \fBtrusted-escape-codes\fP \fIcodes\fP (string, default none) When set to a list of one or more characters, \fInn\fP will trust and *** ./LAST/man/nn.1.D Thu Jul 19 18:12:17 1990 --- man/nn.1.D Wed Nov 7 12:29:49 1990 *************** *** 164,169 **** --- 164,170 ---- .TP \-\fBI\fP Do not read the init file. This must be the first option!! + The global \fIsetup\fP file is still read. .TP \-\fBI\fP\fIfile-list\fP Specifies an alternate list of init files to be loaded instead of the *************** *** 174,179 **** --- 175,182 ---- \fInot\fP be separated from the \fB\-I\fP option by blanks, and it must be the first option. Example: The default behaviour corresponds to using -I,init (first the global file, then the file ~/.nn/init). + The global \fIsetup\fP file is still read as the first init file + independently of the -I option used. .TP \-\fBk\fP {\fBtoggle kill\fP} Do not [do] perform automatic kill and selection of articles. *************** *** 408,413 **** --- 411,417 ---- ?no return # and old prompt is restored read-skip # changes the prompt \fBprompt\fP "" # so forget old prompt + .fi .TP \fBecho\fP \fIstring\fP Display the \fIstring\fP in the prompt line for a short period. Example: *************** *** 652,658 **** .ta \w'continue-no-mark'u+5m +\w'Selection_mode'u+3m .\"ta 4 26 42 .br ! \fIFunction Selection mode Reading mode .br \fBadvance-article\fP \fBnix\fP a .br --- 656,662 ---- .ta \w'continue-no-mark'u+5m +\w'Selection_mode'u+3m .\"ta 4 26 42 .br ! \fIFunction Selection mode Reading mode\fP .br \fBadvance-article\fP \fBnix\fP a .br *************** *** 797,807 **** .SH THE INIT FILES The .I init ! files are used to customize \fInn\fP's behaviour to your personal taste. ! \fINn\fP uses two init files \- a system-wide init file located in the ! library directory, and a private init file located in the user's ! \&\fI.nn\fP directory. The private init file is read after the global ! init file to allow the user to change the default setup. .LP The init file is parsed one line at a time. If a line ends with a backslash `\e', the backslash is ignored, and the following line is --- 801,826 ---- .SH THE INIT FILES The .I init ! files are used to customize \fInn\fP's behaviour to local conventions ! and restrictions and to satisfy each user's personal taste. ! .br ! Normally, \fInn\fP reads upto three init files on start-up if they ! exist (all init files are optional): ! .TP ! $LIB/\fBsetup\fP ! A system-wide file located in the library directory. This file is ! \fIalways\fP loaded before any other init file (even when the ! \-\fBI\fP option is specified). It cannot contain a group ! presentation sequence. ! .TP ! $LIB/\fBinit\fP ! Another system-wide (global) init file located in the library ! directory. This file may be ignored via the \-\fBI\fP option. ! .TP ! ~/.nn/\fBinit\fP ! The private init file located in the user's \&\fI.nn\fP directory. ! It is read after the global init file to allow the user to change the ! default setup. .LP The init file is parsed one line at a time. If a line ends with a backslash `\e', the backslash is ignored, and the following line is *************** *** 831,836 **** --- 850,858 ---- and .B :unset commands described earlier (except that the : prefix is omitted.) + .sp 0.5v + Variables can also be locked via the \fBlock\fP command; this is + typically done in the \fIsetup\fP file to enforce local policies. .TP .B Key mappings You can use all the versions of the *************** *** 868,873 **** --- 890,927 ---- load init.@ .fi .TP + .B Switch to loading a different init file + You can skip the rest of the current init file and start loading a + different init file with the following command: + .sp 0.5v + \fBchain\fP \fIfile\fP + .sp 0.5v + If this occur in the private or global init file, the chained init + file may contain a sequence part which will replace the private or + global presentation sequence respectively. + .TP + .B Stop loading current init file + You can skip the rest of the current init file with the following + command: + .sp 0.5v + \fBstop\fP + .TP + .B Give error messages and/or terminate + If an error is detected in the init file, the following commands can be + used to print an error message and/or terminate execution: + .sp 0.5v + \fBerror\fP \fIfatal error message\fP... + .br + Print the message and terminate execution. + .sp 0.5v + \fBecho\fP \fIwarning message\fP... + .br + Print the message and continue. + .sp 0.5v + \fBexit\fP [ \fIstatus\fP ] + .br + Terminate \fInn\fP with the specified exit status or 0 if omitted. + .TP .B Change working directory of nn You can use the .B cd *************** *** 924,939 **** several times during the \fInn\fP session. .LP A command group begins with the word \fBon\fP and ! ends with the word \fBend\fP. The \fBon\fP symbol must followed by ! one of the following identifiers denoting when the group is executed: .sp 0.5v ! .nf ! \fBon\fP ... ! commands ! \fBend\fP .fi - .sp 0.5v - The following command groups may be defined: .TP \fBon slow\fP .br --- 978,1061 ---- several times during the \fInn\fP session. .LP A command group begins with the word \fBon\fP and ! ends with the word \fBend\fP. The following command groups are ! conditionally executed during the parsing of the init file if the ! specified \fIcondition\fP is true. They may also have an optional ! \fBelse\fP part which is executed if the \fIcondition\fP is false: .sp 0.5v ! .nf ! \fBon\fP \fIcondition\fP ! commands ! [ \fBelse\fP ! commands ] ! \fBend\fP ! .fi ! .LP ! The following conditional command groups may be used in the init file ! to be executed at start-up: ! .TP ! \fBon [\fP \fItest\fP \fB]\fP ! The commands (init file syntax) in the group are executed only if the ! specified \fItest\fP is true. ! A shell is spawned to execute the command "[ \fItest\fP ]", so all the ! options of the \fBtest\fP(1) command is available. For example, to ! unset the flow-control variable if the tty is a pseudo-tty, the ! following conditional can be used: ! .nf ! on [ -n "`tty | grep ttyp`" ] ! unset flow-control ! end ! .fi ! .TP ! \fBon !\fP\fIshell command\fP ! The command group is executed if the given \fIshell command\fP exits ! with 0 status (success). ! Care should be taken that the command does not produce any ! output, e.g. by redirecting its output to /dev/null. For example, to ! prevent people from reading news if load is above a specific level, ! the following conditional might be placed in the global setup file. ! .nf ! on !load-above 5 ! error load is too high, try again later. ! end ! .fi ! .TP ! \fBon `\fP\fIshell command\fP\|\fB`\fP \fIstring\fP... ! The command group is executed if the \fIfirst output line\fP from ! executing the specified \fIshell command\fP is listed among the ! specified \fIstring\fP values. The \fIshell command\fP can be omitted ! on subsequent occurrences of this conditional, in which case ! the output from the last \fBshell command\fP is used. ! For example, the following conditional ! can be used to switch to an init file which has a limited sequence for ! news reading during working hours, evenings, and nights: ! .nf ! on `date +%H` 9 10 11 12 13 14 15 16 ! chain init.work ! end ! on `` 17 18 19 20 21 ! chain init.evening ! else ! chain init.night ! end ! .fi ! .TP ! \fBon ``\fP \fIstring\fP... ! This is equivalent to the previous form except that instead of ! executing a shell command, the output from the previous ! .TP ! \fBon $\fP\fIvariable\fP [ \fIvalue\fP ] ! If no \fIvalue\fP strings are specified, the command group is executed ! if the given \fIvariable\fP is defined in the environment. Otherwise, ! the command group is executed only if the value of the \fIvariable\fP ! occur in the \fIvalue\fP list. For example, if you want \fInn\fP to ! look for mail in whatever $MAIL is set to - if it is set - you can use ! the following code: ! .nf ! on $MAIL ! set mail $(MAIL) ! end .fi .TP \fBon slow\fP .br *************** *** 974,979 **** --- 1096,1105 ---- .br The commands are executed if the current program (\fInn\fP, \fInncheck\fP, etc) in the \fIprogram-name\fP list. + .LP + The following \fBon\fP command groups are really macros which may be + executed during \fInn\fP's normal processing, and as such they cannot + have an \fBelse\fP part. .TP \fBon entry\fP [ \fIgroup list\fP ] .br *************** *** 1347,1353 **** --- 1473,1483 ---- .br ~/.nn/LAST The time stamp of the last news group we have seen. .br + ~/.nn/NEXTG Active group last time \fInn\fP was quit. + .br ~/.nn/.param Parameter file for the aux script + .br + $lib/setup System-wide setup - always read first. .br $lib/init System-wide setup and presentation sequence. .br *** ./LAST/man/nnmaster.8 Mon Jun 25 15:46:47 1990 --- man/nnmaster.8 Wed Oct 31 22:22:12 1990 *************** *** 180,185 **** --- 180,192 ---- \fB4\fP: Recollect all articles on every scan. .br .TP + \-\fBM\fP \fImode\fP + Normally, \fInnmaster\fP will send a message via mail to the news + administrator (OWNER) when an error or potential problems + (primarily nntp related) occur. This can be restricted to only fatal + errors (\fInnmaster\fP terminated) if \fImode\fP is 1, and disabled + completely if \fImode\fP is 0. + .TP \-\fBQ\fP Normally, \fInnmaster\fP will print a message on the system console or in the syslog if a fatal error happens. This option will prevent *** ./LAST/master.c Tue Sep 18 12:45:07 1990 --- master.c Wed Oct 31 23:24:29 1990 *************** *** 60,65 **** --- 60,66 ---- dont_write_console, expire_method, expire_level, + mail_errors_mode, recollect_method, reread_groups_file, ignore_bad_articles, *************** *** 127,132 **** --- 128,134 ---- 'k', Bool_Option( kill_running ), 'l', String_Option_Optional( lock_message, "" ), 'L', String_Option( log_entry_filter ), + 'M', Int_Option( mail_errors_mode ), 'O', Int_Option( max_age_days ), 'Q', Bool_Option( dont_write_console ), 'r', Int_Option_Optional( repeat_delay, 10 ), *** ./LAST/more.c Fri Oct 5 19:07:13 1990 --- more.c Fri Nov 2 17:38:05 1990 *************** *** 768,774 **** col++; break; } ! } *lp++ = c; col++; --- 768,776 ---- col++; break; } ! } else ! if (rot13_active && linenum > 0) ! c = ROT13_DECODE(c); *lp++ = c; col++; *************** *** 856,861 **** --- 858,869 ---- if (lp == match_end) { highlight(0); match_start = NULL; + if (regexec_cf(regular_expr, lp)) { + match_start = regular_expr->startp[0]; + match_end = regular_expr->endp[0]; + lp--; + continue; + } if (match_redraw) goto no_print; } } *************** *** 871,878 **** skip_spaces = 1; has_space = 0; } - if (rot13_active && linenum > 0) - c = ROT13_DECODE(c); } putchar(c); --- 879,884 ---- *** ./LAST/newsrc.c Fri Oct 5 19:07:16 1990 --- newsrc.c Mon Nov 5 15:59:30 1990 *************** *** 236,241 **** --- 236,244 ---- if (no_update) return; if (new_group_action == RCX_RNLAST) { + if (rnlast_line[0] == NULL) + for (i = 0; i < MAX_RNLAST_LINE; i++) + rnlast_line[i] = copy_str(""); lf = open_file(rnlast_path, OPEN_CREATE|MUST_EXIST); fputs(rnlast_line[RN_LAST_GROUP_READ], lf); /* as good as any */ fprintf(lf, "%ld\n", (long)cur_time()); /* RN_LAST_TIME_RUN */ *************** *** 340,345 **** --- 343,350 ---- rc = open_file(newsrc_file, OPEN_READ); if (rc == NULL) { extern FILE *open_file_search_path(); + + last_new_group = -1; /* ignore LAST & .rnlast if no .newsrc */ rc = open_file_search_path(initial_newsrc_path, OPEN_READ); if (rc == NULL) goto new_user; /* ignore groups not in the initial newsrc file */ *************** *** 995,1006 **** * sort_articles(0) MUST HAVE BEEN CALLED BEFORE USE. */ update_rc(gh) register group_header *gh; { register article_header *ah, **ahp; register article_number art; ! register int junk_seen = 0; if (gh->group_flag & (G_FOLDER | G_FAKED)) return; --- 1000,1015 ---- * sort_articles(0) MUST HAVE BEEN CALLED BEFORE USE. */ + export int rc_merged_groups_hack = 0; + update_rc(gh) register group_header *gh; { register article_header *ah, **ahp; register article_number art; ! static int junk_seen = 0; ! ! if (!rc_merged_groups_hack) junk_seen = 0; if (gh->group_flag & (G_FOLDER | G_FAKED)) return; *** ./LAST/nn.c Tue Sep 18 12:45:10 1990 --- nn.c Mon Nov 5 18:27:06 1990 *************** *** 151,157 **** --- 151,211 ---- } export group_header *jump_to_group = NULL; + export int enter_last_read_mode = 1; + static group_header *last_group_maint(last, upd) + group_header *last; + int upd; + { + group_header *gh; + FILE *f; + char *lg_file; + char buf[256], *cp; + + lg_file = relative(nn_directory, "NEXTG"); + if (upd) { + if (last == NULL) + unlink(lg_file); + else { + f = open_file(lg_file, OPEN_CREATE | MUST_EXIST); + fprintf(f, "%s\n", last->group_name); + fclose(f); + } + return NULL; + } + + if (enter_last_read_mode == 0) goto none; + + f = open_file(lg_file, OPEN_READ); + if (f == NULL) goto none; + + if (fgets(buf, 256, f)) { + if (cp = strchr(buf, NL)) *cp = NUL; + gh = lookup(buf); + } + fclose(f); + + if (gh == NULL || gh == last || !(gh->group_flag & G_SEQUENCE)) + goto none; + + switch (enter_last_read_mode) { + case 1: /* confirm if unread, skip if read */ + if (gh->unread_count == 0) goto none; + case 2: /* confirm any case */ + prompt_line = Lines-1; + prompt("Enter %s (%ld unread)? ", gh->group_name, gh->unread_count); + if (!yes(0)) goto none; + break; + case 3: /* enter uncond if unread */ + if (gh->unread_count == 0) goto none; + case 4: /* enter uncond */ + break; + } + return gh; + none: + return last; + } + static read_news(access_mode, mask) flag_type access_mode; char *mask; *************** *** 160,165 **** --- 214,220 ---- flag_type group_mode; int menu_cmd; int must_clear = 0, did_jump = 0; + group_header *last_group_read = NULL; extern int menu(); prev = group_sequence; *************** *** 166,173 **** gh = group_sequence; after_loop = NULL; ! if (access_mode == 0 && !also_read_articles) m_invoke(-2); for (;;) { group_mode = access_mode; --- 221,230 ---- gh = group_sequence; after_loop = NULL; ! if (access_mode == 0 && !also_read_articles) { ! gh = last_group_maint(gh, 0); m_invoke(-2); + } for (;;) { group_mode = access_mode; *************** *** 201,206 **** --- 258,264 ---- continue; } } + last_group_read = NULL; break; } *************** *** 235,240 **** --- 293,299 ---- } if (menu_cmd != ME_NO_ARTICLES) { + last_group_read = gh; after_loop = NULL; must_clear++; } *************** *** 242,248 **** switch (menu_cmd) { case ME_QUIT: /* or jump */ ! if (!jump_to_group) return must_clear; prev = jump_to_group; jump_to_group = NULL; --- 301,307 ---- switch (menu_cmd) { case ME_QUIT: /* or jump */ ! if (!jump_to_group) goto out; prev = jump_to_group; jump_to_group = NULL; *************** *** 272,277 **** --- 331,341 ---- continue; } } + + out: + if (access_mode == 0 && !also_read_articles) + last_group_maint(last_group_read, 1); + return must_clear; } *** ./LAST/nntp.c Fri Oct 5 19:07:16 1990 --- nntp.c Sat Nov 3 00:43:29 1990 *************** *** 460,465 **** --- 460,469 ---- * Contains some code to handle server timeouts intelligently. */ + /* LIST XXX return fatal ERR_FAULT code if requested list does not exist */ + /* This is only fatal for LIST ACTIVE -- else change to ERR_NOGROUPS */ + static int fix_list_response = 0; + /*VARARGS*/ static ask_server(va_alist) va_dcl *************** *** 467,474 **** --- 471,482 ---- char buf[NNTP_STRLEN]; char *fmt; int response; + int fix_err; use_vararg; + fix_err = fix_list_response; + fix_list_response = 0; + start_vararg; fmt = va_arg1(char *); vsprintf(buf, fmt, va_args2toN); *************** *** 489,494 **** --- 497,504 ---- * 500-599 Fatal NNTP errors. Handled below. */ if (response == ERR_GOODBYE || response > ERR_COMMAND) { + if (fix_err && response == ERR_FAULT) return ERR_NOGROUP; + nntp_failed = 1; nntp_close_server(); *************** *** 818,824 **** --- 828,838 ---- again: if (!is_connected && connect_server() < 0) goto err; + fix_list_response = 1; switch (n = ask_server("LIST NEWSGROUPS")) { + case ERR_NOGROUP: /* really ERR_FAULT */ + goto err; + case OK_GROUPS: if (copy_text(new) == 0) { if (fflush(new) != EOF) break; *** ./LAST/patchlevel.h Fri Oct 5 19:07:17 1990 --- patchlevel.h Tue Nov 6 17:55:28 1990 *************** *** 22,28 **** * 1990-07-19: Patch #9 (6.4.9) - MEDIUM * 1990-09-18: Patch #10 (6.4.10) - HIGH * 1990-10-05: Patch #11 (6.4.11) - HIGH */ ! #define PATCHLEVEL 11 --- 22,29 ---- * 1990-07-19: Patch #9 (6.4.9) - MEDIUM * 1990-09-18: Patch #10 (6.4.10) - HIGH * 1990-10-05: Patch #11 (6.4.11) - HIGH + * 1990-11-07: Patch #12 (6.4.12) - LOW */ ! #define PATCHLEVEL 12 *** ./LAST/variable.c Fri Oct 5 19:07:21 1990 --- variable.c Mon Nov 5 16:17:39 1990 *************** *** 8,13 **** --- 8,62 ---- #include "keymap.h" #include "regexp.h" + /* + * Variable types and variants + * + * Boolean: type 'int'. + * + * BOOL 0 Ordinary boolean variable. + * BOOL 1 As 0 + redraw screen on return. + * BOOL 2 Special: reorder menu according to new value. + * BOOL 4 Inverse boolean varible ("set" clears internal var). + * + * Numeric: type 'int'. + * + * INT 0 Ordinary numeric variable ("unset" set var to 0). + * INT 1 As 0 + redraw screen on return. + * INT 2 As 0, but "unset" set var to -1. + * INT 3 As 2 + redraw screen on return. + * + * Strings: type 'char *' + * + * STR 0 Ordinary string ("unset" set var to NULL). + * STR 2 (home relative) file name or full path. + * Automatically expanded. ("unset" set var to NULL). + * STR 3 Ordinary string, but cannot be "unset". + * STR 4 (Expanded) file name - cannot be unset. + * + * CODES n String initialized by list of key names. + * A maximum of 16 CODES variables (n = 0 - 15) exist. + * + * Strings: type 'char []' + * + * STR 1 Ordinary string saved in static array. + * "unset" set array to empty string. + * Warning: no bounds checking! + * Notice: Variable address is "(char **)var" (no &). + * + * Keys: type 'key_type' + * + * KEY 0 Ordinary key. + * + * Pseudo variables: + * + * SPEC n Treated by V_SPECIAL 'case n'. + * + * Modifiers: + * + * INIT Can only be set in init file. + * SAFE Cannot be changed if "shell-restrictions" is set. + */ + import in_init; import char /* string variables */ *************** *** 81,86 **** --- 130,136 ---- edit_print_command, edit_unshar_command, empty_answer_check, + enter_last_read_mode, flow_control, flush_typeahead, fmt_rptsubj, *************** *** 275,280 **** --- 325,331 ---- "edit-unshar-command", BOOL 0, (char **)&edit_unshar_command, "editor", STR 0, (char **)&editor_program, "embedded-header-escape", STR 0, (char **)&saved_header_escape, + "enter-last-read-mode", INT 0, (char **)&enter_last_read_mode, "entry-report-limit", INT 0, (char **)&entry_message_limit, "erase-key", KEY 0, (char **)&erase_key, "expert", BOOL 4, (char **)&novice, *************** *** 1143,1149 **** while ((c = *options) && isascii(c) && isspace(c)) options++; *wp = NUL; ! for (op = optab, n = 0; *op != NULL; op++, n++) { if (strcmp(word, *op)) continue; *res |= FLAG(n); *str = options; --- 1194,1200 ---- while ((c = *options) && isascii(c) && isspace(c)) options++; *wp = NUL; ! for (op = optab, n = 1; *op != NULL; op++, n++) { if (strcmp(word, *op)) continue; *res |= FLAG(n); *str = options; *** ./LAST/xmakefile Fri Oct 5 19:07:22 1990 --- xmakefile Fri Nov 2 20:54:15 1990 *************** *** 150,160 **** * Installation * ! cvt-help: cvt-help.c ! $(CC) -o cvt-help cvt-help.c ! usercheck: usercheck.c ! $(CC) -o usercheck usercheck.c inst: config.h xmakefile inst.sh cvt-help usercheck mkprefix man/nn.1 @echo building install script: ./inst --- 150,160 ---- * Installation * ! cvt-help: PARALLEL config.h cvt-help.c ! $(CC) -o cvt-help cvt-help.c EXTRA_LIB ! usercheck: PARALLEL config.h usercheck.c ! $(CC) -o usercheck usercheck.c EXTRA_LIB inst: config.h xmakefile inst.sh cvt-help usercheck mkprefix man/nn.1 @echo building install script: ./inst *************** *** 179,184 **** --- 179,185 ---- clean: rm -f $(BIN_PROG) $(LIB_PROG) $(MASTER_PROG) cvt-help usercheck rm -f prefix mkprefix inst + rm -f man/nn.1 man/nn.1~ * * dependencies