home *** CD-ROM | disk | FTP | other *** search
- /*
- SNEWS 2.0
-
- active.c - routines to manipulate the active and ng files
-
-
- Copyright (C) 1991 John McCombs, Christchurch, NEW ZEALAND
- john@ahuriri.gen.nz
- PO Box 2708, Christchurch, NEW ZEALAND
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License, version 1, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See the file COPYING, which contains a copy of the GNU General
- Public License.
- */
-
-
- #include "defs.h"
- #include "active.h"
-
- extern INFO my_stuff;
-
-
- /*
- * These private variables are used to do all the i/o on the active
- * file.
- */
- static FILE *active_file;
- static ACTIVE *local_head;
- static POST_GROUPS *pg;
-
-
-
- /*--------------------------- load the active file --------------------------*/
- ACTIVE *load_active_file(void)
- {
- /*
- * This routine opens the active file. It reads the data, allocating
- * ACTIVE elements in a linked list. Returns a pointer to the head of
- * the linked list.
- */
- char fn[80], buf[81];
- char *p;
- ACTIVE *this, *head = NULL ;
- long posn = 0;
- int ct = 0;
- int ct_gp = 0;
-
- /* open the file */
- strcpy(fn, my_stuff.news_dir);
- strcat(fn, "active");
- if ((active_file = fopen(fn, "r+b")) == NULL) {
- fprintf(stderr, "cannot open %s\n", fn);
- exit(1);
- }
-
- /* read and store */
- while (fgets(buf, 80, active_file) != NULL) {
-
- /* exit on ^Z on column 1 */
- if (buf[0] == '\x1A')
- break;
-
- ct++;
-
- if (strlen(buf) > 0) {
-
- if (head == NULL) {
- head = this = xmalloc(sizeof (ACTIVE));
- head->last = NULL;
- head->index = ct_gp;
- } else {
- ct_gp++;
- this->next = xmalloc(sizeof (ACTIVE));
- this->next->last = this;
- this = this->next;
- this->index = ct_gp;
- }
-
- if ((this) == NULL) {
- fprintf(stderr, "cannot allocate memory for active list\n");
- exit(1);
- }
-
-
- if ((p = strtok(buf, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d\n", ct);
- exit(1);
- }
- strcpy(this->group, p);
-
- if ((p = strtok(NULL, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d\n", ct);
- exit(1);
- }
- strcpy(this->gp_file, p);
-
- if ((p = strtok(NULL, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d\n", ct);
- exit(1);
- }
- this->lo_num = atol(p);
-
- if ((p = strtok(NULL, " ")) == NULL) {
- fprintf(stderr, "active file corrupt at line %d\n", ct);
- exit(1);
- }
- this->hi_num = atol(p);
-
- this->num_pos = posn;
- this->read_list = NULL;
- }
-
- posn = ftell(active_file);
- }
-
- this->next = NULL;
- head->groups = ct;
-
- local_head = head;
-
- /* load up the posting list */
- pg = post_group_file();
-
- return(head);
- }
-
-
-
-
- /*------------------------- close the active file ---------------------------*/
- void close_active_file(void)
- {
- /*
- * Close the active file and deallocate the linked list
- */
-
- ACTIVE *this;
-
- this = local_head;
-
- while (this != NULL) {
- local_head = this;
- this = this->next;
- free(local_head);
- }
-
- fclose(active_file);
-
- free_ng();
-
- }
-
-
- /*------------------------- close the active file ---------------------------*/
- void close_active(void)
- {
- /*
- * Close the active file
- */
-
-
- fclose(active_file);
-
- }
-
-
-
- /*--------------------------- load the newsgroups file --------------------------*/
- POST_GROUPS *post_group_file(void)
- {
- /*
- * This routine opens the active file. It reads the data, allocating
- * POST_GROUPS elements in a linked list. Returns a pointer to the head
- * of the linked list.
- */
- char fn[80], buf[81], *p;
- POST_GROUPS *this = NULL, *head = NULL ;
- int ct = 0;
- FILE *ngf;
-
- /* open the file - if none, retun null, ie no posts allowed */
- strcpy(fn, my_stuff.news_dir);
- strcat(fn, "ng");
- if ((ngf = fopen(fn, "rb")) == NULL) {
- return(NULL);
- }
-
- /* read and store */
- while (fgets(buf, 80, ngf) != NULL) {
-
- /* exit on ^Z on column 1 */
- if (buf[0] == '\x1A')
- break;
-
- ct++;
-
- if (strlen(buf) > 0) {
-
- if (head == NULL) {
- head = this = xmalloc(sizeof (ACTIVE));
- } else {
- this->next = xmalloc(sizeof (ACTIVE));
- this = this->next;
- }
-
- if ((this) == NULL) {
- fprintf(stderr, "cannot allocate memory for newsgroup list\n");
- exit(1);
- }
-
- if ((p = strtok(buf, " \n\r\t")) == NULL) {
- fprintf(stderr, "newsgroup 'ng' file corrupt at line %d\n", ct);
- exit(1);
- }
-
- strcpy(this->group, p);
- this -> local = isupper(*this -> group);
- strlwr(this -> group);
- }
-
- }
-
- if ( this )
- this->next = NULL;
-
- fclose(ngf);
-
- return(head);
- }
-
-
-
-
- /*------------------------- close the active file ---------------------------*/
- void free_ng()
- {
- /*
- * deallocate the post_groups linked list
- */
-
- POST_GROUPS *this;
-
- this = pg;
-
- while (this != NULL) {
- pg = this;
- this = this->next;
- free(pg);
- }
-
- pg = NULL;
-
- }
-
-
-
-
- /*------------------------- check group in post list -------------------------*/
- int check_valid_post_group(char *ng)
- {
- /*
- * Check a string as a valid newsgroup name. Returns TRUE if found
- */
-
- POST_GROUPS *this;
-
- this = pg;
-
- while (this != NULL) {
- if (strcmp(ng, this->group) == 0)
- return(TRUE);
- this = this->next;
- }
-
- return (FALSE);
- }
-
-
- int is_local_group(char *ng)
- {
- POST_GROUPS *this;
-
- this = pg;
-
- while (this != NULL) {
- if (strcmp(ng, this->group) == 0)
- return(this->local);
- this = this->next;
- }
-
- return (TRUE);
- }
-
-
-
-
- /*-------------------- find a newsgroup in active list ----------------------*/
- ACTIVE *find_news_group(char *group)
- {
- /*
- * This routine searches the active structure for the specified
- * newsgroup, and returns a pointer to the entry, or to group
- * junk if not found. The search for junk is made via a recursive
- * call. Fatal if junk not found
- */
-
- ACTIVE *this;
-
- this = local_head;
-
- while ((this != NULL) && (stricmp(group, this->group) != 0)) {
- this = this->next;
- }
-
- if (this == NULL) {
- if (stricmp(group, "junk") != 0) {
- this = find_news_group("junk");
- } else {
- fprintf(stderr, "active file must have newsgroup junk\n");
- exit(1);
- }
- }
-
- return(this);
-
- }
-
-
-
-
- /*-------------------------- update active file ---------------------------*/
- void update_active_entry(ACTIVE *a)
- {
- /*
- * This routine takes a pointer to an active entry and updates
- * its data on disk
- */
-
- char buf[(ACTIVE_NUM_LEN*2) + 2];
- int n;
- long where;
-
- sprintf(buf, "%08ld %08ld", a->lo_num, a->hi_num);
-
- n = (ACTIVE_NUM_LEN*2) + 1;
- where = a->num_pos + strlen(a->group) + 1 + strlen(a->gp_file) + 1;
- fseek(active_file, where, SEEK_SET);
- if (fwrite(buf, 1, n, active_file) != n) {
- fprintf(stderr, "active file update failed for %s\n", a->group);
- exit(1);
- }
-
- fflush(active_file);
- }
-
-
-
-
-
- /*------------------- make newsgroup name and directory --------------------*/
- char *make_news_group_name(char *ng)
- {
- /*
- * This routine takes the newsgroup name, replaces the '.' with
- * '\' and creates the directory if none exists. The returned name
- * has a trailing '\'
- */
-
- static char fn[512];
- ACTIVE *tmp;
-
-
- tmp = find_news_group(ng);
-
- sprintf(fn, "%snewsbase\\%s", my_stuff.news_dir, tmp->gp_file);
-
- return(&fn[0]);
- }
-
-
-
-
-
- /*-------------------------- save the seen list -------------------------*/
- void load_read_list(void)
- {
- /*
- * Load the user's list of seen articles
- */
-
- FILE *tmp_file;
- ACTIVE *act;
- int i, continue_flag;
- int articles;
- char *a, buf[256], *p, real_name[80];
-
- /* allocate the arrays and set to unread, ie FALSE */
- act = local_head;
- while (act != NULL) {
-
- articles = (int)(act->hi_num - act->lo_num);
- if (articles > 0) {
- a = act->read_list = xmalloc(articles * sizeof(int));
- for (i = 0; i < articles; i++) {
- *(a+i) = FALSE;
- }
- } else {
- act->read_list = NULL;
- }
- act = act->next;
- }
-
- /* read and process the file - if not present, just carry on */
- strcpy(buf, my_stuff.news_dir);
- strcat(buf, my_stuff.user);
- strcat(buf, ".nrc");
- if ((tmp_file = fopen(buf, "rt")) != NULL) {
-
- continue_flag = FALSE;
- while (fgets(buf, 255, tmp_file) != NULL) {
-
- p = strtok(buf, " \n\r");
-
- if (!continue_flag) {
-
- strcpy(real_name, p);
- act = find_news_group(p);
- articles = (int)(act->hi_num - act->lo_num);
-
- /* if no articles or unknown group eat the rest */
- p = strtok(NULL, " \n\r");
-
- }
-
- /* scan the rest of the line getting numbers and setting flags */
- continue_flag = FALSE;
- while (p != NULL) {
-
- /* check for continuation backslash */
- if (*p != '\\') {
- i = (int) (atol(p) - (act->lo_num + 1));
- if ((i >= 0) && (i < articles) &&
- ((stricmp(act->group, "junk") != 0) ||
- (stricmp(real_name, "junk") == 0))) {
- *((act->read_list)+i) = TRUE;
- }
- } else {
- continue_flag = TRUE;
- break;
- }
- p = strtok(NULL, " \n\r");
- }
- }
-
- fclose(tmp_file);
- }
- }
-
-
-
-
-
- /*-------------------------- load the seen list -------------------------*/
- void save_read_list(void)
- {
- /*
- * Save the user's list of read articles and deallocate storage
- */
-
-
- FILE *tmp_file;
- ACTIVE *act;
- int i, articles, ct;
- char buf[256];
-
- /* open the file */
- strcpy(buf, my_stuff.news_dir);
- strcat(buf, my_stuff.user);
- strcat(buf, ".nrc");
- if ((tmp_file = fopen(buf, "wt")) == NULL) {
- fprintf(stderr, "can't open user's rc file for output\n");
- exit(1);
- }
-
- /* write out the lists and deallocate the arrays */
- act = local_head;
- while (act != NULL) {
-
- articles = (int)(act->hi_num - act->lo_num);
- if (articles > 0) {
- fprintf(tmp_file, "%s ", act->group);
-
- ct = 0;
-
- if (act->read_list)
- for (i = 0; i < articles; i++) {
- if(*((act->read_list)+i)) {
- ct++;
- fprintf(tmp_file, "%d ", i+act->lo_num+1);
- if ((ct % 10) == 0)
- fprintf(tmp_file, "\\ \n");
- }
- }
-
- fprintf(tmp_file, "\n");
- if (act->read_list != NULL) {
- free(act->read_list);
- }
- }
- act = act->next;
- }
-
- fclose(tmp_file);
-
- }
-
-
-
-
- /*------------------------- load UUPC rc files ---------------------------*/
- int load_stuff(void)
- {
- /*
- * Trawl the UUPC files to get the stuff we need - return TRUE
- * if completed ok
- */
-
- int res = 0;
- int i;
- char buf[256], confdir[256];
- char *fn, *p, *v;
- FILE *tmp;
-
-
- /* news base directory */
- if ((fn = getenv("UUPCNEWS")) == NULL) {
- fprintf(stderr, "UUPCNEWS environment variable undefined\n");
- exit(1);
- }
-
- /* give it a trailing \ */
- strcpy(my_stuff.news_dir, fn);
- if (my_stuff.news_dir[ strlen(my_stuff.news_dir)-1 ] != '\\')
- strcat(my_stuff.news_dir, "\\");
-
- /* read the system file first */
- for (i = 0; i < 2; i++) {
-
- /* choose the file to open */
- if (i == 0) {
- fn = getenv("UUPCSYSRC");
- if (fn == NULL) {
- fprintf(stderr, "Enviroment variable UUPCSYSRC not defined\n");
- }
- } else {
- fn = getenv("UUPCUSRRC");
- if (fn == NULL) {
- fprintf(stderr, "Enviroment variable UUPCUSRRC not defined\n");
- }
- }
-
-
- if ((tmp = fopen(fn, "rt")) != NULL) {
-
- while (fgets(buf, 255, tmp)) {
- p = strtok(buf, " =\r\n");
- if (p && *p != '#') {
-
- v = strtok(NULL, " =\r\n");
-
- if (stricmp(p, "confdir") == 0)
- strcpy(confdir, v);
-
- if (stricmp(p, "mailserv") == 0) {
- strcpy(my_stuff.mail_server, v);
- res++;
- }
- if (stricmp(p, "nodename") == 0) {
- strcpy(my_stuff.my_site, v);
- res++;
- }
- if (stricmp(p, "newsdir") == 0) {
- strcpy(my_stuff.incoming_dir, v);
- if (my_stuff.incoming_dir[ strlen(my_stuff.incoming_dir)-1 ] != '\\')
- strcat(my_stuff.incoming_dir, "\\");
- res++;
- }
- if (stricmp(p, "spooldir") == 0) {
- strcpy(my_stuff.spool_dir, v);
- if (my_stuff.spool_dir[ strlen(my_stuff.spool_dir)-1 ] != '\\')
- strcat(my_stuff.spool_dir, "\\");
- res++;
- }
- if (stricmp(p, "domain") == 0) {
- strcpy(my_stuff.my_domain, v);
- res++;
- }
- if (stricmp(p, "tempdir") == 0) {
- strcpy(my_stuff.temp_name, v);
- res++;
- }
- if (stricmp(p, "mailbox") == 0) {
- strcpy(my_stuff.user, v);
- res++;
- }
- if (stricmp(p, "Signature") == 0) {
- strcpy(my_stuff.signature, v);
- res++;
- }
- if (stricmp(p, "name") == 0) {
- strcpy(my_stuff.my_name, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.my_name, " ");
- strcat(my_stuff.my_name, v);
- v = strtok(NULL, " =\r\n");
- }
- res++;
- }
- if (stricmp(p, "Organization") == 0) {
- strcpy(my_stuff.my_organisation, v);
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.my_organisation, " ");
- strcat(my_stuff.my_organisation, v);
- v = strtok(NULL, " =\r\n");
- }
- res++;
- }
- if (stricmp(p, "Editor") == 0) {
- strcpy(my_stuff.editor, v);
- res++;
- v = strtok(NULL, " =\r\n");
- while (v != NULL) {
- strcat(my_stuff.editor, " ");
- strcat(my_stuff.editor, v);
- v = strtok(NULL, " =\r\n");
- }
- }
- if (stricmp(p, "Home") == 0) {
- strcpy(my_stuff.home, v);
- if (my_stuff.home[ strlen(my_stuff.home)-1 ] != '\\')
- strcat(my_stuff.home, "\\");
- res++;
- }
- }
- }
- fclose (tmp);
-
- } else {
- fprintf(stderr, "Cannot open %s\n", fn);
- }
- }
-
- if ( (p = getenv("LOGNAME")) != NULL ) {
- struct passwd *pwd;
- if ( (pwd = getpwnam(p, confdir)) != NULL ) {
- strcpy(my_stuff.user, pwd -> pw_name);
- strcpy(my_stuff.home, pwd -> pw_dir);
- strcpy(my_stuff.my_name, pwd -> pw_gecos);
- if (my_stuff.home[ strlen(my_stuff.home)-1 ] != '\\')
- strcat(my_stuff.home, "\\");
- }
- }
-
- return(res >= 12);
- }
-
-
-
- /*--------------------------- unpack the batch ------------------------*/
- FILE *open_out_file(char *ng)
- {
- /*
- * This routine creates a filename from the newsgroup name.
- * The active file counter are updated.
- */
-
- ACTIVE *gp;
- char *fn;
- FILE *tmp;
-
- gp = find_news_group(ng);
- fn = make_news_group_name(gp->group);
-
- (gp->hi_num)++;
- update_active_entry(gp);
-
- if ((tmp = flockopen(fn, "r+b")) == NULL) {
- fprintf(stderr,"active: cannot open text file %s\n", fn);
- exit(1);
- }
- fseek(tmp, 0, SEEK_END);
-
- return(tmp);
- }
-
-
- /*--------------------------- unpack the batch ------------------------*/
- FILE *open_index_file(char *ng)
- {
- /*
- * This routine open the index file for the newsgroup
- */
-
- ACTIVE *gp;
- char fnx[256], *fn;
- FILE *tmp;
-
- /* printf("news: ng found = %s\n", ng); */
- gp = find_news_group(ng);
- fn = make_news_group_name(gp->group);
- sprintf(fnx, "%s.IDX", fn);
-
- if((tmp = flockopen(fnx, "r+b")) == NULL) {
- fprintf(stderr, "active: cannot open index file %s\n", fn);
- exit(1);
- }
- fseek(tmp, 0, SEEK_END);
-
- return(tmp);
- }
-
-
-
- /*------------------------- post sequence number ----------------------------*/
- int post_sequence(void)
- {
- /*
- * Get the sequnce number from the seq file if it exists - if
- * not create it
- */
-
- FILE *seq_file;
- char fn[256];
- int seq;
-
- strcpy(fn, my_stuff.news_dir);
- strcat(fn, "nseq");
-
- if ((seq_file = flockopen(fn, "r+t")) != NULL) {
- fscanf(seq_file, "%d", &seq);
- seq++;
- rewind(seq_file);
- } else {
- seq = 0;
- seq_file = flockopen(fn, "wt");
- }
-
- fprintf(seq_file, "%d", seq);
-
- fclose(seq_file);
- return(seq);
- }
-
-
- /*-------------------------------- safeish malloc --------------------------*/
- void *xmalloc(size_t size)
- {
- void *p;
- if ((p = malloc(size)) == NULL) {
- fprintf(stderr, "\n\nSORRY - NO MEMORY LEFT \n");
- exit(1);
- }
-
- return(p);
- }
-