/*
 * transact.c - processes all transactions to the events server. each 
 * connection has it's own light weight process (LWP).
 */

#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "lwp/lwp.h"
#include "event.h"

static int      cur_sock;
extern CONN     conntab[];
static int      next_id;
static char     in_buff[5000];
int             PROV = NOBODY;

extern int      debug;
extern int      errno;
extern char    *msglist[];	/* the list of error messages */

extern int      type_size;
extern int      sponsor_size;
extern int      source_size;

static char    *uid;		/* the user id who sent the current
				 * transaction */
static char    *type;
static char    *trans_data;	/* everything after the 1st ":" */
static char     trans_type;
static CONN    *connection;

/* pointers to first + last records in linked list */
static EVENT   *first_rec = 0;
static EVENT   *last_rec = 0;


#define	strnode(str)	web_node(atol(str))

int
hdl_transact(conn)
    CONN           *conn;
{
    char           *machtype;
    char            mode[10];
    char            log_line[256];
    int             length,max,used;
    int             quit, red;
    time_t          secs;
    PROCESS         proc_ptr;

    printf("\nHandling transaction to %s, port %d, socket #%d.\n",
	   conn->c_hostname,
	   conn->c_portnum,
	   conn->c_socket);
    time(&conn->c_last);
    connection = conn;
    cur_sock = conn->c_socket;
    uid = conn->c_uid;
    bzero(in_buff, BUFSIZ);
    length = read(cur_sock, in_buff, BUFSIZ);
    if (length <= 0) {
	if (length)
	    perror("socket read");
	if (errno == EWOULDBLOCK)
	    return 0;
	else
	    return 1;
    }
    if (in_buff[length - 1] == LF)
	length--;
    if (in_buff[length - 1] == CR)
	length--;
    in_buff[length] = '\0';

    if (!parse_trans() || length == 0)
	return 1;		/* quit and close connection */

    sprintf(log_line, "%s:%d:%c:%-50.50s", uid, cur_sock, trans_type, trans_data);
    log_trans(log_line);	/* log the transaction */
    proc_trans(trans_data);
    deliver();
    proc_ptr = LWP_ActiveProcess;
    LWP_StackUsed(LWP_ActiveProcess,&max,&used);
    printf("stack used = %d,pid = %d\n",used,LWP_ActiveProcess->index);
    printf("user = %s\n",connection->c_uid);
    return 0;			/* ok */
}

parse_trans()
{
    char           *c;

    trans_type = *in_buff;
    c = (char *) index(in_buff, DLM);
    if (c)
	trans_data = c + 1;
    else if (in_buff[1] && trans_type)
	trans_data = in_buff + 1;
    else
	trans_data = "";
    printf("Transaction(type=`%c' data=[%s])\n", trans_type, trans_data);
    if (trans_type == T_QUIT)
	return 0;
    return 1;
}

proc_trans(char *trans_data)
{
    int             x;
    EVENT          *event;
    char           *cp;
    switch (trans_type) {

    case T_ADD_EVENT:
	add_event(trans_data);
	break;
    case T_MODIFY_EVENT:
	modify_event(trans_data);
	break;
    case T_QUERY_EVENT:
	parse_query(trans_data);
	break;
    case T_LOAD:
	load_events();
	send_ok();
	break;
    case T_IDENTIFY:
	provider(trans_data);
	break;
    case T_FIND:
	event = find_event(atol(trans_data));
	send_event(event);
	send_eom();
	break;
    case T_SEND_TABLE:
	send_table(*trans_data);
	break;
    case T_SEND_ALL:
	show_all_events();
	break;
    case T_SAVE:
	save_events();
	send_ok();
	break;
    case T_DEL_REC:
	delete_event(trans_data);
	break;
    default:
	send_huh();
    }
}

test_owner(char *source)
{				/* test to see if a certain uid is the owner
				 * of a node */
    char            provline[PROV_LN_SZ];
    char            allline[PROV_LN_SZ];
    char            testline[PROV_LN_SZ], *cp;
    FILE           *fopen(), *provfile;

    provfile = fopen(PROV_FILE, "r");
    if (!provfile) {
	perror(PROV_FILE);
	return;
    }
    sprintf(testline, "%s:%s", source, uid);
    sprintf(allline, "All:%s", uid);
    while (fgets(provline, PROV_LN_SZ, provfile) != '\0') {
	cp = (char *) rindex(provline, ':');
	if (cp) {
	    *cp = '\0';
	    if ((strcasecmp(testline, provline) == 0)
		|| (strcasecmp(allline, provline) == 0)) {
		fclose(provfile);
		return 1;
	    }
	}
    }
    fclose(provfile);
    return 0;

}
valid_source(char *srce)
{				/* test to see if a source has been entered
				 * in the provider table. The provider table
				 * structure is <source>:<user_id>:<password> */

    FILE           *fopen(), *provfile;
    char            provline[PROV_LN_SZ], *cp;
    int             i;

    provfile = fopen(PROV_FILE, "r");
    if (!provfile) {
	perror(PROV_FILE);
	return 0;
    }
    while (fgets(provline, PROV_LN_SZ, provfile) != '\0') {
	cp = (char *) index(provline, ':');
	if (cp) {
	    *cp = '\0';
	    i = strlen(provline);
	    if (strcasecmp(srce, provline, i) == 0) {
		fclose(provfile);
		return 1;
	    }
	}
    }
    fclose(provfile);
    return 0;			/* close file */

}
static char     src[20];

char           *
test_prov()
{				/* test to see if a uid is a provider */

    FILE           *fopen(), *provfile;
    char            provline[PROV_LN_SZ], *id_pswd;
    int             i;

    provfile = fopen(PROV_FILE, "r");
    if (!provfile) {
	perror(PROV_FILE);
	return 0;
    }
    while (fgets(provline, PROV_LN_SZ, provfile) != '\0') {
	id_pswd = (char *) index(provline, DLM);
	if (id_pswd) {
	    *id_pswd = '\0';
	    strcpy(src, provline);
	    id_pswd++;
	    i = strlen(id_pswd);
	    *(id_pswd + i - 1) = '\0';
	    if (strcasecmp(trans_data, id_pswd) == 0) {
		fclose(provfile);
		return src;
	    }
	}
    }
    fclose(provfile);
    return NULL;		/* close file */

}

test_admin(passwd)
    char           *passwd;
{
    /* test to see if a uid is an admin */

    FILE           *fopen(), *adminfile;
    char            adminline[ADMIN_LN_SZ];

    adminfile = fopen(ADMIN_FILE, "r");
    if (!adminfile) {
	perror(ADMIN_FILE);
	return 0;
    }
    while (fgets(adminline, ADMIN_LN_SZ, adminfile) != '\0') {
	adminline[strlen(adminline) - 1] = '\0';
	if (strcasecmp(passwd, adminline) == 0) {
	    fclose(adminfile);
	    return 1;
	}
    }
    fclose(adminfile);
    return 0;			/* close file */

}
provider(char *trans_data)
{
	char           *cp, *source, amsg[25],*uid;

	if (source = test_prov()) {
	  printf("we are here\n");
			cp = (char *) index(trans_data, DLM);
	  if (cp)
	    *cp = '\0';
	  printf("we are\n");
			uid = (char *) malloc(strlen(trans_data) + 1);
	  printf("we are there\n");
			strcpy(uid, trans_data);
			connection->c_uid = uid;
			sprintf(amsg, "0:%s", source);
			send_msg(amsg);
	} else
		send_msg(msglist[2]);	/* auth failed */
}


static int      dfd;
inc_nextid()
{				/* increments next id in mem + on disk */
    char            line[20];

    if ((dfd = open(NEXTID_FILE, O_WRONLY | O_TRUNC | O_CREAT)) == 0)
	printf("error incrementing next id\n");
    next_id++;
    sprintf(line, "%d\n", next_id);
    write(dfd, line, strlen(line));
    close(dfd);
    return;
}

get_nextid()
{				/* reads the next id from disk */
    char            line[20];
    int             red;

    if ((dfd = open(NEXTID_FILE, O_RDONLY)) == 0)
	printf("error getting next id\n");
    red = read(dfd, line, 20);
    line[red] = '\0';
    next_id = atoi(line);
    close(dfd);
    return;
}


log_trans(line)			/* write the transaction to the log file */
    char           *line;
{
    char            logline[300];
    time_t          secs;

    time(&secs);
    sprintf(logline, "%s:%s", line, ctime(&secs));
    if ((dfd = open(TRANS_LOG, O_APPEND | O_CREAT | O_WRONLY, 0644)) == 0)
	printf("error logging transaction\n");
    write(dfd, logline, strlen(logline));
    close(dfd);
    return;
}

find_ver()
{				/* find the version number of the client
				 * associated with a certain machine */
    FILE           *fopen(), *verfile;
    char            verline[ADMIN_LN_SZ];
    int             len;

    verfile = fopen(VER_FILE, "r");
    if (!verfile)
	return;
    len = strlen(trans_data);
    while (fgets(verline, ADMIN_LN_SZ, verfile) != '\0') {
	verline[strlen(verline) - 1] = '\0';
	if (strncmp(trans_data, verline, len) == 0) {
	    fclose(verfile);
	    send_msg(verline);
	    return 0;
	}
    }
    fclose(verfile);
    send_err();

    return 0;			/* close file */
}

int
parse_event_text(char *cp, EVENT * event_rec, ADD_EVENT_INFO *add_rec)
{
    int             next_id, more = TRUE;
    char           *fld_type, *fld_value, *fld, *title;

    fld_type = cp;
    while (more) {
	more = (int) fld_value = cp = next_field(&cp);
	fld = fld_type;
	if (more)
	    more = (int) fld_type = cp = next_field(&cp);
	printf("type = %s, value = <%s>\n", fld, fld_value);
	switch (*fld) {		/* assign value to event records */

	case F_ID:
	    event_rec->id = atol(fld_value);
	    printf("field id -%s-\n", fld_value);
	    break;
	case F_TITLE:
	    title = (char *) malloc(strlen(fld_value) + 1);
	    strcpy(title, fld_value);
	    event_rec->title = title;
	    break;
	case F_SOURCE:
	    event_rec->source = get_idnum_from_table(fld_value, source_table, source_size);
	    break;
	case F_SPONSOR:
	    event_rec->sponsor = get_idnum_from_table(fld_value, sponsor_table, sponsor_size);
	    break;
	case F_TYPE:
	    event_rec->type = get_idnum_from_table(fld_value, type_table, type_size);
	    break;
	case F_DATE:
	    event_rec->event_date = date_from_str(fld_value);
	    break;
	case F_DESC:
	    add_rec->desc = fld_value;
	    break;
        case F_LOCATION:
	    add_rec->location = fld_value;
	    break;
        case F_SPEAKER:
	    add_rec->speaker = fld_value;
	    break;
	default:
	    break;
	    /* send err message + get out */
	}			/* end case */
    }
    return event_rec->source;
}

add_event(char *trans_data)
{
    EVENT          *event_rec;
    ADD_EVENT_INFO  add_event_info;
    long timestamp;
    int src;
    char str[20],*thesrc;

    event_rec = (EVENT *) malloc(sizeof(EVENT));
    bzero(event_rec,sizeof(EVENT));
    bzero(&add_event_info,sizeof(ADD_EVENT_INFO));
    src = parse_event_text(trans_data, event_rec, &add_event_info);
    thesrc = get_value_from_table(src,source_table,source_size);
    printf("the source = %s\n",thesrc);
    if (valid_source(thesrc) && test_owner(thesrc)) {
      time(&timestamp);
      event_rec->last_changed = timestamp;
      get_nextid();
      sprintf(str,"0:%ld",next_id); /* build message returning id */
      event_rec->id = next_id;
      strcpy(add_event_info.last_chgd_by,uid);
      write_rec_to_disk(&add_event_info,event_rec->id);
      add_rec_to_list(event_rec);
      inc_nextid();
      send_msg(str);
  }
	else { /* not auth */
	  send_msg(msglist[1]);
	  free(event_rec);
	}
}

modify_event(char *trans_data)
{
    EVENT          *event_rec,temp_rec;
    ADD_EVENT_INFO  add_event_info;
    char           buf[SIZE],*thesrc,*oldsrc;
    long timestamp,olddate;
    int src;

    event_rec = find_event(atol(trans_data));
    bcopy(event_rec,&temp_rec,sizeof(EVENT));
    olddate = event_rec->event_date;
    read_disk_rec(&add_event_info,buf,event_rec->id);
    trans_data = next_field(&trans_data);
    oldsrc = get_value_from_table(event_rec->source,source_table,source_size);
    src = parse_event_text(trans_data, event_rec, &add_event_info);
    thesrc = get_value_from_table(src,source_table,source_size);

    if (test_owner(oldsrc) && test_owner(thesrc)) { 
      strcpy(add_event_info.last_chgd_by,uid);
      write_rec_to_disk(&add_event_info,event_rec->id);
      time(&timestamp);
      event_rec->last_changed = timestamp;
/* if the date changed we need to remove + then add back to the list to
   keep it sorted by date */
      if (event_rec->event_date != olddate) {
	del_rec_from_list(event_rec);
	add_rec_to_list(event_rec);	
      }
      send_ok();
    }
    else {
      send_msg(msglist[1]);
      bcopy(&temp_rec,event_rec,sizeof(EVENT));      
    }
}

delete_event(char *trans_data)
{
EVENT *event;

event = find_event(atol(trans_data));
if (test_owner(get_value_from_table(event->source,source_table,source_size))) {
  del_rec_from_list(event);
  del_rec_from_disk(event->id);
  send_ok();
 }
    else
    send_msg(msglist[1]);
}

int
add_rec_to_list(EVENT * new_rec)
{				/* add to the linked list sorted by date */
EVENT *next,*prev,*event;

/* find record before which we want the new rec to go */
    for (event = first_rec; event; event = event->next) 
	if (event->event_date > new_rec->event_date)
	  break;

    if (event == first_rec) { 
      first_rec = new_rec;  }
    else if (event) {                    /* fix links backwards */
      prev = event->prev;
      prev->next = new_rec;
      new_rec->prev = prev;
    }

    if (!event) {
      if (last_rec) { /* if not an empty list */
	last_rec->next = new_rec;
	new_rec->prev = last_rec; }
      last_rec = new_rec; }
    else {                    /* fix links forwards */
      event->prev = new_rec;
      new_rec->next = event;
    }
}

int
del_rec_from_list(EVENT * event_rec)
{				/* remove from the linked list */

    EVENT          *prev_rec, *next_rec;

    if (first_rec == event_rec) {
	first_rec = event_rec->next;
	if (last_rec != event_rec)
	    first_rec->prev = 0;
	else
	    last_rec = 0;
    } else {
	prev_rec = event_rec->prev;
	next_rec = event_rec->next;
	prev_rec->next = event_rec->next;
	if (last_rec != event_rec)
	    next_rec->prev = event_rec->prev;
	else
	    last_rec = 0;
    }
}

void
show_all_events()
{
    EVENT          *event;
    CONN           *conn;

    conn = get_curr_conn();
    printf("cur_conn = %ld\n",conn);
    cur_sock = conn->c_socket;
    printf("cur_sock = %d\n",cur_sock);

    send("221:all events\n");
    for (event = first_rec; event; event = event->next) {
        LWP_DispatchProcess();
	send_event_abr(event,cur_sock);
      }
    send_eom();

}

void
send_event_abr(EVENT * event,int cur_sock)
{
    char            buf[1024],date[10];


    sprintf(buf, "%d:%s", event->id, event->title);
    sprintf(buf, "%s:%s",buf, get_value_from_table(event->type, type_table, type_size));
    sprintf(buf, "%s:%s", buf, get_value_from_table(event->source, source_table, source_size));
    sprintf(buf, "%s:%s", buf, get_value_from_table(event->sponsor, sponsor_table, sponsor_size));
    date_from_long(event->event_date,date);
    sprintf(buf, "%s:%s\n", buf,date); 

    send(buf);
}

EVENT          *
find_event(long id)
{
    EVENT          *event;

    for (event = first_rec; event; event = event->next)
	if (event->id == id)
	    return event;
    return 0;
}

void
send_event(EVENT * event)
{
    char            buf[SIZE],date[10];
    
    send("222:event follows\n");
    sprintf(buf, "i:%d\nt:%s\n", event->id, event->title);
    sprintf(buf, "%sy:%s\n", buf, get_value_from_table(event->type, type_table, type_size));
    sprintf(buf, "%ss:%s\n", buf, get_value_from_table(event->source, source_table, source_size));
    sprintf(buf, "%sp:%s\n", buf, get_value_from_table(event->sponsor, sponsor_table, sponsor_size));
    date_from_long(event->event_date,date);
    sprintf(buf, "%sd:%s\n", buf,date); 
    send(buf);
    read_rec_from_disk(buf,event->id);
    send(buf);
}


void
save_events()
{
    EVENT          *event;
    FILE           *fopen(), *eventfile;

    eventfile = fopen(EVENT_FILE, "w+");
    if (!eventfile) {
	perror(eventfile);
	return;
    }
    for (event = first_rec; event; event = event->next) {
	fprintf(eventfile, "%d:%d:%d:%d:%ld:%ld:%s\n", event->id,
		event->type, event->sponsor, event->source,
		event->event_date, event->purge_date, event->title);
    }
    fclose(eventfile);
}
void
load_events()
{
    FILE           *fopen(), *eventfile;
    EVENT          *event_rec;
    char            line[500], *cp, *title;

    eventfile = fopen(EVENT_FILE, "r+");
    if (!eventfile) {
	perror(eventfile);
	return;
    }
    while (fgets(line, 500, eventfile) != '\0') {
	cp = line;
	event_rec = (EVENT *) malloc(sizeof(EVENT));
	event_rec->id = atol(line);
	event_rec->type = atoi(next_field(&cp));
	event_rec->sponsor = atoi(next_field(&cp));
	event_rec->source = atoi(next_field(&cp));
	event_rec->event_date = atol(next_field(&cp));
	event_rec->purge_date = atol(next_field(&cp));
	title = (char *) malloc(strlen(next_field(&cp)) + 1);
	strcpy(title, cp);
	title[strlen(title) - 1] = '\0';
	event_rec->title = title;
	add_rec_to_list(event_rec);
    }
    fclose(eventfile);
}

/*
 * Return pointer to start of next field (after it's starting colon) 
 */
char           *
next_field(char **ptr)
{
    register char  *cp = *ptr;

    while (*cp && *cp != DLM)
	cp++;
    if (*cp == '\0')
	return (char *) *cp;
    *cp = '\0';
    return *ptr = ++cp;
}

int
load_table(TABLE_ENTRY * table, char *filename)
{
    FILE           *fopen(), *fn;
    char            line[50], *temp;
    int             line_size = 50, pos = 0, i;
    TABLE_ENTRY    *tbl_rec;

    fn = fopen(filename, "r");
    if (!fn) {
	perror(filename);
	return 0;
    }
    tbl_rec = table;
    while (fgets(line, line_size, fn) != '\0') {
	tbl_rec->num = atoi(get_token(line, 1));
	temp = get_token(line, 2);
	temp[strlen(temp) - 1] = '\0';
	strcpy(tbl_rec->string, temp);
	tbl_rec++;
	pos++;
    }
    printf("\n number of entries = %d\n", pos);
    for (i = 0; i < pos; i++) {
	printf("%s -- %d\n", table[i].string, table[i].num);
    }
    fclose(fn);
    return pos;
}

int
get_idnum_from_table(char *str, TABLE_ENTRY * table, int table_size)
{
    int             i;
    for (i = 0; i < table_size; i++) {
	if (strcasecmp(table[i].string, str) == 0)
	    return table[i].num;
    }
    return 0;
}

char           *
get_value_from_table(int num, TABLE_ENTRY * table, int table_size)
{
    int             i;
    for (i = 0; i < table_size; i++) {
	if (table[i].num == num)
	    return table[i].string;
    }
    return 0;
}

/* SEND_TABLE - send a validation table to client */
void
send_table(char fld)
{
    char            line[50];
    int             i, table_size = 0;
    TABLE_ENTRY    *atable;

    printf("fld = %c\n", fld);
    switch (fld) {
    case F_TYPE:
	table_size = type_size;
	atable = type_table;
	break;
    case F_SPONSOR:
	table_size = sponsor_size;
	atable = sponsor_table;
	break;
    case F_SOURCE:
	table_size = source_size;
	atable = source_table;
	break;
    }

    sprintf(line, "%d\n", table_size);
    send(line);
    for (i = 0; i < table_size; i++) {
	sprintf(line, "%d:%s\n", atable[i].num, atable[i].string);
	send(line);
    }
    send_eom();
}

int
parse_query(char *cp)
{
    int             next_id, value, more = TRUE;
    int             i, put_ptr,list_size;
    char           *fld_type, *fld_value, *fld, *operator, op, *acp;
    EVENT          *event_list[3024];
    char            str[10],title[200];

    list_size = load_list(event_list);
    fld_type = cp;
    while (more) {
	more = (int) operator = cp = next_field(&cp);
	more = (int) fld_value = cp = next_field(&cp);
	fld = fld_type;
	op = *operator;
	if (more)
	    more = (int) fld_type = cp = next_field(&cp);

	printf("type = %s, op = %c value = <%s>\n", fld, op, fld_value);
	put_ptr = 0;
	switch (*fld) {

	case F_TITLE:		/* string compare, wildcard at end implied */
	    strcpy(title, fld_value);
	    for (i = 0; i < list_size; i++) {
		if (op == EQUALS) {
		    if (strncasecmp(title, event_list[i]->title,strlen(title)) == 0) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
		} else if (op == CONTAINS)
		  for (acp = event_list[i]->title; *acp; acp++) {
		    if (strncasecmp(acp, title,strlen(title)) == 0) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
			break;
		    }
		  }
	    }
	    list_size = put_ptr;
	    break;

	case F_TYPE:		/* integer compare */
	    value = get_idnum_from_table(fld_value, type_table, type_size);
	    for (i = 0; i < list_size; i++) {
		if (op == EQUALS) {
		    if (value == event_list[i]->type) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
		} else if (op == NOT_EQUAL)
		    if (value != event_list[i]->type) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
	    }
	    list_size = put_ptr;
	    break;

	case F_SPONSOR:	/* integer compare */
	    value = get_idnum_from_table(fld_value, sponsor_table, sponsor_size);
	    for (i = 0; i < list_size; i++) {
		if (op == EQUALS) {
		    if (value == event_list[i]->sponsor) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
		} else if (op == NOT_EQUAL)
		    if (value != event_list[i]->sponsor) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
	    }
	    list_size = put_ptr;
	    break;

	case F_SOURCE:		/* integer compare */
	    value = get_idnum_from_table(fld_value, source_table, source_size);
	    for (i = 0; i < list_size; i++) {
		if (op == EQUALS) {
		    if (value == event_list[i]->source) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
		} else if (op == NOT_EQUAL)
		    if (value != event_list[i]->source) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
	    }
	    list_size = put_ptr;
	    break;

	case F_DATE:		/* integer compare */
	    strcpy(str,fld_value);
	    value = date_from_str(str);
	    for (i = 0; i < list_size; i++) {
		if (op == EQUALS) {
		    if (value == event_list[i]->event_date) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
		} else if (op == NOT_EQUAL) {
		    if (value != event_list[i]->event_date) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
		} else if (op == GREATER_THAN) {
		    if (value < event_list[i]->event_date) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
		} else if (op == LESS_THAN) 
		    if (value > event_list[i]->event_date) {
			event_list[put_ptr] = event_list[i];
			put_ptr++;
		    }
	    }
	    list_size = put_ptr;
	    break;

	default:
	    break;
	    /* send err message + get out */
	}			/* end case */
    }
    printf("about to send list #%d\n", list_size);
    send_list(event_list,list_size);
    return;
}

int
load_list(EVENT *event_list[])
{
    EVENT          *event;
    int             cnt;

    for (event = first_rec, cnt = 0; event; event = event->next, cnt++)
	event_list[cnt] = event;
    return cnt;
}

int
send_list(EVENT *event_list[],int list_size)
{
    EVENT          *event;
    int             i;
    char            line[30];
    int             cur_sock;
    CONN           *conn;

    conn = get_curr_conn();
    cur_sock = conn->c_socket;

    sprintf(line, "221:%d events found\n", list_size);
    send(line);
    for (i = 0; i < list_size; i++)
	 send_event_abr(event_list[i],cur_sock); 
    send_eom();
    return;
}

int /* write the additional fields to disk */
write_rec_to_disk(ADD_EVENT_INFO *rec,long id)
{
  char filename[40],buf[SIZE];
  int fd;

  sprintf(filename,"%s%ld",EVENT_DIR,id);
  if ((fd = open(filename,O_WRONLY | O_CREAT | O_TRUNC,0644)) == 0) {
    printf("error opening file\n");
    return -1;
  }
  write(fd,"c:",2); 
  strcpy(buf,rec->desc); /* fld too big for sprintf */
  write(fd,buf,strlen(buf));
  sprintf(buf,"\nl:%s\n",rec->location);
  write(fd,buf,strlen(buf));
  sprintf(buf,"m:%s\n",rec->speaker);
  write(fd,buf,strlen(buf));
  sprintf(buf,"u:%s\n",rec->last_chgd_by);
  write(fd,buf,strlen(buf));

  close(fd);
  return 0;
}

int /* read the additional fields from disk into a buffer */
read_rec_from_disk(char *buf,long id)
{
  char filename[40];
  int fd,rc;

  sprintf(filename,"%s%ld",EVENT_DIR,id);
  if ((fd = open(filename,O_RDONLY,0644)) == 0) {
    printf("error opening file\n");
    return 0;
  }
  rc = read(fd,buf,SIZE);
  buf[rc] = '\0';
  close(fd);
  return rc;
}

del_rec_from_disk(long id)
{
  char filename[40];
  sprintf(filename,"rm %s%ld",EVENT_DIR,id);
  system(filename);
}

int    /* read the additional fields from disk to rec */
read_disk_rec(ADD_EVENT_INFO *rec,char *buf,long id)
{
  char filename[40],*cp;
  int fd,rc;

  sprintf(filename,"%s%ld",EVENT_DIR,id);
  if ((fd = open(filename,O_RDONLY,0644)) == 0) {
    printf("error opening file\n");
    return 0;
  }
  rc = read(fd,buf,SIZE);
  buf[rc] = '\0';
  rec->desc = cp = buf + 2;
  cp = index(cp,'\n');
  *cp = '\0';
  rec->location = cp = cp + 3;
  cp = index(cp,'\n');
  *cp = '\0';
  rec->speaker = cp = cp + 3;
  cp = index(cp,'\n');
  *cp = '\0';
  rec->last_chgd_by = cp = cp + 3;
  cp = index(cp,'\n');
  *cp = '\0';
  printf("desc = %s, loc = %s, spk = %s\n",rec->desc,rec->location,rec->speaker); 
  close(fd);
  return 1;
}

long
date_from_str(char *str) /* from mm/dd/yy -> yymmdd */
{
char *cp,*acp,line[10];
int yy,mm,dd;

mm = atoi(str);
cp = index(str,'/');
*cp = '\0';
acp = ++cp;
cp = index(cp,'/');
*cp = '\0';
dd = atoi(acp);
yy = atoi(++cp);
sprintf(line,"%02d%02d%02d",yy,mm,dd);
return atol(line);
}

void 
date_from_long(long num,char *str)
{
char line[10],aline[10],*cp,*yy,*mm,*dd;

sprintf(line,"%ld",num);
strcpy(aline,line);
aline[2] = '\0';
yy = aline;
line[4] = '\0';
mm = &line[2];
dd = &aline[4];
sprintf(str,"%s/%s/%s",mm,dd,yy);
return;
}
