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