122399Sdist /* 222399Sdist * Copyright (c) 1983 Regents of the University of California. 322399Sdist * All rights reserved. The Berkeley software License Agreement 422399Sdist * specifies the terms and conditions for redistribution. 522399Sdist */ 622399Sdist 716366Skarels #ifndef lint 8*26840Smckusick static char sccsid[] = "@(#)table.c 5.2 (Berkeley) 03/13/86"; 922399Sdist #endif not lint 1016356Skarels 1116366Skarels /* 1216366Skarels * Routines to handle insertion, deletion, etc on the table 1316366Skarels * of requests kept by the daemon. Nothing fancy here, linear 1416366Skarels * search on a double-linked list. A time is kept with each 1516366Skarels * entry so that overly old invitations can be eliminated. 1616366Skarels * 1716366Skarels * Consider this a mis-guided attempt at modularity 1816356Skarels */ 1916366Skarels #include <stdio.h> 2016366Skarels #include <sys/time.h> 21*26840Smckusick #include <syslog.h> 2216356Skarels 23*26840Smckusick #include <protocols/talkd.h> 2416356Skarels 2516366Skarels #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 2616356Skarels 2716366Skarels #define NIL ((TABLE_ENTRY *)0) 2816356Skarels 2916366Skarels extern int debug; 3016366Skarels struct timeval tp; 3116366Skarels struct timezone *txp; 3216356Skarels 3316356Skarels typedef struct table_entry TABLE_ENTRY; 3416356Skarels 3516356Skarels struct table_entry { 3616366Skarels CTL_MSG request; 3716366Skarels long time; 3816366Skarels TABLE_ENTRY *next; 3916366Skarels TABLE_ENTRY *last; 4016356Skarels }; 4116356Skarels 42*26840Smckusick TABLE_ENTRY *table = NIL; 4316356Skarels CTL_MSG *find_request(); 4416356Skarels CTL_MSG *find_match(); 4516366Skarels char *malloc(); 4616356Skarels 4716366Skarels /* 4816366Skarels * Look in the table for an invitation that matches the current 4916366Skarels * request looking for an invitation 5016366Skarels */ 5116366Skarels CTL_MSG * 5216366Skarels find_match(request) 53*26840Smckusick register CTL_MSG *request; 5416356Skarels { 55*26840Smckusick register TABLE_ENTRY *ptr; 5616366Skarels long current_time; 5716356Skarels 5816366Skarels gettimeofday(&tp, &txp); 5916366Skarels current_time = tp.tv_sec; 60*26840Smckusick if (debug) 61*26840Smckusick print_request("find_match", request); 6216366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 6316366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 6416366Skarels /* the entry is too old */ 65*26840Smckusick if (debug) 66*26840Smckusick print_request("deleting expired entry", 67*26840Smckusick &ptr->request); 6816366Skarels delete(ptr); 6916366Skarels continue; 7016366Skarels } 7116366Skarels if (debug) 72*26840Smckusick print_request("", &ptr->request); 7316366Skarels if (strcmp(request->l_name, ptr->request.r_name) == 0 && 7416366Skarels strcmp(request->r_name, ptr->request.l_name) == 0 && 7516366Skarels ptr->request.type == LEAVE_INVITE) 7616366Skarels return (&ptr->request); 7716356Skarels } 7816366Skarels return ((CTL_MSG *)0); 7916356Skarels } 8016356Skarels 8116366Skarels /* 8216366Skarels * Look for an identical request, as opposed to a complimentary 8316366Skarels * one as find_match does 8416366Skarels */ 8516366Skarels CTL_MSG * 8616366Skarels find_request(request) 87*26840Smckusick register CTL_MSG *request; 8816356Skarels { 89*26840Smckusick register TABLE_ENTRY *ptr; 9016366Skarels long current_time; 9116356Skarels 9216366Skarels gettimeofday(&tp, &txp); 9316366Skarels current_time = tp.tv_sec; 9416366Skarels /* 9516366Skarels * See if this is a repeated message, and check for 9616366Skarels * out of date entries in the table while we are it. 9716356Skarels */ 98*26840Smckusick if (debug) 99*26840Smckusick print_request("find_request", request); 10016366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 10116366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 10216366Skarels /* the entry is too old */ 103*26840Smckusick if (debug) 104*26840Smckusick print_request("deleting expired entry", 105*26840Smckusick &ptr->request); 10616366Skarels delete(ptr); 10716366Skarels continue; 10816366Skarels } 10916366Skarels if (debug) 110*26840Smckusick print_request("", &ptr->request); 11116366Skarels if (strcmp(request->r_name, ptr->request.r_name) == 0 && 11216366Skarels strcmp(request->l_name, ptr->request.l_name) == 0 && 11316366Skarels request->type == ptr->request.type && 11416366Skarels request->pid == ptr->request.pid) { 11516366Skarels /* update the time if we 'touch' it */ 11616366Skarels ptr->time = current_time; 11716366Skarels return (&ptr->request); 11816366Skarels } 11916356Skarels } 12016366Skarels return ((CTL_MSG *)0); 12116356Skarels } 12216356Skarels 12316356Skarels insert_table(request, response) 12416366Skarels CTL_MSG *request; 12516366Skarels CTL_RESPONSE *response; 12616356Skarels { 127*26840Smckusick register TABLE_ENTRY *ptr; 12816366Skarels long current_time; 12916356Skarels 13016366Skarels gettimeofday(&tp, &txp); 13116366Skarels current_time = tp.tv_sec; 132*26840Smckusick request->id_num = new_id(); 133*26840Smckusick response->id_num = htonl(request->id_num); 13416356Skarels /* insert a new entry into the top of the list */ 13516366Skarels ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 13616366Skarels if (ptr == NIL) { 137*26840Smckusick syslog(LOG_ERR, "insert_table: Out of memory"); 138*26840Smckusick _exit(1); 13916366Skarels } 14016366Skarels ptr->time = current_time; 14116366Skarels ptr->request = *request; 14216366Skarels ptr->next = table; 14316366Skarels if (ptr->next != NIL) 14416366Skarels ptr->next->last = ptr; 14516366Skarels ptr->last = NIL; 14616366Skarels table = ptr; 14716356Skarels } 14816356Skarels 14916366Skarels /* 15016366Skarels * Generate a unique non-zero sequence number 15116366Skarels */ 15216356Skarels new_id() 15316356Skarels { 15416366Skarels static int current_id = 0; 15516356Skarels 15616366Skarels current_id = (current_id + 1) % MAX_ID; 15716356Skarels /* 0 is reserved, helps to pick up bugs */ 15816366Skarels if (current_id == 0) 15916366Skarels current_id = 1; 16016366Skarels return (current_id); 16116356Skarels } 16216356Skarels 16316366Skarels /* 16416366Skarels * Delete the invitation with id 'id_num' 16516366Skarels */ 16616356Skarels delete_invite(id_num) 16716366Skarels int id_num; 16816356Skarels { 169*26840Smckusick register TABLE_ENTRY *ptr; 17016356Skarels 17116366Skarels ptr = table; 17216366Skarels if (debug) 173*26840Smckusick syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 17416366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 17516366Skarels if (ptr->request.id_num == id_num) 17616366Skarels break; 17716366Skarels if (debug) 178*26840Smckusick print_request("", &ptr->request); 17916366Skarels } 18016366Skarels if (ptr != NIL) { 18116366Skarels delete(ptr); 18216366Skarels return (SUCCESS); 18316366Skarels } 18416366Skarels return (NOT_HERE); 18516356Skarels } 18616356Skarels 18716366Skarels /* 18816366Skarels * Classic delete from a double-linked list 18916366Skarels */ 19016356Skarels delete(ptr) 191*26840Smckusick register TABLE_ENTRY *ptr; 19216356Skarels { 19316356Skarels 194*26840Smckusick if (debug) 195*26840Smckusick print_request("delete", &ptr->request); 19616366Skarels if (table == ptr) 19716366Skarels table = ptr->next; 19816366Skarels else if (ptr->last != NIL) 19916366Skarels ptr->last->next = ptr->next; 20016366Skarels if (ptr->next != NIL) 20116366Skarels ptr->next->last = ptr->last; 20216366Skarels free((char *)ptr); 20316356Skarels } 204