home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * Read presentation sequence file
- */
-
- #include "config.h"
- #include "debug.h"
-
- export group_header *group_sequence;
- export char *read_mail = NULL;
- export int also_subgroups = 1;
- export int hex_group_args = 0;
-
- static int seq_break_enabled = 1; /* !! enabled */
- static int ignore_done_flag = 0; /* % toggle */
-
- static group_header *tail_sequence = NULL;
- static group_header *final_sequence = NULL;
-
- static int gs_more_groups;
-
-
- only_folder_args(args)
- char **args;
- {
- register char *arg;
-
- while (arg = *args++) {
- if (*arg == '+' || *arg == '~' || *arg == '/') continue;
- if (file_exist(arg, "fr")) continue;
- return 0;
- }
- return 1;
- }
-
-
- #define SHOW_NORMAL 0 /* : put this in at current pos */
- #define SHOW_FIRST 1 /* < : show these groups first */
- #define SHOW_LAST 2 /* > : show this as late as possible */
- #define IGNORE_ALWAYS 3 /* ! : ignore these groups completely */
- #define IGN_UNLESS_RC 4 /* !:X ignore these groups unless in rc */
- #define IGN_UNLESS_NEW 5 /* !:O ignore these groups unless new */
- #define IGN_UNL_RC_NEW 6 /* !:U ignore unsubscribed */
- #define IGN_IF_NEW 7 /* !:N ignore these groups if new */
-
- #define SHOW_MODES " <>!-?*"
-
- static enter_sequence(mode, gh)
- int mode;
- group_header *gh;
- {
- #ifdef SEQ_TEST
- if (Debug & SEQ_TEST && mode != SHOW_NORMAL)
- printf("SEQ(%c), %s\n", SHOW_MODES[mode], gh->group_name);
- #endif
-
- if (gh->master_flag & M_IGNORE_GROUP) return 0;
- if (ignore_done_flag) {
- if (gh->group_flag & G_SEQUENCE) return 0;
- } else
- if (gh->group_flag & G_DONE) return 0;
-
- switch (mode) {
- case IGN_UNLESS_NEW:
- if ((gh->group_flag & G_NEW) == 0)
- gh->group_flag |= G_DONE;
- return 0;
-
- case IGN_IF_NEW:
- if (gh->group_flag & G_NEW)
- gh->group_flag |= G_DONE;
- return 0;
-
- case IGN_UNL_RC_NEW:
- if (gh->group_flag & G_NEW) return 0;
- if (gh->newsrc_line == NULL || (gh->group_flag & G_UNSUBSCRIBED))
- gh->group_flag |= G_DONE;
- return 0;
-
- case IGN_UNLESS_RC:
- if (gh->newsrc_line == NULL || (gh->group_flag & (G_UNSUBSCRIBED|G_NEW)))
- gh->group_flag |= G_DONE;
- return 0;
-
- case IGNORE_ALWAYS:
- gh->group_flag |= G_DONE;
- return 0;
-
- default:
- gh->group_flag |= G_DONE;
- break;
- }
-
- gh->group_flag |= G_SEQUENCE;
-
- if (gh->master_flag & M_NO_DIRECTORY)
- return 0; /* for nntidy -s */
-
- switch (mode) {
- case SHOW_FIRST:
- if (tail_sequence) {
- gh->next_group = group_sequence;
- group_sequence = gh;
- break;
- }
- /* fall thru */
-
- case SHOW_NORMAL:
- if (tail_sequence)
- tail_sequence->next_group = gh;
- else
- group_sequence = gh;
- tail_sequence = gh;
- break;
-
- case SHOW_LAST:
- gh->next_group = final_sequence;
- final_sequence = gh;
- break;
- }
- return 1;
- }
-
-
- static faked_entry(name, flag)
- char *name;
- flag_type flag;
- {
- group_header *gh;
-
- gh = newobj(group_header, 1);
-
- gh->group_name = name;
- gh->group_flag = flag | G_FAKED;
- gh->master_flag = 0;
-
- /* "invent" an unread article for read_news */
- gh->last_article = 1;
- gh->last_db_article = 2;
-
- enter_sequence(SHOW_NORMAL, gh);
- }
-
- static end_sequence()
- {
- register group_header *gh, *backp;
- register int seq_ix;
-
- if (tail_sequence)
- tail_sequence->next_group = NULL;
-
- /* set up backward pointers */
-
- backp = NULL;
- seq_ix = 0;
- Loop_Groups_Sequence(gh) {
- gh->preseq_index = (gh->group_flag & G_UNSUBSCRIBED) ? 0 : ++seq_ix;
- gh->prev_group = backp;
- backp = gh;
- }
-
- #ifdef SEQ_DUMP
- if (Debug & SEQ_DUMP) {
- for (gh = group_sequence; gh; gh = gh->next_group)
- printf("%s\t", gh->group_name);
- putchar(NL);
-
- nn_exit(0);
- }
- #endif
-
- }
-
-
- #ifdef MAIL_READING
- static mail_check()
- {
- static group_header mail_group;
- struct stat st;
-
- if (read_mail == NULL) return;
- if (stat(read_mail, &st) < 0) return;
- if (st.st_size == 0 || st.st_mtime < st.st_atime) return;
-
- mail_group.group_name = read_mail;
- gh->group_flag = G_FOLDER | G_MAILBOX | G_FAKED;
- gh->master_flag = 0;
-
- /* "invent" an unread article for read_news */
- gh->last_article = 1;
- gh->last_db_article = 2;
-
-
- if (tail_sequence) {
- mail_group.next_group = group_sequence;
- group_sequence = mail_group;
- } else
- enter_sequence(SHOW_NORMAL, &mail_group);
- }
- #endif
-
-
-
- static visit_presentation_file(directory, seqfile, hook)
- char *directory, *seqfile;
- FILE *hook;
- {
- import int group_name_args;
-
- register FILE *sf;
- register c;
- register group_header *gh;
- group_header *mp_group, *get_group_search();
- char group[FILENAME], *gname;
- char savefile[FILENAME], *dflt_save, *enter_macro;
- extern char *parse_enter_macro();
- register char *gp;
- int mode, merge_groups;
-
- if (gs_more_groups == 0) return 0;
-
- if (hook != NULL)
- sf = hook; /* hook to init file */
- else
- if ((sf = open_file(relative(directory, seqfile), OPEN_READ)) == NULL)
- return 0;
-
- #ifdef SEQ_TEST
- if (Debug & SEQ_TEST)
- printf("Sequence file %s/%s\n", directory, seqfile);
- #endif
-
- mode = SHOW_NORMAL;
- savefile[0] = NUL;
-
- while (gs_more_groups) {
-
- if ((c = getc(sf)) == EOF) break;
- if (!isascii(c) || isspace(c)) continue;
-
- switch (c) {
- case '!':
- mode = IGNORE_ALWAYS;
- if ((c = getc(sf)) == EOF) continue;
- if (c == '!') {
- if (seq_break_enabled) {
- fclose(sf);
- return 1;
- }
- mode = SHOW_NORMAL;
- continue;
- }
- if (c == ':') {
- if ((c = getc(sf)) == EOF) continue;
- if (!isascii(c) || isspace(c) || !isupper(c)) continue;
- switch (c) {
- case 'O':
- mode = IGN_UNLESS_NEW;
- continue;
- case 'N':
- mode = IGN_IF_NEW;
- continue;
- case 'U':
- mode = IGN_UNL_RC_NEW;
- continue;
- case 'X':
- mode = IGN_UNLESS_RC;
- continue;
- default:
- /*should give error here*/
- mode = SHOW_NORMAL;
- continue;
- }
- }
- ungetc(c, sf);
- continue;
-
- case '<':
- mode = SHOW_FIRST;
- continue;
-
- case '>':
- mode = SHOW_LAST;
- continue;
-
- case '%':
- ignore_done_flag = ! ignore_done_flag;
- continue;
-
- case '@':
- seq_break_enabled = 0;
- mode = SHOW_NORMAL;
- continue;
-
- case '#':
- do c = getc(sf);
- while (c != EOF && c != NL);
- mode = SHOW_NORMAL;
- continue;
-
- }
-
- gp = group;
- merge_groups = 0;
- do {
- *gp++ = c;
- if (c == ',') merge_groups = 1;
- c = getc(sf);
- } while (c != EOF && isascii(c) && !isspace(c));
-
- *gp = NUL;
-
- while (c != EOF && (!isascii(c) || isspace(c))) c = getc(sf);
- if (c == '+' || c == '~' || c == '/') {
- gp = savefile;
- if (c == '+') {
- c = getc(sf);
- if (c == EOF || (isascii(c) && isspace(c)))
- goto use_same_savefile;
- *gp++ = '+';
- }
- do {
- *gp++ = c;
- c = getc(sf);
- } while (c != EOF && isascii(c) && !isspace(c));
- *gp = NUL;
- dflt_save = savefile[0] ? copy_str(savefile) : NULL;
- } else
- dflt_save = NULL;
-
- use_same_savefile:
- while (c != EOF && (!isascii(c) || isspace(c))) c = getc(sf);
- if (c == '(') {
- enter_macro = parse_enter_macro(sf, getc(sf));
- } else {
- enter_macro = NULL;
- if (c != EOF) ungetc(c, sf);
- }
-
- mp_group = NULL;
- for (gp = group; *gp;) {
- gname = gp;
- if (merge_groups) {
- while (*gp && *gp != ',') gp++;
- if (*gp) *gp++ = NUL;
- }
- start_group_search(gname);
-
- while (gh = get_group_search()) {
- if (!enter_sequence(mode, gh)) continue;
-
- if (merge_groups && (gh->group_flag & G_UNSUBSCRIBED) == 0) {
- if (mp_group == NULL) {
- gh->group_flag |= G_MERGE_HEAD;
- } else {
- mp_group->merge_with = gh;
- gh->group_flag |= G_MERGE_SUB;
- }
- mp_group = gh;
- }
-
- if (gh->save_file == NULL) /* not set by "save-files" */
- gh->save_file = dflt_save;
- if (gh->enter_macro == NULL) /* not set by "on entry" */
- gh->enter_macro = enter_macro;
- }
- if (!merge_groups) *gp = NUL;
- }
- if (merge_groups && mp_group != NULL)
- mp_group->merge_with = NULL;
- mode = SHOW_NORMAL;
- }
-
- fclose(sf);
- return 0;
- }
-
- parse_save_files(sf)
- register FILE *sf;
- {
- register c;
- register group_header *gh;
- group_header *get_group_search();
- char group[FILENAME];
- char *savefile = NULL;
- char namebuf[FILENAME];
- register char *gp;
-
- for (;;) {
- if ((c = getc(sf)) == EOF) break;
- if (!isascii(c) || isspace(c)) continue;
- if (c == '#') {
- do c = getc(sf); while (c != EOF && c != NL);
- continue;
- }
- gp = group;
- do {
- *gp++ = c;
- c = getc(sf);
- } while (c != EOF && isascii(c) && !isspace(c));
- *gp = NUL;
-
- if (strcmp(group, "end") == 0) break;
-
- while (c != EOF && (!isascii(c) || isspace(c))) c = getc(sf);
-
- gp = namebuf;
- do {
- *gp++ = c;
- c = getc(sf);
- } while (c != EOF && isascii(c) && !isspace(c));
- *gp = NUL;
- if (namebuf[0] == NUL) break;
- if (strcmp(namebuf, "+"))
- savefile = copy_str(namebuf);
-
- start_group_search(group);
-
- while (gh = get_group_search())
- gh->save_file = savefile;
- }
- }
-
- named_group_sequence(groups)
- char **groups;
- {
- register group_header *gh;
- group_header *get_group_search();
- register char *group;
- int found, any, errors, gnum;
-
- group_sequence = NULL;
- also_subgroups = 0;
-
- any = errors = 0;
- while (group = *groups++) {
-
- if (hex_group_args) {
- sscanf(group, "%x", &gnum);
- if (gnum < 0 || gnum >= master.number_of_groups) continue;
- gh = &active_groups[gnum];
- if (enter_sequence(SHOW_NORMAL, gh)) any++;
- continue;
- }
-
- if (gh = lookup(group)) {
- if (enter_sequence(SHOW_NORMAL, gh)) any++;
- continue;
- }
-
- if (file_exist(group, "fr")) {
- faked_entry(group, G_FOLDER);
- any++;
- continue;
- }
-
- if (*group == '+' || *group == '~') {
- char exp_file[FILENAME];
- group_header fake_group;
-
- current_group = &fake_group;
- fake_group.group_name = group;
- group_file_name = NULL;
- if (expand_file_name(exp_file, group, 1) && file_exist(exp_file, "fr")) {
- faked_entry(copy_str(exp_file), G_FOLDER);
- any++;
- continue;
- }
-
- printf("Folder %s not found\n", group); fl;
- errors++;
- continue;
- }
-
- found = 0;
- start_group_search(group);
- while (gh = get_group_search()) {
- found++;
- enter_sequence(SHOW_NORMAL, gh);
- }
-
- if (!found) {
- printf("Group %s not found\n", group); fl;
- errors++;
- } else
- any++;
- }
-
- end_sequence();
-
- if (errors) user_delay(2);
-
- return any;
- }
-
- FILE *loc_seq_hook = NULL; /* sequence in local "init" file */
- FILE *glob_seq_hook = NULL; /* sequence in global "init" file */
-
- normal_group_sequence()
- {
- register group_header *gh;
-
- group_sequence = NULL;
- gs_more_groups = 1;
-
- /* visit_p_f returns non-zero if terminated by !! */
-
- if (visit_presentation_file(nn_directory, "seq", loc_seq_hook))
- goto final;
-
- if (visit_presentation_file(lib_directory, "sequence", glob_seq_hook))
- goto final;
-
- Loop_Groups_Sorted(gh) {
- enter_sequence(SHOW_NORMAL, gh);
- }
-
- final:
- if (final_sequence)
- if (tail_sequence) {
- tail_sequence->next_group = final_sequence;
- tail_sequence = NULL;
- } else
- group_sequence = final_sequence;
-
- #ifdef MAIL_READING
- mail_check();
- #endif
-
- end_sequence();
- }
-
-
-
- static char *gs_group;
- static int gs_length, gs_index, gs_mode;
- static group_header *gs_only_group = NULL;
-
- #define GS_PREFIX0 0 /* group (or group*) */
- #define GS_PREFIX 1 /* group. */
- #define GS_SUFFIX 2 /* .group */
- #define GS_INFIX 3 /* .group. */
- #define GS_NEW_GROUP 4 /* new group */
- #define GS_ALL 5 /* all / . */
- #define GS_NEWSRC 6 /* RC */
-
- start_group_search(group)
- char *group;
- {
- char *dot;
- int last;
- import group_header *rc_sequence;
-
- gs_index = master.number_of_groups; /* loop will fail */
-
- if ((last = strlen(group) - 1) < 0) return;
- if (group[last] == '*')
- group[last] = NUL;
- else
- if (!also_subgroups && (gs_only_group = lookup(group)) != NULL)
- return;
-
- gs_index = 0;
- gs_more_groups = 0;
- gs_length = 0;
- gs_group = NULL;
-
- if (strcmp(group, "NEW") == 0) {
- gs_mode = GS_NEW_GROUP;
- return;
- }
-
- if (strncmp(group, "RC", 2) == 0) {
- gs_mode = GS_NEWSRC;
- gs_only_group = rc_sequence;
- gs_more_groups = 1; /* we just can't know! */
-
- if (group[2] != ':') return;
- if (isdigit(group[3]))
- gs_index = atoi(group+3);
- else {
- gs_group = group+3;
- gs_length = strlen(gs_group);
- }
- return;
- }
-
- if (strcmp(group, "all") == 0 || strcmp(group, ".") == 0) {
- gs_mode = GS_ALL;
- return;
- }
-
- gs_mode = GS_PREFIX0;
-
- if (strncmp(group, "all.", 4) == 0) group += 3;
-
- if (*group == '.') gs_mode = GS_SUFFIX;
-
- if ((dot = strrchr(group, '.')) != NULL && dot != group) {
- if (dot[1] == NUL || strcmp(dot+1, "all") == 0) {
- dot[1] = NUL;
- gs_mode = (gs_mode == GS_SUFFIX) ? GS_INFIX : GS_PREFIX;
- }
- }
-
- gs_length = strlen(group);
- gs_group = group;
- }
-
- group_header *get_group_search()
- {
- register group_header *gh;
- register int c, tail;
-
- if (gs_mode == GS_NEWSRC) {
- do {
- gh = gs_only_group;
- if (gh == NULL) return NULL;
- if (gs_index && --gs_index == 0) {
- gs_only_group = NULL;
- } else
- if (gs_group && gh->group_name_length >= gs_length &&
- strncmp(gh->group_name, gs_group, gs_length) == 0) {
- gs_only_group = NULL;
- } else
- gs_only_group = gh->newsrc_seq;
- } while ((!ignore_done_flag && (gh->group_flag & G_DONE)) ||
- (gh->master_flag & M_IGNORE_GROUP));
- return gh;
- }
-
- if (gs_only_group != NULL) {
- gh = gs_only_group;
- gs_only_group = NULL;
- if (!ignore_done_flag && gh->group_flag & G_DONE) return NULL;
- if (gh->master_flag & M_IGNORE_GROUP) return NULL;
- return gh;
- }
-
- while (gs_index < master.number_of_groups) {
- gh = sorted_groups[gs_index++];
- if (!ignore_done_flag && gh->group_flag & G_DONE) continue;
- if (gh->master_flag & M_IGNORE_GROUP) continue;
-
- gs_more_groups++;
-
- if ((tail = gh->group_name_length - gs_length) < 0) continue;
-
- switch (gs_mode) {
-
- case GS_NEW_GROUP:
- if ((gh->group_flag & G_NEW) == 0) continue;
- break;
-
- case GS_PREFIX0:
- if ((c = (gh->group_name)[gs_length]) != NUL && c != '.') continue;
- case GS_PREFIX:
- if (strncmp(gh->group_name, gs_group, gs_length)) continue;
- break;
-
- case GS_SUFFIX:
- if (strcmp(gh->group_name + tail, gs_group)) continue;
- break;
-
- case GS_INFIX:
- user_error(".name. notation not supported (yet)");
- break;
-
- case GS_ALL:
- break;
- }
-
- gs_more_groups--;
- return gh;
- }
-
- return NULL;
- }
-