DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦dc655a661⟧ TextFile

    Length: 11118 (0x2b6e)
    Types: TextFile
    Names: »make-lists.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« 
        └─⟦e5a54fb17⟧ 
            └─⟦this⟧ »pp-5.0/Tools/make-lists/make-lists.c« 

TextFile

/* make-lists.c: */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Tools/make-lists/RCS/make-lists.c,v 5.0 90/09/20 16:26:39 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Tools/make-lists/RCS/make-lists.c,v 5.0 90/09/20 16:26:39 pp Exp Locker: pp $
 *
 * $Log:	make-lists.c,v $
 * Revision 5.0  90/09/20  16:26:39  pp
 * rcsforce : 5.0 public release
 * 
 */



/*
 * 
 * Reads usernames aliases file, and creates quipu distribution list
 * channel files.
 * 
 * Usage:
 * 
 * make-lists input channel-file list-directory
 * 
 * A line starting with '#' is a comment. Else, a line containg both
 * ':' and ',' is assumed to be the first line of a list; it continues
 * while succeeding lines start with whitespace.
 * 
 * Note that the list directory must be in a form suitable for
 * prefixing directly a filename (ie ends in / on unix, or is like
 * [zxc] or thing: on VMS), this name is placed into the channel-file.
 * 
 * (nb vms/unix compatible, mainly so I can debug with a *decent* debugger.
 * It'll only be run 'in anger' on un*x) (M.A.Scott)
 * 
 * 
 * Modified, fairly extensively A.Macpherson.
 * 
 */


static char sccsid[] = { "%W%\t-\t%E%\tSTL\n" };

#include <stdio.h>

extern char    *malloc();
extern char    *realloc();
extern char    *strchr(), *strrchr();
extern char    *strcpy();

static int readline ();
static int addusers ();
static void panic ();

#define MAXMODERATOR 6
struct list {
  struct list    *next;		/* link pointer */
  struct list    *left;         /* other link */
  char           *list_name;	/* name of the list (eg "200") */
  char           *users;	/* points to '\n' separated record of users */
  int             users_alloc;	/* currently allocated space INCLUDING the
				 * '\0' */
  int             users_used;	/* currently used space including the null */
  char           *moderator[MAXMODERATOR];	/* list-request person(s) */
};

#define USERS_INCR 512		/* increment for 'users' area */

static struct list *list_pointer;

#ifndef BUFSIZ
#	define	BUFSIZ	255    	/* input line length allowed */
#endif

#ifdef VMS
# define	ERROR	(USER_FATAL|USER_INHIBIT)
# define	OK	USER_SUCCESS
# include	<misc.h>
#else
# define	ERROR	1
# define	OK	0
# define	EOS	'\0'
#endif


#define FIRST	0
#define CONTIN	1

static struct list *get_list();
static void	write_tables();
static int	trim();
static int	analyse_first();
static int	analyse_contin();
static int	analyse_request();

static char    *
    mymalloc(n)
int             n;
{
    char           *p = malloc((unsigned) n);
    
    if (p == 0) {
	perror("mymalloc");
	exit(ERROR);
    }
    return p;
}

main(argc, argv)
int             argc;
char           *argv[];

{
    FILE           *input;
    static char     buffer[BUFSIZ + 1];
    int             state;
    struct list    *current = 0;
    
    if (argc != 4) {
	(void) printf("usage: %s input-file channel-table dislist-directory\n",
		      argv[0]);
	exit(ERROR);
    }
    input = fopen(argv[1], "r");
    if (input == 0) {
	perror("cannot read input");
	exit(ERROR);
    }
    /* read entire input file.... */
    state = FIRST;
    
    while (readline(buffer, BUFSIZ, input) != EOF) {
	
	if (buffer[0] == '#' || buffer[0] == '\0')
	    continue;			/* comment line */
	
	switch (state) {
	case FIRST:
	    if (buffer[0] == ' ') {
		(void) printf("unexpected continuation line - ignored!\n%s\n", buffer);
		continue;
	    }
	    trim(buffer);
	    /*
	     * it's not an error if it's not a list, but we need to check for a
	     * request line
	     */
	    if (analyse_request(buffer, current))
		break;
	    if (analyse_first(buffer, &current))
		state = CONTIN;
	    break;
	    
	case CONTIN:
	    if (!analyse_contin(buffer, current))
		state = FIRST;
	    break;
	    
	default:
	    panic();
	    break;
	}
    }
    (void) fclose(input);
    
    write_tables(argv[2], argv[3]);
}


/* returns 1 if user list end in ',' else 0 */
static int analyse_first(buffer, current_pointer)
char           *buffer;
struct list   **current_pointer;
{
    struct list    *p;
    char           *rest;
    int             i;
    
    /* get dis list name */
    rest = strchr(buffer, ':');
    if (rest == 0)
	panic();
    *rest++ = EOS;
    
    p = get_list(buffer);
    
    *current_pointer = p;
    return addusers(rest, p);	/* and user list */
}

/* returns 1 if user list end in ',' else 0 */
static int 
    analyse_contin(buffer, current_pointer)
char           *buffer;
struct list    *current_pointer;
{
    if ((strchr(buffer, ':') != 0) || (buffer[0] != ' ')) {
	(void) printf("continuation line of list expected - ignored!\n%s\n",
		      buffer);
	return 0;
    }
    trim(buffer);
    return addusers(buffer, current_pointer);
}


/*
 * check for a -request, ie moderator, line. This is assumed to occur after
 * the list is defined. Duplicate moderators are appended, up to a maximum.
 */
static 
    analyse_request(buffer, current_pointer)
char           *buffer;
struct list    *current_pointer;
{
    char           *moderator = strchr(buffer, ':');
    char           *dash;
    char           *at;
    struct list    *p = current_pointer;
    int             i;
    
    if (moderator == 0)
	return(0);
    
    *moderator++ = EOS;
    dash = strrchr(buffer, '-');
    if (dash == 0 || strncmp(dash + 1, "request", 7) != 0) {
	*--moderator = ':';
	return(0);
    }
    
    *dash = EOS;			/* buffer now points to list name */
    
    /*
     * good chance current list is the one! If not, scan whole list. 
     */
    if ((p == 0) || strcmp(p->list_name, buffer) != 0)
	p = get_list(buffer);
    
    for (i = 0; i < MAXMODERATOR; ++i) {
	if (dash = strchr(moderator, ','))
	    *dash++ = EOS;
	if (p->moderator[i] == 0) 
	    p->moderator[i] = mymalloc(strlen(moderator) + 1);
	at = strchr(moderator, '@');
	if (at != 0)
	    *at = EOS;
	(void) strcpy(p->moderator[i], moderator);
	if (dash)
	    moderator = dash;
	else
	    break;
    }
    if (i >= MAXMODERATOR)
	(void) printf("too many moderators for list %s: %s ignored!\n",
		      buffer, moderator);
    return(1);
}


static void 
    write_tables(channel_file, table_dir)
char           *channel_file, *table_dir;
{
    struct list    *p;
    FILE           *fch;
    void            inorder_lists();
    
    fch = fopen(channel_file, "w");
    if (fch == 0) {
	(void) printf("channel file open error\n");
	perror(channel_file);
	exit(ERROR);
    }
    if (chdir(table_dir) != 0) {
	(void) printf("list directory error\n");
	perror(table_dir);
	unlink(channel_file);
	exit(ERROR);
    }
    
    inorder_lists(list_pointer, fch, table_dir);
    
    if (ferror(fch) != 0 || (fclose(fch) != 0)) {
	(void) printf("channel file write error\n");
	perror(channel_file);
	exit(ERROR);
    };
}

char	modbuff[BUFSIZ];

void
    inorder_lists(p, fch, table_dir)
struct list *p;
FILE        *fch;
char        *table_dir;
{
    FILE *flist;
    int   i;
    
    if (!p)
	return;
    
    inorder_lists(p->next, fch, table_dir);
    
    if (p->moderator[0] || strchr(p->users, '\n') != (char *)0) {
	flist = fopen(p->list_name, "w");
	if (flist == 0) {
	    (void) printf("list file open error\n");
	    perror(p->list_name);
	    exit(ERROR);
	}
	/*
	 * there's a bug in printf in VMS C, at least for old versions, for >512
	 * chars output at once, so...
	 */
#ifdef VMS
    {
	char           *c;
	
	for (c = p->users; *c != EOS; ++c)
	    fputc(*c, flist);
	fputc('\n', flist);
    }
#else
	(void) fputs(p->users, flist);
	(void) fputc('\n', flist);
#endif
	if (ferror(flist) != 0 || (fclose(flist) != 0)) {
	    (void) printf("list file write error\n");
	    perror(p->list_name);
	    exit(ERROR);
	}
	
	(void) fprintf(fch, "%s:%s",	/* listname */
		       p->list_name,
		       p->moderator[0] != 0 ? p->moderator[0]: "postmaster");
	for (i = 1; i < MAXMODERATOR && p->moderator[i] != 0; ++i)
	    (void) fprintf(fch, "|%s", p->moderator[i]);
	(void) fprintf(fch, ",file=%s%s,%s\n",
		       table_dir, p->list_name, 
		       p->list_name);	/* filename, description */
	strcpy(modbuff, p->list_name);
	strcat(modbuff, "-request");
	if ( p->moderator[0] == 0 || strcmp(modbuff, p->moderator[0])) {
	    (void) fprintf(fch, "%s-request:postmaster,%s", p->list_name,
			   p->moderator[0] != 0 ? p->moderator[0]: "postmaster");
	    for (i = 1; i < MAXMODERATOR && p->moderator[i] != 0; ++i)
		(void) fprintf(fch, "|%s", p->moderator[i]);
	    (void) fprintf(fch, ",Moderators for list %s\n",
			   p->list_name);	/* filename, description */
	}
    }
    inorder_lists(p->left, fch, table_dir);
}

/* remove blanks from string in place */
static int 
    trim(s)
char           *s;
{
    char           *t;
    
    for (t = s; *s != EOS; ++s)
	if (*s != ' ' && *s != '\t')
	    *t++ = *s;
    *t++ = EOS;
    return;
}


/* add users to list, converting ',' to '\n',and increasing space as needed */
/* returns 1 if a trailing comma found, else 0 */
static int 
    addusers(users, p)
char           *users;
struct list    *p;
{
    int             l = strlen(users);
    char           *s;
    int             comma;
    
    /* get enough space and some more */
    if (p->users_used + l > p->users_alloc) {
	p->users = realloc(p->users, (unsigned) (p->users_alloc + l + USERS_INCR));
	if (p->users == 0) {
	    (void) printf("out of memory!\n");
	    exit(ERROR);
	}
	p->users_alloc += (l + USERS_INCR);
    }
    /* copy across list */
    comma = 0;
    for (s = p->users + p->users_used - 1; *users != EOS; ++s, ++users)
	if (comma = (*users == ','))
	    *s = '\n';
	else
	    *s = *users;
    
    p->users_used += l;
    
    return comma;
}


static int 
    readline(buffer, len, input)
char           *buffer;
int             len;
FILE           *input;
{
    int             i;
    
    if (fgets(buffer, len, input) == 0) {
	if (!feof(input)) {
	    perror("read error");
	    exit(ERROR);
	} else
	    return EOF;
    }
    i = strlen(buffer);
    if (buffer[i - 1] != '\n')
	(void) printf("line too long (data may be lost):\n%s\n", buffer);
    else
	buffer[i - 1] = EOS;
    return 0;
}


static void panic()
{
    (void) printf("internal error!!\n");
    exit(ERROR);
}

static struct list *
    get_list(name)
char *name;
{
    register struct list **p;
    int           lr;
    
    /* Double de-reference so only one pointer needed, and
       the empty tree is not a special case */
    
    for (p = &list_pointer; *p != 0; ) {
	if ((lr = strcmp((*p)->list_name, name)) == 0){
	    return(*p);
	}
	p = (lr > 0) ? &(*p)->next : &(*p)->left;
    }
    
    /* grab some store and init it... */
    *p = (struct list *) mymalloc(sizeof(struct list));
    
    (*p)->users = mymalloc(USERS_INCR + 1);
    (*p)->users[0] = EOS;
    (*p)->users_alloc = USERS_INCR + 1;
    (*p)->users_used = 1;		/* the EOS */
    for (lr = 0; lr < MAXMODERATOR; ++lr)
	(*p)->moderator[lr] = 0;
    
    (*p)->next = (struct list *) 0;
    (*p)->left = (struct list *) 0;
    
    (*p)->list_name = mymalloc(strlen(name) + 1);
    (void) strcpy((*p)->list_name, name);	/* copy list name */
    return (*p);    
}