table.c revision 1592
11592Srgrimes/* 21592Srgrimes * Copyright (c) 1983, 1993 31592Srgrimes * The Regents of the University of California. All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 131592Srgrimes * 3. All advertising materials mentioning features or use of this software 141592Srgrimes * must display the following acknowledgement: 151592Srgrimes * This product includes software developed by the University of 161592Srgrimes * California, Berkeley and its contributors. 171592Srgrimes * 4. Neither the name of the University nor the names of its contributors 181592Srgrimes * may be used to endorse or promote products derived from this software 191592Srgrimes * without specific prior written permission. 201592Srgrimes * 211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311592Srgrimes * SUCH DAMAGE. 321592Srgrimes */ 331592Srgrimes 341592Srgrimes#ifndef lint 351592Srgrimesstatic char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; 361592Srgrimes#endif /* not lint */ 371592Srgrimes 381592Srgrimes/* 391592Srgrimes * Routines to handle insertion, deletion, etc on the table 401592Srgrimes * of requests kept by the daemon. Nothing fancy here, linear 411592Srgrimes * search on a double-linked list. A time is kept with each 421592Srgrimes * entry so that overly old invitations can be eliminated. 431592Srgrimes * 441592Srgrimes * Consider this a mis-guided attempt at modularity 451592Srgrimes */ 461592Srgrimes#include <sys/param.h> 471592Srgrimes#include <sys/time.h> 481592Srgrimes#include <sys/socket.h> 491592Srgrimes#include <protocols/talkd.h> 501592Srgrimes#include <syslog.h> 511592Srgrimes#include <unistd.h> 521592Srgrimes#include <stdio.h> 531592Srgrimes#include <stdlib.h> 541592Srgrimes#include <string.h> 551592Srgrimes 561592Srgrimes#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 571592Srgrimes 581592Srgrimes#define NIL ((TABLE_ENTRY *)0) 591592Srgrimes 601592Srgrimesextern int debug; 611592Srgrimesstruct timeval tp; 621592Srgrimesstruct timezone txp; 631592Srgrimes 641592Srgrimestypedef struct table_entry TABLE_ENTRY; 651592Srgrimes 661592Srgrimesstruct table_entry { 671592Srgrimes CTL_MSG request; 681592Srgrimes long time; 691592Srgrimes TABLE_ENTRY *next; 701592Srgrimes TABLE_ENTRY *last; 711592Srgrimes}; 721592Srgrimes 731592SrgrimesTABLE_ENTRY *table = NIL; 741592SrgrimesCTL_MSG *find_request(); 751592SrgrimesCTL_MSG *find_match(); 761592Srgrimes 771592Srgrimes/* 781592Srgrimes * Look in the table for an invitation that matches the current 791592Srgrimes * request looking for an invitation 801592Srgrimes */ 811592SrgrimesCTL_MSG * 821592Srgrimesfind_match(request) 831592Srgrimes register CTL_MSG *request; 841592Srgrimes{ 851592Srgrimes register TABLE_ENTRY *ptr; 861592Srgrimes time_t current_time; 871592Srgrimes 881592Srgrimes gettimeofday(&tp, &txp); 891592Srgrimes current_time = tp.tv_sec; 901592Srgrimes if (debug) 911592Srgrimes print_request("find_match", request); 921592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 931592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 941592Srgrimes /* the entry is too old */ 951592Srgrimes if (debug) 961592Srgrimes print_request("deleting expired entry", 971592Srgrimes &ptr->request); 981592Srgrimes delete(ptr); 991592Srgrimes continue; 1001592Srgrimes } 1011592Srgrimes if (debug) 1021592Srgrimes print_request("", &ptr->request); 1031592Srgrimes if (strcmp(request->l_name, ptr->request.r_name) == 0 && 1041592Srgrimes strcmp(request->r_name, ptr->request.l_name) == 0 && 1051592Srgrimes ptr->request.type == LEAVE_INVITE) 1061592Srgrimes return (&ptr->request); 1071592Srgrimes } 1081592Srgrimes return ((CTL_MSG *)0); 1091592Srgrimes} 1101592Srgrimes 1111592Srgrimes/* 1121592Srgrimes * Look for an identical request, as opposed to a complimentary 1131592Srgrimes * one as find_match does 1141592Srgrimes */ 1151592SrgrimesCTL_MSG * 1161592Srgrimesfind_request(request) 1171592Srgrimes register CTL_MSG *request; 1181592Srgrimes{ 1191592Srgrimes register TABLE_ENTRY *ptr; 1201592Srgrimes time_t current_time; 1211592Srgrimes 1221592Srgrimes gettimeofday(&tp, &txp); 1231592Srgrimes current_time = tp.tv_sec; 1241592Srgrimes /* 1251592Srgrimes * See if this is a repeated message, and check for 1261592Srgrimes * out of date entries in the table while we are it. 1271592Srgrimes */ 1281592Srgrimes if (debug) 1291592Srgrimes print_request("find_request", request); 1301592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 1311592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 1321592Srgrimes /* the entry is too old */ 1331592Srgrimes if (debug) 1341592Srgrimes print_request("deleting expired entry", 1351592Srgrimes &ptr->request); 1361592Srgrimes delete(ptr); 1371592Srgrimes continue; 1381592Srgrimes } 1391592Srgrimes if (debug) 1401592Srgrimes print_request("", &ptr->request); 1411592Srgrimes if (strcmp(request->r_name, ptr->request.r_name) == 0 && 1421592Srgrimes strcmp(request->l_name, ptr->request.l_name) == 0 && 1431592Srgrimes request->type == ptr->request.type && 1441592Srgrimes request->pid == ptr->request.pid) { 1451592Srgrimes /* update the time if we 'touch' it */ 1461592Srgrimes ptr->time = current_time; 1471592Srgrimes return (&ptr->request); 1481592Srgrimes } 1491592Srgrimes } 1501592Srgrimes return ((CTL_MSG *)0); 1511592Srgrimes} 1521592Srgrimes 1531592Srgrimesinsert_table(request, response) 1541592Srgrimes CTL_MSG *request; 1551592Srgrimes CTL_RESPONSE *response; 1561592Srgrimes{ 1571592Srgrimes register TABLE_ENTRY *ptr; 1581592Srgrimes time_t current_time; 1591592Srgrimes 1601592Srgrimes gettimeofday(&tp, &txp); 1611592Srgrimes current_time = tp.tv_sec; 1621592Srgrimes request->id_num = new_id(); 1631592Srgrimes response->id_num = htonl(request->id_num); 1641592Srgrimes /* insert a new entry into the top of the list */ 1651592Srgrimes ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 1661592Srgrimes if (ptr == NIL) { 1671592Srgrimes syslog(LOG_ERR, "insert_table: Out of memory"); 1681592Srgrimes _exit(1); 1691592Srgrimes } 1701592Srgrimes ptr->time = current_time; 1711592Srgrimes ptr->request = *request; 1721592Srgrimes ptr->next = table; 1731592Srgrimes if (ptr->next != NIL) 1741592Srgrimes ptr->next->last = ptr; 1751592Srgrimes ptr->last = NIL; 1761592Srgrimes table = ptr; 1771592Srgrimes} 1781592Srgrimes 1791592Srgrimes/* 1801592Srgrimes * Generate a unique non-zero sequence number 1811592Srgrimes */ 1821592Srgrimesnew_id() 1831592Srgrimes{ 1841592Srgrimes static int current_id = 0; 1851592Srgrimes 1861592Srgrimes current_id = (current_id + 1) % MAX_ID; 1871592Srgrimes /* 0 is reserved, helps to pick up bugs */ 1881592Srgrimes if (current_id == 0) 1891592Srgrimes current_id = 1; 1901592Srgrimes return (current_id); 1911592Srgrimes} 1921592Srgrimes 1931592Srgrimes/* 1941592Srgrimes * Delete the invitation with id 'id_num' 1951592Srgrimes */ 1961592Srgrimesdelete_invite(id_num) 1971592Srgrimes int id_num; 1981592Srgrimes{ 1991592Srgrimes register TABLE_ENTRY *ptr; 2001592Srgrimes 2011592Srgrimes ptr = table; 2021592Srgrimes if (debug) 2031592Srgrimes syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 2041592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 2051592Srgrimes if (ptr->request.id_num == id_num) 2061592Srgrimes break; 2071592Srgrimes if (debug) 2081592Srgrimes print_request("", &ptr->request); 2091592Srgrimes } 2101592Srgrimes if (ptr != NIL) { 2111592Srgrimes delete(ptr); 2121592Srgrimes return (SUCCESS); 2131592Srgrimes } 2141592Srgrimes return (NOT_HERE); 2151592Srgrimes} 2161592Srgrimes 2171592Srgrimes/* 2181592Srgrimes * Classic delete from a double-linked list 2191592Srgrimes */ 2201592Srgrimesdelete(ptr) 2211592Srgrimes register TABLE_ENTRY *ptr; 2221592Srgrimes{ 2231592Srgrimes 2241592Srgrimes if (debug) 2251592Srgrimes print_request("delete", &ptr->request); 2261592Srgrimes if (table == ptr) 2271592Srgrimes table = ptr->next; 2281592Srgrimes else if (ptr->last != NIL) 2291592Srgrimes ptr->last->next = ptr->next; 2301592Srgrimes if (ptr->next != NIL) 2311592Srgrimes ptr->next->last = ptr->last; 2321592Srgrimes free((char *)ptr); 2331592Srgrimes} 234