home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i067: NN, a Usenet news reader, Part06/15
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: storm@texas.dk (Kim F. Storm)
- Posting-number: Volume 19, Issue 67
- Archive-name: nn/part06
-
- #!/bin/sh
- # this is part 6 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file keymap.h continued
- #
- CurArch=6
- 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 keymap.h"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' >> keymap.h
- X#define K_FIRST_PAGE 0x002b /* first page */
- X#define K_LAST_PAGE 0x002c /* last page */
- X
- X#define K_GOTO_LINE 0x002d /* goto specific line */
- X#define K_GOTO_PAGE 0x002e /* goto specific page */
- X#define K_GOTO_MATCH 0x002f /* goto line matching regexp */
- X#define K_NEXT_MATCH 0x0030 /* find next match */
- X
- X#define K_PREVIOUS 0x0031 /* goto prev group or article */
- X /* (no update is performed) */
- X
- X /* more() SPECIFIC COMMANDS */
- X
- X#define K_LEAVE_ARTICLE 0x0033 /* goto next article, mark current */
- X#define K_NEXT_ARTICLE 0x0034 /* goto next article */
- X#define K_NEXT_SUBJECT 0x0035 /* goto next subject */
- X#define K_FULL_DIGEST 0x0036 /* show full digest */
- X#define K_ROT13 0x0037 /* do rot13 */
- X#define K_COMPRESS 0x0038 /* compress spaces */
- X#define K_BACK_TO_MENU 0x0039 /* return to menu */
- X
- X /* menu() SPECIFIC COMMANDS */
- X
- X#define K_SELECT 0x0041 /* select current, move down */
- X#define K_SELECT_INVERT 0x0042 /* invert all selections */
- X#define K_SELECT_SUBJECT 0x0043 /* select all with same subject */
- X#define K_SELECT_RANGE 0x0044 /* select range */
- X#define K_AUTO_SELECT 0x0045 /* auto select from kill file */
- X#define K_UNSELECT_ALL 0x0046 /* undo all selections */
- X
- X#define K_LAYOUT 0x0049 /* change menu layout */
- X
- X#define K_NEXT_GROUP_NO_UPDATE 0x004a /* goto next group, no update */
- X#define K_READ_GROUP_UPDATE 0x004b /* read selected, then next group */
- X#define K_READ_GROUP_THEN_SAME 0x004c /* read selected, then same group */
- X
- X#define K_ADVANCE_GROUP 0x004d /* advance one group in sequence */
- X#define K_BACK_GROUP 0x004e /* back-up one group in sequence */
- X
- X#define K_PREVIEW 0x004f /* preview article */
- X
- X#define K_MACRO 0x0100 /* call macro */
- X#define K_ARTICLE_ID 0x0200 /* article id in lower part */
- X
- X/* special keys returned by get_c() */
- X
- X#define K_interrupt CTRL('G')
- X
- X#define K_up_arrow 0x0081
- X#define K_down_arrow 0x0082
- X#define K_left_arrow 0x0083
- X#define K_right_arrow 0x0084
- X
- X#define K_function(n) (0x0085 + n)
- X
- X
- X#define GETC_COMMAND 0x4000 /* bit set by get_c to return a command */
- X
- X/*
- X * KEY MAP SIZE is:
- X * (128 normal chars) + (0200) + (4 arrow keys) + (10 function keys)
- X */
- X
- X#define MULTI_KEYS (1 + 4 + 10)
- X#define KEY_MAP_SIZE (128 + MULTI_KEYS)
- X
- X
- X/* restrictions */
- X
- X#define K_ONLY_MENU 0x0001
- X#define K_ONLY_MORE 0x0002
- X
- Xextern int menu_key_map[];
- Xextern int more_key_map[];
- X
- Xextern char global_key_map[];
- NO_NEWS_IS_GOOD_NEWS
- echo "File keymap.h is complete"
- chmod 0644 keymap.h || echo "restore of keymap.h fails"
- set `wc -c keymap.h`;Sum=$1
- if test "$Sum" != "4343"
- then echo original size 4343, current size $Sum;fi
- echo "x - extracting kill.c (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > kill.c &&
- X#include "config.h"
- X#include "term.h"
- X
- X/*
- X * kill file handling
- X */
- X
- Xchar KILL_FILE[] = "kill";
- Xchar COMPILED_KILL[] = "KILL.COMP";
- X
- Xextern char *quick_match();
- X
- X#define COMP_KILL_MAGIC 0x4b694c6c /* KiLl */
- X
- X/*
- X * kill flags
- X */
- X
- X#define AUTO_KILL 0x01
- X#define AUTO_SELECT 0x00 /* pseudo flag */
- X#define ON_SUBJECT 0x02
- X#define ON_SENDER 0x00 /* pseudo flag */
- X
- X#define KILL_MUST_MATCH 0x10
- X
- X/*
- X * external flag representation
- X */
- X
- X#define EXT_AUTO_KILL '!'
- X#define EXT_AUTO_SELECT '+'
- X#define EXT_ON_SUBJECT 's'
- X#define EXT_ON_SENDER 'n'
- X#define EXT_KILL_MUST_MATCH '='
- X
- X/*
- X * period = nnn DAYS
- X */
- X
- X#define DAYS * 24 * 60 * 60
- X
- X
- X/*
- X * kill_article
- X *
- X * return 1 to kill article, 0 to include it
- X */
- X
- Xtypedef struct kill_list_entry {
- X int kill_flag;
- X char *kill_pattern;
- X struct kill_list_entry *next_kill;
- X} kill_list_entry;
- X
- X
- Xstatic kill_list_entry dummy_kill = {
- X 0, (char *)NULL, (kill_list_entry *)NULL
- X};
- Xstatic kill_list_entry *global_kill_list = &dummy_kill;
- Xstatic kill_list_entry *end_kill_list = &dummy_kill;
- X
- X
- Xkill_article(ah)
- Xarticle_header *ah;
- X{
- X register kill_list_entry *kl;
- X char *string;
- X
- X end_kill_list->next_kill = (kill_list_entry *)(current_group->kill_list);
- X
- X kl = global_kill_list;
- X while (kl = kl->next_kill) {
- X if (kl->kill_flag & ON_SUBJECT)
- X string = ah->subject;
- X else
- X string = ah->sender;
- X
- X if (kl->kill_flag & KILL_MUST_MATCH) {
- X if (strcmp(kl->kill_pattern, string))
- X continue;
- X } else
- X if (quick_match(string, kl->kill_pattern) == NULL)
- X continue;
- X
- X if (kl->kill_flag & AUTO_KILL)
- X return 1;
- X
- X ah->flag |= A_SELECT;
- X break;
- X }
- X
- X return 0;
- X}
- X
- X
- Xauto_select_article(ah)
- Xarticle_header *ah;
- X{
- X register kill_list_entry *kl;
- X char *string;
- X
- X end_kill_list->next_kill = ah->a_group ?
- X (kill_list_entry *)(ah->a_group->kill_list) :
- X (kill_list_entry *)(current_group->kill_list);
- X
- X kl = global_kill_list;
- X while (kl = kl->next_kill) {
- X if (kl->kill_flag & AUTO_KILL) continue;
- X
- X if (kl->kill_flag & ON_SUBJECT)
- X string = ah->subject;
- X else
- X string = ah->sender;
- X
- X if (kl->kill_flag & KILL_MUST_MATCH) {
- X if (strcmp(kl->kill_pattern, string))
- X continue;
- X } else
- X if (quick_match(string, kl->kill_pattern) == NULL)
- X continue;
- X return 1;
- X }
- X
- X return 0;
- X}
- X
- X
- X
- X
- X
- Xenter_kill_file(gh, pattern, flag, days)
- Xgroup_header *gh;
- Xchar *pattern;
- Xint flag;
- Xint days;
- X{
- X time_t now;
- X FILE *killf;
- X register kill_list_entry *kl;
- X char *str;
- X
- X killf = open_file(relative(nn_directory, "kill"), OPEN_APPEND);
- X if (killf == NULL) {
- X msg("cannot create kill file");
- X return;
- X }
- X
- X if (days >= 0) {
- X time(&now);
- X if (days == 0) days = 30;
- X fprintf(killf, "%lu:", (long)(now + days DAYS));
- X }
- X
- X if (gh) fputs(gh->group_name, killf);
- X fputc(':', killf);
- X
- X fputc(flag & AUTO_KILL ? EXT_AUTO_KILL : EXT_AUTO_SELECT, killf);
- X fputc(flag & ON_SUBJECT ? EXT_ON_SUBJECT : EXT_ON_SENDER, killf);
- X if (flag & KILL_MUST_MATCH) fputc(EXT_KILL_MUST_MATCH, killf);
- X fputc(':', killf);
- X
- X fputs(pattern, killf);
- X fputc(NL, killf);
- X
- X fclose(killf);
- X rm_kill_file();
- X
- X str = malloc(strlen(pattern) + 1);
- X mem_check(str, 1, "string");
- X
- X strcpy(str, pattern);
- X
- X if ((flag & KILL_MUST_MATCH) == 0)
- X init_quick_match(str);
- X
- X kl = (kill_list_entry *)calloc(1, sizeof(kill_list_entry));
- X mem_check(kl, 1, "kill list entry");
- X
- X kl->kill_pattern = str;
- X kl->kill_flag = flag;
- X
- X if (gh) {
- X kl->next_kill = (kill_list_entry *)(gh->kill_list);
- X gh->kill_list = (char *)kl;
- X } else {
- X kl->next_kill = NULL;
- X end_kill_list->next_kill = kl;
- X end_kill_list = kl;
- X }
- X}
- X
- X
- Xtypedef struct {
- X group_number ck_group;
- X char ck_flag;
- X long ck_pattern_index;
- X} comp_kill_entry;
- X
- Xtypedef struct {
- X long ckh_magic;
- X off_t ckh_pattern_offset;
- X long ckh_pattern_size;
- X long ckh_entries;
- X} comp_kill_header;
- X
- X
- Xkill_menu(ah)
- Xarticle_header *ah;
- X{
- X int flag, days;
- X char *mode1, *mode2;
- X char *pattern, *dflt, *days_str, buffer[512];
- X extern article_header *get_menu_article();
- X group_header *gh;
- X
- X prompt("\1AUTO\1 (K)ill or (S)elect (CR => Kill subject 1 month) ");
- X switch (get_c()) {
- X case CR:
- X case NL:
- X if (ah == NULL) {
- X ah = get_menu_article();
- X if (ah == NULL) return;
- X }
- X
- X strcpy(buffer, ah->subject);
- X enter_kill_file(current_group, buffer,
- X AUTO_KILL | ON_SUBJECT | KILL_MUST_MATCH, 30);
- X msg("DONE");
- X return;
- X
- X case 'k':
- X case 'K':
- X case '!':
- X flag = AUTO_KILL;
- X mode1 = "KILL";
- X break;
- X case 's':
- X case 'S':
- X case '+':
- X flag = AUTO_SELECT;
- X mode1 = "SELECT";
- X break;
- X default:
- X return;
- X }
- X
- X prompt("\1AUTO %s\1 on (S)ubject or (N)ame ?", mode1);
- X
- X dflt = NULL;
- X switch (get_c()) {
- X case 'n':
- X case 'N':
- X flag |= ON_SENDER;
- X if (ah) dflt = ah->sender;
- X mode2 = "Name";
- X break;
- X case 's':
- X case 'S':
- X case SP:
- X case CR:
- X case NL:
- X flag |= ON_SUBJECT;
- X if (ah) dflt = ah->subject;
- X mode2 = "Subject";
- X break;
- X default:
- X return;
- X }
- X
- X prompt("\1%s %s:\1", mode1, mode2);
- X
- X pattern = get_s(dflt, NONE, "%=", NO_COMPLETION);
- X if (pattern == NULL) return;
- X if (*pattern == NUL || *pattern == '%' || *pattern == '=') {
- X if (dflt && *dflt)
- X pattern = dflt;
- X else {
- X if ((ah = get_menu_article()) == NULL) return;
- X pattern = (flag & ON_SUBJECT) ? ah->subject : ah->sender;
- X }
- X flag |= KILL_MUST_MATCH;
- X }
- X
- X strcpy(buffer, pattern);
- X pattern = buffer;
- X
- X prompt("\1%s\1 in (G)roup '%s' or in (A)ll groups",
- X mode1, current_group->group_name);
- X
- X switch (get_c()) {
- X case 'g':
- X case 'G':
- X case SP:
- X case CR:
- X case NL:
- X gh = current_group;
- X break;
- X case 'A':
- X case 'a':
- X gh = NULL;
- X break;
- X default:
- X return;
- X }
- X
- X prompt("\1Lifetime of entry in days\1 (P)ermanent ");
- X days_str = get_s(" 30 days", NONE, "pP", NO_COMPLETION);
- X if (days_str == NULL) return;
- X
- X if (*days_str == NUL) {
- X days_str = "30 days";
- X days = 30;
- X } else if (*days_str == 'p' || *days_str == 'P') {
- X days_str = "perm";
- X days = -1;
- X } else if (isdigit(*days_str)) {
- X days = atoi(days_str);
- X sprintf(days_str, "%d days", days);
- X } else {
- X ding();
- X return;
- X }
- X
- X prompt("\1CONFIRM\1 %s %s %s%s: %-.35s%s ",
- X mode1, mode2, days_str,
- X (flag & KILL_MUST_MATCH) ? " exact" : "",
- X pattern, strlen(pattern) > 35 ? "..." : "");
- X if (yes(0) <= 0) return;
- X
- X enter_kill_file(gh, pattern, flag, days);
- X}
- X
- X
- X
- X
- Xinit_kill()
- X{
- X FILE *killf;
- X comp_kill_header header;
- X comp_kill_entry entry;
- X kill_list_entry *kill_tab;
- X register group_header *gh;
- X register kill_list_entry *kl;
- X char *patterns;
- X time_t kill_age, comp_age;
- X register n;
- X
- X Loop_Groups_Header(gh)
- X gh->kill_list = NULL;
- X
- X kill_age = file_exist(relative(nn_directory, KILL_FILE), "frw");
- X if (kill_age == 0) return 0;
- X
- X comp_age = file_exist(relative(nn_directory, COMPILED_KILL), "fr");
- X if (comp_age < kill_age && !compile_kill_file()) return 0;
- X
- X killf = open_file(relative(nn_directory, COMPILED_KILL), OPEN_READ);
- X if (killf == NULL) return 0;
- X
- X if (fread(&header, sizeof(header), 1, killf) != 1) goto err;
- X if (header.ckh_magic != COMP_KILL_MAGIC) goto err;
- X
- X patterns = malloc(header.ckh_pattern_size);
- X mem_check(patterns, header.ckh_pattern_size, "kill bytes");
- X
- X kill_tab = (kill_list_entry *)
- X calloc(header.ckh_entries, sizeof(kill_list_entry));
- X mem_check(kill_tab, header.ckh_entries, "kill entries");
- X
- X for (n = header.ckh_entries, kl = kill_tab; --n >= 0; kl++) {
- X if (fread(&entry, sizeof(entry), 1, killf) != 1) goto err;
- X
- X kl->kill_pattern = patterns + entry.ck_pattern_index;
- X kl->kill_flag = entry.ck_flag;
- X
- X if (entry.ck_group >= 0) {
- X gh = active_groups + entry.ck_group;
- X kl->next_kill = (kill_list_entry *)(gh->kill_list);
- X gh->kill_list = (char *)kl;
- X } else {
- X kl->next_kill = NULL;
- X end_kill_list->next_kill = kl;
- X end_kill_list = kl;
- X }
- X }
- X
- X if (fread(patterns, sizeof(char), header.ckh_pattern_size, killf)
- X != header.ckh_pattern_size) goto err;
- X
- X fclose(killf);
- X
- X return 1;
- X
- X err:
- X fclose(killf);
- X msg("Error in compiled kill file");
- X rm_kill_file();
- X
- X Loop_Groups_Header(gh)
- X gh->kill_list = NULL;
- X
- X end_kill_list = global_kill_list = &dummy_kill;
- X
- X return 0;
- X}
- X
- X
- Xstatic compile_kill_file()
- X{
- X FILE *killf, *compf, *patternf, *dropf;
- X comp_kill_header header;
- X comp_kill_entry entry;
- X time_t now, age;
- X off_t cur_line_start;
- X char line[512];
- X register char *cp, *np;
- X register int c;
- X group_header *gh;
- X int flag, any_errors;
- X extern char *temp_file;
- X
- X any_errors = 0;
- X header.ckh_entries = 0;
- X
- X killf = open_file(relative(nn_directory, KILL_FILE),
- X OPEN_READ | DONT_CREATE);
- X if (killf == NULL) return 0;
- X
- X compf = open_file(relative(nn_directory, COMPILED_KILL), OPEN_CREATE);
- X if (compf == NULL) goto err1;
- X
- X if ((patternf = open_file(temp_file, OPEN_CREATE)) == NULL)
- X goto err2;
- X
- X dropf = NULL;
- X
- X printf("\nCompiling kill file\n");
- X
- X fseek(compf, (off_t)sizeof(header), 0);
- X
- X time(&now);
- X
- X next_entry:
- X
- X for (;;) {
- X cur_line_start = ftell(killf);
- X
- X if (fgets(line, 512, killf) == NULL) break;
- X
- X cp = line;
- X while (*cp && isascii(*cp) && isspace(*cp)) cp++;
- X if (*cp == NUL || *cp == '#' || !isascii(*cp)) continue;
- X
- X if ((np = strchr(cp, ':')) == NULL) goto bad_entry;
- X
- X /* optional "age:" */
- X
- X if (np != cp && isdigit(*cp)) {
- X *np++ = NUL;
- X age = (time_t)atol(cp);
- X if (age < now) goto drop_entry;
- X cp = np;
- X if ((np = strchr(cp, ':')) == NULL) goto bad_entry;
- X }
- X
- X /* "group-name:" or ":" for all groups */
- X
- X if (np == cp) {
- X entry.ck_group = -1;
- X np++;
- X } else {
- X *np++ = NUL;
- X if ((gh = lookup(cp)) == NULL) {
- X printf("Unknown group in kill file: %s\n", cp);
- X any_errors++;
- X goto drop_entry;
- X }
- X entry.ck_group = gh->group_num;
- X }
- X
- X /* flags */
- X
- X cp = np;
- X flag = 0;
- X
- X for (;;) {
- X switch (*cp++) {
- X case EXT_AUTO_KILL:
- X flag |= AUTO_KILL;
- X continue;
- X case EXT_AUTO_SELECT:
- X flag |= AUTO_SELECT;
- X continue;
- X case EXT_ON_SUBJECT:
- X flag |= ON_SUBJECT;
- X continue;
- X case EXT_ON_SENDER:
- X flag |= ON_SENDER;
- X continue;
- X case EXT_KILL_MUST_MATCH:
- X flag |= KILL_MUST_MATCH;
- X continue;
- X case ':':
- X break;
- X case NL:
- X goto bad_entry;
- X default:
- X printf("Ignored flag '%c' in kill file\n", cp[-1]);
- X any_errors++;
- X continue;
- X }
- X break;
- X }
- X
- X entry.ck_flag = flag;
- X
- X if ((np = strchr(cp, NL)) == NULL) goto bad_entry;
- X
- X *np++ = NUL;
- X if ((flag & KILL_MUST_MATCH) == 0)
- X init_quick_match(cp);
- X
- X entry.ck_pattern_index = ftell(patternf);
- X
- X if (fwrite(&entry, sizeof(entry), 1, compf) != 1)
- X goto err3;
- X
- X if (fwrite(cp, sizeof(char), np - cp, patternf) != (np - cp))
- X goto err3;
- X
- X header.ckh_entries++;
- X }
- X
- X header.ckh_pattern_size = ftell(patternf);
- X
- X fclose(patternf);
- X patternf = open_file(temp_file, OPEN_READ | OPEN_UNLINK);
- X if (patternf == NULL) goto err2;
- X
- X header.ckh_pattern_offset = ftell(compf);
- X
- X while ((c = getc(patternf)) != EOF)
- X putc(c, compf);
- X
- X fclose(patternf);
- X
- X rewind(compf);
- X
- X header.ckh_magic = COMP_KILL_MAGIC;
- X
- X if (fwrite(&header, sizeof(header), 1, compf) != 1)
- X goto err2;
- X
- X fclose(compf);
- X fclose(killf);
- X if (dropf != NULL) fclose(dropf);
- X
- X if (any_errors) {
- X putchar(NL);
- X any_key(0);
- X }
- X
- X return 1;
- X
- X bad_entry:
- X printf("Incomplete kill file entry:\n%s", line);
- X fl;
- X any_errors++;
- X
- X drop_entry:
- X if (dropf == NULL) {
- X dropf = open_file(relative(nn_directory, KILL_FILE),
- X OPEN_UPDATE | DONT_CREATE);
- X if (dropf == NULL) goto next_entry;
- X }
- X fseek(dropf, cur_line_start, 0);
- X fwrite("# ", sizeof(char), 2, dropf);
- X goto next_entry;
- X
- X err3:
- X fclose(patternf);
- X unlink(temp_file);
- X err2:
- X fclose(compf);
- X rm_kill_file();
- X err1:
- X fclose(killf);
- X if (dropf != NULL) fclose(dropf);
- X
- X msg("cannot compile kill file");
- X return 0;
- X}
- X
- X
- Xrm_kill_file()
- X{
- X unlink(relative(nn_directory, COMPILED_KILL));
- X}
- X
- X
- Xdump_kill_list()
- X{
- X register kill_list_entry *kl;
- X
- X pg_init(0, 1);
- X
- X pg_next();
- X so_printf("\1GLOBAL kill list entries:\1");
- X
- X kl = end_kill_list->next_kill = NULL;
- X
- X kl = global_kill_list;
- X while (kl = kl->next_kill)
- X if (print_kill(kl) < 0) goto out;
- X
- X if (pg_next() < 0) goto out;
- X if (pg_next() < 0) goto out;
- X so_printf("\1GROUP %s kill list entries\1", current_group->group_name);
- X
- X kl = (kill_list_entry *)(current_group->kill_list);
- X while (kl) {
- X if (print_kill(kl) < 0) break;
- X kl = kl->next_kill;
- X }
- X
- X out:
- X
- X pg_end();
- X}
- X
- X
- X
- Xprint_kill(kl)
- Xregister kill_list_entry *kl;
- X{
- X if (pg_next() < 0) return -1;
- X
- X printf("\r%s ON %s '%.35s'%s\n",
- X kl->kill_flag & AUTO_KILL ? "KILL" : "SELECT",
- X kl->kill_flag & ON_SUBJECT ? "SUBJECT" : "NAME",
- X kl->kill_pattern,
- X kl->kill_flag & KILL_MUST_MATCH ? " (exact)" : "");
- X
- X return 0;
- X}
- X
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 kill.c || echo "restore of kill.c fails"
- set `wc -c kill.c`;Sum=$1
- if test "$Sum" != "13252"
- then echo original size 13252, current size $Sum;fi
- echo "x - extracting log_entry.c (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > log_entry.c &&
- X/*
- X * log_entry type string
- X *
- X * Enter a message in the Log.
- X */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X if (argc != 3) exit(1);
- X
- X init_global(0);
- X
- X if (log_entry(argv[1][0], "%s", argv[2]) == 0)
- X exit(1);
- X
- X nn_exit(0);
- X}
- X
- Xnn_exit(n)
- Xint n;
- X{
- X exit(n);
- X}
- X
- Xuser_error()
- X{
- X nn_exit(1);
- X}
- X
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 log_entry.c || echo "restore of log_entry.c fails"
- set `wc -c log_entry.c`;Sum=$1
- if test "$Sum" != "320"
- then echo original size 320, current size $Sum;fi
- echo "x - extracting m-att3b.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-att3b.h &&
- X
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * Define appropriate types for the following ranges of integer
- X * variables. These are processor & compiler dependent, but the
- X * distributed definitions will probably work on most systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X/*
- X * Define NETWORK_BYTE_ORDER if the machine's int32's are
- X * already in network byte order, i.e. m68k based.
- X */
- X
- X#define NETWORK_BYTE_ORDER /* */
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-att3b.h || echo "restore of m-att3b.h fails"
- set `wc -c m-att3b.h`;Sum=$1
- if test "$Sum" != "688"
- then echo original size 688, current size $Sum;fi
- echo "x - extracting m-dec3100.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-dec3100.h &&
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * This file is for a DECstation 3100, running Ultrix
- X */
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X#undef NO_VARARGS
- X
- X#ifdef NETWORK_DATABASE
- X#undef NETWORK_BYTE_ORDER
- X#include <netinet/in.h>
- X#endif /* NETWORK DATABASE */
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-dec3100.h || echo "restore of m-dec3100.h fails"
- set `wc -c m-dec3100.h`;Sum=$1
- if test "$Sum" != "519"
- then echo original size 519, current size $Sum;fi
- echo "x - extracting m-gould.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-gould.h &&
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * Define appropriate types for the following ranges of integer
- X * variables. These are processor & compiler dependent, but the
- X * distributed definitions will probably work on most systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X/*
- X * GOULD/UTX has varargs.h but not v[s]printf()
- X */
- X
- X#define NO_VARARGS
- X
- X
- X/*
- X * Not in network byte order on the GOULD
- X */
- X
- X#undef NETWORK_BYTE_ORDER /* */
- X#ifdef NETWORK_DATABASE
- X#include <netinet/in.h>
- X#endif
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-gould.h || echo "restore of m-gould.h fails"
- set `wc -c m-gould.h`;Sum=$1
- if test "$Sum" != "751"
- then echo original size 751, current size $Sum;fi
- echo "x - extracting m-hp9000.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-hp9000.h &&
- X
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * This is for HP9000 Series 320 and 800 (at least)
- X */
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X/*
- X * Define NETWORK_BYTE_ORDER if the machine's int32's are
- X * already in network byte order, i.e. m68k based.
- X */
- X
- X#define NETWORK_BYTE_ORDER /* */
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-hp9000.h || echo "restore of m-hp9000.h fails"
- set `wc -c m-hp9000.h`;Sum=$1
- if test "$Sum" != "550"
- then echo original size 550, current size $Sum;fi
- echo "x - extracting m-m680x0.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-m680x0.h &&
- X
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * These are for 680x0 based systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X/*
- X * Define NETWORK_BYTE_ORDER if the machine's int32's are
- X * already in network byte order, i.e. m68k based.
- X */
- X
- X#define NETWORK_BYTE_ORDER /* */
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-m680x0.h || echo "restore of m-m680x0.h fails"
- set `wc -c m-m680x0.h`;Sum=$1
- if test "$Sum" != "534"
- then echo original size 534, current size $Sum;fi
- echo "x - extracting m-sparc.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-sparc.h &&
- X
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * Define appropriate types for the following ranges of integer
- X * variables. These are processor & compiler dependent, but the
- X * distributed definitions will probably work on most systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X
- X/*
- X * Define NETWORK_BYTE_ORDER if the machine's longs are
- X * already in network byte order.
- X */
- X
- X#define NETWORK_BYTE_ORDER
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-sparc.h || echo "restore of m-sparc.h fails"
- set `wc -c m-sparc.h`;Sum=$1
- if test "$Sum" != "664"
- then echo original size 664, current size $Sum;fi
- echo "x - extracting m-sun.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-sun.h &&
- X
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * Define appropriate types for the following ranges of integer
- X * variables. These are processor & compiler dependent, but the
- X * distributed definitions will probably work on most systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X
- X/*
- X * Define NETWORK_BYTE_ORDER if the machine's longs are
- X * already in network byte order.
- X */
- X
- X#define NETWORK_BYTE_ORDER /* */
- X
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-sun.h || echo "restore of m-sun.h fails"
- set `wc -c m-sun.h`;Sum=$1
- if test "$Sum" != "671"
- then echo original size 671, current size $Sum;fi
- echo "x - extracting m-sun386i.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-sun386i.h &&
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * Define appropriate types for the following ranges of integer
- X * variables. These are processor & compiler dependent, but the
- X * distributed definitions will probably work on most systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X
- X/*
- X * Not in network byte order on the 386
- X */
- X
- X#undef NETWORK_BYTE_ORDER /* */
- X#ifdef NETWORK_DATABASE
- X#include <netinet/in.h>
- X#endif
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-sun386i.h || echo "restore of m-sun386i.h fails"
- set `wc -c m-sun386i.h`;Sum=$1
- if test "$Sum" != "673"
- then echo original size 673, current size $Sum;fi
- echo "x - extracting m-template.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-template.h &&
- X
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * Define appropriate types for the following ranges of integer
- X * variables. These are processor & compiler dependent, but the
- X * distributed definitions will probably work on most systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X/*
- X * Define NO_VARARGS if the varargs feature is not available
- X *
- X * Also define NO_VARARGS if the vprintf/vsprintf routines are not
- X * available (however, this will only by safe on some machines, like
- X * the VAX).
- X *
- X */
- X
- X/* #define NO_VARARGS */
- X
- X
- X
- X#ifdef NETWORK_DATABASE
- X
- X/*
- X * Define NETWORK_BYTE_ORDER if the machine's int32's are
- X * already in network byte order, i.e. m68k based.
- X */
- X
- X#define NETWORK_BYTE_ORDER /* */
- X
- X/*
- X * OTHERWISE provide the functions/macros ntohl/htonl to
- X * convert longs from and to network byte order
- X */
- X
- X#ifndef NETWORK_BYTE_ORDER
- X
- X/*
- X * Include appropriate files or define macroes or functions (include them
- X * in data.c) to convert longs and shorts to and from network byte order.
- X */
- X
- X/*
- X * This will work on most BSD based systems...
- X */
- X
- X#include <netinet/in.h>
- X
- X/*
- X * Otherwise, define something appropriate below
- X */
- X
- X#define htonl(l) ... /* host long to network long */
- X#define ntohl(l) ... /* network long to host long */
- X
- X#endif /* not NETWORK BYTE ORDER */
- X
- X#endif /* NETWORK DATABASE */
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-template.h || echo "restore of m-template.h fails"
- set `wc -c m-template.h`;Sum=$1
- if test "$Sum" != "1577"
- then echo original size 1577, current size $Sum;fi
- echo "x - extracting m-vax.h (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > m-vax.h &&
- X
- X/************** Machine (and compiler) dependent definitions. **************
- X *
- X * Define appropriate types for the following ranges of integer
- X * variables. These are processor & compiler dependent, but the
- X * distributed definitions will probably work on most systems.
- X */
- X
- X
- X
- X/* MACHINE TYPE DEFINED TYPE VALUE RANGE */
- X
- Xtypedef unsigned char int8; /* 0 .. 255 */
- Xtypedef short int16; /* -10,000 .. 10,000 */
- Xtypedef long int32; /* -100,000 .. 100,000 */
- Xtypedef unsigned long uint32; /* 0 .. 2^31-1 */
- X
- X
- X/*
- X * VAX/BSD has varargs.h but not v[s]printf()
- X */
- X
- X#define NO_VARARGS
- X
- X
- X/*
- X * The VAX does not have longs in network byte order
- X */
- X
- X#undef NETWORK_BYTE_ORDER /* we need to use ntohl/htonl */
- X#ifdef NETWORK_DATABASE
- X#include <netinet/in.h>
- X#endif
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 m-vax.h || echo "restore of m-vax.h fails"
- set `wc -c m-vax.h`;Sum=$1
- if test "$Sum" != "789"
- then echo original size 789, current size $Sum;fi
- echo "x - extracting macro.c (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > macro.c &&
- X#include "config.h"
- X#include "keymap.h"
- X#include "term.h"
- X
- Xexport int in_menu_mode = 0;
- Xexport int get_from_macro = 0;
- Xexport int macro_debug = 0;
- X
- X#define M_DUMMY 0 /* do nothing (end of branch) */
- X
- X#define M_COMMAND 1 /* a command (get_c()) */
- X#define M_KEY 2 /* a key stroke (get_c()) */
- X#define M_STRING 3 /* a string (get_s()) */
- X
- X#define M_INPUT 4 /* take input from keyboard (get_c/get_s) */
- X
- X#define M_YES 5 /* answer yes to confirmation */
- X#define M_NO 6 /* answer no to confirmation and break */
- X /* -- if neither are present, take input */
- X
- X#define M_PROMPT 8 /* prompt(...) */
- X#define M_ECHO 9 /* msg(...) */
- X
- X#define M_IS_MENU 10 /* in menu mode ? */
- X#define M_IS_SHOW 11 /* in reading mode ? */
- X#define M_IS_GROUP 12 /* are we in a news group ? */
- X#define M_IS_FOLDER 13 /* are we in a folder ? */
- X#define M_CONFIRM 14 /* ask for confirmation to procede */
- X#define M_REJECT 15 /* ask for !confirmation to procede */
- X#define M_VARTEST 16 /* test value of variable */
- X#define M_BREAK 17 /* exit from macroes */
- X#define M_RETURN 18 /* return from this macro */
- X
- X
- Xstruct macro {
- X int m_type; /* entry type */
- X union {
- X int mu_int; /* command or char */
- X char *mu_string; /* string for get_s */
- X struct macro *mu_branch; /* false conditional */
- X } m_value;
- X struct macro *m_next; /* next macro element */
- X};
- X
- X#define m_int m_value.mu_int
- X#define m_string m_value.mu_string
- X#define m_branch m_value.mu_branch
- X
- X#define NMACRO 32 /* max number of macros */
- X#define MSTACK 5 /* max nesting level */
- X
- Xstatic struct macro *macro[NMACRO]; /* macro table */
- X
- Xstatic struct macro *mstack[MSTACK]; /* macro stack */
- Xstatic int cstack[MSTACK];
- Xstatic int m_level = 0;
- X
- Xstatic struct macro *m = NULL; /* current macro */
- Xstatic int no_advance = 0;
- X
- Xstatic int cur_m;
- X
- X#define MERROR ((struct macro *)1)
- X
- Xinit_macro()
- X{
- X int n;
- X
- X for (n = 0; n < NMACRO; n++)
- X macro[n] = NULL;
- X}
- X
- Xstatic m_new(t)
- Xint t;
- X{
- X struct macro *m1;
- X
- X m1 = (struct macro *)calloc(1, sizeof(struct macro));
- X mem_check(m1, sizeof(struct macro), "for macro");
- X
- X if (m == NULL)
- X m = macro[cur_m] = m1;
- X else {
- X m->m_next = m1;
- X m = m1;
- X }
- X m->m_type = t;
- X m->m_next = NULL;
- X}
- X
- X
- X/*
- X * Define macro "id" reading from file f until "end"
- X *
- X * Macro definition syntax:
- X * define <id>
- X * <body>
- X * end
- X */
- X
- X
- Xm_define(id, f)
- Xchar *id;
- XFILE *f;
- X{
- X char line[256], *lp, skip;
- X
- X if (id) {
- X cur_m = atoi(id);
- X if (cur_m < 0 || cur_m >= NMACRO) {
- X m_error("macro number out of range\n", id);
- X return 0;
- X }
- X } else {
- X for (cur_m = 0; cur_m < NMACRO; cur_m++)
- X if (macro[cur_m] == NULL) break;
- X if (cur_m == NMACRO) {
- X init_message("No unused macro numbers");
- X return 0;
- X }
- X }
- X
- X if (f == NULL) {
- X clrdisp();
- X printf("DEFINE MACRO %d -- END WITH 'end'\n\n\r", cur_m);
- X no_raw();
- X f = stdin;
- X }
- X
- X m = NULL;
- X skip = 0;
- X
- X while (fgets(line, 256, f)) {
- X for (lp = line; *lp && isspace(*lp); lp++);
- X if (*lp == NUL) continue;
- X if (strncmp(lp, "end", 3) == 0) goto out;
- X if (!skip && parse_line(lp)) {
- X macro[cur_m] = NULL;
- X skip++;
- X }
- X }
- X
- X if (f != stdin)
- X m_error("end missing", (char *)NULL);
- X
- X out:
- X if (f == stdin) raw();
- X m = NULL;
- X return 1;
- X}
- X
- Xstatic parse_line(lp)
- Xchar *lp;
- X{
- X char *word;
- X struct macro *m1, *branch = NULL;
- X
- X while (*lp) {
- X if (*lp == '#') break;
- X
- X if (*lp == ':') {
- X m_new(M_COMMAND);
- X m->m_int = GETC_COMMAND | K_EXTENDED_CMD;
- X m_new(M_STRING);
- X m->m_string = copy_str(lp + 1);
- X break;
- X }
- X
- X if (*lp == '?') {
- X m_new(M_IS_MENU);
- X if (branch == NULL) {
- X m1 = m;
- X m_new(M_DUMMY);
- X branch = m;
- X m = m1;
- X }
- X m->m_branch = branch;
- X }
- X
- X word = lp;
- X if (*lp == '"')
- X do lp++;
- X while (*lp && *lp != '"');
- X else
- X if (*lp == '\'')
- X do lp++;
- X while (*lp && *lp != '\'');
- X else
- X while (*lp && !isspace(*lp)) lp++;
- X if (*lp) {
- X *lp++ = NUL;
- X while (*lp && isspace(*lp)) lp++;
- X }
- X if (parse_word(word)) return 1;
- X }
- X
- X if (branch) {
- X m->m_next = branch;
- X m = branch;
- X }
- X return 0;
- X}
- X
- Xstatic parse_word(w)
- Xchar *w;
- X{
- X int cmd;
- X register struct macro *m1;
- X
- X if (m && m->m_type == M_COMMAND && m->m_int == (GETC_COMMAND | K_MACRO)) {
- X if (isdigit(*w)) {
- X m->m_int |= atoi(w);
- X goto ok;
- X }
- X m_error("macro number missing", (char *)NULL);
- X return 1;
- X }
- X
- X if (*w == '"') {
- X if (m == NULL || (m->m_type != M_PROMPT && m->m_type != M_ECHO))
- X m_new(M_STRING);
- X m->m_string = copy_str(w + 1);
- X goto ok;
- X }
- X
- X if (*w == '\'') {
- X m_new(M_KEY);
- X m->m_int = parse_key(w + 1);
- X goto ok;
- X }
- X
- X if (*w == '?') {
- X if (strchr(w, '=')) {
- X m->m_type = M_VARTEST;
- X m1 = m;
- X m_new(M_DUMMY);
- X m->m_branch = m1->m_branch;
- X m1->m_string = copy_str(w + 1);
- X goto ok;
- X }
- X
- X switch (w[1]) {
- X case 'f': /* ?folder */
- X cmd = M_IS_FOLDER;
- X break;
- X case 'g': /* ?group */
- X cmd = M_IS_GROUP;
- X break;
- X case 'm': /* ?menu */
- X cmd = M_IS_MENU;
- X break;
- X case 'n': /* ?no */
- X cmd = M_REJECT;
- X break;
- X case 's': /* ?show */
- X cmd = M_IS_SHOW;
- X break;
- X case 'y': /* ?yes */
- X cmd = M_CONFIRM;
- X break;
- X default:
- X m_error("unknown conditional %s", w - 1);
- X return 1;
- X }
- X m->m_type = cmd;
- X goto ok;
- X }
- X
- X if ((cmd = lookup_command(w, (K_ONLY_MENU | K_ONLY_MORE))) != K_INVALID) {
- X m_new(M_COMMAND);
- X m->m_int = GETC_COMMAND | cmd;
- X goto ok;
- X }
- X
- X if (strcmp(w, "prompt") == 0) {
- X m_new(M_PROMPT);
- X m->m_string = "?";
- X goto ok;
- X }
- X if (strcmp(w, "echo") == 0) {
- X m_new(M_ECHO);
- X m->m_string = "ups";
- X goto ok;
- X }
- X if (strcmp(w, "input") == 0) {
- X m_new(M_INPUT);
- X goto ok;
- X }
- X if (strcmp(w, "yes") == 0) {
- X m_new(M_YES);
- X goto ok;
- X }
- X if (strcmp(w, "no") == 0) {
- X m_new(M_NO);
- X goto ok;
- X }
- X if (strcmp(w, "break") == 0) {
- X m_new(M_BREAK);
- X goto ok;
- X }
- X if (strcmp(w, "return") == 0) {
- X m_new(M_RETURN);
- X goto ok;
- X }
- X
- X m_error("Unknown word >>%s<<", w);
- X return 1;
- X
- X ok:
- X return 0;
- X}
- X
- X/*
- X * Invoke macro # N
- X */
- X
- Xm_invoke(n)
- Xint n;
- X{
- X if (n < 0 || n > NMACRO || macro[n] == NULL) {
- X msg("undefined macro %d", n);
- X return;
- X }
- X
- X if (m == NULL)
- X no_advance = 0;
- X else {
- X if (m_level == MSTACK) {
- X msg("Macro stack overflow");
- X m = NULL;
- X m_level = 0;
- X return;
- X }
- X mstack[m_level] = m;
- X cstack[m_level] = cur_m;
- X m_level++;
- X }
- X
- X cur_m = n;
- X m = macro[cur_m];
- X}
- X
- Xm_startinput()
- X{
- X no_advance = 1;
- X}
- X
- Xm_endinput()
- X{
- X if (no_advance) {
- X no_advance = 0;
- X if (m && m->m_type == M_INPUT)
- X m = m->m_next;
- X }
- X}
- X
- Xm_advinput()
- X{
- X if (m && m->m_type == M_INPUT)
- X m = m->m_next;
- X}
- X
- Xstatic struct macro *m_call(who)
- Xint who;
- X{
- X struct macro *m1;
- X
- X for (;;) {
- X while (m == NULL && m_level > 0) {
- X m_level--;
- X m = mstack[m_level];
- X cur_m = cstack[m_level];
- X }
- X if (m == NULL) {
- X if (macro_debug) msg("end");
- X return NULL;
- X }
- X
- X if (macro_debug)
- X macro_dbg();
- X
- X if (who == 3) {
- X if (m->m_type == M_YES || m->m_type == M_NO) goto out;
- X return NULL;
- X }
- X
- X switch (m->m_type) {
- X case M_COMMAND:
- X case M_KEY:
- X if (who == 1) goto out;
- X goto err;
- X
- X case M_STRING:
- X if (who == 2) goto out;
- X goto err;
- X
- X case M_INPUT:
- X if (no_advance) return m;
- X goto out;
- X
- X case M_YES:
- X case M_NO:
- X case M_DUMMY:
- X break;
- X
- X case M_PROMPT:
- X prompt("\1%s\1 ", m->m_string);
- X break;
- X
- X case M_ECHO:
- X msg(m->m_string);
- X break;
- X
- X case M_IS_MENU:
- X if (!in_menu_mode) m = m->m_branch;
- X break;
- X case M_IS_SHOW:
- X if (in_menu_mode) m = m->m_branch;
- X break;
- X case M_IS_GROUP:
- X if (current_group->group_flag & G_FOLDER) m = m->m_branch;
- X break;
- X case M_IS_FOLDER:
- X if ((current_group->group_flag & G_FOLDER) == 0) m = m->m_branch;
- X break;
- X case M_CONFIRM:
- X if (!yes(0)) m = m->m_branch;
- X break;
- X case M_REJECT:
- X if (yes(0)) m = m->m_branch;
- X break;
- X
- X case M_VARTEST:
- X m1 = m;
- X m = m->m_next;
- X
- X switch (test_variable(m1->m_string)) {
- X case 0:
- X m = m->m_branch;
- X break;
- X case -1:
- X goto err1;
- X }
- X break;
- X
- X case M_RETURN:
- X m = NULL;
- X continue;
- X
- X case M_BREAK:
- X goto term;
- X }
- X
- X m = m->m_next;
- X }
- X
- X out:
- X m1 = m;
- X m = m->m_next;
- X no_advance = 0;
- X return m1;
- X
- X err:
- X msg("Error in macro %d", cur_m);
- X err1:
- X user_delay(1);
- X m = NULL;
- X m_level = 0;
- X return MERROR;
- X
- X term:
- X m = NULL;
- X m_level = 0;
- X return NULL;
- X}
- X
- Xm_break()
- X{
- X m = NULL;
- X m_level = 0;
- X}
- X
- Xmacro_dbg()
- X{
- X extern char *command_name(), *key_name();
- X char *name;
- X
- X switch (m->m_type) {
- X case M_COMMAND:
- X msg("COMMAND: %s", command_name(m->m_int));
- X goto delay;
- X
- X case M_KEY:
- X msg("KEY: %s", key_name(m->m_int));
- X goto delay;
- X
- X case M_STRING:
- X msg("STRING: %s", m->m_string);
- X goto delay;
- X
- X case M_INPUT:
- X name = "input";
- X break;
- X
- X case M_YES:
- X name = "yes";
- X break;
- X
- X case M_NO:
- X name = "no";
- X break;
- X
- X case M_DUMMY:
- X name = "dummy";
- X break;
- X
- X case M_PROMPT:
- X msg("PROMPT: %s", m->m_string);
- X goto delay;
- X
- X case M_ECHO:
- X msg("ECHO: %s", m->m_string);
- X goto delay;
- X
- X case M_IS_MENU:
- X msg("?menu => %d", in_menu_mode);
- X goto delay;
- X
- X case M_IS_SHOW:
- X msg("?show => %d", !in_menu_mode);
- X goto delay;
- X
- X case M_IS_GROUP:
- X msg("?group => %d", (current_group->group_flag & G_FOLDER) == 0);
- X goto delay;
- X
- X case M_IS_FOLDER:
- X msg("?group => %d", (current_group->group_flag & G_FOLDER));
- X goto delay;
- X
- X case M_CONFIRM:
- X name = "?yes";
- X break;
- X
- X case M_REJECT:
- X name = "?no";
- X break;
- X
- X case M_VARTEST:
- X msg("?%s => %d", m->m_string, test_variable(m->m_string));
- X goto delay;
- X
- X case M_RETURN:
- X name = "return";
- X break;
- X
- X case M_BREAK:
- X name = "break";
- X break;
- X }
- X msg(name);
- X
- X delay:
- X user_delay(1);
- X}
- X/*
- X * Macro processing for get_c()
- X */
- X
- Xm_getc(cp)
- Xint *cp;
- X{
- X struct macro *m1;
- X
- X get_from_macro = 0;
- X if (m && (m1 = m_call(1))) {
- X if (m1 == MERROR) return 2;
- X if (m1->m_type == M_INPUT) return 0;
- X *cp = m1->m_int;
- X get_from_macro = 1;
- X return 1;
- X }
- X return 0;
- X}
- X
- X/*
- X * Macro processing for get_s()
- X */
- X
- Xm_gets(s)
- Xchar *s;
- X{
- X struct macro *m1;
- X
- X get_from_macro = 0;
- X if (m && (m1 = m_call(2))) {
- X if (m1 == MERROR) return 2;
- X if (m1->m_type == M_INPUT) return 0;
- X strcpy(s, m1->m_string);
- X get_from_macro = 1;
- X return 1;
- X }
- X return 0;
- X}
- X
- X/*
- X * Macro processing for yes()
- X */
- X
- Xm_yes()
- X{
- X struct macro *m1;
- X
- X if (m) {
- X if (m1 = m_call(3))
- X if (m1->m_type == M_NO)
- X return 1;
- X else
- X return 2;
- X else
- X return 3;
- X }
- X return 0;
- X}
- X
- Xstatic m_error(fmt, arg)
- Xchar *fmt, *arg;
- X{
- X char buf[80];
- X
- X if (arg) {
- X sprintf(buf, fmt, arg);
- X fmt = buf;
- X }
- X
- X init_message("Error in macro %d: %s", cur_m, fmt);
- X}
- NO_NEWS_IS_GOOD_NEWS
- chmod 0644 macro.c || echo "restore of macro.c fails"
- set `wc -c macro.c`;Sum=$1
- if test "$Sum" != "10847"
- then echo original size 10847, current size $Sum;fi
- echo "x - extracting master.c (Text)"
- sed 's/^X//' << 'NO_NEWS_IS_GOOD_NEWS' > master.c &&
- X/*
- X * nn master daemon
- X *
- X * maintains the article header database.
- X */
- X
- X#include <signal.h>
- X#include <errno.h>
- X#include "config.h"
- X#include "db.h"
- X
- X/*
- X * nnmaster options:
- X *
- X * -e N expire a group if more than N articles are gone
- X * -r N repeat every N minutes
- X *
- X * -E expire by recolleting entire groups rather than copying files
- X * -C check consistency of database on start-up
- X *
- X * -I initialize
- X * -t trace collection of each group
- X * -v print version and exit
- X * -u update even if active is not modified
- X * -w send wakeup to real master
- X * -D debug
- X */
- X
- X#include "options.h"
- X
- Xstatic int
- X initialize = 0,
- X prt_vers = 0,
- X unconditional = 0,
- X wakeup_master = 0,
- X expire_level = 1,
- X clean_to_expire = 0,
- X check_on_startup = 0,
- X repeat_delay = 0,
- X debug_mode = 0;
- X
- Xexport int
- X trace = 0,
- X#ifdef NNTP
- X silent = 1,
- X#endif
- X Debug = 0;
- X
- X
- XOption_Description(master_options) {
- X
- X 'I', Bool_Option( initialize ),
- X 'v', Bool_Option( prt_vers ),
- X 'u', Bool_Option( unconditional ),
- X 'w', Bool_Option( wakeup_master ),
- X
- X 'e', Int_Option( expire_level ),
- X 'r', Int_Option_Optional( repeat_delay, 10 ),
- X
- X 'E', Bool_Option( clean_to_expire ),
- X 'C', Bool_Option( check_on_startup ),
- X
- X 'D', Bool_Option( debug_mode ),
- X 't', Bool_Option( trace ),
- X
- X '\0',
- X};
- X
- X
- Ximport FILE *master_file;
- Ximport char news_active[];
- X
- Xstatic int rm_mpid_on_exit = 0;
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X time_t age_active;
- X register group_header *gh;
- X register int cur_group;
- X int col_article_count, col_group_count;
- X int exp_article_count, exp_group_count;
- X int temp;
- X time_t start_time;
- X FILE *m_pid;
- X
- X
- X umask(002); /* avoid paranoia */
- X
- X init_global(1);
- X
- X parse_options(argc, argv, (char *)NULL, master_options, (char *)NULL);
- X
- X if (wakeup_master) {
- X if (!kill_master(SIGALRM) && errno == ESRCH)
- X printf("master is not running\n");
- X nn_exit(0);
- X }
- X
- X if (prt_vers) {
- X print_version("Master: Release %R.%V.%P, Compilation %U\n");
- X nn_exit(0);
- X }
- X
- X if (kill_master(SIGALRM)) {
- X printf("The master is already running\n");
- X nn_exit(0);
- X }
- X#ifdef NNTP
- X nntp_check();
- X#endif
- X if (initialize) {
- X build_master();
- X nn_exit(0);
- X }
- X
- X if (repeat_delay && !debug_mode) {
- X while ((temp = fork()) < 0) sleep(1);
- X if (temp) nn_exit(0);
- X
- X process_id = getpid(); /* init_global saved parent's pid */
- X
- X DETATCH_TERMINAL
- X }
- X
- X rm_mpid_on_exit = 1;
- X m_pid = open_file(relative(lib_directory, "MPID"),
- X OPEN_CREATE|MUST_EXIST);
- X fprintf(m_pid, "%d\n", process_id);
- X fclose(m_pid);
- X
- X log_entry('M', "Master started -r%d -e%d%s",
- X repeat_delay, expire_level, clean_to_expire ? " -E" : "");
- X
- X if (check_on_startup) {
- X char cmd[FILENAME];
- X sprintf(cmd, "%s/nnadmin Z", BIN_DIRECTORY);
- X system(cmd);
- X log_entry('M', "Database validation completed");
- X }
- X
- X repeat_delay *= 60;
- X
- X init_digest_parsing();
- X
- X open_master(OPEN_READ);
- X close_master();
- X
- X open_master(OPEN_UPDATE);
- X
- X again:
- X
- X#ifdef NNTP
- X if (use_nntp) {
- X if (nntp_get_active() < 0) {
- X nntp_close_server();
- X current_group = NULL; /* for init_group */
- X log_entry('N', "Can't access active file --- %s",
- X repeat_delay ? "sleeping" : "termating");
- X if (repeat_delay == 0)
- X nn_exit(1);
- X sleep(repeat_delay);
- X goto again;
- X }
- X }
- X#endif
- X
- X age_active = file_exist(news_active, "fr");
- X#ifdef NNTP
- X if (!use_nntp)
- X#endif
- X if (age_active == (time_t)0)
- X sys_error("Cannot access active file");
- X
- X temp = receive_admin();
- X
- X if (!temp && !unconditional && age_active <= master.last_scan) {
- X if (repeat_delay == 0)
- X goto out;
- X
- X if (s_hangup) goto out;
- X#ifdef NNTP
- X if (use_nntp)
- X nntp_cleanup();
- X#endif /* NNTP */
- X if (debug_mode)
- X printf("NONE (*** SLEEP ***)\n");
- X else {
- X if (trace) log_entry('T', "none");
- X sleep(repeat_delay);
- X }
- X
- X if (s_hangup) goto out;
- X
- X goto again;
- X }
- X
- X unconditional = 0; /* only first pass */
- X
- X time(&start_time);
- X col_article_count = col_group_count = 0;
- X exp_article_count = exp_group_count = 0;
- X
- X visit_active_file();
- X
- X for (cur_group = 0; cur_group < master.number_of_groups; cur_group++) {
- X
- X if (s_hangup) break;
- X
- X gh = &active_groups[cur_group];
- X
- X if (gh->group_flag & G_NO_DIRECTORY) {
- X if (gh->group_flag & G_BLOCKED) goto unblock_group;
- X continue;
- X }
- X
- X if (gh->last_l_article > gh->last_article ||
- X gh->first_l_article > gh->first_article) {
- X log_entry('X', "group %s renumbered", gh->group_name);
- X clean_group(gh);
- X
- X goto do_collect;
- X }
- X
- X if (expire_level > 0 && gh->last_l_article > 0) {
- X if ((gh->first_l_article + expire_level) <= gh->first_article) {
- X if (trace) log_entry('T', "%s expire level", gh->group_name);
- X gh->group_flag |= G_EXPIRE;
- X goto do_collect;
- X }
- X
- X if (gh->first_article > gh->last_l_article) {
- X if (trace) log_entry('T', "%s expire void", gh->group_name);
- X clean_group(gh);
- X goto do_collect;
- X }
- X }
- X
- X if (gh->last_l_article == gh->last_article) {
- X if (gh->group_flag & G_BLOCKED) goto unblock_group;
- X continue;
- X }
- X
- X do_collect:
- X if (!init_group(gh)) {
- X log_entry('R', "%s: no directory", gh->group_name);
- X gh->group_flag |= G_NO_DIRECTORY;
- X gh->group_flag &= ~(G_EXPIRE | G_BLOCKED);
- X save_group(current_group);
- X continue;
- X }
- X
- X if (gh->group_flag & G_EXPIRE) {
- X if (clean_to_expire) {
- X temp = gh->first_article - gh->first_l_article;
- X clean_group(gh);
- X } else {
- X if ((gh->group_flag & G_BLOCKED) == 0) {
- X gh->group_flag |= G_BLOCKED;
- X save_group(gh);
- X }
- X temp = expire_group(gh);
- X }
- X if (temp) {
- X exp_article_count += temp;
- X exp_group_count++;
- X }
- X }
- X
- X temp = collect_group(gh);
- X#ifdef NNTP
- X if (temp < 0) {
- X /* connection broken */
- X gh->group_flag &= ~G_EXPIRE; /* remains blocked */
- X save_group(gh);
- X age_active = master.last_scan; /* did not complete */
- X current_group = NULL; /* for init_group */
- X break;
- X }
- X#endif
- X if (temp > 0) {
- X col_article_count += temp;
- X col_group_count++;
- X }
- X
- X unblock_group:
- X if (temp || (gh->group_flag & G_BLOCKED)) {
- X gh->group_flag &= ~(G_EXPIRE | G_BLOCKED);
- X save_group(gh);
- X }
- X }
- X
- X /* if master is interrupted, all new articles may not be collected */
- X
- X if (!s_hangup)
- X master.last_scan = age_active;
- X
- X save_master();
- X
- X if (exp_article_count)
- X log_entry('X', "Expire: %3d art, %2d gr, %2ld s %s",
- X exp_article_count, exp_group_count,
- X time((time_t *)0) - start_time,
- X col_article_count ? "(incl. collect)" : "");
- X
- X if (col_article_count)
- X log_entry('C', "Collect: %3d art, %2d gr, %2ld s %s",
- X col_article_count, col_group_count,
- X time((time_t *)0) - start_time,
- X exp_article_count ? "(incl. expire)" : "");
- X
- X if (!s_hangup && repeat_delay) {
- X#ifdef NNTP
- X if (use_nntp)
- X nntp_cleanup();
- X#endif /* NNTP */
- X if (!debug_mode) sleep(repeat_delay);
- X if (!s_hangup) goto again;
- X }
- X
- X out:
- X nn_exit(0);
- X /*NOTREACHED*/
- X}
- X
- X
- X/*
- X * nn_exit() --- called whenever a program exits.
- X */
- X
- Xnn_exit(n)
- X{
- X#ifdef NNTP
- X if (use_nntp)
- X nntp_cleanup();
- X#endif /* NNTP */
- X close_master();
- X
- X if (rm_mpid_on_exit)
- X unlink(relative(lib_directory, "MPID"));
- X
- X if (n)
- X log_entry('E', "Abnormal termination, exit=%d", n);
- X else
- X if (rm_mpid_on_exit)
- X log_entry('M', "Master terminated%s", s_hangup ? " (hangup)" : "");
- X
- X exit(n);
- X}
- X
- X
- X/*
- X * add new group to master file
- X */
- X
- Xgroup_header *add_new_group(name)
- Xchar *name;
- X{
- X register group_header *gh;
- X FILE *group_file;
- X static has_warned = 0;
- X
- X if (master.free_groups <= 0) {
- X if (!has_warned) {
- X log_entry('R', "NO MORE FREE GROUP SLOTS -- RESTART MASTER");
- X has_warned++;
- X }
- X return NULL;
- X }
- X
- X master.free_groups--;
- X
- X gh = &active_groups[master.number_of_groups];
- X sorted_groups[master.number_of_groups] = gh;
- X
- X gh->group_name_length = strlen(name);
- X gh->group_name = (char *)malloc(gh->group_name_length + 1);
- X mem_check(gh->group_name, gh->group_name_length, "bytes for group name");
- X strcpy(gh->group_name, name);
- X
- X gh->group_num = master.number_of_groups++;
- X
- X group_file = open_groups(OPEN_UPDATE|MUST_EXIST);
- X
- X fseek(group_file, master.next_group_write_offset, 0);
- X name[gh->group_name_length] = NL;
- X Fwrite(name, sizeof(char), gh->group_name_length + 1, group_file);
- X name[gh->group_name_length] = NUL;
- X fclose(group_file);
- X
- X master.next_group_write_offset += gh->group_name_length + 1;
- X
- X clean_group(gh);
- X
- X save_master();
- X
- X sort_groups();
- X
- X log_entry('C', "new group: %s (%d)", gh->group_name, gh->group_num);
- X
- X return gh;
- X}
- X
- X
- Xsave_group(gh)
- Xgroup_header *gh;
- X{
- X int flag;
- X
- X flag = gh->group_flag;
- X gh->group_flag &= G_MASTER_FLAGS;
- X
- X if (!db_write_group(master_file, gh, gh->group_num))
- X write_error();
- X fflush(master_file);
- X
- X gh->group_flag = flag;
- X}
- X
- X
- Xsave_master()
- X{
- X rewind(master_file);
- X if (!db_write_master(master_file, &master))
- NO_NEWS_IS_GOOD_NEWS
- echo "End of part 6"
- echo "File master.c is continued in part 7"
- echo "7" > s2_seq_.tmp
- exit 0
- ---
- Kim F. Storm storm@texas.dk Tel +45 429 174 00
- Texas Instruments, Marielundvej 46E, DK-2730 Herlev, Denmark
- No news is good news, but nn is better!
-
-