home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- *
- * nnadmin - nn administator program
- */
-
- #include <signal.h>
- #include <errno.h>
- #include "config.h"
- #include "db.h"
- #include "proto.h"
- #include "term.h"
-
- import char
- *master_directory, *db_directory, *db_data_directory,
- *bin_directory, *news_directory, *news_lib_directory,
- *log_file, *news_active, *pager,
- group_path_name[];
-
- import char *exec_chdir_to;
-
-
- static char *pre_input;
- static int verbose = 1;
-
- extern int group_completion();
-
-
- static get_cmd(prompt1, prompt2)
- char *prompt1, *prompt2;
- {
- char c;
-
- if (s_hangup) {
- printf("\nnnmaster hangup\n");
- nn_exit(0);
- }
-
- s_keyboard = 0;
-
- if (pre_input) {
- if ((c = *pre_input++) == NUL)
- nn_exit(0);
- } else {
- do {
- if (prompt1) printf("\r%s\n", prompt1);
- if (prompt2) printf("\r%s >>>", prompt2);
- fl;
- raw();
- c = get_c();
- unset_raw();
- if (c == K_interrupt)
- s_keyboard++;
- else
- if (c == '!') {
- putchar(NL);
- if (exec_chdir_to != NULL)
- printf("\n\rDirectory: %s", exec_chdir_to);
- run_shell((char *)NULL, 0);
- } else
- printf("%c\n\n\r", c);
- } while (c == '!');
- }
-
- if (islower(c))
- c = toupper(c);
-
- return c;
- }
-
-
- static long get_entry(prompt_str, min_val, max_val)
- char *prompt_str;
- long min_val, max_val;
- {
- char buf[100];
- long val;
-
- loop:
-
- printf("%s %ld..%ld (or all): ", prompt_str, min_val, max_val);
- fl;
- gets(buf);
- if (buf[0] == 'a' || buf[0] == NUL)
- return -1L;
-
- val = atol(buf);
- if (val < min_val || val > max_val) goto loop;
-
- return val;
- }
-
-
- static admin_confirm(action, must_confirm)
- char *action;
- {
- char buffer[100];
-
- if (pre_input && !must_confirm) return 1;
-
- sprintf(buffer, "Confirm %s Y)es N)o", action);
-
- return get_cmd((char *)NULL, buffer) == 'Y';
- }
-
- static char *get_groupname()
- {
- char * groupname;
-
- raw();
- printf("\n\n\r");
- prompt_line = Lines - 2;
- prompt("Group: ");
- fl;
- groupname = get_s(NONE, NONE, NONE, group_completion);
- unset_raw();
-
- putchar(NL); putchar(CR);
-
- if (groupname == NULL) return NULL;
-
- if (groupname[0]) return groupname;
-
- if (current_group == NULL) return NULL;
- if (current_group->group_flag & G_FOLDER) return NULL;
-
- return current_group->group_name;
- }
-
-
- static update_master()
- {
- register group_header *gh;
- int ngp;
-
- if (who_am_i != I_AM_ADMIN) {
- printf("Can only perform (U)pdate as nnadmin\n");
- return;
- }
-
- ngp = master.number_of_groups;
-
- open_master(OPEN_READ);
-
- if (master.number_of_groups != ngp) {
- printf("\nNumber of groups changed from %d to %d\n",
- ngp, master.number_of_groups);
- }
-
- ngp = 0;
-
- Loop_Groups_Header(gh)
- if (update_group(gh) == -1) ngp++;
-
- if (ngp) printf("There are %d blocked groups\n", ngp);
- }
-
- static find_files(gh)
- group_header *gh;
- {
- char command[512], name[FILENAME], *db_data_path();
-
- if (gh == NULL) {
- if (db_data_directory == NULL) {
- printf("Cannot list all files (they are scattered over the news partition)\n");
- return;
- }
- sprintf(command, "ls -l %s | %s", db_data_directory, pager);
- } else
- sprintf(command, "ls -l %s", db_data_path(name, gh, '*'));
- system(command);
- }
-
- static master_status()
- {
- int cur_group, nblocked, nignored;
- long articles, disk_use;
- register group_header *gh;
-
- printf("\nMaster:\n");
- printf(" initialized: %s\n", date_time(master.db_created));
- printf(" last_scan: %s\n", date_time(master.last_scan));
- printf(" last_size: %ld\n", (long)master.last_size);
- printf(" no of groups: %d\n", master.number_of_groups);
-
- articles = disk_use = 0;
- nblocked = nignored = 0;
-
- for (cur_group = 0; cur_group < master.number_of_groups; cur_group++) {
- gh = &active_groups[cur_group];
-
- #define DISK_BLOCKS(bytes) (((bytes) + 1023) / 1024)
-
- disk_use += DISK_BLOCKS(gh->index_write_offset);
- disk_use += DISK_BLOCKS(gh->data_write_offset);
-
- articles += gh->last_db_article - gh->first_db_article + 1;
-
- if (gh->master_flag & M_BLOCKED) nblocked++;
- if (gh->master_flag & M_IGNORE_GROUP) nignored++;
- }
-
- printf("\n Articles: %ld\n", articles);
- printf( " Disk usage: %ld k\n\n", disk_use);
-
- if (nblocked) printf("Blocked groups: %3d\n", nblocked);
- if (nignored) printf("Ignored groups: %3d\n", nignored);
- }
-
- static dump_g_flag(gh)
- register group_header *gh;
- {
- printf("Flags: ");
- if (gh->master_flag & M_BLOCKED) printf(" BLOCKED");
- if (gh->master_flag & M_EXPIRE) printf(" EXPIRE");
- if (gh->master_flag & M_MODERATED) printf(" MODERATED");
- if (gh->master_flag & M_CONTROL) printf(" CONTROL");
- if (gh->master_flag & M_NO_DIRECTORY) printf(" NO_DIRECTORY");
- if (gh->master_flag & M_ALWAYS_DIGEST) printf(" ALWAYS_DIGEST");
- if (gh->master_flag & M_NEVER_DIGEST) printf(" NEVER_DIGEST");
- if (gh->master_flag & M_INCLUDE_OLD) printf(" INCL_OLD");
- if (gh->master_flag & M_AUTO_RECOLLECT) printf(" RECOLLECT");
- if (gh->master_flag & M_AUTO_ARCHIVE) printf(" ARCHIVE");
- if (gh->master_flag & M_IGNORE_GROUP) printf(" IGNORE");
- if (gh->master_flag & M_VALID) printf(" VALID");
- printf("\n");
- }
-
- static dump_m_entry(gh)
- register group_header *gh;
- {
- update_group(gh);
-
- printf("\n%s\t%d\n", gh->group_name, gh->group_num);
- printf("first/last art: %06ld %06d\n",
- gh->first_db_article, gh->last_db_article);
- printf(" active info: %06ld %06d\n",
- gh->first_a_article, gh->last_a_article);
- printf("Offsets: index->%ld, data->%ld\n",
- gh->index_write_offset,
- gh->data_write_offset);
- if (gh->master_flag & M_AUTO_ARCHIVE)
- printf("Archive file: %s\n", gh->archive_file);
- if (gh->master_flag)
- dump_g_flag(gh);
- }
-
- #define valerr( xxx , tp) { \
- if (verbose) { printf xxx ; fl; } \
- err_type = tp; \
- goto err; \
- }
-
- static validate_group(gh)
- group_header *gh;
- {
- FILE *data, *ix;
- off_t data_offset, next_offset;
- cross_post_number cross_post;
- article_number cur_article;
- int n, err_type;
-
- data = ix = NULL;
-
- if (gh->first_db_article == (gh->last_db_article + 1)
- && gh->index_write_offset == 0)
- return 1;
-
- if (verbose) { printf("\r%s: ", gh->group_name); clrline(); }
-
- if (init_group(gh) <= 0) {
- printf("NO DIRECTORY (ok)");
- return 1; /* no directory/ignored */
- }
-
- update_group(gh);
-
- if (gh->master_flag & M_BLOCKED) {
- if (verbose) printf("BLOCKED (ok)\n");
- return 1;
- }
-
- /*
- * Check for major inconcistencies.
- * Sometimes, news expire will reset article numbers
- * to start from 0 again
- */
-
- if (gh->last_db_article == 0) {
- return 1;
- }
-
- #ifdef RENUMBER_DANGER
- if (gh->first_a_article > (gh->last_db_article + 1) ||
- gh->last_db_article > gh->last_a_article ||
- gh->first_db_article > gh->first_a_article) {
-
- if (verbose)
- printf("RENUMBERING OF ARTICLES (active=%ld..%ld master=%ld..%ld)",
- gh->first_a_article, gh->last_a_article,
- gh->first_db_article, gh->last_db_article);
- err_type = 99;
- goto err;
- }
- #endif
-
- ix = open_data_file(gh, 'x', OPEN_READ);
- if (ix == NULL) valerr(("NO INDEX FILE"), 1);
-
- data = open_data_file(gh, 'd', OPEN_READ);
- if (data == NULL) valerr(("NO DATA FILE"), 2);
-
- cur_article = gh->first_db_article - 1;
-
- while (cur_article <= gh->last_db_article) {
- if (s_hangup || s_keyboard) goto out;
-
- data_offset = ftell(data);
-
- switch (db_read_art(data)) {
- case 0:
- if (data_offset == gh->data_write_offset) goto out;
- valerr(("No header for article # %ld", (long)cur_article+1), 3);
- case 1:
- break;
- case -1:
- valerr(("END OF FILE on DATA FILE"), 4);
- }
-
- if (db_hdr.dh_number <= 0 || cur_article > db_hdr.dh_number)
- valerr(("OUT OF SEQUENCE: %ld after %ld", (long)db_hdr.dh_number, (long)cur_article), 11);
-
- if (cur_article < db_hdr.dh_number) {
- if (db_data.dh_type == DH_SUB_DIGEST)
- valerr(("NO DIGEST HEADER: %ld", (long)db_hdr.dh_number), 5);
-
- do {
- cur_article++;
- if (!db_read_offset(ix, &next_offset))
- valerr(("NO INDEX FOR ARTICLE %ld", (long)cur_article), 6);
-
- if (data_offset != next_offset)
- valerr(("OFFSET ERROR: %ld: %ld != %ld", (long)cur_article, (long)data_offset, (long)next_offset), 7);
- } while (cur_article < db_hdr.dh_number);
- }
-
- for (n = 0; n < db_hdr.dh_cross_postings; n++) {
- cross_post = NETW_CROSS_INT(db_data.dh_cross[n]);
- if (cross_post < master.number_of_groups) continue;
- valerr(("CROSS POST RANGE ERROR: %ld (article # %ld)", (long)cross_post, (long)cur_article), 8);
- }
- }
-
- out:
- if (!s_keyboard && !s_hangup) {
- data_offset = ftell(data);
- if (data_offset != gh->data_write_offset)
- valerr(("DATA OFFSET %ld != %ld", (long)gh->data_write_offset, (long)data_offset), 9);
- data_offset = ftell(ix);
- if (data_offset != gh->index_write_offset)
- valerr(("INDEX OFFSET %ld != %ld", (long)gh->index_write_offset, (long)data_offset), 10);
- }
-
- fclose(data);
- fclose(ix);
- if (verbose) printf("OK");
- return 1;
-
- err:
- if (data != NULL) fclose(data);
- if (ix != NULL) fclose(ix);
- log_entry('V', "%s: database error %d", gh->group_name, err_type);
- if (verbose) {
- putchar(NL);
- dump_m_entry(gh);
- }
-
- if (!pre_input) {
- ding();
-
- for (;;) {
- switch (get_cmd((char *)NULL,
- "\nRepair group Y)es N)o E)nter Q)uit")) {
- case 'Y':
- break;
- case 'N':
- return 0;
- case 'Q':
- s_keyboard++;
- return 0;
- case 'E':
- group_admin(gh);
- continue;
- default:
- continue;
- }
- break;
- }
- }
-
- send_master(SM_RECOLLECT, gh, SP, 0L);
- return 0;
- }
-
- static dump_group(gh)
- group_header *gh;
- {
- FILE *data, *ix;
- off_t offset;
- cross_post_number cross_post;
- article_number first_article;
- int n;
-
- if (init_group(gh) <= 0)
- printf("cannot access group %s\n", gh->group_name);
-
- update_group(gh);
-
- first_article = get_entry("First article",
- (long)gh->first_db_article,
- (long)gh->last_db_article);
-
- if (first_article < 0) first_article = gh->first_db_article;
- if (first_article <= 0) first_article = 1;
-
- ix = open_data_file(gh, 'x', OPEN_READ);
- data = open_data_file(gh, 'd', OPEN_READ);
- if (ix == NULL || data == NULL) goto err;
-
- fseek(ix, get_index_offset(gh, first_article), 0);
- if (!db_read_offset(ix, &offset)) goto err;
- fseek(data, offset, 0);
-
- clrdisp();
- pg_init(1, 1);
-
- for (;;) {
- if (s_hangup || s_keyboard) break;
-
- if (pg_scroll(6)) {
- s_keyboard = 1;
- break;
- }
-
- offset = ftell(data);
-
- switch (db_read_art(data)) {
- case 0:
- goto out;
- case 1:
- break;
- case -1:
- goto err;
- }
-
- printf("\noffset = %ld, article # = %ld",
- (long)offset, (long)(db_hdr.dh_number));
-
- switch (db_data.dh_type) {
- case DH_DIGEST_HEADER:
- printf(" (digest header)\n");
- break;
- case DH_SUB_DIGEST:
- printf(" (digest sub-article)\n");
- break;
- case DH_NORMAL:
- putchar(NL);
- break;
- }
-
- if (db_hdr.dh_cross_postings) {
- printf("xpost(%d):", db_hdr.dh_cross_postings);
-
- for (n = 0; n < db_hdr.dh_cross_postings; n++) {
- cross_post = NETW_CROSS_INT(db_data.dh_cross[n]);
- printf(" %d", cross_post);
- }
- putchar(NL);
- }
-
- printf("ts=%lu hp=%ld, fp=+%d, lp=%ld, ref=%d%s, lines=%d\n",
- (long unsigned)db_hdr.dh_date, (long)db_hdr.dh_hpos,
- (int)db_hdr.dh_fpos, (long)db_hdr.dh_lpos,
- db_hdr.dh_replies & 0x7f,
- (db_hdr.dh_replies & 0x80) ? "+Re" : "",
- db_hdr.dh_lines);
-
- if (db_hdr.dh_sender_length)
- printf("Sender(%d): %s\n", db_hdr.dh_sender_length, db_data.dh_sender);
- else
- printf("No sender\n");
-
- if (db_hdr.dh_subject_length)
- printf("Subj(%d): %s\n", db_hdr.dh_subject_length, db_data.dh_subject);
- else
- printf("No subject\n");
- }
-
- out:
- if (!s_keyboard && !s_hangup && ftell(data) != gh->data_write_offset)
- goto err;
-
- fclose(data);
- fclose(ix);
- return 1;
-
- err:
- if (data != NULL) fclose(data);
- if (ix != NULL) fclose(ix);
- printf("\n*** DATABASE INCONSISTENCY DETECTED - run V)alidate\n");
- return 0;
- }
-
- static kill_master(term)
- int term;
- {
- switch (proto_lock(I_AM_MASTER, term ? PL_TERMINATE : PL_WAKEUP_SOFT)) {
- case 1:
- if (verbose)
- printf("sent %s signal to master\n", term ? "termination" : "wakeup");
- break;
- case 0:
- printf("cannot signal master\n");
- break;
- case -1:
- if (verbose) printf("master is not running\n");
- break;
- }
- }
-
- static master_admin()
- {
- register char c;
- int cur_group;
- long value;
- register group_header *gh;
-
- exec_chdir_to = db_directory;
-
- for (;;) {
- switch (c = get_cmd(
- "\nD)ump F)iles G)roup K)ill O)ptions S)tat T)race",
- "MASTER")) {
-
- case 'G':
- cur_group = (int)get_entry("Group number",
- 0L, (long)(master.number_of_groups - 1));
- if (cur_group >= 0)
- dump_m_entry(&active_groups[cur_group]);
- break;
-
- case 'D':
- do {
- c = get_cmd(
- "\nA)ll B)locked E)mpty H)oles I)gnored N)on-empty V)alid in(W)alid",
- "DUMP");
- cur_group = -1;
- pg_init(1, 1);
-
- while (++cur_group < master.number_of_groups) {
- if (s_keyboard || s_hangup) break;
-
- gh = &active_groups[cur_group];
- #define NODUMP(cond) if (cond) continue; break
- switch (c) {
- case 'N':
- NODUMP(gh->index_write_offset == 0);
- case 'E':
- NODUMP(gh->index_write_offset != 0);
- case 'H':
- NODUMP(gh->first_a_article >= gh->first_db_article);
- case 'B':
- NODUMP((gh->master_flag & M_BLOCKED) == 0);
- case 'I':
- NODUMP((gh->master_flag & M_IGNORE_GROUP) == 0);
- case 'V':
- NODUMP((gh->master_flag & M_VALID) == 0);
- case 'W':
- NODUMP(gh->master_flag & M_VALID);
- default:
- s_keyboard = 1; continue;
- }
-
- if (pg_scroll(6)) break;
- dump_m_entry(gh);
- }
- } while (!s_keyboard && !s_hangup);
- break;
-
- case 'F':
- find_files((group_header *)NULL);
- break;
-
- case 'O':
- c = get_cmd("r)epeat_delay e)xpire_level", "OPTION");
- if (c != 'R' && c != 'E') break;
- value = get_entry("Option value", 1L, 10000L);
- if (value < 0) break;
- send_master(SM_SET_OPTION, (group_header *)NULL, tolower(c), value);
- break;
-
- case 'S':
- master_status();
- break;
-
- case 'T':
- send_master(SM_SET_OPTION, (group_header *)NULL, 't', -1L);
- break;
-
- case 'K':
- if (admin_confirm("Stop nn Master", 0))
- kill_master(1);
- break;
-
- default:
- exec_chdir_to = NULL;
- return;
- }
- }
- }
-
-
- static log_admin()
- {
- char command[FILENAME + 100], c;
-
- if (pre_input && *pre_input == NUL) {
- c = SP;
- goto log_tail;
- }
-
- loop:
-
- c = get_cmd(
- "\n1-9)tail A)dm C)ollect E)rr N)ntp G)roup R)eport e(X)pire .)all @)clean",
- "LOG");
-
- if (c < SP || c == 'Q') return;
-
- if (c == '@') {
- if (admin_confirm("Truncation", 0)) {
- sprintf(command, "%s.old", log_file);
- unlink(command);
- if (link(log_file, command) < 0) goto tr_failed;
- if (unlink(log_file) < 0) {
- unlink(command);
- goto tr_failed;
- }
- log_entry('A', "Log Truncated");
- chmod(log_file, 0666);
- }
- return;
-
- tr_failed:
- printf("Truncation failed -- check permissions etc.\n");
- goto loop;
- }
-
- if (c == 'G') {
- char *groupname;
-
- if ((groupname = get_groupname()) == NULL) goto loop;
- sprintf(command, "fgrep '%s' %s | %s",
- groupname, log_file, pager);
- system(command);
-
- goto loop;
- }
-
- log_tail:
- if (c == '$' || c == SP || isdigit(c)) {
- int n;
-
- n = isdigit(c) ? 10 * (c - '0') : 10;
- sprintf(command, "tail -%d %s", n, log_file);
- system(command);
- goto loop;
- }
-
- if (c == '*') {
- c = '.';
- }
-
- sprintf(command, "grep '^%c:' %s | %s", c, log_file, pager);
- system(command);
-
- goto loop;
- }
-
-
- static flag_admin(gh, mode_str, set_flag)
- group_header *gh;
- char *mode_str;
- int set_flag;
- {
- char buffer[50];
- int new_flag = 0;
-
- putchar(NL);
-
- dump_g_flag(gh);
-
- sprintf(buffer, "%s FLAG", mode_str);
-
- switch (get_cmd(
- "\nA)lways_digest N)ever_digest M)oderated C)ontrol no_(D)ir",
- buffer)) {
-
- default:
- return;
-
- case 'M':
- new_flag = M_MODERATED;
- break;
-
- case 'C':
- new_flag = M_CONTROL;
- break;
-
- case 'D':
- new_flag = M_NO_DIRECTORY;
- break;
-
- case 'A':
- new_flag = M_ALWAYS_DIGEST;
- break;
-
- case 'N':
- new_flag = M_NEVER_DIGEST;
- break;
- }
-
- if (new_flag & (M_CONTROL | M_NO_DIRECTORY))
- if (!admin_confirm("Flag Change", 0))
- new_flag = 0;
-
- if (new_flag) {
- if (set_flag) {
- if (gh->master_flag & new_flag)
- new_flag = 0;
- else {
- send_master(SM_SET_FLAG, gh, 's', (long)new_flag);
- gh->master_flag |= new_flag;
- }
- } else {
- if ((gh->master_flag & new_flag) == 0)
- new_flag = 0;
- else {
- send_master(SM_SET_FLAG, gh, 'c', (long)new_flag);
- gh->master_flag &= ~new_flag;
- }
- }
- }
-
- if (new_flag == 0)
- printf("NO CHANGE\n");
- else
- dump_g_flag(gh);
- }
-
-
- static rmgroup(gh)
- group_header *gh;
- {
- char command[FILENAME*2];
-
- if (!file_exist(news_active, "w")) {
- printf("Not privileged to run rmgroup\n");
- return;
- }
-
- sprintf(command, "%s/rmgroup %s", news_lib_directory, gh->group_name);
- system(command);
- any_key(0);
- gh->master_flag &= ~M_VALID; /* just for nnadmin */
- gh->master_flag |= M_IGNORE_A;
- }
-
- static group_admin(gh)
- register group_header *gh;
- {
- char *groupname, gbuf[FILENAME], dirbuf[FILENAME];
-
- if (gh != NULL) goto have_group;
-
- new_group:
- if ((groupname = get_groupname()) == NULL) return;
-
- gh = lookup(groupname);
- if (gh == NULL) {
- printf("No group named %s\n", groupname);
- goto new_group;
- }
-
- have_group:
- if (!use_nntp && init_group(gh)) {
- strcpy(dirbuf, group_path_name);
- dirbuf[strlen(dirbuf)-1] = NUL;
- exec_chdir_to = dirbuf;
- }
-
- sprintf(gbuf, "GROUP %s", gh->group_name);
-
- for (;;) {
- switch (get_cmd(
- "\nD)ata E)xpire F)iles G)roup H)eader R)ecollect V)alidate Z)ap",
- gbuf)) {
- case 'D':
- dump_group(gh);
- break;
-
- case 'V':
- verbose = 1;
- validate_group(gh);
- putchar(NL);
- break;
-
- case 'H':
- dump_m_entry(gh);
- break;
-
- case 'F':
- find_files(gh);
- break;
-
- case 'S':
- flag_admin(gh, "Set", 1);
- break;
-
- case 'C':
- flag_admin(gh, "Clear", 0);
- break;
-
- case 'R':
- if (admin_confirm("Recolletion of Group", 0))
- send_master(SM_RECOLLECT, gh, SP, 0L);
- break;
-
- case 'Z':
- if (admin_confirm("Remove Group (run rmgroup)", 1))
- rmgroup(gh);
- break;
-
- case 'E':
- if (admin_confirm("Expire Group", 0))
- send_master(SM_EXPIRE, gh, SP, 0L);
- break;
-
- case 'G':
- goto new_group;
-
- default:
- exec_chdir_to = NULL;
- return;
- }
- }
- }
-
-
- static show_config()
- {
- #ifdef NNTP
- extern char nntp_server[];
- #endif
-
- printf("\nConfiguration:\n\n");
- printf("BIN: %s\nLIB: %s\nNEWS SPOOL: %s\nNEWS LIB: %s\n",
- bin_directory,
- lib_directory,
- news_directory,
- news_lib_directory);
-
- printf("DB: %s %s\n", db_directory,
- db_data_directory != NULL ? db_data_directory :
- "(per-group files in group directories)");
-
- printf("ACTIVE: %s\n", news_active);
-
- #ifdef NNTP
- if (use_nntp)
- printf("NNTP ACTIVE. server=%s\n", nntp_server);
- else
- printf("NNTP NOT ACTIVE\n");
- #endif
-
- #ifdef NETWORK_DATABASE
- printf("Database is machine independent (network format).\n");
- #ifdef NETWORK_BYTE_ORDER
- printf("Local system assumes to use network byte order\n");
- #endif
- #else
- printf("Database format is machine dependent (byte order and alignment)\n");
- #endif
- printf("Database version: %d\n", NNDB_MAGIC & 0xff);
-
- #ifdef STATISTICS
- printf("Recording usage statistics\n");
- #else
- printf("No usage statistics are recorded\n");
- #endif
-
- printf("Mail delivery program: %s\n", REC_MAIL);
- #ifdef APPEND_SIGNATURE
- printf("Query for appending .signature ENABLED\n");
- #else
- printf("Query for appending .signature DISABLED\n");
- #endif
-
- printf("Max pathname length is %d bytes\n", FILENAME-1);
- }
-
-
- admin_mode(input_string)
- char *input_string;
- {
- register group_header *gh;
- int was_raw = unset_raw();
-
- if (input_string && *input_string) {
- pre_input = input_string;
- } else {
- pre_input = NULL;
- printf("\nMaster is%s running\n",
- proto_lock(I_AM_MASTER, PL_CHECK) < 0 ? " NOT" : "");
- }
-
- for (;;) {
- switch(get_cmd(
- "\nC)onf E)xpire G)roups I)nit L)og M)aster Q)uit S)tat U)pdate V)alidate W)akeup",
- "ADMIN")) {
-
- case 'M':
- master_admin();
- break;
-
- case 'W':
- kill_master(0);
- break;
-
- case 'E':
- if (admin_confirm("Expire All Groups", 1))
- send_master(SM_EXPIRE, (group_header *)NULL, SP, 0L);
- break;
-
- case 'I':
- if (admin_confirm("INITIALIZATION, i.e. recollect all groups", 1))
- send_master(SM_RECOLLECT, (group_header *)NULL, SP, 0L);
- break;
-
- case 'G':
- group_admin((group_header *)NULL);
- break;
-
- case 'L':
- log_admin();
- break;
-
- case 'S':
- master_status();
- break;
-
- case 'C':
- show_config();
- break;
-
- case 'U':
- update_master();
- break;
-
- case 'Z':
- verbose = 0;
- /* FALL THRU */
-
- case 'V':
- Loop_Groups_Sorted(gh) {
- if (s_hangup || s_keyboard) break;
- validate_group(gh);
- }
- verbose = 1;
- break;
-
- case '=':
- verbose = !verbose;
- break;
-
- case 'Q':
- if (was_raw) raw();
- return;
- }
- }
- }
-