$title('nstabl - name server table routines') $compact /************************************************************************** * * MODULE NAME: nstabl * * DESCRIPTION: This module implements the nameserver table routines. * * The table is implemented as a circular linked list with * a dummy head node. The following table access routines are * implemented in this module: lookup, * insert_name, * get_sock, * delete_name, * change_sock, * get_table. ***************************************************************************/ nstabl: DO; $include(:rmx:inc/rmxplm.ext) $include(strutl.ext) $include(strutl.lit) $include(nservr.lit) $include(nstabl.lit) DECLARE /* globals */ ns_tab_ptr POINTER, /* points to nameserver table */ ns_tab BASED ns_tab_ptr ns_tab_ent; $eject $subtitle('cr$tab') /******************************************************************** * * PROC NAME: cr$tab * * DESCRIPTION: Create the nameserver table. * * CALL: CALL cr$tab; * * GLOBALS: ns_tab_ptr * * *********************************************************************/ cr_tab: PROCEDURE PUBLIC; ns_tab_ptr = cr$ent; ns_tab.next = ns_tab_ptr; ns_tab.n_ptr = NIL; ns_tab.sock = 0; END cr_tab; $eject $subtitle('cr$ent') /******************************************************************** * * PROC NAME: cr$ent * * DESCRIPTION: Create a new table entry and return a pointer to it. * * CALL: ent_ptr = cr$ent; * * RETURNS: ent_ptr - points to a newly created table entry * * *********************************************************************/ cr$ent: PROCEDURE POINTER; DECLARE /* locals */ new_entry_ptr POINTER, /* newly created entry */ new_entry BASED new_entry_ptr ns_tab_ent, new_ent_t TOKEN, /* token for new entry */ status WORD; /* begin cr$ent */ new_ent_t = rq$create$segment(size(new_entry), @status); new_entry_ptr = build$ptr(new_ent_t, 0); RETURN new_entry_ptr; END cr$ent; $eject $subtitle('') /******************************************************************** * * PROC NAME: lookup * * DESCRIPTION: Look for name described by name_ptr in the nameserver table. * If found, return pointer to entry and its predecessor * otherwise return NIL and a pointer to the entry where name * should be inserted. * * CALL: ent_ptr = lookup(name_ptr, pred_ptr); * * INPUT: name_ptr - points to name to be looked up * OUTPUT: pred_ptr - points to ent_ptr's predecessor if foundi * or where entry should be inserted if not found * RETURNS: ent_ptr - points to entry if found * *********************************************************************/ lookup: PROCEDURE(name_ptr, pred_ptr) POINTER PUBLIC; DECLARE /* params */ name_ptr POINTER, pred_ptr POINTER; DECLARE /* locals */ cur_ptr POINTER, /* current entry processed */ cur_ent BASED cur_ptr ns_tab_ent, p_ptr BASED pred_ptr POINTER, res WORD; /* result of string compare */ /* begin lookup*/ res = STRGREATER; cur_ptr = ns_tab.next; p_ptr = ns_tab_ptr; DO WHILE (cur_ptr <> ns_tab_ptr) AND (res = STRGREATER); res = str$cmp(name_ptr, cur_ent.n_ptr); IF res = STREQUAL THEN DO; RETURN cur_ptr; END; ELSE IF res = STRGREATER THEN DO; p_ptr = cur_ptr; cur_ptr = cur_ent.next; END; END; RETURN NIL; END lookup; $eject $subtitle('get_sock') /******************************************************************** * * PROC NAME: get_sock * * DESCRIPTON: Lookup the name associated with name_ptr, get the socket and * return pointer to socket to caller. Sock_ptr_ptr returns * a pointer to a valid segment whether lookup succeeds or * fails. * * CALL: result = get_sock(name_ptr, sock_ptr_ptr) * * INPUT: name_ptr - points to name whose socket is requested * OUTPUT: sock_ptr_ptr - points to socket pointer associated with name * RETURN: result - result of get_sock * *********************************************************************/ get_sock: PROCEDURE(name_ptr, sock_ptr_ptr)BYTE PUBLIC; DECLARE /* params */ name_ptr POINTER, sock_ptr_ptr POINTER; DECLARE /* locals */ sock_ptr BASED sock_ptr_ptr POINTER, status WORD, sock_t TOKEN, /* token for socket segment */ new_sock_ptr POINTER, /* pointer to socket segment */ sock BASED new_sock_ptr DWORD, /* socket associated with name_ptr */ pred_ptr POINTER, /* points to predecessor of name_ptr entry */ ent_ptr POINTER, /* points to table entry */ ent BASED ent_ptr ns_tab_ent; /* table entry requested */ sock_t = rq$create$segment(size(sock), @status); new_sock_ptr = build$ptr(sock_t,0); sock_ptr = new_sock_ptr; ent_ptr = lookup(name_ptr, @pred_ptr); IF ent_ptr <> NIL THEN DO; sock = ent.sock; RETURN REQCOMPLETED; END; ELSE RETURN NOTEXIST; END get_sock; $eject $subtitle('') /******************************************************************** * * PROC NAME: insert_name * * DESCRIPTION: Insert a new entry in the name table. * * CALL: result = insert$name(socket, new_name_ptr, stat_ptr) * * INPUTS: socket - socket for new entry in name table * new_name_ptr - points to name for new table entry * OUTPUT: stat_ptr - points to status word * * GLOBALS: ns_tab * *********************************************************************/ insert_name: PROCEDURE(socket, new_name_ptr, stat_ptr) BYTE PUBLIC; DECLARE /* params */ socket DWORD, new_name_ptr POINTER, stat_ptr POINTER; DECLARE /* locals */ ent_ptr POINTER, /* indicates whether new_name found */ status based stat_ptr WORD, new_name based new_name_ptr (1) BYTE, str_size WORD, /* size of name string for new entry */ name_str_t TOKEN, /* name string token */ name_str_ptr POINTER, /* pointer to name string */ tab_ent_ptr POINTER, /* points to new name server entry */ tab_ent BASED tab_ent_ptr ns_tab_ent, pred_ptr POINTER, /* points to predecessor entry for new_name */ pred_ent based pred_ptr ns_tab_ent; /* begin insert$name */ ent_ptr = lookup(new_name_ptr, @pred_ptr); if ent_ptr <> NIL THEN RETURN NAMEINTAB; ELSE DO; /* copy name to name table buffer */ str_size = new_name(0) + 1; name_str_t = rq$create$segment(str_size, stat_ptr); name_str_ptr = build$ptr(name_str_t, 0); CALL movb(new_name_ptr, name_str_ptr, str_size); /* insert new entry in table */ tab_ent_ptr = cr$ent; tab_ent.sock = socket; tab_ent.n_ptr = name_str_ptr; tab_ent.next = pred_ent.next; pred_ent.next = tab_ent_ptr; END; RETURN REQCOMPLETED; END insert_name; $eject $subtitle('delete$name') /******************************************************************** * * PROC NAME: delete$name * * DESCRIPTION: Delete an entry from the name table * * CALL: result = delete$name(name$ptr) * * INPUT: name$ptr - points to name associated with entry to be deleted. * * *********************************************************************/ delete_name: PROCEDURE(name_ptr)BYTE PUBLIC; DECLARE /* params */ name_ptr POINTER; DECLARE /* locals */ ent_ptr POINTER, /* indicates whether new_name found */ ent BASED ent_ptr ns_tab_ent, status WORD, del_sel SELECTOR, /* seg. sel. for deleted entry */ pred_ptr POINTER, /* points to predecessor entry for new_name */ pred_ent based pred_ptr ns_tab_ent; /* begin delete$name */ ent_ptr = lookup(name_ptr, @pred_ptr); if ent_ptr <> NIL THEN DO; /* delete entry from table;*/ pred_ent.next = ent.next; del_sel = selector$of(ent.n_ptr); call rq$delete$segment(del_sel, @status); del_sel = selector$of(ent_ptr); call rq$delete$segment(del_sel, @status); END; RETURN REQCOMPLETED; END delete_name; $eject $subtitle('change_sock') /******************************************************************** * * DESCRIPTION: change_sock * * CALL: CALL change$sock(name_ptr, sock, status_ptr) * * INPUTS: name_ptr - points to name to be changed * sock - socket that replaces socket in current entry * OUTPUT: status_ptr - points to status word * * DESCRIPTION: If the requested entry exists, change the socket to the * value sock; if not, return an indication that entry does * not exist. * *********************************************************************/ change_sock: PROCEDURE(name_ptr, sock, status_ptr) BYTE PUBLIC; DECLARE /* params */ name_ptr POINTER, sock DWORD, status_ptr POINTER; DECLARE /* locals */ status BASED status_ptr WORD, ent_ptr POINTER, /* indicates whether new_name found */ ent BASED ent_ptr ns_tab_ent, pred_ptr POINTER; /* points to predecessor entry */ /* begin change$name */ ent_ptr = lookup(name_ptr, @pred_ptr); IF ent_ptr <> NIL THEN ent.sock = sock; ELSE RETURN NOTEXIST; RETURN REQCOMPLETED; END change_sock; $eject $subtitle('get_table') /******************************************************************** * * DESCRIPTION: get_table * * CALL: result = get$table(table_ptr_ptr, tab_size_ptr) * * OUTPUT: tab_ptr_ptr - pointer to name table pointer whose entries * do not include the link field * tab_size_ptr - pointer to number of bytes in table * RETURN: result - result of operation * * GLOBALS: ns_tab * * DESCRIPTION: Determine the size of the table minus the link fields and * create a segment of that size. Fill this segment with * all the entries(socket,name) and return a pointer * to this segment. * *********************************************************************/ get_table: PROCEDURE(table_ptr_ptr, tab_size_ptr) BYTE PUBLIC; DECLARE /* params */ table_ptr_ptr POINTER, tab_size_ptr POINTER; DECLARE /* literals */ FIXEDSIZE LITERALLY '5', /* num bytes in fixed part of tab ent */ SOCKSIZE LITERALLY '4', COUNTSIZE LITERALLY '2'; /* size of count field in table */ DECLARE /* locals */ table_ptr based table_ptr_ptr POINTER, t_size based tab_size_ptr DWORD, cur_ent_ptr POINTER, cur_ent BASED cur_ent_ptr ns_tab_ent, /* entry currently being processed */ ts_ptr POINTER, /* points to above segment */ t_store BASED ts_ptr STRUCTURE ( /* segment holding table */ count WORD, tab (1) BYTE), t_store_tok TOKEN, /* token for above segment */ t_idx WORD, /* index for t_store */ tab_size DWORD, /* size of name table */ name_ptr POINTER, /* points to current name */ name BASED name_ptr (1) BYTE, status WORD, num_trans WORD; /* bytes moved from ent to tstore */ /* begin get$table */ tab_size = size(t_store.count); t_size = 0; cur_ent_ptr = ns_tab.next; DO WHILE cur_ent_ptr <> ns_tab_ptr; name_ptr = cur_ent.n_ptr; tab_size = tab_size + name(0) + FIXEDSIZE; cur_ent_ptr = cur_ent.next; END; IF tab_size <> 0 THEN DO; tab_size = tab_size + COUNTSIZE; t_store_tok = rq$create$segment(tab_size, @status); table_ptr = build$ptr(t_store_tok, 0); ts_ptr = table_ptr; cur_ent_ptr = ns_tab.next; t_store.count = tab_size; t_idx = 0; DO WHILE cur_ent_ptr <> ns_tab_ptr; CALL movb(@cur_ent.sock, @t_store.tab(t_idx), SOCKSIZE); t_idx = t_idx + SOCKSIZE; name_ptr = cur_ent.n_ptr; num_trans = name(0) + 1; CALL movb(cur_ent.n_ptr, @t_store.tab(t_idx), num_trans); t_idx = t_idx + num_trans; cur_ent_ptr = cur_ent.next; END; t_store.count = tab_size - size(t_store.count); t_size = tab_size; RETURN REQCOMPLETED; END; ELSE RETURN NOTEXIST; END get_table; END nstabl;