/* .TITLE DB_REQUESTER - Database request program * * .IDENT 'X-2' */ /***************************************************************************/ /* */ /* COPYRIGHT (c) 1978, 1980, 1982, 1984 BY */ /* DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS. */ /* ALL RIGHTS RESERVED. */ /* */ /* THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED */ /* ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE */ /* INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER */ /* COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY */ /* OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY */ /* TRANSFERRED. */ /* */ /* THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE */ /* AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT */ /* CORPORATION. */ /* */ /* DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS */ /* SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. */ /* */ /* */ /***************************************************************************/ /*++ */ /* FACILITY: DECnet nontransparent task-to-task communication. */ /* ABSTRACT: DB_REQUESTER */ /* This program demonstrates how to perform nontransparent * * task-to-task communication with a known network object, DB_SERVER, on * * a remote node. The program accepts key information (a name) from the * * user and sends it to the DB_SERVER process at the target node. * * DB_SERVER executes a database inquiry based on the key information and * * returns a response to the requester. */ /* ENVIRONMENT: User mode */ /* AUTHOR: Scott A. Shurts, CREATION DATE: 10-Nov-1986 */ /* MODIFIED BY: */ /* */ /* X-2 JC00001 Jim Colombo 13-Dec-1991 */ /* Added support for new CPU architecture and prompting of remote */ /* node information. */ /* INCLUDE EXTERNAL CONSTANTS */ #include #include #pragma nomember_alignment #include #pragma member_alignment #include #include #include #include /* DEFINE LOCAL CONSTANTS */ #define MAX_NAME 20 #define MAX_ACCOUNT 11 #define MAX_PHONE 14 #define MAX_ADDRESS 30 #define MAX_LOCATION 30 #define MAX_DISPLAY 160 #define MAX_NODE 6 #define MAX_USERNAME 32 #define MAX_PASSWORD 32 /* DECLARE GLOBAL DATA */ struct io_stat_blk { /* I/O status block */ short int status ; short int msg_len ; int unused; } iosb; struct msgvec_blk { /* Message vector for $putmsg */ short int count; short int options; int msg_code; } msgvec = { 1, 15, 0 }; struct net_con_blk { /* Network Connect Block (NCB) */ char node[64]; char task_delimeter; char task[15]; short int resrvd; char ncb_end; } ncb = { "",'"',"TASK=DB_SERVER/",0,'"' }; #pragma nomember_alignment struct buff_blk { /* Buffer layout matches one in DB_SERVER */ char name[MAX_NAME]; char account[MAX_ACCOUNT]; char phone[MAX_PHONE]; char address[MAX_ADDRESS]; char location[MAX_LOCATION]; int status; char spare[7]; } buffer; #pragma member_alignment unsigned short int inquire_account(); int return_status, buf_quo = 128, max_msg = 128; int buff_len = sizeof(buffer), name_len = MAX_NAME; short int net_chan, mbx_chan; char disp_buff[MAX_DISPLAY]; char node_name[MAX_NODE]; char username[MAX_USERNAME]; char password[MAX_PASSWORD]; /* BUILD DESCRIPTORS */ static $DESCRIPTOR (input_prompt, "Input name of ^Z to exit : "); static $DESCRIPTOR (node_prompt, "Remote node name: "); static $DESCRIPTOR (username_prompt, "Remote username: "); static $DESCRIPTOR (password_prompt, "Remote password: "); static $DESCRIPTOR (net_device, "_NET:"); static $DESCRIPTOR (fao_ctrl, "!/!AF Account: !AF Phone: !AF!/ Address: !AF City: !AF!/" ); struct dsc$descriptor_s inq_name; struct dsc$descriptor_s ncb_desc; struct dsc$descriptor_s disp_desc; struct dsc$descriptor_s inq_account; main () /* After initialization, this program processes requests entered by the * * user at the name prompt until ^Z is entered. Processing is synchronous.* * After accepting each name input, the program sends a request to * * DB_SERVER over the logical link, then waits until it receives and * * displays a response before prompting for another name. */ { return_status = initialization () ; if ( return_status & STS$M_SUCCESS ) { return_status = inquire_name () ; while ( return_status & STS$M_SUCCESS ) { return_status = issue_request () ; if ( return_status & STS$M_SUCCESS ) { return_status = rcv_and_disp_response (); if ( return_status & STS$M_SUCCESS ) return_status = inquire_name () ; } } if ( return_status != RMS$_EOF ) exit ( return_status ); } else exit ( return_status ); } initialization () /* Set up descriptors and establish communication with the DB_SERVER * * process. Requesting a logical link over DECnet using nontransparent * * communications involves three steps: * * 1. Create a temporary mailbox (optional). * * 2. Assign a channel to the _NET device and associate the temporary * * mailbox with it. * * 3. Issue a QIO with a function code of IO$_ACCESS and the P2 * * parameter containing the address of the descriptor of the network * * connect block (NCB). * * In this program, steps 1 and 2 are combined through the use of the * * Run Time Library routine LIB$ASN_WTH_MBX. */ { unsigned short int size; inq_account.dsc$w_length = MAX_NODE; inq_account.dsc$a_pointer = &node_name; inq_account.dsc$b_dtype = DSC$K_DTYPE_T; inq_account.dsc$b_class = DSC$K_CLASS_S; size = inquire_account(&node_prompt); if (size) node_name[size] = 0; else strcpy(node_name, "BIGRED"); strcpy(&ncb.node, &node_name); inq_account.dsc$w_length = MAX_USERNAME; inq_account.dsc$a_pointer = &username; inq_account.dsc$b_dtype = DSC$K_DTYPE_T; inq_account.dsc$b_class = DSC$K_CLASS_S; size = inquire_account(&username_prompt); if (size) { username[size] = 0; strcat(&ncb.node, "\""); strcat(&ncb.node, &username); strcat(&ncb.node, " "); inq_account.dsc$w_length = MAX_PASSWORD; inq_account.dsc$a_pointer = &password; inq_account.dsc$b_dtype = DSC$K_DTYPE_T; inq_account.dsc$b_class = DSC$K_CLASS_S; password[inquire_account(&password_prompt)] = 0; strcat(&ncb.node, &password); strcat(&ncb.node, "\"::"); } else strcat(&ncb.node, "::"); inq_name.dsc$w_length = MAX_NAME; inq_name.dsc$a_pointer = &buffer.name; inq_name.dsc$b_dtype = DSC$K_DTYPE_T; inq_name.dsc$b_class = DSC$K_CLASS_S; ncb_desc.dsc$w_length = sizeof( ncb ); ncb_desc.dsc$a_pointer = &ncb; ncb_desc.dsc$b_dtype = DSC$K_DTYPE_T; ncb_desc.dsc$b_class = DSC$K_CLASS_S; disp_desc.dsc$w_length = MAX_DISPLAY; disp_desc.dsc$a_pointer = &disp_buff; disp_desc.dsc$b_dtype = DSC$K_DTYPE_T; disp_desc.dsc$b_class = DSC$K_CLASS_S; return_status = lib$asn_wth_mbx ( &net_device, &max_msg, &buf_quo, &net_chan, &mbx_chan ); if ( return_status & STS$M_SUCCESS ) { return_status = sys$qiow ( 0, net_chan, IO$_ACCESS, &iosb, 0, 0, 0, &ncb_desc, 0, 0, 0, 0 ); if ( return_status & STS$M_SUCCESS ) return_status = iosb.status; } return return_status; } inquire_name () /* Prompt the user for the query name. */ { unsigned short int size; return_status = lib$get_input ( &inq_name, &input_prompt, &size ); buffer.name[size] = 0; return return_status; } unsigned short int inquire_account (prompt_desc) struct dsc$descriptor_s *prompt_desc; { unsigned short int size; char *string_ptr; return_status = lib$get_input ( &inq_account, prompt_desc, &size ); return size; } issue_request () /* Issue writes, (IO$_WRITEVBLK), over the logical link.*/ { return_status = sys$qiow ( 0, net_chan, IO$_WRITEVBLK, &iosb, 0, 0, &buffer.name, inq_name.dsc$w_length, 0, 0, 0, 0 ); if ( return_status & STS$M_SUCCESS ) return_status = iosb.status; return return_status; } rcv_and_disp_response () /* This module waits on a read over the logical link to DB_SERVER for a * * response. After receiving the response, it formats the buffer and * * displays the contents at the user's terminal. If the server encountered* * any errors on the request, the status of the buffer will reflect the * * condition. */ { return_status = sys$qiow ( 0, net_chan, IO$_READVBLK, &iosb, 0, 0, &buffer, buff_len, 0, 0, 0, 0 ); if ( return_status & STS$M_SUCCESS ) { return_status = iosb.status; if ( return_status & STS$M_SUCCESS ) { if ( buffer.status & STS$M_SUCCESS ) { disp_desc.dsc$w_length = MAX_DISPLAY; return_status = sys$fao ( &fao_ctrl, &disp_desc.dsc$w_length, &disp_desc, MAX_NAME, &buffer.name, MAX_ACCOUNT, &buffer.account, MAX_PHONE, &buffer.phone, MAX_ADDRESS, &buffer.address, MAX_LOCATION, &buffer.location ); if ( return_status & STS$M_SUCCESS ) return_status = lib$put_output ( &disp_desc ); } else { msgvec.msg_code = buffer.status; return_status = sys$putmsg ( &msgvec, 0, 0, 0 ); } } } return return_status; }