xref: /csrg-svn/libexec/talkd/table.c (revision 26840)
122399Sdist /*
222399Sdist  * Copyright (c) 1983 Regents of the University of California.
322399Sdist  * All rights reserved.  The Berkeley software License Agreement
422399Sdist  * specifies the terms and conditions for redistribution.
522399Sdist  */
622399Sdist 
716366Skarels #ifndef lint
8*26840Smckusick static char sccsid[] = "@(#)table.c	5.2 (Berkeley) 03/13/86";
922399Sdist #endif not lint
1016356Skarels 
1116366Skarels /*
1216366Skarels  * Routines to handle insertion, deletion, etc on the table
1316366Skarels  * of requests kept by the daemon. Nothing fancy here, linear
1416366Skarels  * search on a double-linked list. A time is kept with each
1516366Skarels  * entry so that overly old invitations can be eliminated.
1616366Skarels  *
1716366Skarels  * Consider this a mis-guided attempt at modularity
1816356Skarels  */
1916366Skarels #include <stdio.h>
2016366Skarels #include <sys/time.h>
21*26840Smckusick #include <syslog.h>
2216356Skarels 
23*26840Smckusick #include <protocols/talkd.h>
2416356Skarels 
2516366Skarels #define MAX_ID 16000	/* << 2^15 so I don't have sign troubles */
2616356Skarels 
2716366Skarels #define NIL ((TABLE_ENTRY *)0)
2816356Skarels 
2916366Skarels extern	int debug;
3016366Skarels struct	timeval tp;
3116366Skarels struct	timezone *txp;
3216356Skarels 
3316356Skarels typedef struct table_entry TABLE_ENTRY;
3416356Skarels 
3516356Skarels struct table_entry {
3616366Skarels 	CTL_MSG request;
3716366Skarels 	long	time;
3816366Skarels 	TABLE_ENTRY *next;
3916366Skarels 	TABLE_ENTRY *last;
4016356Skarels };
4116356Skarels 
42*26840Smckusick TABLE_ENTRY *table = NIL;
4316356Skarels CTL_MSG *find_request();
4416356Skarels CTL_MSG *find_match();
4516366Skarels char	*malloc();
4616356Skarels 
4716366Skarels /*
4816366Skarels  * Look in the table for an invitation that matches the current
4916366Skarels  * request looking for an invitation
5016366Skarels  */
5116366Skarels CTL_MSG *
5216366Skarels find_match(request)
53*26840Smckusick 	register CTL_MSG *request;
5416356Skarels {
55*26840Smckusick 	register TABLE_ENTRY *ptr;
5616366Skarels 	long current_time;
5716356Skarels 
5816366Skarels 	gettimeofday(&tp, &txp);
5916366Skarels 	current_time = tp.tv_sec;
60*26840Smckusick 	if (debug)
61*26840Smckusick 		print_request("find_match", request);
6216366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
6316366Skarels 		if ((ptr->time - current_time) > MAX_LIFE) {
6416366Skarels 			/* the entry is too old */
65*26840Smckusick 			if (debug)
66*26840Smckusick 				print_request("deleting expired entry",
67*26840Smckusick 				    &ptr->request);
6816366Skarels 			delete(ptr);
6916366Skarels 			continue;
7016366Skarels 		}
7116366Skarels 		if (debug)
72*26840Smckusick 			print_request("", &ptr->request);
7316366Skarels 		if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
7416366Skarels 		    strcmp(request->r_name, ptr->request.l_name) == 0 &&
7516366Skarels 		     ptr->request.type == LEAVE_INVITE)
7616366Skarels 			return (&ptr->request);
7716356Skarels 	}
7816366Skarels 	return ((CTL_MSG *)0);
7916356Skarels }
8016356Skarels 
8116366Skarels /*
8216366Skarels  * Look for an identical request, as opposed to a complimentary
8316366Skarels  * one as find_match does
8416366Skarels  */
8516366Skarels CTL_MSG *
8616366Skarels find_request(request)
87*26840Smckusick 	register CTL_MSG *request;
8816356Skarels {
89*26840Smckusick 	register TABLE_ENTRY *ptr;
9016366Skarels 	long current_time;
9116356Skarels 
9216366Skarels 	gettimeofday(&tp, &txp);
9316366Skarels 	current_time = tp.tv_sec;
9416366Skarels 	/*
9516366Skarels 	 * See if this is a repeated message, and check for
9616366Skarels 	 * out of date entries in the table while we are it.
9716356Skarels 	 */
98*26840Smckusick 	if (debug)
99*26840Smckusick 		print_request("find_request", request);
10016366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
10116366Skarels 		if ((ptr->time - current_time) > MAX_LIFE) {
10216366Skarels 			/* the entry is too old */
103*26840Smckusick 			if (debug)
104*26840Smckusick 				print_request("deleting expired entry",
105*26840Smckusick 				    &ptr->request);
10616366Skarels 			delete(ptr);
10716366Skarels 			continue;
10816366Skarels 		}
10916366Skarels 		if (debug)
110*26840Smckusick 			print_request("", &ptr->request);
11116366Skarels 		if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
11216366Skarels 		    strcmp(request->l_name, ptr->request.l_name) == 0 &&
11316366Skarels 		    request->type == ptr->request.type &&
11416366Skarels 		    request->pid == ptr->request.pid) {
11516366Skarels 			/* update the time if we 'touch' it */
11616366Skarels 			ptr->time = current_time;
11716366Skarels 			return (&ptr->request);
11816366Skarels 		}
11916356Skarels 	}
12016366Skarels 	return ((CTL_MSG *)0);
12116356Skarels }
12216356Skarels 
12316356Skarels insert_table(request, response)
12416366Skarels 	CTL_MSG *request;
12516366Skarels 	CTL_RESPONSE *response;
12616356Skarels {
127*26840Smckusick 	register TABLE_ENTRY *ptr;
12816366Skarels 	long current_time;
12916356Skarels 
13016366Skarels 	gettimeofday(&tp, &txp);
13116366Skarels 	current_time = tp.tv_sec;
132*26840Smckusick 	request->id_num = new_id();
133*26840Smckusick 	response->id_num = htonl(request->id_num);
13416356Skarels 	/* insert a new entry into the top of the list */
13516366Skarels 	ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
13616366Skarels 	if (ptr == NIL) {
137*26840Smckusick 		syslog(LOG_ERR, "insert_table: Out of memory");
138*26840Smckusick 		_exit(1);
13916366Skarels 	}
14016366Skarels 	ptr->time = current_time;
14116366Skarels 	ptr->request = *request;
14216366Skarels 	ptr->next = table;
14316366Skarels 	if (ptr->next != NIL)
14416366Skarels 		ptr->next->last = ptr;
14516366Skarels 	ptr->last = NIL;
14616366Skarels 	table = ptr;
14716356Skarels }
14816356Skarels 
14916366Skarels /*
15016366Skarels  * Generate a unique non-zero sequence number
15116366Skarels  */
15216356Skarels new_id()
15316356Skarels {
15416366Skarels 	static int current_id = 0;
15516356Skarels 
15616366Skarels 	current_id = (current_id + 1) % MAX_ID;
15716356Skarels 	/* 0 is reserved, helps to pick up bugs */
15816366Skarels 	if (current_id == 0)
15916366Skarels 		current_id = 1;
16016366Skarels 	return (current_id);
16116356Skarels }
16216356Skarels 
16316366Skarels /*
16416366Skarels  * Delete the invitation with id 'id_num'
16516366Skarels  */
16616356Skarels delete_invite(id_num)
16716366Skarels 	int id_num;
16816356Skarels {
169*26840Smckusick 	register TABLE_ENTRY *ptr;
17016356Skarels 
17116366Skarels 	ptr = table;
17216366Skarels 	if (debug)
173*26840Smckusick 		syslog(LOG_DEBUG, "delete_invite(%d)", id_num);
17416366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
17516366Skarels 		if (ptr->request.id_num == id_num)
17616366Skarels 			break;
17716366Skarels 		if (debug)
178*26840Smckusick 			print_request("", &ptr->request);
17916366Skarels 	}
18016366Skarels 	if (ptr != NIL) {
18116366Skarels 		delete(ptr);
18216366Skarels 		return (SUCCESS);
18316366Skarels 	}
18416366Skarels 	return (NOT_HERE);
18516356Skarels }
18616356Skarels 
18716366Skarels /*
18816366Skarels  * Classic delete from a double-linked list
18916366Skarels  */
19016356Skarels delete(ptr)
191*26840Smckusick 	register TABLE_ENTRY *ptr;
19216356Skarels {
19316356Skarels 
194*26840Smckusick 	if (debug)
195*26840Smckusick 		print_request("delete", &ptr->request);
19616366Skarels 	if (table == ptr)
19716366Skarels 		table = ptr->next;
19816366Skarels 	else if (ptr->last != NIL)
19916366Skarels 		ptr->last->next = ptr->next;
20016366Skarels 	if (ptr->next != NIL)
20116366Skarels 		ptr->next->last = ptr->last;
20216366Skarels 	free((char *)ptr);
20316356Skarels }
204