table.c revision 50476
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 3531491Scharnier#if 0 361592Srgrimesstatic char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; 3731491Scharnier#endif 3831491Scharnierstatic const char rcsid[] = 3950476Speter "$FreeBSD: head/libexec/talkd/table.c 50476 1999-08-28 00:22:10Z peter $"; 401592Srgrimes#endif /* not lint */ 411592Srgrimes 421592Srgrimes/* 431592Srgrimes * Routines to handle insertion, deletion, etc on the table 441592Srgrimes * of requests kept by the daemon. Nothing fancy here, linear 458870Srgrimes * search on a double-linked list. A time is kept with each 461592Srgrimes * entry so that overly old invitations can be eliminated. 471592Srgrimes * 481592Srgrimes * Consider this a mis-guided attempt at modularity 491592Srgrimes */ 501592Srgrimes#include <sys/param.h> 511592Srgrimes#include <sys/time.h> 521592Srgrimes#include <sys/socket.h> 531592Srgrimes#include <protocols/talkd.h> 541592Srgrimes#include <stdio.h> 551592Srgrimes#include <stdlib.h> 561592Srgrimes#include <string.h> 5731491Scharnier#include <syslog.h> 5831491Scharnier#include <unistd.h> 591592Srgrimes 601592Srgrimes#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 611592Srgrimes 621592Srgrimes#define NIL ((TABLE_ENTRY *)0) 631592Srgrimes 641592Srgrimesextern int debug; 651592Srgrimesstruct timeval tp; 661592Srgrimesstruct timezone txp; 671592Srgrimes 681592Srgrimestypedef struct table_entry TABLE_ENTRY; 691592Srgrimes 701592Srgrimesstruct table_entry { 711592Srgrimes CTL_MSG request; 721592Srgrimes long time; 731592Srgrimes TABLE_ENTRY *next; 741592Srgrimes TABLE_ENTRY *last; 751592Srgrimes}; 761592Srgrimes 771592SrgrimesTABLE_ENTRY *table = NIL; 7831491Scharnier 7931491Scharniervoid delete __P((TABLE_ENTRY *)); 801592SrgrimesCTL_MSG *find_request(); 811592SrgrimesCTL_MSG *find_match(); 8231491Scharnierint new_id __P((void)); 8331491Scharniervoid print_request __P((char *, CTL_MSG *)); 841592Srgrimes 851592Srgrimes/* 861592Srgrimes * Look in the table for an invitation that matches the current 871592Srgrimes * request looking for an invitation 881592Srgrimes */ 891592SrgrimesCTL_MSG * 901592Srgrimesfind_match(request) 911592Srgrimes register CTL_MSG *request; 921592Srgrimes{ 931592Srgrimes register TABLE_ENTRY *ptr; 941592Srgrimes time_t current_time; 951592Srgrimes 961592Srgrimes gettimeofday(&tp, &txp); 971592Srgrimes current_time = tp.tv_sec; 981592Srgrimes if (debug) 991592Srgrimes print_request("find_match", request); 1001592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 1011592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 1021592Srgrimes /* the entry is too old */ 1031592Srgrimes if (debug) 1041592Srgrimes print_request("deleting expired entry", 1051592Srgrimes &ptr->request); 1061592Srgrimes delete(ptr); 1071592Srgrimes continue; 1081592Srgrimes } 1091592Srgrimes if (debug) 1101592Srgrimes print_request("", &ptr->request); 1111592Srgrimes if (strcmp(request->l_name, ptr->request.r_name) == 0 && 1121592Srgrimes strcmp(request->r_name, ptr->request.l_name) == 0 && 1131592Srgrimes ptr->request.type == LEAVE_INVITE) 1141592Srgrimes return (&ptr->request); 1151592Srgrimes } 1161592Srgrimes return ((CTL_MSG *)0); 1171592Srgrimes} 1181592Srgrimes 1191592Srgrimes/* 1201592Srgrimes * Look for an identical request, as opposed to a complimentary 1218870Srgrimes * one as find_match does 1221592Srgrimes */ 1231592SrgrimesCTL_MSG * 1241592Srgrimesfind_request(request) 1251592Srgrimes register CTL_MSG *request; 1261592Srgrimes{ 1271592Srgrimes register TABLE_ENTRY *ptr; 1281592Srgrimes time_t current_time; 1291592Srgrimes 1301592Srgrimes gettimeofday(&tp, &txp); 1311592Srgrimes current_time = tp.tv_sec; 1321592Srgrimes /* 1331592Srgrimes * See if this is a repeated message, and check for 1341592Srgrimes * out of date entries in the table while we are it. 1351592Srgrimes */ 1361592Srgrimes if (debug) 1371592Srgrimes print_request("find_request", request); 1381592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 1391592Srgrimes if ((ptr->time - current_time) > MAX_LIFE) { 1401592Srgrimes /* the entry is too old */ 1411592Srgrimes if (debug) 1421592Srgrimes print_request("deleting expired entry", 1431592Srgrimes &ptr->request); 1441592Srgrimes delete(ptr); 1451592Srgrimes continue; 1461592Srgrimes } 1471592Srgrimes if (debug) 1481592Srgrimes print_request("", &ptr->request); 1491592Srgrimes if (strcmp(request->r_name, ptr->request.r_name) == 0 && 1501592Srgrimes strcmp(request->l_name, ptr->request.l_name) == 0 && 1511592Srgrimes request->type == ptr->request.type && 1521592Srgrimes request->pid == ptr->request.pid) { 1531592Srgrimes /* update the time if we 'touch' it */ 1541592Srgrimes ptr->time = current_time; 1551592Srgrimes return (&ptr->request); 1561592Srgrimes } 1571592Srgrimes } 1581592Srgrimes return ((CTL_MSG *)0); 1591592Srgrimes} 1601592Srgrimes 16131491Scharniervoid 1621592Srgrimesinsert_table(request, response) 1631592Srgrimes CTL_MSG *request; 1641592Srgrimes CTL_RESPONSE *response; 1651592Srgrimes{ 1661592Srgrimes register TABLE_ENTRY *ptr; 1671592Srgrimes time_t current_time; 1681592Srgrimes 1691592Srgrimes gettimeofday(&tp, &txp); 1701592Srgrimes current_time = tp.tv_sec; 1711592Srgrimes request->id_num = new_id(); 1721592Srgrimes response->id_num = htonl(request->id_num); 1731592Srgrimes /* insert a new entry into the top of the list */ 1741592Srgrimes ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 1751592Srgrimes if (ptr == NIL) { 1761592Srgrimes syslog(LOG_ERR, "insert_table: Out of memory"); 1771592Srgrimes _exit(1); 1781592Srgrimes } 1791592Srgrimes ptr->time = current_time; 1801592Srgrimes ptr->request = *request; 1811592Srgrimes ptr->next = table; 1821592Srgrimes if (ptr->next != NIL) 1831592Srgrimes ptr->next->last = ptr; 1841592Srgrimes ptr->last = NIL; 1851592Srgrimes table = ptr; 1861592Srgrimes} 1871592Srgrimes 1881592Srgrimes/* 1891592Srgrimes * Generate a unique non-zero sequence number 1901592Srgrimes */ 19131491Scharnierint 1921592Srgrimesnew_id() 1931592Srgrimes{ 1941592Srgrimes static int current_id = 0; 1951592Srgrimes 1961592Srgrimes current_id = (current_id + 1) % MAX_ID; 1971592Srgrimes /* 0 is reserved, helps to pick up bugs */ 1981592Srgrimes if (current_id == 0) 1991592Srgrimes current_id = 1; 2001592Srgrimes return (current_id); 2011592Srgrimes} 2021592Srgrimes 2031592Srgrimes/* 2041592Srgrimes * Delete the invitation with id 'id_num' 2051592Srgrimes */ 20631491Scharnierint 2071592Srgrimesdelete_invite(id_num) 2081592Srgrimes int id_num; 2091592Srgrimes{ 2101592Srgrimes register TABLE_ENTRY *ptr; 2111592Srgrimes 2121592Srgrimes ptr = table; 2131592Srgrimes if (debug) 2141592Srgrimes syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 2151592Srgrimes for (ptr = table; ptr != NIL; ptr = ptr->next) { 2161592Srgrimes if (ptr->request.id_num == id_num) 2171592Srgrimes break; 2181592Srgrimes if (debug) 2191592Srgrimes print_request("", &ptr->request); 2201592Srgrimes } 2211592Srgrimes if (ptr != NIL) { 2221592Srgrimes delete(ptr); 2231592Srgrimes return (SUCCESS); 2241592Srgrimes } 2251592Srgrimes return (NOT_HERE); 2261592Srgrimes} 2271592Srgrimes 2281592Srgrimes/* 2291592Srgrimes * Classic delete from a double-linked list 2301592Srgrimes */ 23131491Scharniervoid 2321592Srgrimesdelete(ptr) 2331592Srgrimes register TABLE_ENTRY *ptr; 2341592Srgrimes{ 2351592Srgrimes 2361592Srgrimes if (debug) 2371592Srgrimes print_request("delete", &ptr->request); 2381592Srgrimes if (table == ptr) 2391592Srgrimes table = ptr->next; 2401592Srgrimes else if (ptr->last != NIL) 2411592Srgrimes ptr->last->next = ptr->next; 2421592Srgrimes if (ptr->next != NIL) 2431592Srgrimes ptr->next->last = ptr->last; 2441592Srgrimes free((char *)ptr); 2451592Srgrimes} 246