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