122399Sdist /* 222399Sdist * Copyright (c) 1983 Regents of the University of California. 3*34360Sbostic * All rights reserved. 4*34360Sbostic * 5*34360Sbostic * Redistribution and use in source and binary forms are permitted 6*34360Sbostic * provided that this notice is preserved and that due credit is given 7*34360Sbostic * to the University of California at Berkeley. The name of the University 8*34360Sbostic * may not be used to endorse or promote products derived from this 9*34360Sbostic * software without specific prior written permission. This software 10*34360Sbostic * is provided ``as is'' without express or implied warranty. 1122399Sdist */ 1222399Sdist 1316366Skarels #ifndef lint 14*34360Sbostic static char sccsid[] = "@(#)table.c 5.4 (Berkeley) 05/20/88"; 15*34360Sbostic #endif /* not lint */ 1616356Skarels 1716366Skarels /* 1816366Skarels * Routines to handle insertion, deletion, etc on the table 1916366Skarels * of requests kept by the daemon. Nothing fancy here, linear 2016366Skarels * search on a double-linked list. A time is kept with each 2116366Skarels * entry so that overly old invitations can be eliminated. 2216366Skarels * 2316366Skarels * Consider this a mis-guided attempt at modularity 2416356Skarels */ 2516366Skarels #include <stdio.h> 2616366Skarels #include <sys/time.h> 2726840Smckusick #include <syslog.h> 2832103Smckusick #include <sys/param.h> 2916356Skarels 3026840Smckusick #include <protocols/talkd.h> 3116356Skarels 3216366Skarels #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 3316356Skarels 3416366Skarels #define NIL ((TABLE_ENTRY *)0) 3516356Skarels 3616366Skarels extern int debug; 3716366Skarels struct timeval tp; 3816366Skarels struct timezone *txp; 3916356Skarels 4016356Skarels typedef struct table_entry TABLE_ENTRY; 4116356Skarels 4216356Skarels struct table_entry { 4316366Skarels CTL_MSG request; 4416366Skarels long time; 4516366Skarels TABLE_ENTRY *next; 4616366Skarels TABLE_ENTRY *last; 4716356Skarels }; 4816356Skarels 4926840Smckusick TABLE_ENTRY *table = NIL; 5016356Skarels CTL_MSG *find_request(); 5116356Skarels CTL_MSG *find_match(); 5216366Skarels char *malloc(); 5316356Skarels 5416366Skarels /* 5516366Skarels * Look in the table for an invitation that matches the current 5616366Skarels * request looking for an invitation 5716366Skarels */ 5816366Skarels CTL_MSG * 5916366Skarels find_match(request) 6026840Smckusick register CTL_MSG *request; 6116356Skarels { 6226840Smckusick register TABLE_ENTRY *ptr; 6316366Skarels long current_time; 6416356Skarels 6516366Skarels gettimeofday(&tp, &txp); 6616366Skarels current_time = tp.tv_sec; 6726840Smckusick if (debug) 6826840Smckusick print_request("find_match", request); 6916366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 7016366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 7116366Skarels /* the entry is too old */ 7226840Smckusick if (debug) 7326840Smckusick print_request("deleting expired entry", 7426840Smckusick &ptr->request); 7516366Skarels delete(ptr); 7616366Skarels continue; 7716366Skarels } 7816366Skarels if (debug) 7926840Smckusick print_request("", &ptr->request); 8016366Skarels if (strcmp(request->l_name, ptr->request.r_name) == 0 && 8116366Skarels strcmp(request->r_name, ptr->request.l_name) == 0 && 8216366Skarels ptr->request.type == LEAVE_INVITE) 8316366Skarels return (&ptr->request); 8416356Skarels } 8516366Skarels return ((CTL_MSG *)0); 8616356Skarels } 8716356Skarels 8816366Skarels /* 8916366Skarels * Look for an identical request, as opposed to a complimentary 9016366Skarels * one as find_match does 9116366Skarels */ 9216366Skarels CTL_MSG * 9316366Skarels find_request(request) 9426840Smckusick register CTL_MSG *request; 9516356Skarels { 9626840Smckusick register TABLE_ENTRY *ptr; 9716366Skarels long current_time; 9816356Skarels 9916366Skarels gettimeofday(&tp, &txp); 10016366Skarels current_time = tp.tv_sec; 10116366Skarels /* 10216366Skarels * See if this is a repeated message, and check for 10316366Skarels * out of date entries in the table while we are it. 10416356Skarels */ 10526840Smckusick if (debug) 10626840Smckusick print_request("find_request", request); 10716366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 10816366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 10916366Skarels /* the entry is too old */ 11026840Smckusick if (debug) 11126840Smckusick print_request("deleting expired entry", 11226840Smckusick &ptr->request); 11316366Skarels delete(ptr); 11416366Skarels continue; 11516366Skarels } 11616366Skarels if (debug) 11726840Smckusick print_request("", &ptr->request); 11816366Skarels if (strcmp(request->r_name, ptr->request.r_name) == 0 && 11916366Skarels strcmp(request->l_name, ptr->request.l_name) == 0 && 12016366Skarels request->type == ptr->request.type && 12116366Skarels request->pid == ptr->request.pid) { 12216366Skarels /* update the time if we 'touch' it */ 12316366Skarels ptr->time = current_time; 12416366Skarels return (&ptr->request); 12516366Skarels } 12616356Skarels } 12716366Skarels return ((CTL_MSG *)0); 12816356Skarels } 12916356Skarels 13016356Skarels insert_table(request, response) 13116366Skarels CTL_MSG *request; 13216366Skarels CTL_RESPONSE *response; 13316356Skarels { 13426840Smckusick register TABLE_ENTRY *ptr; 13516366Skarels long current_time; 13616356Skarels 13716366Skarels gettimeofday(&tp, &txp); 13816366Skarels current_time = tp.tv_sec; 13926840Smckusick request->id_num = new_id(); 14026840Smckusick response->id_num = htonl(request->id_num); 14116356Skarels /* insert a new entry into the top of the list */ 14216366Skarels ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 14316366Skarels if (ptr == NIL) { 14426840Smckusick syslog(LOG_ERR, "insert_table: Out of memory"); 14526840Smckusick _exit(1); 14616366Skarels } 14716366Skarels ptr->time = current_time; 14816366Skarels ptr->request = *request; 14916366Skarels ptr->next = table; 15016366Skarels if (ptr->next != NIL) 15116366Skarels ptr->next->last = ptr; 15216366Skarels ptr->last = NIL; 15316366Skarels table = ptr; 15416356Skarels } 15516356Skarels 15616366Skarels /* 15716366Skarels * Generate a unique non-zero sequence number 15816366Skarels */ 15916356Skarels new_id() 16016356Skarels { 16116366Skarels static int current_id = 0; 16216356Skarels 16316366Skarels current_id = (current_id + 1) % MAX_ID; 16416356Skarels /* 0 is reserved, helps to pick up bugs */ 16516366Skarels if (current_id == 0) 16616366Skarels current_id = 1; 16716366Skarels return (current_id); 16816356Skarels } 16916356Skarels 17016366Skarels /* 17116366Skarels * Delete the invitation with id 'id_num' 17216366Skarels */ 17316356Skarels delete_invite(id_num) 17416366Skarels int id_num; 17516356Skarels { 17626840Smckusick register TABLE_ENTRY *ptr; 17716356Skarels 17816366Skarels ptr = table; 17916366Skarels if (debug) 18026840Smckusick syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 18116366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 18216366Skarels if (ptr->request.id_num == id_num) 18316366Skarels break; 18416366Skarels if (debug) 18526840Smckusick print_request("", &ptr->request); 18616366Skarels } 18716366Skarels if (ptr != NIL) { 18816366Skarels delete(ptr); 18916366Skarels return (SUCCESS); 19016366Skarels } 19116366Skarels return (NOT_HERE); 19216356Skarels } 19316356Skarels 19416366Skarels /* 19516366Skarels * Classic delete from a double-linked list 19616366Skarels */ 19716356Skarels delete(ptr) 19826840Smckusick register TABLE_ENTRY *ptr; 19916356Skarels { 20016356Skarels 20126840Smckusick if (debug) 20226840Smckusick print_request("delete", &ptr->request); 20316366Skarels if (table == ptr) 20416366Skarels table = ptr->next; 20516366Skarels else if (ptr->last != NIL) 20616366Skarels ptr->last->next = ptr->next; 20716366Skarels if (ptr->next != NIL) 20816366Skarels ptr->next->last = ptr->last; 20916366Skarels free((char *)ptr); 21016356Skarels } 211