xref: /csrg-svn/libexec/talkd/table.c (revision 34776)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)table.c	5.5 (Berkeley) 06/18/88";
20 #endif /* not lint */
21 
22 /*
23  * Routines to handle insertion, deletion, etc on the table
24  * of requests kept by the daemon. Nothing fancy here, linear
25  * search on a double-linked list. A time is kept with each
26  * entry so that overly old invitations can be eliminated.
27  *
28  * Consider this a mis-guided attempt at modularity
29  */
30 #include <stdio.h>
31 #include <sys/time.h>
32 #include <syslog.h>
33 #include <sys/param.h>
34 
35 #include <protocols/talkd.h>
36 
37 #define MAX_ID 16000	/* << 2^15 so I don't have sign troubles */
38 
39 #define NIL ((TABLE_ENTRY *)0)
40 
41 extern	int debug;
42 struct	timeval tp;
43 struct	timezone *txp;
44 
45 typedef struct table_entry TABLE_ENTRY;
46 
47 struct table_entry {
48 	CTL_MSG request;
49 	long	time;
50 	TABLE_ENTRY *next;
51 	TABLE_ENTRY *last;
52 };
53 
54 TABLE_ENTRY *table = NIL;
55 CTL_MSG *find_request();
56 CTL_MSG *find_match();
57 char	*malloc();
58 
59 /*
60  * Look in the table for an invitation that matches the current
61  * request looking for an invitation
62  */
63 CTL_MSG *
64 find_match(request)
65 	register CTL_MSG *request;
66 {
67 	register TABLE_ENTRY *ptr;
68 	long current_time;
69 
70 	gettimeofday(&tp, &txp);
71 	current_time = tp.tv_sec;
72 	if (debug)
73 		print_request("find_match", request);
74 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
75 		if ((ptr->time - current_time) > MAX_LIFE) {
76 			/* the entry is too old */
77 			if (debug)
78 				print_request("deleting expired entry",
79 				    &ptr->request);
80 			delete(ptr);
81 			continue;
82 		}
83 		if (debug)
84 			print_request("", &ptr->request);
85 		if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
86 		    strcmp(request->r_name, ptr->request.l_name) == 0 &&
87 		     ptr->request.type == LEAVE_INVITE)
88 			return (&ptr->request);
89 	}
90 	return ((CTL_MSG *)0);
91 }
92 
93 /*
94  * Look for an identical request, as opposed to a complimentary
95  * one as find_match does
96  */
97 CTL_MSG *
98 find_request(request)
99 	register CTL_MSG *request;
100 {
101 	register TABLE_ENTRY *ptr;
102 	long current_time;
103 
104 	gettimeofday(&tp, &txp);
105 	current_time = tp.tv_sec;
106 	/*
107 	 * See if this is a repeated message, and check for
108 	 * out of date entries in the table while we are it.
109 	 */
110 	if (debug)
111 		print_request("find_request", request);
112 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
113 		if ((ptr->time - current_time) > MAX_LIFE) {
114 			/* the entry is too old */
115 			if (debug)
116 				print_request("deleting expired entry",
117 				    &ptr->request);
118 			delete(ptr);
119 			continue;
120 		}
121 		if (debug)
122 			print_request("", &ptr->request);
123 		if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
124 		    strcmp(request->l_name, ptr->request.l_name) == 0 &&
125 		    request->type == ptr->request.type &&
126 		    request->pid == ptr->request.pid) {
127 			/* update the time if we 'touch' it */
128 			ptr->time = current_time;
129 			return (&ptr->request);
130 		}
131 	}
132 	return ((CTL_MSG *)0);
133 }
134 
135 insert_table(request, response)
136 	CTL_MSG *request;
137 	CTL_RESPONSE *response;
138 {
139 	register TABLE_ENTRY *ptr;
140 	long current_time;
141 
142 	gettimeofday(&tp, &txp);
143 	current_time = tp.tv_sec;
144 	request->id_num = new_id();
145 	response->id_num = htonl(request->id_num);
146 	/* insert a new entry into the top of the list */
147 	ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
148 	if (ptr == NIL) {
149 		syslog(LOG_ERR, "insert_table: Out of memory");
150 		_exit(1);
151 	}
152 	ptr->time = current_time;
153 	ptr->request = *request;
154 	ptr->next = table;
155 	if (ptr->next != NIL)
156 		ptr->next->last = ptr;
157 	ptr->last = NIL;
158 	table = ptr;
159 }
160 
161 /*
162  * Generate a unique non-zero sequence number
163  */
164 new_id()
165 {
166 	static int current_id = 0;
167 
168 	current_id = (current_id + 1) % MAX_ID;
169 	/* 0 is reserved, helps to pick up bugs */
170 	if (current_id == 0)
171 		current_id = 1;
172 	return (current_id);
173 }
174 
175 /*
176  * Delete the invitation with id 'id_num'
177  */
178 delete_invite(id_num)
179 	int id_num;
180 {
181 	register TABLE_ENTRY *ptr;
182 
183 	ptr = table;
184 	if (debug)
185 		syslog(LOG_DEBUG, "delete_invite(%d)", id_num);
186 	for (ptr = table; ptr != NIL; ptr = ptr->next) {
187 		if (ptr->request.id_num == id_num)
188 			break;
189 		if (debug)
190 			print_request("", &ptr->request);
191 	}
192 	if (ptr != NIL) {
193 		delete(ptr);
194 		return (SUCCESS);
195 	}
196 	return (NOT_HERE);
197 }
198 
199 /*
200  * Classic delete from a double-linked list
201  */
202 delete(ptr)
203 	register TABLE_ENTRY *ptr;
204 {
205 
206 	if (debug)
207 		print_request("delete", &ptr->request);
208 	if (table == ptr)
209 		table = ptr->next;
210 	else if (ptr->last != NIL)
211 		ptr->last->next = ptr->next;
212 	if (ptr->next != NIL)
213 		ptr->next->last = ptr->last;
214 	free((char *)ptr);
215 }
216