122399Sdist /* 222399Sdist * Copyright (c) 1983 Regents of the University of California. 334360Sbostic * All rights reserved. 434360Sbostic * 5*42673Sbostic * %sccs.include.redist.c% 622399Sdist */ 722399Sdist 816366Skarels #ifndef lint 9*42673Sbostic static char sccsid[] = "@(#)table.c 5.6 (Berkeley) 06/01/90"; 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 */ 2016366Skarels #include <stdio.h> 2116366Skarels #include <sys/time.h> 2226840Smckusick #include <syslog.h> 2332103Smckusick #include <sys/param.h> 2416356Skarels 2526840Smckusick #include <protocols/talkd.h> 2616356Skarels 2716366Skarels #define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ 2816356Skarels 2916366Skarels #define NIL ((TABLE_ENTRY *)0) 3016356Skarels 3116366Skarels extern int debug; 3216366Skarels struct timeval tp; 3316366Skarels struct timezone *txp; 3416356Skarels 3516356Skarels typedef struct table_entry TABLE_ENTRY; 3616356Skarels 3716356Skarels struct table_entry { 3816366Skarels CTL_MSG request; 3916366Skarels long time; 4016366Skarels TABLE_ENTRY *next; 4116366Skarels TABLE_ENTRY *last; 4216356Skarels }; 4316356Skarels 4426840Smckusick TABLE_ENTRY *table = NIL; 4516356Skarels CTL_MSG *find_request(); 4616356Skarels CTL_MSG *find_match(); 4716366Skarels char *malloc(); 4816356Skarels 4916366Skarels /* 5016366Skarels * Look in the table for an invitation that matches the current 5116366Skarels * request looking for an invitation 5216366Skarels */ 5316366Skarels CTL_MSG * 5416366Skarels find_match(request) 5526840Smckusick register CTL_MSG *request; 5616356Skarels { 5726840Smckusick register TABLE_ENTRY *ptr; 5816366Skarels long current_time; 5916356Skarels 6016366Skarels gettimeofday(&tp, &txp); 6116366Skarels current_time = tp.tv_sec; 6226840Smckusick if (debug) 6326840Smckusick print_request("find_match", request); 6416366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 6516366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 6616366Skarels /* the entry is too old */ 6726840Smckusick if (debug) 6826840Smckusick print_request("deleting expired entry", 6926840Smckusick &ptr->request); 7016366Skarels delete(ptr); 7116366Skarels continue; 7216366Skarels } 7316366Skarels if (debug) 7426840Smckusick print_request("", &ptr->request); 7516366Skarels if (strcmp(request->l_name, ptr->request.r_name) == 0 && 7616366Skarels strcmp(request->r_name, ptr->request.l_name) == 0 && 7716366Skarels ptr->request.type == LEAVE_INVITE) 7816366Skarels return (&ptr->request); 7916356Skarels } 8016366Skarels return ((CTL_MSG *)0); 8116356Skarels } 8216356Skarels 8316366Skarels /* 8416366Skarels * Look for an identical request, as opposed to a complimentary 8516366Skarels * one as find_match does 8616366Skarels */ 8716366Skarels CTL_MSG * 8816366Skarels find_request(request) 8926840Smckusick register CTL_MSG *request; 9016356Skarels { 9126840Smckusick register TABLE_ENTRY *ptr; 9216366Skarels long current_time; 9316356Skarels 9416366Skarels gettimeofday(&tp, &txp); 9516366Skarels current_time = tp.tv_sec; 9616366Skarels /* 9716366Skarels * See if this is a repeated message, and check for 9816366Skarels * out of date entries in the table while we are it. 9916356Skarels */ 10026840Smckusick if (debug) 10126840Smckusick print_request("find_request", request); 10216366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 10316366Skarels if ((ptr->time - current_time) > MAX_LIFE) { 10416366Skarels /* the entry is too old */ 10526840Smckusick if (debug) 10626840Smckusick print_request("deleting expired entry", 10726840Smckusick &ptr->request); 10816366Skarels delete(ptr); 10916366Skarels continue; 11016366Skarels } 11116366Skarels if (debug) 11226840Smckusick print_request("", &ptr->request); 11316366Skarels if (strcmp(request->r_name, ptr->request.r_name) == 0 && 11416366Skarels strcmp(request->l_name, ptr->request.l_name) == 0 && 11516366Skarels request->type == ptr->request.type && 11616366Skarels request->pid == ptr->request.pid) { 11716366Skarels /* update the time if we 'touch' it */ 11816366Skarels ptr->time = current_time; 11916366Skarels return (&ptr->request); 12016366Skarels } 12116356Skarels } 12216366Skarels return ((CTL_MSG *)0); 12316356Skarels } 12416356Skarels 12516356Skarels insert_table(request, response) 12616366Skarels CTL_MSG *request; 12716366Skarels CTL_RESPONSE *response; 12816356Skarels { 12926840Smckusick register TABLE_ENTRY *ptr; 13016366Skarels long current_time; 13116356Skarels 13216366Skarels gettimeofday(&tp, &txp); 13316366Skarels current_time = tp.tv_sec; 13426840Smckusick request->id_num = new_id(); 13526840Smckusick response->id_num = htonl(request->id_num); 13616356Skarels /* insert a new entry into the top of the list */ 13716366Skarels ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); 13816366Skarels if (ptr == NIL) { 13926840Smckusick syslog(LOG_ERR, "insert_table: Out of memory"); 14026840Smckusick _exit(1); 14116366Skarels } 14216366Skarels ptr->time = current_time; 14316366Skarels ptr->request = *request; 14416366Skarels ptr->next = table; 14516366Skarels if (ptr->next != NIL) 14616366Skarels ptr->next->last = ptr; 14716366Skarels ptr->last = NIL; 14816366Skarels table = ptr; 14916356Skarels } 15016356Skarels 15116366Skarels /* 15216366Skarels * Generate a unique non-zero sequence number 15316366Skarels */ 15416356Skarels new_id() 15516356Skarels { 15616366Skarels static int current_id = 0; 15716356Skarels 15816366Skarels current_id = (current_id + 1) % MAX_ID; 15916356Skarels /* 0 is reserved, helps to pick up bugs */ 16016366Skarels if (current_id == 0) 16116366Skarels current_id = 1; 16216366Skarels return (current_id); 16316356Skarels } 16416356Skarels 16516366Skarels /* 16616366Skarels * Delete the invitation with id 'id_num' 16716366Skarels */ 16816356Skarels delete_invite(id_num) 16916366Skarels int id_num; 17016356Skarels { 17126840Smckusick register TABLE_ENTRY *ptr; 17216356Skarels 17316366Skarels ptr = table; 17416366Skarels if (debug) 17526840Smckusick syslog(LOG_DEBUG, "delete_invite(%d)", id_num); 17616366Skarels for (ptr = table; ptr != NIL; ptr = ptr->next) { 17716366Skarels if (ptr->request.id_num == id_num) 17816366Skarels break; 17916366Skarels if (debug) 18026840Smckusick print_request("", &ptr->request); 18116366Skarels } 18216366Skarels if (ptr != NIL) { 18316366Skarels delete(ptr); 18416366Skarels return (SUCCESS); 18516366Skarels } 18616366Skarels return (NOT_HERE); 18716356Skarels } 18816356Skarels 18916366Skarels /* 19016366Skarels * Classic delete from a double-linked list 19116366Skarels */ 19216356Skarels delete(ptr) 19326840Smckusick register TABLE_ENTRY *ptr; 19416356Skarels { 19516356Skarels 19626840Smckusick if (debug) 19726840Smckusick print_request("delete", &ptr->request); 19816366Skarels if (table == ptr) 19916366Skarels table = ptr->next; 20016366Skarels else if (ptr->last != NIL) 20116366Skarels ptr->last->next = ptr->next; 20216366Skarels if (ptr->next != NIL) 20316366Skarels ptr->next->last = ptr->last; 20416366Skarels free((char *)ptr); 20516356Skarels } 206