122399Sdist /* 222399Sdist * Copyright (c) 1983 Regents of the University of California. 334360Sbostic * All rights reserved. 434360Sbostic * 542673Sbostic * %sccs.include.redist.c% 622399Sdist */ 722399Sdist 816366Skarels #ifndef lint 9*46683Sbostic static char sccsid[] = "@(#)table.c 5.7 (Berkeley) 02/26/91"; 1034360Sbostic #endif /* not lint */ 1116356Skarels 1216366Skarels /* 1316366Skarels * Routines to handle insertion, deletion, etc on the table 1416366Skarels * of requests kept by the daemon. Nothing fancy here, linear 1516366Skarels * search on a double-linked list. A time is kept with each 1616366Skarels * entry so that overly old invitations can be eliminated. 1716366Skarels * 1816366Skarels * Consider this a mis-guided attempt at modularity 1916356Skarels */ 20*46683Sbostic #include <sys/param.h> 2116366Skarels #include <sys/time.h> 22*46683Sbostic #include <sys/socket.h> 23*46683Sbostic #include <protocols/talkd.h> 2426840Smckusick #include <syslog.h> 25*46683Sbostic #include <unistd.h> 26*46683Sbostic #include <stdio.h> 27*46683Sbostic #include <stdlib.h> 28*46683Sbostic #include <string.h> 2916356Skarels 3016366Skarels #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 3116356Skarels 3216366Skarels #define NIL ((TABLE_ENTRY *)0) 3316356Skarels 3416366Skarels extern int debug; 3516366Skarels struct timeval tp; 36*46683Sbostic struct timezone txp; 3716356Skarels 3816356Skarels typedef struct table_entry TABLE_ENTRY; 3916356Skarels 4016356Skarels struct table_entry { 4116366Skarels CTL_MSG request; 4216366Skarels long time; 4316366Skarels TABLE_ENTRY *next; 4416366Skarels TABLE_ENTRY *last; 4516356Skarels }; 4616356Skarels 4726840Smckusick TABLE_ENTRY *table = NIL; 4816356Skarels CTL_MSG *find_request(); 4916356Skarels CTL_MSG *find_match(); 5016356Skarels 5116366Skarels /* 5216366Skarels * Look in the table for an invitation that matches the current 5316366Skarels * request looking for an invitation 5416366Skarels */ 5516366Skarels CTL_MSG * 5616366Skarels find_match(request) 5726840Smckusick register CTL_MSG *request; 5816356Skarels { 5926840Smckusick register TABLE_ENTRY *ptr; 60*46683Sbostic time_t current_time; 6116356Skarels 6216366Skarels gettimeofday(&tp, &txp); 6316366Skarels current_time = tp.tv_sec; 6426840Smckusick if (debug) 6526840Smckusick print_request("find_match", request); 6616366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 6716366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 6816366Skarels /* the entry is too old */ 6926840Smckusick if (debug) 7026840Smckusick print_request("deleting expired entry", 7126840Smckusick &ptr->request); 7216366Skarels delete(ptr); 7316366Skarels continue; 7416366Skarels } 7516366Skarels if (debug) 7626840Smckusick print_request("", &ptr->request); 7716366Skarels if (strcmp(request->l_name, ptr->request.r_name) == 0 && 7816366Skarels strcmp(request->r_name, ptr->request.l_name) == 0 && 7916366Skarels ptr->request.type == LEAVE_INVITE) 8016366Skarels return (&ptr->request); 8116356Skarels } 8216366Skarels return ((CTL_MSG *)0); 8316356Skarels } 8416356Skarels 8516366Skarels /* 8616366Skarels * Look for an identical request, as opposed to a complimentary 8716366Skarels * one as find_match does 8816366Skarels */ 8916366Skarels CTL_MSG * 9016366Skarels find_request(request) 9126840Smckusick register CTL_MSG *request; 9216356Skarels { 9326840Smckusick register TABLE_ENTRY *ptr; 94*46683Sbostic time_t current_time; 9516356Skarels 9616366Skarels gettimeofday(&tp, &txp); 9716366Skarels current_time = tp.tv_sec; 9816366Skarels /* 9916366Skarels * See if this is a repeated message, and check for 10016366Skarels * out of date entries in the table while we are it. 10116356Skarels */ 10226840Smckusick if (debug) 10326840Smckusick print_request("find_request", request); 10416366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 10516366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 10616366Skarels /* the entry is too old */ 10726840Smckusick if (debug) 10826840Smckusick print_request("deleting expired entry", 10926840Smckusick &ptr->request); 11016366Skarels delete(ptr); 11116366Skarels continue; 11216366Skarels } 11316366Skarels if (debug) 11426840Smckusick print_request("", &ptr->request); 11516366Skarels if (strcmp(request->r_name, ptr->request.r_name) == 0 && 11616366Skarels strcmp(request->l_name, ptr->request.l_name) == 0 && 11716366Skarels request->type == ptr->request.type && 11816366Skarels request->pid == ptr->request.pid) { 11916366Skarels /* update the time if we 'touch' it */ 12016366Skarels ptr->time = current_time; 12116366Skarels return (&ptr->request); 12216366Skarels } 12316356Skarels } 12416366Skarels return ((CTL_MSG *)0); 12516356Skarels } 12616356Skarels 12716356Skarels insert_table(request, response) 12816366Skarels CTL_MSG *request; 12916366Skarels CTL_RESPONSE *response; 13016356Skarels { 13126840Smckusick register TABLE_ENTRY *ptr; 132*46683Sbostic time_t current_time; 13316356Skarels 13416366Skarels gettimeofday(&tp, &txp); 13516366Skarels current_time = tp.tv_sec; 13626840Smckusick request->id_num = new_id(); 13726840Smckusick response->id_num = htonl(request->id_num); 13816356Skarels /* insert a new entry into the top of the list */ 13916366Skarels ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 14016366Skarels if (ptr == NIL) { 14126840Smckusick syslog(LOG_ERR, "insert_table: Out of memory"); 14226840Smckusick _exit(1); 14316366Skarels } 14416366Skarels ptr->time = current_time; 14516366Skarels ptr->request = *request; 14616366Skarels ptr->next = table; 14716366Skarels if (ptr->next != NIL) 14816366Skarels ptr->next->last = ptr; 14916366Skarels ptr->last = NIL; 15016366Skarels table = ptr; 15116356Skarels } 15216356Skarels 15316366Skarels /* 15416366Skarels * Generate a unique non-zero sequence number 15516366Skarels */ 15616356Skarels new_id() 15716356Skarels { 15816366Skarels static int current_id = 0; 15916356Skarels 16016366Skarels current_id = (current_id + 1) % MAX_ID; 16116356Skarels /* 0 is reserved, helps to pick up bugs */ 16216366Skarels if (current_id == 0) 16316366Skarels current_id = 1; 16416366Skarels return (current_id); 16516356Skarels } 16616356Skarels 16716366Skarels /* 16816366Skarels * Delete the invitation with id 'id_num' 16916366Skarels */ 17016356Skarels delete_invite(id_num) 17116366Skarels int id_num; 17216356Skarels { 17326840Smckusick register TABLE_ENTRY *ptr; 17416356Skarels 17516366Skarels ptr = table; 17616366Skarels if (debug) 17726840Smckusick syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 17816366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 17916366Skarels if (ptr->request.id_num == id_num) 18016366Skarels break; 18116366Skarels if (debug) 18226840Smckusick print_request("", &ptr->request); 18316366Skarels } 18416366Skarels if (ptr != NIL) { 18516366Skarels delete(ptr); 18616366Skarels return (SUCCESS); 18716366Skarels } 18816366Skarels return (NOT_HERE); 18916356Skarels } 19016356Skarels 19116366Skarels /* 19216366Skarels * Classic delete from a double-linked list 19316366Skarels */ 19416356Skarels delete(ptr) 19526840Smckusick register TABLE_ENTRY *ptr; 19616356Skarels { 19716356Skarels 19826840Smckusick if (debug) 19926840Smckusick print_request("delete", &ptr->request); 20016366Skarels if (table == ptr) 20116366Skarels table = ptr->next; 20216366Skarels else if (ptr->last != NIL) 20316366Skarels ptr->last->next = ptr->next; 20416366Skarels if (ptr->next != NIL) 20516366Skarels ptr->next->last = ptr->last; 20616366Skarels free((char *)ptr); 20716356Skarels } 208