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