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