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