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