Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!apple!bbn!bbn.com!rsalz From: rsalz@uunet.uu.net (Rich Salz) Newsgroups: comp.sources.unix Subject: v19i071: NN, a Usenet news reader, Part10/15 Message-ID: <1849@papaya.bbn.com> Date: 26 Jun 89 19:49:17 GMT Lines: 1751 Approved: rsalz@uunet.UU.NET Submitted-by: storm@texas.dk (Kim F. Storm) Posting-number: Volume 19, Issue 71 Archive-name: nn/part10 #!/bin/sh # this is part 10 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file nn.1 continued # CurArch=10 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file nn.1" sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' >> nn.1 Xa total of 32 different macros. X.LP XTo define macro number \fIM\fP, the following construction is used X(the line breaks are mandatory): X.nf X \fBdefine\fP \fIM\fP X \fIbody\fP X \fBend\fP X.fi X.LP XThe \fIbody\fP consists of a sequence of \fItokens\fP separated by Xwhite space (blanks or newlines). However, certain \fItokens\fP Xcontinue to the end of the current line. X.LP XThe following \fItokens\fP may occur in the macro \fIbody\fP: X.TP X.I Comments XEmpty lines and text following a # character (preceded by white space) Xis ignored. X.TP X.I Command Names XAny command name listed in the key mapping section can be included in Xa macro causing that command to be invoked when the macro is executed. X.TP X.I Extended Commands XAll the extended commands which can be executed through the X.B command Xcommand (normally bound to the : key) can also be executed in a macro. XAn extended command starts with a colon (:) and continues to the Xend of the current line. Example: X.br X :show groups total X.TP X.I Key Strokes XA key stroke (which is normally mapped into a command depending on the Xcurrent mode) is specified as a key name enclosed in single quotes. XExamples (A-key, left arrow key, RETURN key): X.br X 'A' 'left' '^M' X.TP X.I Strings XInput to commands prompting for a string, e.g. a file name, can be Xspecified in a macro as a double quoted string. Example (save without Xprompting for a file name): X.br X \fBsave-short\fP "+$G" X.TP X.I Conditionals XConditionals may occur anywhere in a macro; a conditional is evaluated Xwhen the macro is executed, and if the condition is false \fIthe rest Xof the current line is ignored\fP. The following conditionals are available: X.nf X \fB?menu\fP True in menu mode X \fB?show\fP True in reading mode X \fB?folder\fP True when looking at a folder X \fB?group\fP True when looking at a news group X \fB?yes\fP Query user, true if answer is yes X \fB?no\fP Query user, true if answer is no X.fi XExample (stop macro execution if user rejects to continue): X.br X \fBprompt\fP "continue? " \fB?no break\fP X.sp 0.5v XIn addition to these conditionals, it is possible to test the current Xvalue of boolean and integer variables using the following form: X.br X \fB?\fP\fIvariable\fP\fB=\fP\fIvalue\fP X.br XThis conditional will be true (1) if the variable is an integer variable Xwhose current value is the one specified, or (2) if the variable is a Xboolean variable which is either \fBon\fP or \fBoff\fP. Examples: X.nf X ?layout=3 :set layout 1 X ?monitor=on break X ?sort=off :sort age X.fi X.TP X.B break XTerminate macro execution completely. This includes nested macros. XExample (stop if looking at a folder): X.br X \fB?folder\fP \fBbreak\fP X.TP X.B return XTerminate execution of current macro. If the current macro is called Xfrom another macro, execution of that macro continues immediately. X.TP X.B input XQuery the user for a key stroke or a string, for example a file name. XExample (prompt the user for a file name in the usual way): X.br X \fBsave-short\fP \fBinput\fP X.TP X.B yes XConfirm unconditionally \fIif\fP a command requires confirmation. It Xis ignored if the command does not require confirmation. Example X(confirm creation of new files): X.br X \fBsave-short\fP "+$G" \fByes\fP X.TP X.B no XTerminate execution of current macro \fIif\fP a command requires Xconfirmation; otherwise ignore it. If neither \fByes\fP nor \fBno\fP Xis specified when a command requires confirmation, the user must Xanswer the question as usual \- if the user confirms the action Xexecution continues normally; otherwise the execution of the current Xmacro is terminated. Example (do not create new files): X.br X \fBsave-short\fP "+$L/misc" \fBno\fP X.TP X\fBprompt\fP \fIstring\fP XPrint the \fIstring\fP in the prompt line (highlighted). The string Xmust be enclosed in double quotes. Example: X.br X \fBprompt\fP "Enter recipient name" X.TP X\fBecho\fP \fIstring\fP XDisplay the \fIstring\fP in the prompt line for a short period. Example: X.br X ?show \fBecho\fP "Cannot be used in reading mode" break X.TP X\fBmacro\fP \fIM\fP XInvoke macro number \fIM\fP. The maximum macro nesting level is five X(also catches macro loops). X.LP XI use the following macro to quickly save all the selected files in a Xfile whose name is entered as usual. It also works in reading mode X(saving just the current article). X.nf X \fBdefine\fP 1 X :unset save-report X save-short input yes X ?menu '+' X :set save-report X \fBend\fP X.fi X.SH THE INIT FILES XThe X.I init Xfiles are used to customize \fInn\fP's behaviour to your personal taste. X\fINn\fP uses two init files \- a system-wide init file located in the Xlibrary directory, and a private init file located in the user's X\&\fI.nn\fP directory. The private init file is read after the global Xinit file to allow the user to change the default setup. X.LP XThe init file may contain the following types of commands (and data): X.TP X.B Comments XEmpty lines and lines with a # character as the first non-blank Xcharacter are ignored. X.TP X.B Variable settings XYou can X.B set X(or X.BR unset ) Xall the variables described earlier to change Xnn's behaviour permanently. The X.B set Xand X.B unset Xcommands you can use in the init file have exactly the same format as Xthe X.B :set Xand X.B :unset Xcommands described earlier (except that the : prefix is omitted.) X.TP X.B Key mappings XYou can use all the versions of the X.B map Xcommand in the init file. X.TP X.B Macro Definitions XYou can define sequences of commands and key strokes using the X\fBdefine\fP...\fBend\fP construction, Xwhich can then be Xbound to single keys with the X.B map Xcommand. X.TP X.B Load terminal specific files XYou can load a terminal specific file using the X.sp 0.5v X \fBload\fP \fIfile\fP X.sp 0.5v XThe character X.B @ Xin the X.I file Xwill be replaced by the terminal type defined in the TERM environment Xvariable. \fInn\fP silently ingores the X.B load Xcommand if the file does not exist (so you don't have to have a Xspecific init file for terminals which does not require remapping). XIf the file is not specified by an absolute pathname, it must reside Xin your ~/.nn directory. Examples: X.nf X # load local customizations X load /usr/lib/nninit X # load personal terminal specific customizations X load init.@ X.fi X.TP X.B Change working directory of nn XYou can use the X.B cd Xcommand to change the working directory whenever you enter \fInn\fP. XExample: X.nf X # Use folder directory as working directory inside \fInn\fP X cd ~/News X.fi X.TP X.B The news group presentation sequence XThe X.I last Xpart of the init file may specify the sequence in which you want the Xnews groups to be presented. This part starts with the command X.B sequence Xand continues to the end of the init file. X.LP XBoth init files may contain a presentation sequence. In this case, Xthe global sequence is \fIappended\fP to the private sequence. X.SH GROUP PRESENTATION SEQUENCE XNews groups are normally presented in the sequence defined in the Xsystem-wide X.B init Xfile in \fInn\fP's library directory. X.LP XYou can personalize the presentation sequence Xby specifying an alternative sequence in the private X.I init Xfile. XThe sequence in the private init file is used X.I before Xthe global presentation sequence, and need only Xdescribe the deviations from the default presentation sequence. X.LP XThe presentation sequence must start with the word X.br X \fBsequence\fP X.br Xfollowed by a list of the news group names in the order you want them Xto be presented. XThe group names must be separated by white space. XThe sequence list must be the \fIlast\fP part of the Xinit file (the parsing of commands from the init file stops when the Xword \fBsequence\fP is encountered). X.LP XYou may use a full group name like "comp.unix.questions", or just the Xname of a main group or subgroup, e.g. "comp" or "comp.unix". XHowever, if "comp" precedes "comp.unix.questions" in the list, this Xsubgroup will be placed in the normal alphabetic sequence during the Xcollection of all the "comp" groups. X.LP XGroups which are not explicitly mentioned in any of the sequence files Xwill be placed after the mentioned groups, unless `!!' is used and it Xhas not been disabled (as described below). X.LP XEach group name may be followed by a file or folder name (must start Xwith either of / . ~ or +) which will specify the default save file Xfor that group (and its subgroups). A single "+" following the group Xname is an abbreviation for the last save file name used. X.LP XWhen an article is saved, the default save name will be used as the Xinitial contents of the file name prompt for further editing. It Xtherefore does not need to be be a complete file name (unless you use Xthe quick save mode). X.LP XThe following meta notation can be used in a sequence file: X.TP Xgroup.name XAppend the group (and its subgroups) to the presentation sequence list. X.TP X\&! group.name XCompletely ignore the group (and its subgroups) Xunless they are already in the presentation sequence (i.e. has been Xexplicitly mentioned earlier in the sequence). X.TP X\&!! XStop building the presentation sequence. This eliminates all groups Xthat are not already in the presentation sequence. X.TP X\fBNEW\fP XThis is a pseudo group name which matches all new groups; you could place Xthis symbol early in your presentation sequence to see new groups `out Xof sequence' (to attract your attention to them). X.TP X\&< group.name XPlace the group (and its subgroups) at the beginning of the Xpresentation sequence. X.TP X\&> group.name XPlace the group (and its subgroups) after all other groups that are Xand will be entered into the presentation sequence. X.TP X\&@ XDisable the `!!' command. This can be included in the personal Xpresentation sequence if the global X.B sequence Xfile contains a !! entry (see example 1 below). X.LP X.sp 0.5v X.B Example 1: XIn a company where ordinary users only should read the local Xnews groups, and ignore the rest (including new news groups which are Xotherwise always subscribed to initially), can use the following Xglobal presentation sequence: X.sp 0.5v X.nf X general X follow X !local.test X local X !! X.fi X.sp 0.5v XThe "expert" users in the company must put the X.B @ Xcommand somewhere Xin their private sequence to avoid losing news groups which they have Xnot explicitly mentioned in their init file. X.sp X.B Example 2: XThis is the global sequence for systems with Xheavy news addicts who setup their own sequences anyway. X.nf X.sp 0.5v X # all must read the general news first X < general X.sp 0.5v X # test is test, and junk is junk, X # so it is placed at the very end X > test X > .test X > junk X.sp 0.5v X # this is the standard sequence which everybody may X # change to their own liking X local # our local groups X dk # the Danish groups X eunet.general # to present it before eunet.followup X eunet # the other European groups X comp # the serious groups X news # news on news X sci # other serious groups X rec # not really that important (don't quote me) X misc # well, it must be somewhere X.sp 0.5v X # the groups that are not listed above goes here X.sp 0.5v X.fi XNotice the use of comments in the sequence where they are allowed at Xthe end of non-empty lines as well. X.sp X.B Example 3: XMy own presentation sequence (in the init file) simply Xlists my favourite groups and the corresponding default save files: X.nf X.sp 0.5v X \fBsequence\fP X rec.music.synth +synth/ X comp.emacs +emacs/misc X gnu.emacs + X NEW # show new groups here X comp.risks +risks X news.admin X eunet.sources +src/unix/ X comp.sources +src/$L/ X comp.sys.ti +ti/$L X.sp 0.5v X.fi XThe presentation sequence is not used when \fInn\fP is called with one or Xmore news group names on the command line; it is thus possible to read Xignored groups (on explicit request) wihtout changing the init file. X(Of course, you can also use the X.B G Xcommand to read ignored groups). X.SH THE NN RECORD FILE XThe directory ~/.nn contains all the files that are related to X\fInn\fP. Besides the init file, most of these files are maintained Xautomatically by \fInn\fP, and the most Ximportant is the X.B rc Xfile which contains a record of which articles have been read in which Xgroups, and which groups have been unsubscribed to. (This is the Xequivalent of the .newsrc file used by other news reader programs; the X\&.newsrc file is not supported in the present release of \fInn\fP.) X.LP XNormally, you will not need to change this file, because you can use Xthe \fBU\fP command to unsubscribe and resubscribe to news groups, and Xthe X.IR nngoback (1) Xprogram is available to `turn back' the rc file one or more days. X.LP XEach line in the rc file has the following format: X.br X.sp 0.5v X + 000000 news.group.name X.sp 0.5v X.br XThe "+" indicates that you subscribe to the news group. A "!" instead Xof the "+" indicates that you have unsubscribed to the group. The Xsix digits are the number of the last article you have read in the Xgroup, and the rest of the line is the name of the news group. X.LP XThe order of the lines in the rc file is not important, and Xentries for new newsgroups are automatically appended to the file X(with subscription, unless you immediately unsubscribe to them). X.SH ENVIRONMENT XThe following environment variables are used by \fInn\fP: X.LP X.BR EDITOR . XThe editor invoked when editing replies, follow-ups, and composing Xmail. \fInn\fP knows about the following editors: X.BR vi (1), X.BR ded (1), X.B GNU X.BR emacs (1), Xand X.B Micro X.BR emacs (1), Xand will try to position the cursor on the first line following the Xheader, i.e. after the blank line which must not be deleted! If an Xarticle has been included, the cursor is placed on the first line of Xthe included text (to allow you to delete sections easily). X.LP X.BR SHELL . XThis is the shell which is spawned if the system cannot suspend X\fInn\fP, and it will be used to execute the shell escapes. X.LP X.BR TERM . XThe terminal type. X.SH AUTHOR XKim F. Storm, Texas Instruments A/S, Denmark X.br XE-mail: storm@texas.dk (but see the addresses below) X.LP XThe NNTP support was designed and implemented by XRen\o'\(aae' Seindal, Institute of Datalogy, University of Copenhagen, Denmark, Xwho also ported \fInn\fP to BSD 4.3 and SunOS 4.0. X.SH FILES X.DT X.nr tW \w'~/.nn/KILL.COMP' X.nr tX \w'/usr/lib/terminfo/*' X.if \n(tWu>\n(tXu .nr tX \n(tWu X.ta \n(tWu+3m X~/.nn/rc The record of read articles. X.br X~/.nn/rc.bak Copy of rc file saved on entry to \fInn\fP. X.br X~/.nn/init Personal configuration and presentation sequence. X.br X~/.nn/kill The automatic kills and selections. X.br X~/.nn/KILL.COMP The compiled kill file. X.br X$lib/init System-wide setup and presentation sequence. X.br X$lib/aux The response edit and send script. X.br X$lib/routes Mapping rules for mail addresses (on non-domain systems). X.br X$db/* The news data base. X.br X/etc/termcap Terminal data base [BSD]. X.br X/usr/lib/terminfo/* Terminal data base [SysV]. X.br X/usr/lib/nntp-server Name of remote nntp server. X.sp 0.5v X.DT XThe name $lib and $db are the directories used for the auxiliary files Xand the news data base respectively. Their name and location is Xdefined at compile time. Common choices are /usr/local/lib/nn or X/usr/lib/news/nn for $lib and /usr/spool/nn or /usr/spool/news/.nn for X$db. X.SH SEE ALSO XOther netnews documentation. X.br Xnncheck(1), nngoback(1), nngrep(1), nntidy(1) X.br Xnnadmin(1M), nnquery(1M), nnusage(1M), nnmaster(8) X.SH MAILING LISTS XBugs and fixes, suggestions, ideas, critique, etc. can be sent to Xthe following address: X.br X nn-bugs@dkuug.dk X.LP XWe have created a moderated mailing list for news about \fInn\fP. The Xmoderator is Ren\o'\(aae' Seindal, seindal@diku.dk. Send Xyour contributions to the address: X.br X nn-info@dkuug.dk X.LP XYou are welcome to join the nn-info mailing list, just send your Xname and E-mail address to the following address: X.br X nn-info-request@dkuug.dk X.LP XIf these addresses fail, you may want to know that dkuug.dk is the Xdanish EUnet backbone, so if you can reach uunet or mcvax, you can Xalso reach us (e.g. using ...!uunet!dkuug.dk!nn-info). NO_NEWS_IS_GOOD_NEWS echo "File nn.1 is complete" chmod 0644 nn.1 || echo "restore of nn.1 fails" set `wc -c nn.1`;Sum=$1 if test "$Sum" != "93389" then echo original size 93389, current size $Sum;fi echo "x - extracting nn.c (Text)" sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > nn.c && X/* X * The User Interface main program X */ X X#include "config.h" X#include "menu.h" X#include "term.h" X#include "keymap.h" X#include "options.h" X Xstatic int X dont_read_init_file = 0, X prompt_for_group = 0; X Xstatic char X *match_subject = NULL; X Xexport int X article_limit = -1, X also_read_articles = 0, X do_kill_handling = 1, X group_name_args = 0, X merged_menu = 0, X silent = 0, X Debug = 0; X Ximport int X keep_rc_backup, no_update, /* rc.c */ X preview_window, fmt_linenum, fmt_rptsubj, /* menu.c */ X show_article_date, first_page_lines, /* more.c */ X dont_split_digests, dont_sort_articles, /* group.c */ X dont_sort_folders, /* folder.c */ X show_current_time, conf_dont_sleep; /* term.c */ X XOption_Description(nn_options) { X 'a', Int_Option(article_limit), X 'B', Bool_Option(keep_rc_backup), X 'd', Bool_Option(dont_split_digests), X 'f', Bool_Option(dont_sort_folders), X 'g', Bool_Option(prompt_for_group), X 'I', Bool_Option(dont_read_init_file), X 'k', Bool_Option(do_kill_handling), X 'l', Int_Option(first_page_lines), X 'L', Int_Option_Optional(fmt_linenum, 3), X 'm', Bool_Option(merged_menu), X 'N', Bool_Option(no_update), X 'q', Bool_Option(dont_sort_articles), X 'Q', Bool_Option(silent), X 's', String_Option(match_subject), X 'S', Bool_Option(fmt_rptsubj), X 'T', Bool_Option(show_current_time), X 'w', Int_Option_Optional(preview_window, 5), X 'W', Bool_Option(conf_dont_sleep), X 'x', Int_Option_Optional(also_read_articles, -1), X 'Z', Int_Option(Debug), X '\0', X}; X X Xstatic int X report_number_of_articles = 0, X report_group_names = 0; Xstatic char X *check_message_format = NULL; X XOption_Description(check_options) { X 'Q', Bool_Option(silent), X 'r', Bool_Option(report_number_of_articles), X 'f', String_Option(check_message_format), X 't', Bool_Option(report_group_names), X '\0', X}; X X X/* program name == argv[0] without path */ X Xchar *pname; X X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern long unread_articles; X extern char *program_name(); X int emacs_slave_mode = 0, check_news = 0, enter_admin_mode = 0; X X pname = program_name(argv); X if (strcmp(pname, "nnadmin") == 0) X enter_admin_mode = 1; X else X if (strcmp(pname, "nnemacs") == 0) X emacs_slave_mode = 1; X else X if (strcmp(pname, "nncheck") == 0) { X keep_rc_backup = 0; X check_news = 1; X } X X if (!check_news && !emacs_slave_mode && (!enter_admin_mode || argc == 1)) X if (!isatty(0)) { X fprintf(stderr, "Input is not a tty\n"); X nn_exit(1); X } X X init_global(0); X init_key_map(); X init_execute(); X init_macro(); X X#ifdef NNTP X nntp_check(); X#endif X if (enter_admin_mode) { X if (argc == 1) { X init_term(); X visit_init_file(); X } X open_master(OPEN_READ); X visit_active_file(); X admin_mode(argv[1]); X nn_exit(0); X } X X if (check_news) X parse_options(argc, argv, (char *)NULL, check_options, ""); X else X if (!emacs_slave_mode) { X init_term(); X X if (argc < 2 || strncmp(argv[1], "-I", 2)) X visit_init_file(); X X group_name_args = X parse_options(argc, argv, (char *)NULL, X nn_options, " [group | [+]folder]..."); X X if (!silent) X print_version("Release %R.%V.%P #%U, Kim F. Storm, 1989\n\n"); X } X X open_master(OPEN_READ); X X if (also_read_articles) { X if (article_limit < 0) X article_limit = also_read_articles; X do_kill_handling = 0; X no_update++; X } X X if (match_subject) { X if (*match_subject != '/') init_quick_match(match_subject); X no_update++; X do_kill_handling = 0; X } X X if (merged_menu) { X no_update++; X } X X if (!no_update && group_name_args > 0) X no_update = only_folder_args(argv + 1); X X visit_rc_file(); X X count_unread_articles(report_group_names); X X if (emacs_slave_mode) X prt_unread("%U %G\n"); X X if (check_news) { X if (check_message_format) { X if (unread_articles || !silent) X prt_unread(check_message_format); X } else X if (report_number_of_articles) { X prt_unread("%U"); X nn_exit(0); X } else X if (!silent) { X if (unread_articles || report_number_of_articles) X prt_unread("There %i %u in %g\n"); X else X prt_unread((char *)NULL); X } X X nn_exit( unread_articles ? 0 : 99 ); X } X X if (unread_articles == 0 && X group_name_args == 0 && X !also_read_articles && X !prompt_for_group) { X if (!silent) prt_unread((char *)NULL); X nn_exit(0); X } X X if (do_kill_handling) X do_kill_handling = init_kill(); X X if (group_name_args > 0) X named_group_sequence(argv + 1); X else X normal_group_sequence(); X X if (emacs_slave_mode) { X emacs_mode(); X goto out; X } X X if (prompt_for_group) { X raw(); X current_group = NULL; X prompt_line = Lines - 1; X goto_group(K_GOTO_GROUP, (article_header *)NULL); X no_raw(); X clrdisp(); X goto out; X } X if (!no_update && article_limit == 0) { X char answer[50]; X X prt_unread("\nCatch-up on %u ? (all) (i)nteractive "); X fl; X if (gets(answer)) { X if (strncmp(answer, "all", 3) == 0) { X printf("\nUPDATING rc FILE...."); X fl; X read_news(-1); X printf("DONE\n"); X goto out; X } X if (*answer == 'i') { X read_news(1); X goto out; X } X } X printf("\nNO UPDATE\n"); X goto out; X } X X if (merged_menu) { X merge_and_read(match_subject, do_kill_handling); X clrdisp(); X } else X if (read_news(0)) { X clrdisp(); X } else { X gotoxy(0,Lines-1); X if (group_name_args == 0) X printf("No News\n"); X else X printf("\r\n"); X } X X#ifdef STATISTICS X log_usage(); X#endif X X if (!also_read_articles && unread_articles > 0 && !silent && group_name_args == 0) X prt_unread("There %i still %u in %g\n\n\r"); X X out: X X nn_exit(0); X /*NOTREACHED*/ X} X X/* X * nn_exit() --- called whenever a program exits. X */ X Xnn_exit(n) X{ X static int loop = 0; X X if (loop) exit(n); X loop++; X X#ifdef NNTP X nntp_cleanup(); X#endif /* NNTP */ X close_master(); X close_rc(); X X exit(n); X} X Xexport group_header *jump_to_group = NULL; X Xstatic read_news(mode) X{ X register group_header *cur, *prev, *tmp; X int menu_cmd; X int must_clear = 0, did_jump = 0; X extern int menu(); X X prev = group_sequence; X X cur = group_sequence; X X while (cur != NULL || did_jump) { X if (s_hangup) break; X X if (cur == NULL) { X did_jump = 0; X cur = group_sequence; X continue; X } X X if (!also_read_articles) X if (cur->last_article >= cur->last_l_article) { X cur = cur->next_group; X continue; X } X X if (mode) { X if (mode > 0) { X char answer[50]; X printf("Update %s (%ld)? ", X cur->group_name, X (long)(cur->last_l_article - cur->last_article)); X fl; X if (gets(answer) == NULL || s_keyboard) { X putchar(NL); X printf("Update rest? "); X fl; X if (gets(answer) == NULL || *answer != 'y') X return 0; X mode = -1; X *answer = 'y'; X } X if (*answer == '?') { X printf("Enter (y)es to update current group\n"); X continue; /* redo current group */ X } X if (*answer != 'y') { X cur = cur->next_group; X continue; X } X } X update_rc(cur); X continue; X } X X free_memory(); X X if (cur->group_flag & G_FOLDER) { X menu_cmd = folder_menu(cur->group_name); X if (menu_cmd == ME_NO_REDRAW) { X menu_cmd = ME_NO_ARTICLES; X cur->last_l_article = 0; X } X } else X menu_cmd = group_menu(cur, -1, X match_subject, do_kill_handling, menu); X X if (menu_cmd != ME_NO_ARTICLES) X must_clear++; X X switch (menu_cmd) { X X case ME_PREV: X tmp = cur; X cur = prev; X prev = tmp; X cur->last_article = cur->first_article; X continue; X X case ME_READ: X cur->last_article = cur->last_l_article; X /* fall thru */ X X case ME_NEXT: X prev = cur; X /* fall thru */ X X case ME_NO_ARTICLES: X cur = cur->next_group; X continue; X X case ME_QUIT: X if (jump_to_group) { X prev = cur; X cur = jump_to_group; X jump_to_group = NULL; X did_jump = 1; X continue; X } X X return must_clear; X } X } X return must_clear; X} X X X Xexport char *mail_box = NULL; X Xunread_mail(t) Xtime_t t; X{ X struct stat st; X static time_t next = 0; X static int any = 0; X X if (next > t) return any; X X next = t + 60; X any = 0; X X if (mail_box == NULL || X stat(mail_box, &st) != 0 || X st.st_size == 0 || X st.st_mtime < st.st_atime) return 0; X X any = 1; X X return 1; X} X X#ifdef STATISTICS Xstatic time_t usage_time = 0; X Xtick_usage(end_t, start_t) Xtime_t *end_t, *start_t; X{ X time_t temp_t; X static time_t last_t = 0; X X if (end_t == NULL) end_t = &temp_t; X X time(end_t); X X if (start_t == 0) { X /* X * We ignore delays > 2 minutes because the user has probably X * just left the terminal inside nn and done something else X */ X if ((last_t + 120) > *end_t) X usage_time += *end_t - last_t; X } else X usage_time += (*end_t - *start_t)/60; X X last_t = *end_t; X} X Xlog_usage() X{ X usage_time /= 60; X X if (usage_time < STATISTICS) return; /* don't log short sessions */ X X log_entry('U', "USAGE %d.%02d", usage_time/60, usage_time%60); X} X#endif X X#ifdef MALLOC_TEST Xstatic int in_calloc = 0; X Xchar *malloc(n) Xunsigned int n; X{ X char *p, *sbrk(); X X if (p = sbrk(n + 3)) X while ( ((int)p) & 3) p++; X X if (!in_calloc) X printf("MALLOC(%u) => %lx\n", n, (long)p); X X return p; X} X Xchar *calloc(n, s) Xunsigned n, s; X{ X char *p; X X in_calloc = 1; X p = malloc(n*s); X in_calloc = 0; X X printf("CALLOC(%u,%u) => %lx\n", n, s, (long)p); X X return p; X} X Xfree(p) Xchar *p; X{ X printf("FREE(%lx)\n", p); X} X Xchar *realloc() X{ X printf("REALLOC\n"); X} X X#endif /* MALLOC_TEST */ X X/* this will go into emacs_mode.c when it is completed someday */ X Xemacs_mode() X{ X printf("EMACS MODE IS NOT SUPPORTED YET.\n"); X} NO_NEWS_IS_GOOD_NEWS chmod 0644 nn.c || echo "restore of nn.c fails" set `wc -c nn.c`;Sum=$1 if test "$Sum" != "9858" then echo original size 9858, current size $Sum;fi echo "x - extracting nnadmin.1m (Text)" sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > nnadmin.1m && X.TH NNADMIN 1M "Release 6.3" X.\" (c) Copyright 1988, Kim F. Storm X.UC 4 X.SH NAME Xnnadmin \- nn database administration X.SH SYNOPSIS X.B nnadmin X[ X.I commands X] X.SH DESCRIPTION X.I nnadmin Xis a control program for the \fInnmaster\fP(1M) daemon which is Xresponsible for building and maintaining the database used by the X\fInn\fP(1) news reader. X.LP X\fInnadmin\fP allows you to display extracts from the log file, Xdisplay the "raw" contents of the database, make consistency checks on Xthe database, instruct the running \fInnmaster\fP to expire one or Xmore groups, alter the options of the running \fInnmaster\fP, and much Xmore. X.LP X\fInnadmin\fP runs in two modes: interactive and non-interactive. X.LP XIn interactive mode, simple one line menus are used to show the Xavailable operations which are then selected by typing the letter Xassociated with the command (normally the first letter in the command Xname). X.LP XIn non-interactive mode, the X.I commands Xargument will be used as a series of key-strokes which are interpreted Xexactly as if they were typed in from the keyboard in interactive Xmode. For example, to stop the \fInnmaster\fP, the following Xinvokation of nnadmin can be used: X.br X \fInnadmin\fP MK X.br Xwhich will select the (M)aster submenu from the main menu, and then Xthe (K)ill entry from the submenu. X.LP XIn non-interactive mode, the menus are not displayed and the commands Xare not echoed! \fInnadmin\fP will exit when there are no more Xkey-strokes to be read from the X.I commands Xargument. It is not possible to specify a group name in the X.I commands Xargument, so the functionalities of \fInnadmin\fP that relates to Xspecific groups are only available in interactive mode. X.LP XYou can also invoke an interactive \fInnadmin\fP using the X.B :admin Xcommand in \fInn\fP. The only operation which is not available is the XValidation command, because it whould disturb the normal operation of X\fInn\fP. X.SH MAIN MENU XFrom the main menu (identified by the X.B ADMIN Xprompt) you can select the following operations: X.TP X.B C)onf X.br XShow current configuration parameters such as directories, files, Xprograms, network usage, etc. X.TP X.B E)xpire X.br XSend a request to the \fInnmaster\fP daemon to run expire on all Xgroups in the database. This is equal to the Init operation when Xthe \fInnmaster\fP is started with the \-E option. X.TP X.B G)roups X.br XEnter the GROUP submenu. X.TP X.B I)nit X.br XSend a request to the \fInnmaster\fP daemon to recollect all Xgroups in the database. X.TP X.B L)ogs X.br XEnter the LOG submenu. X.TP X.B M)aster X.br XEnter the MASTER submenu. X.TP X.B Q)uit X.br XQuit \fInnadmin\fP. X.TP X.B S)tat X.br XPrint general statistics about the database. See the section on XDatabase Statistics below. X.TP X.B U)pdate X.br XUpdate the incore copy of the database master index. X.TP X.B V)alidate X.br XMake a thorough consistency check on the database. If inconsistencies Xare found in a group, you will be asked whether a request should be Xsent to the \fInnmaster\fP daemon to recollect the group (in Xnon-interactive mode, requests will be sent automatically for all Xcorrupted groups). X.TP X.B W)akeup X.br XSend a wakeup signal to the \fInnmaster\fP daemon to have it receive Xmessages sent to it, perform the required actions, and then collect Xarticles as necessary. X.TP X.B Z (silent validation) X.br XThis operation is identical to the Validate operation, expect that no Xoutput is produced during the consistency check; this operation is Xused by the \fInnmaster\fP to execute the \-C option. X.SH THE MASTER MENU XThe master menu (identified by the X.B MASTER Xprompt) provides access to overall database information, and to send Xcontrol messages to the \fInnmaster\fP daemon. X.TP X.B A)ll X.br XPrint the master index entry for all groups in the database. X.TP X.B E)mpty X.br XPrint the master index entry for the empty groups in the database. X.TP X.B F)iles X.br XPrint a listing (using X.IR ls (1)) Xof all the data and index files in the database. X.TP X.B G)roup X.br XPrint the master index entry for a single group identified by its Xinternal group number. X.TP X.B K)ill X.br XStop the \fInnmaster\fP when it has finished its current task. X.TP X.B N)on-empty X.br XPrint the master index entry for the non-empty groups in the database. X.TP X.B O)ptions X.br XChange the runtime options of the running \fInnmaster\fP daemon. XCurrently, only the value of the \-r and \-e options can be modified. X.TP X.B S)tat X.br XPrint general statistics about the database. See the section on XDatabase Statistics below. X.TP X.B T)race X.br XTurn the trace option \-t on or off in the running \fInnmaster\fP. X.SH THE LOG MENU XThe log menu (identified by the X.B LOG Xprompt) enables you the extract specific entries from the log file, Xand to truncate the log file. X.LP XThe entries in the log file share the following format: X.sp 0.5v X :