+-+-+-+ Beginning of part 11 +-+-+-+ X`009" "+f$element(3, " ", line) X$ goto Dir_scan_real X$ ! X$Dir_scan_Done: X$ write clean_up "" X$ close clean_up X$ close dir_in X$ delete notes_temp.tmp; X$ ! X$ goto Top_of_file_search X$ ! X$Past_file_search: X$ ! X$ if did_one then goto Parse_Initial X$ write sys$output "%NOTPURG-F-NONETOPURGE No files to purge" X$ delete notes_list.out; X$ exit X$ ! X$ ! Now, first parse pass of the file... X$ ! X$Parse_Initial: X$ did_one = "F" X$ open/read file_list notes_list.out X$ open/write file_purge_list notes_purge.ctl X$Next_list_record: X$ read/end=List_scan_Done file_list line X$ record_command = "Parse_"+f$element(0, " ", line) X$ goto 'record_command' X$Parse_F: X$ filename = f$element(1, " ", line) X$ expired = 0 X$ unexpired = 0 X$ open/write expire_list expired.tmp X$ open/write unexpire_list unexpired.tmp X$ goto Next_list_record X$Parse_E: X$ expired = expired + 1 X$ write expire_list line X$ goto Next_list_record X$Parse_U: X$ unexpired = unexpired + 1 X$ write unexpire_list line X$ goto Next_list_record X$Parse_: X$ close expire_list X$ close unexpire_list X$ if expired .le. 0 then goto File_list_indiv_clean X$ ! X$File_list_copy: X$ did_one = "T" X$ write file_purge_list "F "+filename X$ open/read expire_list expired.tmp X$File_list_copy_1: X$ read expire_list line X$ write file_purge_list line X$ expired = expired - 1 X$ if expired .gt. 0 then goto File_list_copy_1 X$ write file_purge_list " " X$ close expire_list X$File_list_indiv_clean: X$ delete expired.tmp; X$ delete unexpired.tmp; X$ goto Next_list_record X$ ! X$List_scan_Done: X$ close file_list X$ close file_purge_list X$ delete notes_list.out; X$ if did_one then goto Purge_build X$ write sys$output "%NOTPURG-F-NONETOPURGE No files to purge" X$ delete notes_purge.ctl; X$ exit X$ ! X$ ! Now we start building the actual delete command file (Oy!) X$ ! X$Purge_build: X$ ! X$ open/write/share=read purge_cmd notes_purge_execute.com X$ open/read purge_list notes_purge.ctl X$Next_purge_record: X$ read/end=Purge_build_Done purge_list line X$ record_command = "Purge_"+f$element(0, " ", line) X$ goto 'record_command' X$Purge_F: X$ fname = f$element(1, " ", line) X$ write purge_cmd "$ WRITE SYS$OUTPUT ""Deleting topics from ''fname'""" X$ write purge_cmd "$ NOTES/NONOTEBOOK "+fname X$ write purge_cmd "SET MODERATOR" X$ goto Next_purge_record X$Purge_E: X$ topic = f$element(1, " ", line) X$ if archive_Notes then write purge_cmd "EXTRACT/APPEND ''fname'."+ - X`009f$element(3, " ", line)+" ''topic'.*" X$ replies = f$integer(f$element(2, " ", line)) X$Purge_E_1: X$ write purge_cmd "DELETE/NOCONFIRM NOTE ''topic'."+f$string(replies) X$ replies = replies - 1 X$ if replies .ge. 0 then goto Purge_E_1 X$ goto Next_purge_record X$Purge_: X$ write purge_cmd "EXIT" X$ full_filename = lib_spec+fname+".NOTE" X$ write purge_cmd "$ CONVERT/FDL=NOTES_PURGE.FDL "+full_filename+" "+- X`009full_filename X$ write purge_cmd "$ SET FILE/PROT=(S:RWED) "+full_filename+";-1" X$ write purge_cmd "$ PURGE "+full_filename X$ goto Next_purge_record X$ ! X$Purge_build_Done: X$ write purge_cmd "$ EXIT" X$ close purge_cmd X$ close purge_list X$ delete notes_purge.ctl; X$ ! X$ Jnet_node = f$edit(f$trnlnm("JAN_LOCAL_NODE"), "TRIM") X$ BBoard_name = f$edit(f$trnlnm("BBOARD_HOOK_NAME"), "TRIM") X$ send 'BBoard_name'@'Jnet_node' suspend X$ ! X$ oldpriv = f$setprv("WORLD") X$ pid_context = "" X$ ! X$Find_Notes_PID: X$ pid = f$pid(pid_context) X$ if pid .eqs. "" then goto Ready_to_run ! didn't find a Notes process X$ if f$getjpi(pid, "MODE") .nes. "NETWORK" then goto Find_Notes_PID X$ if f$extract(0, 6, f$getjpi(pid, "PRCNAM")) .nes. "NOTES$" then - X`009goto Find_Notes_PID X$ ! X$ ! Now we've got the PID, next loop until it's not serving anyone X$ ! X$Wait_until_clear: X$ prcnam = f$getjpi(pid, "PRCNAM") X$ num = f$integer(f$element(0, "*", f$element(1, "_", prcnam))) X$ if num .eq. 0 then goto Ready_to_run X$ wait 00:00:15 `009`009`009! 15 seconds should be good X$ goto Wait_until_clear X$ ! X$ ! Finally, we're clear to go for it X$ ! X$Ready_to_run: X$ x = f$setprv(oldpriv) X$ @notes_purge_execute.com X$ send 'BBoard_name'@'Jnet_node' resume X$ delete notes_purge_execute.com; X$ exit $ GOSUB UNPACK_FILE $ FILE_IS = "NOTES_PURGE.FDL" $ CHECKSUM_IS = 1601924934 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY XSYSTEM X`009SOURCE VAX/VMS X XFILE X`009BEST_TRY_CONTIGUOUS yes X`009BUCKET_SIZE 3 X`009CLUSTER_SIZE 2 X`009CONTIGUOUS no X`009EXTENSION 15 X`009FILE_MONITORING no X`009GLOBAL_BUFFER_COUNT 0 X`009ORGANIZATION indexed X`009PROTECTION (system:RWE, owner:RWE, group:, world:) X XRECORD X`009BLOCK_SPAN yes X`009CARRIAGE_CONTROL none X`009FORMAT variable X`009SIZE 1024 X XAREA 0 X`009BEST_TRY_CONTIGUOUS yes X`009BUCKET_SIZE 3 X`009EXTENSION 15 X XAREA 1 X`009BEST_TRY_CONTIGUOUS yes X`009BUCKET_SIZE 3 X`009EXTENSION 3 X XAREA 2 X`009BEST_TRY_CONTIGUOUS yes X`009BUCKET_SIZE 3 X`009EXTENSION 12 X XKEY 0 X`009CHANGES no X`009DATA_KEY_COMPRESSION no X`009DATA_RECORD_COMPRESSION yes X`009DATA_AREA 0 X`009DATA_FILL 100 X`009DUPLICATES no X`009INDEX_AREA 1 X`009INDEX_COMPRESSION no X`009INDEX_FILL 100 X`009LEVEL1_INDEX_AREA 1 X`009NAME "" X`009NULL_KEY no X`009PROLOG 3 X`009SEG0_LENGTH 4 X`009SEG0_POSITION 0 X`009TYPE bin4 X XKEY 1 X`009CHANGES yes X`009DATA_KEY_COMPRESSION no X`009DATA_AREA 2 X`009DATA_FILL 100 X`009DUPLICATES yes X`009INDEX_AREA 2 X`009INDEX_COMPRESSION no X`009INDEX_FILL 100 X`009LEVEL1_INDEX_AREA 2 X`009NAME "" X`009NULL_KEY no X`009SEG0_LENGTH 4 X`009SEG0_POSITION 72 X`009TYPE bin4 X XKEY 2 X`009CHANGES yes X`009DATA_KEY_COMPRESSION yes X`009DATA_AREA 2 X`009DATA_FILL 100 X`009DUPLICATES yes X`009INDEX_AREA 2 X`009INDEX_COMPRESSION yes X`009INDEX_FILL 100 X`009LEVEL1_INDEX_AREA 2 X`009NAME "" X`009NULL_KEY yes X`009NULL_VALUE 0 X`009SEG0_LENGTH 64 X`009SEG0_POSITION 4 X`009TYPE string $ GOSUB UNPACK_FILE $ FILE_IS = "RULES.C" $ CHECKSUM_IS = 36402187 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X#include X#include X#include X#include X#include X#include X#include X#include "bboard.h" X X#define LOAD_LIST`0090x0001 X#define LOAD_SOURCE`0090x0002 X#define LOAD_RULE`0090x0004 X#define LOAD_DIGEST`0090x0008 X#define LOAD_MANAGER`0090x0010 X#define LOAD_LINKS`0090x0020 X#define LOAD_IGNORE`0090x0040 X X#define LOAD_LOG`0090x0100 X#define LOAD_ERR`0090x0200 X#define LOAD_TIMER`0090x0400 X#define LOAD_COUNT`0090x0800 X#define LOAD_CONTACT`0090x1000 X X#define LOAD_MANDATORY`0090x0017 X#define LOAD_SINGULAR`0090x1f00 X Xstatic int scan_ctl_file(FILE * in, char * node, char * user); Xstatic void parse_ctl_file(FILE * in); Xstatic void singular_cleanup(void); Xstatic void parse_control_line(struct rule_ctl * cur_ctl, char * in_line, X`009int item); Xstatic void load_text(char * so, char * si, int len); Xstatic void release_control_memory(void); Xstatic int search_lists(FILE * note, struct rule_info * rule); Xstatic int hdr_item_found(char * line, struct source_info * cur); Xstatic void build_header_line(struct source_info * cur, char * line); X Xstruct ctl_base `123 X int count; X int n_count; X void * p; X`125; X Xstruct rule_ctl `123 X char * string; X int section; X int size; X struct ctl_base * ctl; X`125; X Xstruct digest_def `123 X char digest_id; X int split_len; X int split_error; X`125; X Xstruct manager_list `123 X char user[9]; X`125; X Xstruct link_info `123 X char link[9]; X`125; X Xstruct ignore_list `123 X char node[9]; X char user[9]; X`125; X Xstatic struct ctl_base lst, src, rul, dig, man; Xstatic struct ctl_base lnk, ign; Xstatic struct ctl_base s_log, s_err, s_tim, s_cou, s_ctct; X Xstatic struct rule_ctl rule_control[] = `123 V `123 ":lists", LOAD_LIST, sizeof(struct list_info), &lst `125 X, V `123 ":sources", LOAD_SOURCE, sizeof(struct source_info), &src `125 X, V `123 ":rules", LOAD_RULE, sizeof(struct rule_info), &rul `125 X, V `123 ":digests", LOAD_DIGEST, sizeof(struct digest_def),`009 &dig `1 X25, V `123 ":manager", LOAD_MANAGER, sizeof(struct manager_list), &man `125 X, X V `123 ":links", LOAD_LINKS, sizeof(struct link_info), &lnk `125 X, V `123 ":ignore", LOAD_IGNORE, sizeof(struct ignore_list), &ign `125 X, X V `123 ":log_file.", LOAD_LOG, 256, &s_log `1 X25, V `123 ":err_conf.", LOAD_ERR, 80, &s_err `1 X25, V `123 ":time_int.", LOAD_TIMER, 14, &s_tim `1 X25, V `123 ":count_int.", LOAD_COUNT, 4, &s_cou `1 X25, V `123 ":local_ctct.", LOAD_CONTACT, 12, &s_ctct ` X125, X `123 NULL,`009 0,`009`0090,`009`009`009 0 `125 X`125; X X/* Read the control information, checking if it's all there */ X Xint read_control_file(int reload, char * node, char * user) X`123 X FILE * in;`009`009`009`009/* Control file */ X struct rule_ctl * cur;`009`009/* Used to obtain pointers */ X X /* First, let's open the file */ X X in = fopen(control_file.dsc$a_pointer, "r"); X if (in == NULL) `123 X`009sprintf(temp, "Unable to open rules control file '%s'.", X`009`009control_file.dsc$a_pointer); X`009inter_error("F ", temp, node, user); X`009return (FALSE); X `125 X X /* Does the file have the necessary sections */ X X if (!scan_ctl_file(in, node, user)) `123 X`009if (!reload) `123 X`009 sprintf(temp, "F Control file errors causing %s abort.\n", X`009`009 hook_name.dsc$a_pointer); X`009 critical_error(temp); X`009`125 X`009return(FALSE); X `125 X X /* If we have old information, lose it */ X X if (reload) `123 X`009release_control_memory(); X `125 X X /* Allocate some new memory for all of the sections that need it */ X X#ifdef DEBUG X printf("read_control_file: about to allocate structure memory\n"); X#endif X X for (cur = rule_control; cur->string; cur++) `123 X`009cur->ctl->count = cur->ctl->n_count; X`009if (cur->ctl->count) `123 X`009 cur->ctl->p = xmalloc(cur->size * (cur->ctl->count+SLOP_LEN)); X`009 memset(cur->ctl->p, 0, cur->size * (cur->ctl->count+SLOP_LEN)); X`009`125 else `123 X`009 cur->ctl->p = NULL; X`009`125 X `125 X X /* Back to the beginning to read it again */ X X rewind(in); X X /* And read in the info */ X X#ifdef DEBUG X printf("read_control_file: about to build new control information\n"); X#endif X X parse_ctl_file(in); X X /* What d'ya know... It worked! */ X X return(TRUE); X`125 X X/* Make sure that the right sections are present and figure out how many */ X Xstatic int scan_ctl_file(FILE * in, char * node, char * user) X`123 X char line[200];`009`009`009/* For reading the control file */ X int cur_section;`009`009`009/* What are we looking at? */ X int item_cnt;`009`009`009/* How many have we seen? */ X int sections_seen;`009`009`009/* What have we seen in total */ X struct rule_ctl * cur;`009`009/* For figuring out what we're seeing */ X X /* Zero out the new counts */ X X for (cur = rule_control; cur->string; cur++) `123 X`009cur->ctl->n_count = 0; X `125 X X /* Nothing happened yet */ X X cur_section = sections_seen = 0; X X /* Let's start reading the file */ X X while (TRUE) `123 X X`009/* Read lines until we fall off the end or we get an error */ X X`009if (!fgets_lcl(line, 200, in)) `123 /* error or EOF */ X`009 break;`009`009`009/* Stop in either event */ X`009`125 X X`009/* Stare at the first character of the line */ X X`009switch (line[0]) `123 X X`009/* Comment character, so ignore the line */ X`009 case '!': X`009`009continue; X X`009/* Section header, so handle it */ X`009 case ':': X X#ifdef DEBUG X`009`009printf("scan_ctl_file: new section header\n"); X#endif X X`009`009/* We're currently in a section, save and start a new one */ X X`009`009if (cur_section) `123 X`009`009 cur->ctl->n_count = item_cnt; /* Save the count */ X X`009`009 /* Do we have to have anything here? */ X X`009`009 if (!item_cnt && (cur_section & LOAD_MANDATORY)) `123 X`009`009`009sprintf(temp, X`009`009`009`009"'%s' section must have at least one line.", X`009`009`009`009cur->string); X`009`009`009inter_error("F ", temp, node, user); X`009`009`009return(FALSE); X`009`009 `125 X`009`009`125 X X`009`009/* So which one are we going to be looking at */ X X`009`009for (cur = rule_control; cur->string; cur++) `123 X`009`009 if (strncmp(line, cur->string, strlen(cur->string))) `123 X`009`009`009continue; X`009`009 `125 X`009`009 cur_section = cur->section; /* Found the right one */ X`009`009 break; X`009`009`125 X X`009`009/* Did we find the section, or is it unknown? */ X X`009`009if (!cur->string) `123 X`009`009 sprintf(temp, "Invalid control command line '%s'.", line); X`009`009 inter_error("F ", temp, node, user); X`009`009 return(FALSE); X`009`009`125 X X`009`009/* Have we already seen this section? No duplicates, please */ X X`009`009if (sections_seen & cur_section) `123 X`009`009 sprintf(temp, "Duplicate section '%s' in control file.", X`009`009`009 line); X`009`009 inter_error("F ", temp, node, user); X`009`009 return(FALSE); X`009`009`125 X X`009`009/* Ok. So it's new and it's valid. Let's set up for it */ X X`009`009sections_seen `124= cur_section;`009/* We've got it */ X`009`009item_cnt = 0;`009`009`009/* And nothing in it, yet */ X X`009`009/* But, is it a single-line section? If so, we're not */ X`009`009/* actually in a section. */ X X`009`009if (cur_section & LOAD_SINGULAR) `123 X`009`009 cur_section = 0; X`009`009 cur->ctl->n_count = 1;`009/* Always just one */ X`009`009`125 X X`009`009break;`009`009`009`009/* Nothing else to do */ X X`009/* Data line. Is it ok? */ X`009 default: X X`009`009/* Are we in a section yet? */ X X`009`009if (!cur_section) `123 X`009`009 sprintf(temp, "Improper sequence for '%s'.", line); X`009`009 inter_error("F ", temp, node, user); X`009`009 return(FALSE); X`009`009`125 X X`009`009/* One more line in the current section */ X X`009`009item_cnt++; X -+-+-+-+-+ End of part 11 +-+-+-+-+-