home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
com
/
utils
/
smplnews
/
active.c
next >
Wrap
C/C++ Source or Header
|
1992-08-08
|
20KB
|
776 lines
/*
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);
}