home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * The nn user interface main program
- */
-
- #include "config.h"
- #include "menu.h"
- #include "term.h"
- #include "keymap.h"
- #include "options.h"
- #include "proto.h"
- #include "articles.h"
-
- import char *bin_directory;
-
- import int
- seq_cross_filtering, /* articles */
- dont_sort_folders, /* folder.c */
- dont_split_digests, dont_sort_articles, also_unsub_groups, /* group.c */
- also_cross_postings,
- case_fold_search, /* match.c */
- preview_window, fmt_linenum, fmt_rptsubj, /* menu.c */
- show_article_date, first_page_lines, /* more.c */
- keep_rc_backup, no_update, /* newsrc.c */
- hex_group_args, /* sequence */
- show_current_time, conf_dont_sleep; /* term.c */
-
- export int
- article_limit = -1,
- also_read_articles = 0,
- conf_auto_quit = 0,
- do_kill_handling = 1,
- group_name_args = 0,
- merged_menu = 0,
- repeat_group_query = 0,
- report_cost_on_exit = 1,
- silent = 0,
- verbose = 0,
- Debug = 0;
-
- static int
- nngrab_mode = 0,
- prompt_for_group = 0;
-
- static char
- *match_subject = NULL,
- *match_sender = NULL,
- *init_file = NULL;
-
- Option_Description(nn_options) {
- 'a', Int_Option(article_limit),
- 'B', Bool_Option(keep_rc_backup),
- 'd', Bool_Option(dont_split_digests),
- 'f', Bool_Option(dont_sort_folders),
- 'g', Bool_Option(prompt_for_group),
- 'G', Bool_Option(nngrab_mode),
- 'i', Bool_Option(case_fold_search),
- 'I', String_Option_Optional(init_file, NULL),
- 'k', Bool_Option(do_kill_handling),
- 'l', Int_Option(first_page_lines),
- 'L', Int_Option_Optional(fmt_linenum, 3),
- 'm', Bool_Option(merged_menu),
- 'n', String_Option(match_sender),
- 'N', Bool_Option(no_update),
- 'q', Bool_Option(dont_sort_articles),
- 'Q', Bool_Option(silent),
- 'r', Bool_Option(repeat_group_query),
- 's', String_Option(match_subject),
- 'S', Bool_Option(fmt_rptsubj),
- 'T', Bool_Option(show_current_time),
- 'w', Int_Option_Optional(preview_window, 5),
- 'W', Bool_Option(conf_dont_sleep),
- 'x', Int_Option_Optional(also_read_articles, -1),
- 'X', Bool_Option(also_unsub_groups),
- 'Z', Int_Option(Debug),
- '\0',
- };
-
-
- static int
- report_number_of_articles = 0;
- static char
- *check_message_format = NULL;
- import int
- quick_unread_count;
-
- Option_Description(check_options) {
- 'Q', Bool_Option(silent),
- 'r', Bool_Option(report_number_of_articles),
- 'f', String_Option(check_message_format),
- 't', Bool_Option(verbose),
- 'v', Bool_Option(verbose),
- 'c', Bool_Option(quick_unread_count),
- '\0',
- };
-
- /* program name == argv[0] without path */
-
- char *pname;
-
- static int must_unlock = 0;
-
- static int nn_locked()
- {
- if (no_update) return 0;
-
- switch (who_am_i) {
- case I_AM_ADMIN:
- case I_AM_CHECK:
- case I_AM_POST:
- case I_AM_GREP:
- case I_AM_SPEW:
- return 0; /* will not update .newsrc */
- }
-
- if (proto_lock(I_AM_NN, PL_SET)) {
- printf("\nAnother nn process is already running\n\n");
- return 1;
- }
-
- must_unlock = 1;
- return 0;
- }
-
- static flag_type setup_access()
- {
- flag_type access_mode = 0;
-
- if (do_kill_handling)
- access_mode |= ACC_DO_KILL;
- if (also_cross_postings)
- access_mode |= ACC_ALSO_CROSS_POSTINGS;
- if (also_read_articles)
- access_mode |= ACC_ALSO_READ_ARTICLES;
- if (dont_split_digests)
- access_mode |= ACC_DONT_SPLIT_DIGESTS;
- if (dont_sort_articles)
- access_mode |= ACC_DONT_SORT_ARTICLES;
-
- return access_mode;
- }
-
- export group_header *jump_to_group = NULL;
-
- static read_news(access_mode, mask)
- flag_type access_mode;
- char *mask;
- {
- register group_header *gh, *prev, *tmp, *after_loop;
- flag_type group_mode;
- int menu_cmd;
- int must_clear = 0, did_jump = 0;
- extern int menu();
-
- prev = group_sequence;
- gh = group_sequence;
- after_loop = NULL;
-
- for (;;) {
- group_mode = access_mode;
-
- if (s_hangup) break;
-
- if (gh == NULL) {
- if (after_loop != NULL) {
- gh = after_loop;
- after_loop = NULL;
- if (gh->unread_count <= 0)
- group_mode |= ACC_ORIG_NEWSRC;
- goto enter_direct;
- }
-
- if (did_jump) {
- did_jump = 0;
- gh = group_sequence;
- continue;
- }
-
- if (must_clear && conf_auto_quit) {
- prompt("\1LAST GROUP READ. QUIT NOW?\1");
- switch (yes(1)) {
- case 1:
- break;
- case 0:
- gh = group_sequence;
- default:
- after_loop = prev;
- continue;
- }
- }
- break;
- }
-
- if (gh->group_flag & G_UNSUBSCRIBED) {
- if (!also_unsub_groups) {
- gh = gh->next_group;
- continue;
- }
- } else
- if (!also_read_articles && gh->unread_count <= 0) {
- gh = gh->next_group;
- continue;
- }
-
- enter_direct:
-
- free_memory();
-
- if (gh->group_flag & G_FOLDER) {
- menu_cmd = folder_menu(gh->group_name);
- if (menu_cmd == ME_NO_REDRAW) {
- menu_cmd = ME_NO_ARTICLES;
- gh->last_db_article = 0;
- }
- } else {
- group_mode |= setup_access();
- if (group_mode & ACC_ORIG_NEWSRC)
- gh->last_article = gh->first_article;
-
- menu_cmd = group_menu(gh, (article_number)(-1), group_mode, mask, menu);
- group_mode = access_mode;
- }
-
- if (menu_cmd != ME_NO_ARTICLES) {
- after_loop = NULL;
- must_clear++;
- }
-
- switch (menu_cmd) {
-
- case ME_QUIT: /* or jump */
- if (!jump_to_group) return must_clear;
-
- prev = jump_to_group;
- jump_to_group = NULL;
- did_jump = 1;
- /* fall thru */
-
- case ME_PREV:
- tmp = gh;
- gh = prev;
- prev = tmp;
- if (gh->unread_count <= 0)
- group_mode |= ACC_ORIG_NEWSRC;
- goto enter_direct;
-
- case ME_NEXT:
- prev = gh;
- /* fall thru */
-
- case ME_NO_ARTICLES:
- if (gh->group_flag & G_MERGE_HEAD) {
- do gh = gh->next_group;
- while (gh && (gh->group_flag & G_MERGE_SUB));
- } else
- gh = gh->next_group;
- continue;
- }
- }
- return must_clear;
- }
-
-
- static catch_up()
- {
- register group_header *gh;
- char answer[50];
- int mode, must_help;
- import int newsrc_update_freq, novice;
- import int menu();
- flag_type access_mode;
-
- access_mode = setup_access();
-
- prt_unread("\nCatch-up on %u ? (auto)matically (i)nteractive ");
- fl;
- mode = 0;
-
- if (gets(answer)) {
- if (strncmp(answer, "auto", 4) == 0) {
- printf("\nUPDATING .newsrc FILE....");
- fl;
- mode = -1;
- } else
- if (*answer == 'i')
- mode = 1;
- }
-
- if (mode == 0) {
- printf("\nNO UPDATE\n");
- return;
- }
-
- newsrc_update_freq = 9999;
- must_help = novice;
-
- Loop_Groups_Sequence(gh) {
-
- if ((gh->group_flag & G_COUNTED) == 0) continue;
-
- if (mode < 0) {
- update_rc_all(gh, 0);
- continue;
- }
-
- again:
- if (must_help) {
- printf("\n y - mark all articles as read in current group\n");
- printf(" n - do not update group\n");
- printf(" r - read the group now\n");
- printf(" U - unsubscribe to current group\n");
- printf(" ? - this message\n");
- printf(" q - quit\n\n");
-
- must_help = 0;
- }
-
- printf("Update %s (%ld)? (ynrU?q) n\b", gh->group_name,
- (long)(gh->last_db_article - gh->last_article));
- fl;
-
- if (gets(answer) == NULL || s_keyboard)
- *answer = 'q';
-
- switch (*answer) {
-
- case 'q':
- putchar(NL);
- printf("Update rest? (yn) n\b");
- fl;
- if (gets(answer) == NULL || *answer != 'y')
- return;
-
- mode = -1;
- break;
-
- case NUL:
- case 'n':
- continue;
-
- case 'r':
- raw();
- group_menu(gh, (article_number)(-1), access_mode, (char *)NULL, menu);
- unset_raw();
- clrdisp();
- if (gh->unread_count > 0) goto again;
- continue;
-
- case 'U':
- update_rc_all(gh, 1);
- continue;
-
- case 'y':
- break;
-
- default:
- must_help = 1;
- goto again;
- }
-
- update_rc_all(gh, 0);
- }
-
- printf("DONE\n");
-
- flush_newsrc();
- }
-
- export char *mail_box = NULL;
-
- unread_mail(t)
- time_t t;
- {
- struct stat st;
- static time_t next = 0;
- static int any = 0;
-
- if (next > t) return any;
-
- next = t + 60;
- any = 0;
-
- if (mail_box == NULL ||
- stat(mail_box, &st) != 0 ||
- st.st_size == 0 ||
- st.st_mtime < st.st_atime) return 0;
-
- any = 1;
-
- return 1;
- }
-
- #ifdef ACCOUNTING
- #ifndef STATISTICS
- #define STATISTICS 1
- #endif
- #define NEED_ACCOUNT
- #else
- #ifdef AUTHORIZE
- #define NEED_ACCOUNT
- #endif
- #endif
-
- #ifdef STATISTICS
- static time_t usage_time = 0;
- static time_t last_tick = 0;
-
- stop_usage()
- {
- last_tick = 0;
- }
-
- time_t tick_usage()
- {
- register time_t now;
-
- now = cur_time();
-
- /*
- * We ignore ticks > 2 minutes because the user has probably
- * just left the terminal inside nn and done something else
- */
- if (last_tick > (now - 120))
- usage_time += now - last_tick;
-
- last_tick = now;
- return now;
- }
-
- log_usage()
- {
- #ifdef ACCOUNTING
- account('U', report_cost_on_exit);
- #else
- if (usage_time < (STATISTICS * 60)) return; /* don't log short sessions */
-
- usage_time /= 60;
- log_entry('U', "USAGE %d.%02d", usage_time/60, usage_time%60);
- #endif
- }
-
- #else
- stop_usage()
- {
- }
-
- time_t tick_usage()
- {
- return cur_time();
- }
-
- log_usage()
- {
- }
- #endif
-
- #ifdef NEED_ACCOUNT
- account(option, report)
- char option;
- int report;
- {
- char *args[10], **ap;
- char buf1[16], buf2[16];
- int ok;
-
- if (who_am_i != I_AM_NN && who_am_i != I_AM_POST) return 0;
-
- if (report) {
- putchar(CR); clrline(); fl;
- }
-
- ap = args;
- *ap++ = "nnacct";
- if (report) *ap++ = "-r";
- sprintf(buf1, "-%c%ld", option, (long)usage_time/60);
- *ap++ = buf1;
- sprintf(buf2, "-W%d", who_am_i);
- *ap++ = buf2;
- *ap++ = NULL;
- ok = execute(relative(bin_directory, "nnacct"), args, 0);
- if (option == 'U' && report) putchar(NL);
- return ok;
- }
- #endif
-
- /* this will go into emacs_mode.c when it is completed someday */
-
- emacs_mode()
- {
- printf("EMACS MODE IS NOT SUPPORTED YET.\n");
- }
-
-
- static do_nnspew()
- {
- register group_header *gh;
- import int seq_cross_filtering;
- int ix;
-
- ix = 0;
- Loop_Groups_Header(gh) {
- if (gh->master_flag & M_IGNORE_GROUP) continue;
- gh->preseq_index = ++ix;
- }
-
- /* Only output each article once */
- /* Must also use this mode when using nngrab! */
-
- seq_cross_filtering = 1;
-
- Loop_Groups_Header(gh) {
- if (s_hangup) return 1;
- if (gh->master_flag & M_IGNORE_GROUP) continue;
- access_group(gh, gh->first_db_article, gh->last_db_article,
- ACC_DONT_SORT_ARTICLES | ACC_ALSO_FULL_DIGEST |
- ACC_SPEW_MODE, (char *)NULL);
- }
- return 0;
- }
-
-
- clean_group(gh)
- group_header *gh;
- {
- }
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- extern long unread_articles;
- extern char *program_name();
- int say_welcome = 0, cmd;
- flag_type access_mode;
- char *mask;
-
- pname = program_name(argv);
-
- if (strcmp(pname, "nnadmin") == 0) {
- who_am_i = I_AM_ADMIN;
- } else
- if (strcmp(pname, "nnemacs") == 0) {
- who_am_i = I_AM_EMACS;
- } else
- if (strcmp(pname, "nncheck") == 0) {
- who_am_i = I_AM_CHECK;
- } else
- if (strcmp(pname, "nntidy") == 0) {
- who_am_i = I_AM_TIDY;
- } else
- if (strcmp(pname, "nngoback") == 0) {
- who_am_i = I_AM_GOBACK;
- } else
- if (strcmp(pname, "nngrep") == 0) {
- who_am_i = I_AM_GREP;
- } else
- if (strcmp(pname, "nnpost") == 0) {
- who_am_i = I_AM_POST;
- } else {
- who_am_i = I_AM_NN;
- }
-
- if (who_am_i == I_AM_NN || (who_am_i == I_AM_ADMIN && argc == 1)) {
- if (!isatty(0)) {
- if (who_am_i == I_AM_NN && argc == 2) {
- if (strcmp(argv[1], "-SPEW") == 0) {
- who_am_i = I_AM_SPEW;
- init_global();
- goto nnspew;
- }
- }
-
- fprintf(stderr, "Input is not a tty\n");
- exit(1);
- }
- }
-
- #ifdef AUTHORIZE
- init_execute();
- if (cmd = account('P', 0)) {
- switch (cmd) {
- case 1:
- if (who_am_i == I_AM_POST) {
- printf("You are not authorized to post news\n");
- exit(41);
- }
- /* ok_to_post = 0; */
- cmd = 0;
- break;
- case 2:
- printf("You are not authorized to read news\n");
- break;
- case 3:
- printf("You cannot read news at this time\n");
- break;
- case 4:
- printf("Your news reading quota is exceeded\n");
- break;
- default:
- printf("Bad authorization -- reason %d\n", cmd);
- break;
- }
- if (cmd) exit(40 + cmd);
- }
- #endif
-
- if ((say_welcome = init_global()) < 0) {
- printf("%s: nn must been invoked to initialize user files\n", pname);
- nn_exit(1);
- }
-
- #ifdef NNTP
- nntp_check();
- #endif
-
- init_key_map();
- #ifndef AUTHORIZE
- init_execute();
- #endif
- init_macro();
-
- nnspew:
-
- open_master(OPEN_READ);
-
- switch (who_am_i) {
-
- case I_AM_NN:
- init_term();
-
- if (say_welcome) {
- display_file("adm.welcome", CLEAR_DISPLAY | CONFIRMATION);
- clrdisp();
- }
-
- visit_init_file(0, argv[1]);
-
- group_name_args =
- parse_options(argc, argv, (char *)NULL, nn_options,
- " [group | [+]folder]...");
-
- if (also_read_articles) {
- if (article_limit < 0)
- article_limit = also_read_articles;
- do_kill_handling = 0;
- no_update++;
- }
-
- if (match_subject) {
- mask = match_subject;
- access_mode = ACC_ON_SUBJECT;
- } else if (match_sender) {
- mask = match_sender;
- access_mode = ACC_ON_SENDER;
- } else {
- mask = NULL;
- access_mode = 0;
- }
-
- if (mask) {
- if (case_fold_search) fold_string(mask);
- no_update++;
- do_kill_handling = 0;
- }
-
- if (nngrab_mode) {
- seq_cross_filtering = 1;
- hex_group_args = 1;
- no_update = 1;
- }
-
- if (merged_menu) {
- no_update++;
- }
-
- if (!no_update && group_name_args > 0)
- no_update = only_folder_args(argv + 1);
-
- break;
-
- case I_AM_ADMIN:
- if (argc == 1) {
- init_term();
- visit_init_file(0, (char *)NULL);
- }
- admin_mode(argv[1]);
- nn_exit(0);
-
- case I_AM_CHECK:
- visit_init_file(1, (char *)NULL);
- group_name_args =
- parse_options(argc, argv, (char *)NULL, check_options,
- " [group]...");
- break;
-
- case I_AM_EMACS:
- silent = 1;
- break;
-
- case I_AM_TIDY:
- visit_init_file(1, (char *)NULL);
- group_name_args = opt_nntidy(argc, argv);
- break;
-
- case I_AM_GOBACK:
- group_name_args = opt_nngoback(argc, &argv);
- break;
-
- case I_AM_GREP:
- visit_init_file(1, (char *)NULL);
- opt_nngrep(argc, argv);
- silent = 1;
- break;
-
- case I_AM_POST:
- do_nnpost(argc, argv);
- nn_exit(0);
-
- case I_AM_SPEW:
- if (proto_lock(I_AM_SPEW, PL_SET) == 0) {
- cmd = do_nnspew();
- proto_lock(I_AM_SPEW, PL_CLEAR);
- } else
- cmd = 1; /* don't interfere with other nnspew */
- nn_exit(cmd);
- }
-
- if (!silent || who_am_i == I_AM_CHECK)
- printf("Release %s, Kim F. Storm, 1990\n\n", version_id);
-
- if (nn_locked()) nn_exit(2);
-
- visit_rc_file();
-
- if (group_name_args > 0)
- named_group_sequence(argv + 1);
- else
- normal_group_sequence();
-
- if (who_am_i != I_AM_TIDY && who_am_i != I_AM_GOBACK)
- count_unread_articles();
-
- switch (who_am_i) {
-
- case I_AM_EMACS:
- prt_unread("%U %G\n");
- emacs_mode();
- break;
-
- case I_AM_CHECK:
- if (report_number_of_articles) {
- prt_unread("%U");
- break;
- }
-
- if (check_message_format) {
- if (unread_articles || !silent)
- prt_unread(check_message_format);
- } else
- if (!silent) {
- if (unread_articles || report_number_of_articles)
- prt_unread("There %i %u in %g\n");
- else
- prt_unread((char *)NULL);
- }
-
- nn_exit( unread_articles ? 0 : 99 );
- /*NOTREACHED*/
-
- case I_AM_TIDY:
- do_tidy_newsrc();
- break;
-
- case I_AM_GOBACK:
- do_goback();
- break;
-
- case I_AM_NN:
- if (unread_articles == 0 &&
- group_name_args == 0 &&
- !also_read_articles &&
- !prompt_for_group) {
- if (!silent) prt_unread((char *)NULL);
- break;
- }
-
- if (do_kill_handling)
- do_kill_handling = init_kill();
-
- if (prompt_for_group) {
- import int also_cross_postings;
-
- if (mask != NULL)
- user_error("Cannot use -s/-n with -g\n\r");
-
- also_cross_postings = 1;
- do {
- raw();
- clrdisp();
- current_group = NULL;
- prompt_line = 2;
- cmd = goto_group(K_GOTO_GROUP, (article_header *)NULL, setup_access());
-
- } while (repeat_group_query && cmd != ME_QUIT && cmd != ME_NO_REDRAW);
- clrdisp();
- unset_raw();
- break;
- }
-
- if (!no_update && article_limit == 0) {
- catch_up();
- break;
- }
-
- if (merged_menu) {
- merge_and_read(access_mode | setup_access(), mask);
- clrdisp();
- break;
- }
-
- if (read_news(access_mode, mask)) {
- clrdisp();
-
- if (master.db_lock[0])
- printf("Database has been locked:\n%s\n", master.db_lock);
-
- if (!also_read_articles &&
- unread_articles > 0 &&
- !silent && group_name_args == 0)
- prt_unread("There %i still %u in %g\n\n\r");
- break;
- }
- gotoxy(0,Lines-1);
- if (group_name_args == 0)
- printf("No News\n");
- else
- printf("\r\n");
- break;
-
- case I_AM_GREP:
- do_grep(argv+1);
- break;
- }
-
- nn_exit(0);
- /*NOTREACHED*/
- }
-
- /*
- * nn_exit() --- called whenever a program exits.
- */
-
- nn_exit(n)
- {
- static int loop = 0;
-
- if (loop) exit(n);
- loop++;
-
- visual_off();
-
- #ifdef NNTP
- nntp_cleanup();
- #endif /* NNTP */
- close_master();
- flush_newsrc();
-
- if (who_am_i == I_AM_NN)
- log_usage();
-
- if (must_unlock)
- proto_lock(I_AM_NN, PL_CLEAR);
-
- exit(n);
- }
-