table.c revision 18471
1131087Smarcel/* 2131087Smarcel * Copyright (c) 1983, 1993 3131087Smarcel * The Regents of the University of California. All rights reserved. 4131087Smarcel * 5131087Smarcel * Redistribution and use in source and binary forms, with or without 6131087Smarcel * modification, are permitted provided that the following conditions 7131087Smarcel * are met: 8131087Smarcel * 1. Redistributions of source code must retain the above copyright 9131087Smarcel * notice, this list of conditions and the following disclaimer. 10131087Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11131087Smarcel * notice, this list of conditions and the following disclaimer in the 12131087Smarcel * documentation and/or other materials provided with the distribution. 13131087Smarcel * 3. All advertising materials mentioning features or use of this software 14131087Smarcel * must display the following acknowledgement: 15131087Smarcel * This product includes software developed by the University of 16131087Smarcel * California, Berkeley and its contributors. 17131087Smarcel * 4. Neither the name of the University nor the names of its contributors 18131087Smarcel * may be used to endorse or promote products derived from this software 19131087Smarcel * without specific prior written permission. 20131087Smarcel * 21131087Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22131087Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23131087Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24131087Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25131087Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26131087Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27131087Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28131087Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29131087Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30131087Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31131087Smarcel * SUCH DAMAGE. 32131087Smarcel * 33131087Smarcel * $Id$ 34131087Smarcel */ 35131087Smarcel 36131087Smarcel#ifndef lint 37131087Smarcelstatic char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; 38131087Smarcel#endif /* not lint */ 39131087Smarcel 40131087Smarcel/* 41131087Smarcel * Routines to handle insertion, deletion, etc on the table 42131087Smarcel * of requests kept by the daemon. Nothing fancy here, linear 43131087Smarcel * search on a double-linked list. A time is kept with each 44131087Smarcel * entry so that overly old invitations can be eliminated. 45131087Smarcel * 46131087Smarcel * Consider this a mis-guided attempt at modularity 47131087Smarcel */ 48131087Smarcel#include <sys/param.h> 49131087Smarcel#include <sys/time.h> 50131087Smarcel#include <sys/socket.h> 51131087Smarcel#include <protocols/talkd.h> 52131087Smarcel#include <syslog.h> 53131087Smarcel#include <unistd.h> 54131087Smarcel#include <stdio.h> 55131087Smarcel#include <stdlib.h> 56131087Smarcel#include <string.h> 57131087Smarcel 58131087Smarcel#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 59131087Smarcel 60131087Smarcel#define NIL ((TABLE_ENTRY *)0) 61131087Smarcel 62131087Smarcelextern int debug; 63131087Smarcelstruct timeval tp; 64131087Smarcelstruct timezone txp; 65131087Smarcel 66131087Smarceltypedef struct table_entry TABLE_ENTRY; 67131087Smarcel 68131087Smarcelstruct table_entry { 69131087Smarcel CTL_MSG request; 70131087Smarcel long time; 71131087Smarcel TABLE_ENTRY *next; 72131087Smarcel TABLE_ENTRY *last; 73131087Smarcel}; 74131087Smarcel 75131087SmarcelTABLE_ENTRY *table = NIL; 76131087SmarcelCTL_MSG *find_request(); 77131087SmarcelCTL_MSG *find_match(); 78131087Smarcel 79131087Smarcel/* 80131087Smarcel * Look in the table for an invitation that matches the current 81131087Smarcel * request looking for an invitation 82131087Smarcel */ 83131087SmarcelCTL_MSG * 84131087Smarcelfind_match(request) 85131087Smarcel register CTL_MSG *request; 86131087Smarcel{ 87131087Smarcel register TABLE_ENTRY *ptr; 88131087Smarcel time_t current_time; 89131087Smarcel 90131087Smarcel gettimeofday(&tp, &txp); 91131087Smarcel current_time = tp.tv_sec; 92131087Smarcel if (debug) 93131087Smarcel print_request("find_match", request); 94131087Smarcel for (ptr = table; ptr != NIL; ptr = ptr->next) { 95131087Smarcel if ((ptr->time - current_time) > MAX_LIFE) { 96131087Smarcel /* the entry is too old */ 97131087Smarcel if (debug) 98131087Smarcel print_request("deleting expired entry", 99131087Smarcel &ptr->request); 100131087Smarcel delete(ptr); 101131087Smarcel continue; 102131087Smarcel } 103131087Smarcel if (debug) 104131087Smarcel print_request("", &ptr->request); 105131087Smarcel if (strcmp(request->l_name, ptr->request.r_name) == 0 && 106131087Smarcel strcmp(request->r_name, ptr->request.l_name) == 0 && 107131087Smarcel ptr->request.type == LEAVE_INVITE) 108131087Smarcel return (&ptr->request); 109131087Smarcel } 110131087Smarcel return ((CTL_MSG *)0); 111131087Smarcel} 112131087Smarcel 113131087Smarcel/* 114131087Smarcel * Look for an identical request, as opposed to a complimentary 115131087Smarcel * one as find_match does 116131087Smarcel */ 117131087SmarcelCTL_MSG * 118131087Smarcelfind_request(request) 119131087Smarcel register CTL_MSG *request; 120131087Smarcel{ 121131087Smarcel register TABLE_ENTRY *ptr; 122131087Smarcel time_t current_time; 123131087Smarcel 124131087Smarcel gettimeofday(&tp, &txp); 125131087Smarcel current_time = tp.tv_sec; 126131087Smarcel /* 127131087Smarcel * See if this is a repeated message, and check for 128131087Smarcel * out of date entries in the table while we are it. 129131087Smarcel */ 130131087Smarcel if (debug) 131131087Smarcel print_request("find_request", request); 132131087Smarcel for (ptr = table; ptr != NIL; ptr = ptr->next) { 133131087Smarcel if ((ptr->time - current_time) > MAX_LIFE) { 134131087Smarcel /* the entry is too old */ 135131087Smarcel if (debug) 136131087Smarcel print_request("deleting expired entry", 137131087Smarcel &ptr->request); 138131087Smarcel delete(ptr); 139131087Smarcel continue; 140131087Smarcel } 141131087Smarcel if (debug) 142131087Smarcel print_request("", &ptr->request); 143131087Smarcel if (strcmp(request->r_name, ptr->request.r_name) == 0 && 144131087Smarcel strcmp(request->l_name, ptr->request.l_name) == 0 && 145131087Smarcel request->type == ptr->request.type && 146131087Smarcel request->pid == ptr->request.pid) { 147131087Smarcel /* update the time if we 'touch' it */ 148131087Smarcel ptr->time = current_time; 149131087Smarcel return (&ptr->request); 150131087Smarcel } 151131087Smarcel } 152131087Smarcel return ((CTL_MSG *)0); 153131087Smarcel} 154131087Smarcel 155131087Smarcelinsert_table(request, response) 156131087Smarcel CTL_MSG *request; 157131087Smarcel CTL_RESPONSE *response; 158131087Smarcel{ 159131087Smarcel register TABLE_ENTRY *ptr; 160131087Smarcel time_t current_time; 161131087Smarcel 162131087Smarcel gettimeofday(&tp, &txp); 163131087Smarcel current_time = tp.tv_sec; 164131087Smarcel request->id_num = new_id(); 165131087Smarcel response->id_num = htonl(request->id_num); 166131087Smarcel /* insert a new entry into the top of the list */ 167131087Smarcel ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 168131087Smarcel if (ptr == NIL) { 169131087Smarcel syslog(LOG_ERR, "insert_table: Out of memory"); 170131087Smarcel _exit(1); 171131087Smarcel } 172131087Smarcel ptr->time = current_time; 173131087Smarcel ptr->request = *request; 174131087Smarcel ptr->next = table; 175131087Smarcel if (ptr->next != NIL) 176131087Smarcel ptr->next->last = ptr; 177138383Smarcel ptr->last = NIL; 178131087Smarcel table = ptr; 179138383Smarcel} 180131087Smarcel 181131087Smarcel/* 182131087Smarcel * Generate a unique non-zero sequence number 183131087Smarcel */ 184131087Smarcelnew_id() 185131087Smarcel{ 186131087Smarcel static int current_id = 0; 187131087Smarcel 188131087Smarcel current_id = (current_id + 1) % MAX_ID; 189131087Smarcel /* 0 is reserved, helps to pick up bugs */ 190131087Smarcel if (current_id == 0) 191131087Smarcel current_id = 1; 192131087Smarcel return (current_id); 193131087Smarcel} 194131087Smarcel 195131087Smarcel/* 196131087Smarcel * Delete the invitation with id 'id_num' 197131087Smarcel */ 198131087Smarceldelete_invite(id_num) 199131087Smarcel int id_num; 200131087Smarcel{ 201131087Smarcel register TABLE_ENTRY *ptr; 202131087Smarcel 203131087Smarcel ptr = table; 204131087Smarcel if (debug) 205131087Smarcel syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 206131087Smarcel for (ptr = table; ptr != NIL; ptr = ptr->next) { 207131087Smarcel if (ptr->request.id_num == id_num) 208131087Smarcel break; 209131087Smarcel if (debug) 210131087Smarcel print_request("", &ptr->request); 211131087Smarcel } 212131087Smarcel if (ptr != NIL) { 213131087Smarcel delete(ptr); 214131087Smarcel return (SUCCESS); 215131087Smarcel } 216131087Smarcel return (NOT_HERE); 217131087Smarcel} 218131087Smarcel 219131087Smarcel/* 220131087Smarcel * Classic delete from a double-linked list 221131087Smarcel */ 222131087Smarceldelete(ptr) 223131087Smarcel register TABLE_ENTRY *ptr; 224131087Smarcel{ 225131087Smarcel 226131087Smarcel if (debug) 227131087Smarcel print_request("delete", &ptr->request); 228131087Smarcel if (table == ptr) 229131087Smarcel table = ptr->next; 230131087Smarcel else if (ptr->last != NIL) 231131087Smarcel ptr->last->next = ptr->next; 232131087Smarcel if (ptr->next != NIL) 233131087Smarcel ptr->next->last = ptr->last; 234131087Smarcel free((char *)ptr); 235131087Smarcel} 236131087Smarcel