home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / nn6.4 / part05 / sequence.c < prev   
Encoding:
C/C++ Source or Header  |  1990-06-07  |  14.1 KB  |  680 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Read presentation sequence file
  5.  */
  6.  
  7. #include "config.h"
  8. #include "debug.h"
  9.  
  10. export group_header *group_sequence;
  11. export char *read_mail = NULL;
  12. export int also_subgroups = 1;
  13. export int hex_group_args = 0;
  14.  
  15. static int seq_break_enabled = 1;    /* !! enabled */
  16. static int ignore_done_flag = 0;     /* % toggle */
  17.  
  18. static group_header *tail_sequence = NULL;
  19. static group_header *final_sequence = NULL;
  20.  
  21. static int gs_more_groups;
  22.  
  23.  
  24. only_folder_args(args)
  25. char **args;
  26. {
  27.     register char *arg;
  28.  
  29.     while (arg = *args++) {
  30.     if (*arg == '+' || *arg == '~' || *arg == '/') continue;
  31.     if (file_exist(arg, "fr")) continue;
  32.     return 0;
  33.     }
  34.     return 1;
  35. }
  36.  
  37.  
  38. #define    SHOW_NORMAL    0    /*   : put this in at current pos */
  39. #define    SHOW_FIRST    1    /* < : show these groups first */
  40. #define    SHOW_LAST    2    /* > : show this as late as possible */
  41. #define    IGNORE_ALWAYS    3    /* ! : ignore these groups completely */
  42. #define IGN_UNLESS_RC    4    /* !:X ignore these groups unless in rc */
  43. #define    IGN_UNLESS_NEW    5    /* !:O ignore these groups unless new */
  44. #define IGN_UNL_RC_NEW    6    /* !:U ignore unsubscribed */
  45. #define    IGN_IF_NEW    7    /* !:N ignore these groups if new */
  46.  
  47. #define    SHOW_MODES    " <>!-?*"
  48.  
  49. static enter_sequence(mode, gh)
  50. int mode;
  51. group_header *gh;
  52. {
  53. #ifdef SEQ_TEST
  54.     if (Debug & SEQ_TEST && mode != SHOW_NORMAL)
  55.     printf("SEQ(%c), %s\n", SHOW_MODES[mode], gh->group_name);
  56. #endif
  57.  
  58.     if (gh->master_flag & M_IGNORE_GROUP) return 0;
  59.     if (ignore_done_flag) {
  60.     if (gh->group_flag & G_SEQUENCE) return 0;
  61.     } else
  62.     if (gh->group_flag & G_DONE) return 0;
  63.  
  64.     switch (mode) {
  65.      case IGN_UNLESS_NEW:
  66.     if ((gh->group_flag & G_NEW) == 0)
  67.         gh->group_flag |= G_DONE;
  68.     return 0;
  69.  
  70.      case IGN_IF_NEW:
  71.     if (gh->group_flag & G_NEW)
  72.         gh->group_flag |= G_DONE;
  73.     return 0;
  74.  
  75.      case IGN_UNL_RC_NEW:
  76.     if (gh->group_flag & G_NEW) return 0;
  77.         if (gh->newsrc_line == NULL || (gh->group_flag & G_UNSUBSCRIBED))
  78.         gh->group_flag |= G_DONE;
  79.     return 0;
  80.  
  81.      case IGN_UNLESS_RC:
  82.         if (gh->newsrc_line == NULL || (gh->group_flag & (G_UNSUBSCRIBED|G_NEW)))
  83.         gh->group_flag |= G_DONE;
  84.     return 0;
  85.  
  86.      case IGNORE_ALWAYS:
  87.     gh->group_flag |= G_DONE;
  88.     return 0;
  89.  
  90.      default:
  91.     gh->group_flag |= G_DONE;
  92.     break;
  93.     }
  94.  
  95.     gh->group_flag |= G_SEQUENCE;
  96.  
  97.     if (gh->master_flag & M_NO_DIRECTORY)
  98.     return 0;        /* for nntidy -s */
  99.  
  100.     switch (mode) {
  101.      case SHOW_FIRST:
  102.     if (tail_sequence) {
  103.         gh->next_group = group_sequence;
  104.         group_sequence = gh;
  105.         break;
  106.     }
  107.     /* fall thru */
  108.  
  109.      case SHOW_NORMAL:
  110.     if (tail_sequence)
  111.         tail_sequence->next_group = gh;
  112.     else
  113.         group_sequence = gh;
  114.     tail_sequence = gh;
  115.     break;
  116.  
  117.      case SHOW_LAST:
  118.     gh->next_group = final_sequence;
  119.     final_sequence = gh;
  120.     break;
  121.     }
  122.     return 1;
  123. }
  124.  
  125.  
  126. static faked_entry(name, flag)
  127. char *name;
  128. flag_type flag;
  129. {
  130.     group_header *gh;
  131.  
  132.     gh = newobj(group_header, 1);
  133.  
  134.     gh->group_name = name;
  135.     gh->group_flag = flag | G_FAKED;
  136.     gh->master_flag = 0;
  137.  
  138.     /* "invent" an unread article for read_news */
  139.     gh->last_article = 1;
  140.     gh->last_db_article = 2;
  141.  
  142.     enter_sequence(SHOW_NORMAL, gh);
  143. }
  144.  
  145. static end_sequence()
  146. {
  147.     register group_header *gh, *backp;
  148.     register int seq_ix;
  149.  
  150.     if (tail_sequence)
  151.     tail_sequence->next_group = NULL;
  152.  
  153.     /* set up backward pointers */
  154.  
  155.     backp = NULL;
  156.     seq_ix = 0;
  157.     Loop_Groups_Sequence(gh) {
  158.     gh->preseq_index = (gh->group_flag & G_UNSUBSCRIBED) ? 0 : ++seq_ix;
  159.     gh->prev_group = backp;
  160.     backp = gh;
  161.     }
  162.  
  163. #ifdef SEQ_DUMP
  164.     if (Debug & SEQ_DUMP) {
  165.     for (gh = group_sequence; gh; gh = gh->next_group)
  166.         printf("%s\t", gh->group_name);
  167.     putchar(NL);
  168.  
  169.     nn_exit(0);
  170.     }
  171. #endif
  172.  
  173. }
  174.  
  175.  
  176. #ifdef MAIL_READING
  177. static mail_check()
  178. {
  179.     static group_header mail_group;
  180.     struct stat st;
  181.  
  182.     if (read_mail == NULL) return;
  183.     if (stat(read_mail, &st) < 0) return;
  184.     if (st.st_size == 0 || st.st_mtime < st.st_atime) return;
  185.  
  186.     mail_group.group_name = read_mail;
  187.     gh->group_flag = G_FOLDER | G_MAILBOX | G_FAKED;
  188.     gh->master_flag = 0;
  189.  
  190.     /* "invent" an unread article for read_news */
  191.     gh->last_article = 1;
  192.     gh->last_db_article = 2;
  193.  
  194.  
  195.     if (tail_sequence) {
  196.     mail_group.next_group = group_sequence;
  197.     group_sequence = mail_group;
  198.     } else
  199.     enter_sequence(SHOW_NORMAL, &mail_group);
  200. }
  201. #endif
  202.  
  203.  
  204.  
  205. static visit_presentation_file(directory, seqfile, hook)
  206. char *directory, *seqfile;
  207. FILE *hook;
  208. {
  209.     import int group_name_args;
  210.  
  211.     register FILE *sf;
  212.     register c;
  213.     register group_header *gh;
  214.     group_header *mp_group, *get_group_search();
  215.     char group[FILENAME], *gname;
  216.     char savefile[FILENAME], *dflt_save, *enter_macro;
  217.     extern char *parse_enter_macro();
  218.     register char *gp;
  219.     int mode, merge_groups;
  220.  
  221.     if (gs_more_groups == 0) return 0;
  222.  
  223.     if (hook != NULL)
  224.     sf = hook;    /* hook to init file */
  225.     else
  226.     if ((sf = open_file(relative(directory, seqfile), OPEN_READ)) == NULL)
  227.         return 0;
  228.  
  229. #ifdef SEQ_TEST
  230.     if (Debug & SEQ_TEST)
  231.     printf("Sequence file %s/%s\n", directory, seqfile);
  232. #endif
  233.  
  234.     mode = SHOW_NORMAL;
  235.     savefile[0] = NUL;
  236.  
  237.     while (gs_more_groups) {
  238.  
  239.     if ((c = getc(sf)) == EOF) break;
  240.     if (!isascii(c) || isspace(c)) continue;
  241.  
  242.     switch (c) {
  243.      case '!':
  244.         mode = IGNORE_ALWAYS;
  245.         if ((c = getc(sf)) == EOF) continue;
  246.         if (c == '!') {
  247.         if (seq_break_enabled) {
  248.             fclose(sf);
  249.             return 1;
  250.         }
  251.         mode = SHOW_NORMAL;
  252.         continue;
  253.         }
  254.         if (c == ':') {
  255.         if ((c = getc(sf)) == EOF) continue;
  256.         if (!isascii(c) || isspace(c) || !isupper(c)) continue;
  257.         switch (c) {
  258.          case 'O':
  259.             mode = IGN_UNLESS_NEW;
  260.             continue;
  261.          case 'N':
  262.             mode = IGN_IF_NEW;
  263.             continue;
  264.          case 'U':
  265.             mode = IGN_UNL_RC_NEW;
  266.             continue;
  267.          case 'X':
  268.             mode = IGN_UNLESS_RC;
  269.             continue;
  270.          default:
  271.             /*should give error here*/
  272.             mode = SHOW_NORMAL;
  273.             continue;
  274.         }
  275.         }
  276.         ungetc(c, sf);
  277.         continue;
  278.  
  279.      case '<':
  280.         mode = SHOW_FIRST;
  281.         continue;
  282.  
  283.      case '>':
  284.         mode = SHOW_LAST;
  285.         continue;
  286.  
  287.      case '%':
  288.         ignore_done_flag = ! ignore_done_flag;
  289.         continue;
  290.  
  291.      case '@':
  292.         seq_break_enabled = 0;
  293.         mode = SHOW_NORMAL;
  294.         continue;
  295.  
  296.      case '#':
  297.         do c = getc(sf);
  298.         while (c != EOF && c != NL);
  299.         mode = SHOW_NORMAL;
  300.         continue;
  301.  
  302.     }
  303.  
  304.     gp = group;
  305.     merge_groups = 0;
  306.     do {
  307.         *gp++ = c;
  308.         if (c == ',') merge_groups = 1;
  309.         c = getc(sf);
  310.     } while (c != EOF && isascii(c) && !isspace(c));
  311.  
  312.     *gp = NUL;
  313.  
  314.     while (c != EOF && (!isascii(c) || isspace(c))) c = getc(sf);
  315.     if (c == '+' || c == '~' || c == '/') {
  316.         gp = savefile;
  317.         if (c == '+') {
  318.         c = getc(sf);
  319.         if (c == EOF || (isascii(c) && isspace(c)))
  320.             goto use_same_savefile;
  321.         *gp++ = '+';
  322.         }
  323.         do {
  324.         *gp++ = c;
  325.         c = getc(sf);
  326.         } while (c != EOF && isascii(c) && !isspace(c));
  327.         *gp = NUL;
  328.         dflt_save = savefile[0] ? copy_str(savefile) : NULL;
  329.     } else
  330.         dflt_save = NULL;
  331.  
  332.      use_same_savefile:
  333.     while (c != EOF && (!isascii(c) || isspace(c))) c = getc(sf);
  334.     if (c == '(') {
  335.         enter_macro = parse_enter_macro(sf, getc(sf));
  336.     } else {
  337.         enter_macro = NULL;
  338.         if (c != EOF) ungetc(c, sf);
  339.     }
  340.  
  341.     mp_group = NULL;
  342.     for (gp = group; *gp;) {
  343.         gname = gp;
  344.         if (merge_groups) {
  345.         while (*gp && *gp != ',') gp++;
  346.         if (*gp) *gp++ = NUL;
  347.         }
  348.         start_group_search(gname);
  349.  
  350.         while (gh = get_group_search()) {
  351.         if (!enter_sequence(mode, gh)) continue;
  352.  
  353.         if (merge_groups && (gh->group_flag & G_UNSUBSCRIBED) == 0) {
  354.             if (mp_group == NULL) {
  355.             gh->group_flag |= G_MERGE_HEAD;
  356.             } else {
  357.             mp_group->merge_with = gh;
  358.             gh->group_flag |= G_MERGE_SUB;
  359.             }
  360.             mp_group = gh;
  361.         }
  362.  
  363.         if (gh->save_file == NULL) /* not set by "save-files" */
  364.             gh->save_file = dflt_save;
  365.         if (gh->enter_macro == NULL) /* not set by "on entry" */
  366.             gh->enter_macro = enter_macro;
  367.         }
  368.         if (!merge_groups) *gp = NUL;
  369.     }
  370.     if (merge_groups && mp_group != NULL)
  371.         mp_group->merge_with = NULL;
  372.     mode = SHOW_NORMAL;
  373.     }
  374.  
  375.     fclose(sf);
  376.     return 0;
  377. }
  378.  
  379. parse_save_files(sf)
  380. register FILE *sf;
  381. {
  382.     register c;
  383.     register group_header *gh;
  384.     group_header *get_group_search();
  385.     char group[FILENAME];
  386.     char *savefile = NULL;
  387.     char namebuf[FILENAME];
  388.     register char *gp;
  389.  
  390.     for (;;) {
  391.     if ((c = getc(sf)) == EOF) break;
  392.     if (!isascii(c) || isspace(c)) continue;
  393.     if (c == '#') {
  394.         do c = getc(sf); while (c != EOF && c != NL);
  395.         continue;
  396.     }
  397.     gp = group;
  398.     do {
  399.         *gp++ = c;
  400.         c = getc(sf);
  401.     } while (c != EOF && isascii(c) && !isspace(c));
  402.     *gp = NUL;
  403.  
  404.     if (strcmp(group, "end") == 0) break;
  405.  
  406.     while (c != EOF && (!isascii(c) || isspace(c))) c = getc(sf);
  407.  
  408.     gp = namebuf;
  409.     do {
  410.         *gp++ = c;
  411.         c = getc(sf);
  412.     } while (c != EOF && isascii(c) && !isspace(c));
  413.     *gp = NUL;
  414.     if (namebuf[0] == NUL) break;
  415.     if (strcmp(namebuf, "+"))
  416.         savefile = copy_str(namebuf);
  417.  
  418.     start_group_search(group);
  419.  
  420.     while (gh = get_group_search())
  421.         gh->save_file = savefile;
  422.     }
  423. }
  424.  
  425. named_group_sequence(groups)
  426. char **groups;
  427. {
  428.     register group_header *gh;
  429.     group_header *get_group_search();
  430.     register char *group;
  431.     int found, any, errors, gnum;
  432.  
  433.     group_sequence = NULL;
  434.     also_subgroups = 0;
  435.  
  436.     any = errors = 0;
  437.     while (group = *groups++) {
  438.  
  439.     if (hex_group_args) {
  440.         sscanf(group, "%x", &gnum);
  441.         if (gnum < 0 || gnum >= master.number_of_groups) continue;
  442.         gh = &active_groups[gnum];
  443.         if (enter_sequence(SHOW_NORMAL, gh)) any++;
  444.         continue;
  445.     }
  446.  
  447.     if (gh = lookup(group)) {
  448.         if (enter_sequence(SHOW_NORMAL, gh)) any++;
  449.         continue;
  450.     }
  451.  
  452.     if (file_exist(group, "fr")) {
  453.         faked_entry(group, G_FOLDER);
  454.         any++;
  455.         continue;
  456.     }
  457.  
  458.     if (*group == '+' || *group == '~') {
  459.         char exp_file[FILENAME];
  460.         group_header fake_group;
  461.  
  462.         current_group = &fake_group;
  463.         fake_group.group_name = group;
  464.         group_file_name = NULL;
  465.         if (expand_file_name(exp_file, group, 1) && file_exist(exp_file, "fr")) {
  466.         faked_entry(copy_str(exp_file), G_FOLDER);
  467.         any++;
  468.         continue;
  469.         }
  470.  
  471.         printf("Folder %s not found\n", group); fl;
  472.         errors++;
  473.         continue;
  474.     }
  475.  
  476.     found = 0;
  477.     start_group_search(group);
  478.     while (gh = get_group_search()) {
  479.         found++;
  480.         enter_sequence(SHOW_NORMAL, gh);
  481.     }
  482.  
  483.     if (!found) {
  484.         printf("Group %s not found\n", group); fl;
  485.         errors++;
  486.     } else
  487.         any++;
  488.     }
  489.  
  490.     end_sequence();
  491.  
  492.     if (errors) user_delay(2);
  493.  
  494.     return any;
  495. }
  496.  
  497. FILE *loc_seq_hook = NULL;    /* sequence in local "init" file */
  498. FILE *glob_seq_hook = NULL;    /* sequence in global "init" file */
  499.  
  500. normal_group_sequence()
  501. {
  502.     register group_header *gh;
  503.  
  504.     group_sequence = NULL;
  505.     gs_more_groups = 1;
  506.  
  507.     /* visit_p_f returns non-zero if terminated by !! */
  508.  
  509.     if (visit_presentation_file(nn_directory, "seq", loc_seq_hook))
  510.     goto final;
  511.  
  512.     if (visit_presentation_file(lib_directory, "sequence", glob_seq_hook))
  513.     goto final;
  514.  
  515.     Loop_Groups_Sorted(gh) {
  516.     enter_sequence(SHOW_NORMAL, gh);
  517.     }
  518.  
  519.  final:
  520.     if (final_sequence)
  521.     if (tail_sequence) {
  522.         tail_sequence->next_group = final_sequence;
  523.         tail_sequence = NULL;
  524.     } else
  525.         group_sequence = final_sequence;
  526.  
  527. #ifdef MAIL_READING
  528.     mail_check();
  529. #endif
  530.  
  531.     end_sequence();
  532. }
  533.  
  534.  
  535.  
  536. static char *gs_group;
  537. static int gs_length, gs_index, gs_mode;
  538. static group_header *gs_only_group = NULL;
  539.  
  540. #define GS_PREFIX0    0    /* group (or group*) */
  541. #define    GS_PREFIX    1    /* group. */
  542. #define    GS_SUFFIX    2    /* .group */
  543. #define GS_INFIX    3    /* .group. */
  544. #define GS_NEW_GROUP    4    /* new group */
  545. #define GS_ALL        5    /* all / . */
  546. #define    GS_NEWSRC    6    /* RC */
  547.  
  548. start_group_search(group)
  549. char *group;
  550. {
  551.     char *dot;
  552.     int last;
  553.     import group_header *rc_sequence;
  554.  
  555.     gs_index = master.number_of_groups;    /* loop will fail */
  556.  
  557.     if ((last = strlen(group) - 1) < 0) return;
  558.     if (group[last] == '*')
  559.     group[last] = NUL;
  560.     else
  561.     if (!also_subgroups && (gs_only_group = lookup(group)) != NULL)
  562.         return;
  563.  
  564.     gs_index = 0;
  565.     gs_more_groups = 0;
  566.     gs_length = 0;
  567.     gs_group = NULL;
  568.  
  569.     if (strcmp(group, "NEW") == 0) {
  570.     gs_mode = GS_NEW_GROUP;
  571.     return;
  572.     }
  573.  
  574.     if (strncmp(group, "RC", 2) == 0) {
  575.     gs_mode = GS_NEWSRC;
  576.     gs_only_group = rc_sequence;
  577.     gs_more_groups = 1;    /* we just can't know! */
  578.  
  579.     if (group[2] != ':') return;
  580.     if (isdigit(group[3]))
  581.         gs_index = atoi(group+3);
  582.     else {
  583.         gs_group = group+3;
  584.         gs_length = strlen(gs_group);
  585.     }
  586.     return;
  587.     }
  588.  
  589.     if (strcmp(group, "all") == 0 || strcmp(group, ".") == 0) {
  590.     gs_mode = GS_ALL;
  591.     return;
  592.     }
  593.  
  594.     gs_mode = GS_PREFIX0;
  595.  
  596.     if (strncmp(group, "all.", 4) == 0) group += 3;
  597.  
  598.     if (*group == '.') gs_mode = GS_SUFFIX;
  599.  
  600.     if ((dot = strrchr(group, '.')) != NULL && dot != group) {
  601.     if (dot[1] == NUL || strcmp(dot+1, "all") == 0) {
  602.         dot[1] = NUL;
  603.         gs_mode = (gs_mode == GS_SUFFIX) ? GS_INFIX : GS_PREFIX;
  604.     }
  605.     }
  606.  
  607.     gs_length = strlen(group);
  608.     gs_group = group;
  609. }
  610.  
  611. group_header *get_group_search()
  612. {
  613.     register group_header *gh;
  614.     register int c, tail;
  615.  
  616.     if (gs_mode == GS_NEWSRC) {
  617.     do {
  618.         gh = gs_only_group;
  619.         if (gh == NULL) return NULL;
  620.         if (gs_index && --gs_index == 0) {
  621.         gs_only_group = NULL;
  622.         } else
  623.         if (gs_group && gh->group_name_length >= gs_length &&
  624.         strncmp(gh->group_name, gs_group, gs_length) == 0) {
  625.         gs_only_group = NULL;
  626.         } else
  627.         gs_only_group = gh->newsrc_seq;
  628.     } while ((!ignore_done_flag && (gh->group_flag & G_DONE)) ||
  629.          (gh->master_flag & M_IGNORE_GROUP));
  630.     return gh;
  631.     }
  632.  
  633.     if (gs_only_group != NULL) {
  634.     gh = gs_only_group;
  635.     gs_only_group = NULL;
  636.     if (!ignore_done_flag && gh->group_flag & G_DONE) return NULL;
  637.     if (gh->master_flag & M_IGNORE_GROUP) return NULL;
  638.     return gh;
  639.     }
  640.  
  641.     while (gs_index < master.number_of_groups) {
  642.     gh = sorted_groups[gs_index++];
  643.     if (!ignore_done_flag && gh->group_flag & G_DONE) continue;
  644.     if (gh->master_flag & M_IGNORE_GROUP) continue;
  645.  
  646.     gs_more_groups++;
  647.  
  648.     if ((tail = gh->group_name_length - gs_length) < 0) continue;
  649.  
  650.     switch (gs_mode) {
  651.  
  652.      case GS_NEW_GROUP:
  653.         if ((gh->group_flag & G_NEW) == 0) continue;
  654.         break;
  655.  
  656.      case GS_PREFIX0:
  657.         if ((c = (gh->group_name)[gs_length]) != NUL && c != '.') continue;
  658.      case GS_PREFIX:
  659.         if (strncmp(gh->group_name, gs_group, gs_length)) continue;
  660.         break;
  661.  
  662.      case GS_SUFFIX:
  663.         if (strcmp(gh->group_name + tail, gs_group)) continue;
  664.         break;
  665.  
  666.      case GS_INFIX:
  667.         user_error(".name. notation not supported (yet)");
  668.         break;
  669.  
  670.      case GS_ALL:
  671.         break;
  672.     }
  673.  
  674.     gs_more_groups--;
  675.     return gh;
  676.     }
  677.  
  678.     return NULL;
  679. }
  680.