xref: /csrg-svn/libexec/talkd/table.c (revision 32103)
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*32103Smckusick static char sccsid[] = "@(#)table.c	5.3 (Berkeley) 09/04/87";
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>
2126840Smckusick #include <syslog.h>
22*32103Smckusick #include <sys/param.h>
2316356Skarels 
2426840Smckusick #include <protocols/talkd.h>
2516356Skarels 
2616366Skarels #define MAX_ID 16000	/* << 2^15 so I don't have sign troubles */
2716356Skarels 
2816366Skarels #define NIL ((TABLE_ENTRY *)0)
2916356Skarels 
3016366Skarels extern	int debug;
3116366Skarels struct	timeval tp;
3216366Skarels struct	timezone *txp;
3316356Skarels 
3416356Skarels typedef struct table_entry TABLE_ENTRY;
3516356Skarels 
3616356Skarels struct table_entry {
3716366Skarels 	CTL_MSG request;
3816366Skarels 	long	time;
3916366Skarels 	TABLE_ENTRY *next;
4016366Skarels 	TABLE_ENTRY *last;
4116356Skarels };
4216356Skarels 
4326840Smckusick TABLE_ENTRY *table = NIL;
4416356Skarels CTL_MSG *find_request();
4516356Skarels CTL_MSG *find_match();
4616366Skarels char	*malloc();
4716356Skarels 
4816366Skarels /*
4916366Skarels  * Look in the table for an invitation that matches the current
5016366Skarels  * request looking for an invitation
5116366Skarels  */
5216366Skarels CTL_MSG *
5316366Skarels find_match(request)
5426840Smckusick 	register CTL_MSG *request;
5516356Skarels {
5626840Smckusick 	register TABLE_ENTRY *ptr;
5716366Skarels 	long current_time;
5816356Skarels 
5916366Skarels 	gettimeofday(&tp, &txp);
6016366Skarels 	current_time = tp.tv_sec;
6126840Smckusick 	if (debug)
6226840Smckusick 		print_request("find_match", request);
6316366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
6416366Skarels 		if ((ptr->time - current_time) > MAX_LIFE) {
6516366Skarels 			/* the entry is too old */
6626840Smckusick 			if (debug)
6726840Smckusick 				print_request("deleting expired entry",
6826840Smckusick 				    &ptr->request);
6916366Skarels 			delete(ptr);
7016366Skarels 			continue;
7116366Skarels 		}
7216366Skarels 		if (debug)
7326840Smckusick 			print_request("", &ptr->request);
7416366Skarels 		if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
7516366Skarels 		    strcmp(request->r_name, ptr->request.l_name) == 0 &&
7616366Skarels 		     ptr->request.type == LEAVE_INVITE)
7716366Skarels 			return (&ptr->request);
7816356Skarels 	}
7916366Skarels 	return ((CTL_MSG *)0);
8016356Skarels }
8116356Skarels 
8216366Skarels /*
8316366Skarels  * Look for an identical request, as opposed to a complimentary
8416366Skarels  * one as find_match does
8516366Skarels  */
8616366Skarels CTL_MSG *
8716366Skarels find_request(request)
8826840Smckusick 	register CTL_MSG *request;
8916356Skarels {
9026840Smckusick 	register TABLE_ENTRY *ptr;
9116366Skarels 	long current_time;
9216356Skarels 
9316366Skarels 	gettimeofday(&tp, &txp);
9416366Skarels 	current_time = tp.tv_sec;
9516366Skarels 	/*
9616366Skarels 	 * See if this is a repeated message, and check for
9716366Skarels 	 * out of date entries in the table while we are it.
9816356Skarels 	 */
9926840Smckusick 	if (debug)
10026840Smckusick 		print_request("find_request", request);
10116366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
10216366Skarels 		if ((ptr->time - current_time) > MAX_LIFE) {
10316366Skarels 			/* the entry is too old */
10426840Smckusick 			if (debug)
10526840Smckusick 				print_request("deleting expired entry",
10626840Smckusick 				    &ptr->request);
10716366Skarels 			delete(ptr);
10816366Skarels 			continue;
10916366Skarels 		}
11016366Skarels 		if (debug)
11126840Smckusick 			print_request("", &ptr->request);
11216366Skarels 		if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
11316366Skarels 		    strcmp(request->l_name, ptr->request.l_name) == 0 &&
11416366Skarels 		    request->type == ptr->request.type &&
11516366Skarels 		    request->pid == ptr->request.pid) {
11616366Skarels 			/* update the time if we 'touch' it */
11716366Skarels 			ptr->time = current_time;
11816366Skarels 			return (&ptr->request);
11916366Skarels 		}
12016356Skarels 	}
12116366Skarels 	return ((CTL_MSG *)0);
12216356Skarels }
12316356Skarels 
12416356Skarels insert_table(request, response)
12516366Skarels 	CTL_MSG *request;
12616366Skarels 	CTL_RESPONSE *response;
12716356Skarels {
12826840Smckusick 	register TABLE_ENTRY *ptr;
12916366Skarels 	long current_time;
13016356Skarels 
13116366Skarels 	gettimeofday(&tp, &txp);
13216366Skarels 	current_time = tp.tv_sec;
13326840Smckusick 	request->id_num = new_id();
13426840Smckusick 	response->id_num = htonl(request->id_num);
13516356Skarels 	/* insert a new entry into the top of the list */
13616366Skarels 	ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
13716366Skarels 	if (ptr == NIL) {
13826840Smckusick 		syslog(LOG_ERR, "insert_table: Out of memory");
13926840Smckusick 		_exit(1);
14016366Skarels 	}
14116366Skarels 	ptr->time = current_time;
14216366Skarels 	ptr->request = *request;
14316366Skarels 	ptr->next = table;
14416366Skarels 	if (ptr->next != NIL)
14516366Skarels 		ptr->next->last = ptr;
14616366Skarels 	ptr->last = NIL;
14716366Skarels 	table = ptr;
14816356Skarels }
14916356Skarels 
15016366Skarels /*
15116366Skarels  * Generate a unique non-zero sequence number
15216366Skarels  */
15316356Skarels new_id()
15416356Skarels {
15516366Skarels 	static int current_id = 0;
15616356Skarels 
15716366Skarels 	current_id = (current_id + 1) % MAX_ID;
15816356Skarels 	/* 0 is reserved, helps to pick up bugs */
15916366Skarels 	if (current_id == 0)
16016366Skarels 		current_id = 1;
16116366Skarels 	return (current_id);
16216356Skarels }
16316356Skarels 
16416366Skarels /*
16516366Skarels  * Delete the invitation with id 'id_num'
16616366Skarels  */
16716356Skarels delete_invite(id_num)
16816366Skarels 	int id_num;
16916356Skarels {
17026840Smckusick 	register TABLE_ENTRY *ptr;
17116356Skarels 
17216366Skarels 	ptr = table;
17316366Skarels 	if (debug)
17426840Smckusick 		syslog(LOG_DEBUG, "delete_invite(%d)", id_num);
17516366Skarels 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
17616366Skarels 		if (ptr->request.id_num == id_num)
17716366Skarels 			break;
17816366Skarels 		if (debug)
17926840Smckusick 			print_request("", &ptr->request);
18016366Skarels 	}
18116366Skarels 	if (ptr != NIL) {
18216366Skarels 		delete(ptr);
18316366Skarels 		return (SUCCESS);
18416366Skarels 	}
18516366Skarels 	return (NOT_HERE);
18616356Skarels }
18716356Skarels 
18816366Skarels /*
18916366Skarels  * Classic delete from a double-linked list
19016366Skarels  */
19116356Skarels delete(ptr)
19226840Smckusick 	register TABLE_ENTRY *ptr;
19316356Skarels {
19416356Skarels 
19526840Smckusick 	if (debug)
19626840Smckusick 		print_request("delete", &ptr->request);
19716366Skarels 	if (table == ptr)
19816366Skarels 		table = ptr->next;
19916366Skarels 	else if (ptr->last != NIL)
20016366Skarels 		ptr->last->next = ptr->next;
20116366Skarels 	if (ptr->next != NIL)
20216366Skarels 		ptr->next->last = ptr->last;
20316366Skarels 	free((char *)ptr);
20416356Skarels }
205