xref: /csrg-svn/libexec/talkd/table.c (revision 61449)
122399Sdist /*
2*61449Sbostic  * Copyright (c) 1983, 1993
3*61449Sbostic  *	The Regents of the University of California.  All rights reserved.
434360Sbostic  *
542673Sbostic  * %sccs.include.redist.c%
622399Sdist  */
722399Sdist 
816366Skarels #ifndef lint
9*61449Sbostic static char sccsid[] = "@(#)table.c	8.1 (Berkeley) 06/04/93";
1034360Sbostic #endif /* not lint */
1116356Skarels 
1216366Skarels /*
1316366Skarels  * Routines to handle insertion, deletion, etc on the table
1416366Skarels  * of requests kept by the daemon. Nothing fancy here, linear
1516366Skarels  * search on a double-linked list. A time is kept with each
1616366Skarels  * entry so that overly old invitations can be eliminated.
1716366Skarels  *
1816366Skarels  * Consider this a mis-guided attempt at modularity
1916356Skarels  */
2046683Sbostic #include <sys/param.h>
2116366Skarels #include <sys/time.h>
2246683Sbostic #include <sys/socket.h>
2346683Sbostic #include <protocols/talkd.h>
2426840Smckusick #include <syslog.h>
2546683Sbostic #include <unistd.h>
2646683Sbostic #include <stdio.h>
2746683Sbostic #include <stdlib.h>
2846683Sbostic #include <string.h>
2916356Skarels 
3016366Skarels #define MAX_ID 16000	/* << 2^15 so I don't have sign troubles */
3116356Skarels 
3216366Skarels #define NIL ((TABLE_ENTRY *)0)
3316356Skarels 
3416366Skarels extern	int debug;
3516366Skarels struct	timeval tp;
3646683Sbostic struct	timezone txp;
3716356Skarels 
3816356Skarels typedef struct table_entry TABLE_ENTRY;
3916356Skarels 
4016356Skarels struct table_entry {
4116366Skarels 	CTL_MSG request;
4216366Skarels 	long	time;
4316366Skarels 	TABLE_ENTRY *next;
4416366Skarels 	TABLE_ENTRY *last;
4516356Skarels };
4616356Skarels 
4726840Smckusick TABLE_ENTRY *table = NIL;
4816356Skarels CTL_MSG *find_request();
4916356Skarels CTL_MSG *find_match();
5016356Skarels 
5116366Skarels /*
5216366Skarels  * Look in the table for an invitation that matches the current
5316366Skarels  * request looking for an invitation
5416366Skarels  */
5516366Skarels CTL_MSG *
find_match(request)5616366Skarels find_match(request)
5726840Smckusick 	register CTL_MSG *request;
5816356Skarels {
5926840Smckusick 	register TABLE_ENTRY *ptr;
6046683Sbostic 	time_t current_time;
6116356Skarels 
6216366Skarels 	gettimeofday(&tp, &txp);
6316366Skarels 	current_time = tp.tv_sec;
6426840Smckusick 	if (debug)
6526840Smckusick 		print_request("find_match", request);
6616366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
6716366Skarels 		if ((ptr->time - current_time) > MAX_LIFE) {
6816366Skarels 			/* the entry is too old */
6926840Smckusick 			if (debug)
7026840Smckusick 				print_request("deleting expired entry",
7126840Smckusick 				    &ptr->request);
7216366Skarels 			delete(ptr);
7316366Skarels 			continue;
7416366Skarels 		}
7516366Skarels 		if (debug)
7626840Smckusick 			print_request("", &ptr->request);
7716366Skarels 		if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
7816366Skarels 		    strcmp(request->r_name, ptr->request.l_name) == 0 &&
7916366Skarels 		     ptr->request.type == LEAVE_INVITE)
8016366Skarels 			return (&ptr->request);
8116356Skarels 	}
8216366Skarels 	return ((CTL_MSG *)0);
8316356Skarels }
8416356Skarels 
8516366Skarels /*
8616366Skarels  * Look for an identical request, as opposed to a complimentary
8716366Skarels  * one as find_match does
8816366Skarels  */
8916366Skarels CTL_MSG *
find_request(request)9016366Skarels find_request(request)
9126840Smckusick 	register CTL_MSG *request;
9216356Skarels {
9326840Smckusick 	register TABLE_ENTRY *ptr;
9446683Sbostic 	time_t current_time;
9516356Skarels 
9616366Skarels 	gettimeofday(&tp, &txp);
9716366Skarels 	current_time = tp.tv_sec;
9816366Skarels 	/*
9916366Skarels 	 * See if this is a repeated message, and check for
10016366Skarels 	 * out of date entries in the table while we are it.
10116356Skarels 	 */
10226840Smckusick 	if (debug)
10326840Smckusick 		print_request("find_request", request);
10416366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
10516366Skarels 		if ((ptr->time - current_time) > MAX_LIFE) {
10616366Skarels 			/* the entry is too old */
10726840Smckusick 			if (debug)
10826840Smckusick 				print_request("deleting expired entry",
10926840Smckusick 				    &ptr->request);
11016366Skarels 			delete(ptr);
11116366Skarels 			continue;
11216366Skarels 		}
11316366Skarels 		if (debug)
11426840Smckusick 			print_request("", &ptr->request);
11516366Skarels 		if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
11616366Skarels 		    strcmp(request->l_name, ptr->request.l_name) == 0 &&
11716366Skarels 		    request->type == ptr->request.type &&
11816366Skarels 		    request->pid == ptr->request.pid) {
11916366Skarels 			/* update the time if we 'touch' it */
12016366Skarels 			ptr->time = current_time;
12116366Skarels 			return (&ptr->request);
12216366Skarels 		}
12316356Skarels 	}
12416366Skarels 	return ((CTL_MSG *)0);
12516356Skarels }
12616356Skarels 
insert_table(request,response)12716356Skarels insert_table(request, response)
12816366Skarels 	CTL_MSG *request;
12916366Skarels 	CTL_RESPONSE *response;
13016356Skarels {
13126840Smckusick 	register TABLE_ENTRY *ptr;
13246683Sbostic 	time_t current_time;
13316356Skarels 
13416366Skarels 	gettimeofday(&tp, &txp);
13516366Skarels 	current_time = tp.tv_sec;
13626840Smckusick 	request->id_num = new_id();
13726840Smckusick 	response->id_num = htonl(request->id_num);
13816356Skarels 	/* insert a new entry into the top of the list */
13916366Skarels 	ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
14016366Skarels 	if (ptr == NIL) {
14126840Smckusick 		syslog(LOG_ERR, "insert_table: Out of memory");
14226840Smckusick 		_exit(1);
14316366Skarels 	}
14416366Skarels 	ptr->time = current_time;
14516366Skarels 	ptr->request = *request;
14616366Skarels 	ptr->next = table;
14716366Skarels 	if (ptr->next != NIL)
14816366Skarels 		ptr->next->last = ptr;
14916366Skarels 	ptr->last = NIL;
15016366Skarels 	table = ptr;
15116356Skarels }
15216356Skarels 
15316366Skarels /*
15416366Skarels  * Generate a unique non-zero sequence number
15516366Skarels  */
new_id()15616356Skarels new_id()
15716356Skarels {
15816366Skarels 	static int current_id = 0;
15916356Skarels 
16016366Skarels 	current_id = (current_id + 1) % MAX_ID;
16116356Skarels 	/* 0 is reserved, helps to pick up bugs */
16216366Skarels 	if (current_id == 0)
16316366Skarels 		current_id = 1;
16416366Skarels 	return (current_id);
16516356Skarels }
16616356Skarels 
16716366Skarels /*
16816366Skarels  * Delete the invitation with id 'id_num'
16916366Skarels  */
delete_invite(id_num)17016356Skarels delete_invite(id_num)
17116366Skarels 	int id_num;
17216356Skarels {
17326840Smckusick 	register TABLE_ENTRY *ptr;
17416356Skarels 
17516366Skarels 	ptr = table;
17616366Skarels 	if (debug)
17726840Smckusick 		syslog(LOG_DEBUG, "delete_invite(%d)", id_num);
17816366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
17916366Skarels 		if (ptr->request.id_num == id_num)
18016366Skarels 			break;
18116366Skarels 		if (debug)
18226840Smckusick 			print_request("", &ptr->request);
18316366Skarels 	}
18416366Skarels 	if (ptr != NIL) {
18516366Skarels 		delete(ptr);
18616366Skarels 		return (SUCCESS);
18716366Skarels 	}
18816366Skarels 	return (NOT_HERE);
18916356Skarels }
19016356Skarels 
19116366Skarels /*
19216366Skarels  * Classic delete from a double-linked list
19316366Skarels  */
delete(ptr)19416356Skarels delete(ptr)
19526840Smckusick 	register TABLE_ENTRY *ptr;
19616356Skarels {
19716356Skarels 
19826840Smckusick 	if (debug)
19926840Smckusick 		print_request("delete", &ptr->request);
20016366Skarels 	if (table == ptr)
20116366Skarels 		table = ptr->next;
20216366Skarels 	else if (ptr->last != NIL)
20316366Skarels 		ptr->last->next = ptr->next;
20416366Skarels 	if (ptr->next != NIL)
20516366Skarels 		ptr->next->last = ptr->last;
20616366Skarels 	free((char *)ptr);
20716356Skarels }
208