#module IPC_SERVER /* ************************************************************************** * Copyright (C) 1990 by * * DIGITAL Equipment Corporation, Maynard, Mass. * * * * 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 or 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-Vax OSI IPC Example Programs * * ABSTRACT: * * This program is an example of a server task that communicates with a * (remote) client via the IPC system service. * * It is built by IPC_BUILD.COM. (Note: If you build the executables * in the EXAMPLES directory, you may want to set the file protections * to allow non-privileged users to execute them.) * * It must be executed as a foreign command, and expects 2 command line * arguments: * * : The name of the task to declare itself as * : A string to pass back to the client. * * Define the foreign command as, for example: * * $ server :== $sys$common:[syshlp.examples.dnvosi]ipc_server.exe * * Execute it by, for example: * * $ server task1 "Listen very carefully: Put.. the candle ... back." * * * Program Summary : * * Validate command line arguments * Open an association, creating a task * [ WARNING: This requires the NET$DECLAREOBJECT right ] * Get a single connection from a client * Print out the node fullname and username of the client * Accept the connection. * Receive a message, and print it out * Transmit a message * Wait for a disconnect event * Close the association * * AUTHOR: * * MwD * * CREATION DATE: Dec-1991 * * MODIFICATION HISTORY: * * X-10 MWD0073 MwD 02-Nov-1993 * Request fullname not synonym on GET_CONNECT, and comment * synonym availability. * * X-09 LES0074 LES 15-Jul-1992 * Fix edit history * * X-08 LES0070 LES 08-Jun-1992 * Merge gen 7n2 with mainline to incorporate symbol * name changes * * X-07N2 LES0070 LES 14-May-1992 * Oops...make some aggregate name fixes from last time * (change NET$IPCBDEF back to Ipcb, change IPCBDEF * to NET$IBCBDEF) * * X-07N1 LES0070 LES 11-May-1992 * Change aggregate name Ipcb to NET$IPCBDEF * * X-00 MWD0000 MwD Dec-1991 * Creation. * */ /* * Include the definition of an IPCB. */ #include /* * Include the definitions for the IPC example common routines. */ #include "ipc_def.h" #define LIST_SIZE 128 #define RECEIVE_BUFFER_SIZE 128 main( unsigned int argc, char *argv[] ) { struct NET$IPCBDEF Ipcb; char Receive_Buffer[ RECEIVE_BUFFER_SIZE ]; void *List1_P, *List2_P, *List3_P; unsigned int Event_Mask; int Sts; /* * Validate the command line arguments. */ if( argc != 3 ) { printf( "Usage: $ipc_server \n" ); printf( "See the comments in IPC_SERVER.C for details.\n" ); exit( 0 ); } /* * Allocate 3 item lists. */ List1_P = item_list__new( LIST_SIZE ); List2_P = item_list__new( LIST_SIZE ); List3_P = item_list__new( LIST_SIZE ); if( ( List1_P == NULL ) || ( List2_P == NULL ) || ( List3_P == NULL ) ) { printf( "Can't allocate VM\n" ); exit( 0 ); } /* * Clear the IPCB. */ clear_ipcb( &Ipcb ); /* * Build an input item list specifying this server's task name, * and that we want notification of disconnection. * Then link it into the IPCB input descriptor. The task name * to use is the command line argument. */ Sts = item_list__add( List1_P, strlen( argv[ 1 ] ), NET$K_TAG_ENDUSERID_TASK, argv[ 1 ] ); VMS_CHECK( Sts ); Event_Mask = NET$M_EVENT_DISCONNECTS; Sts = item_list__add( List1_P, sizeof( Event_Mask ), NET$K_TAG_EVENTMASK, &Event_Mask ); VMS_CHECK( Sts ); item_list__to_desc( List1_P, &Ipcb.IPCB$R_INPUTLSTDESC ); /* * Open an association. Since we specified a task name in the * input list, this call requires the account we are running in to * hold the process rights identifier NET$DECLAREOBJECT. */ Sts = SYS$IPCW( 0, /* no efn */ IPC$K_FC_OPEN_ASSOCIATION, &Ipcb, 0, /* No AST addr */ 0 ); /* or param */ VMS_CHECK( Sts ); IPC_CHECK( Ipcb ); /* * Clear the input list and descriptor. */ item_list__clear( List1_P, &Ipcb.IPCB$R_INPUTLSTDESC ); /* * Build an item list requesting the node fullname and * user name of the client issuing the connect initiate. Link this * the IPCB template descriptor. Link the empty List3 into the * IPCB output descriptor. The requested info will be written there. * * Note that if the source node synonym is requested it will only * be supplied if the server application indicates it: * * NCL> set Session Control Application Node Synonym true * */ item_list__add( List2_P, 0, NET$K_TAG_NODENAME, NULL ); VMS_CHECK( Sts ); item_list__add( List2_P, 0, NET$K_TAG_SOURCEUSER, NULL ); VMS_CHECK( Sts ); item_list__to_desc( List2_P, &Ipcb.IPCB$R_TEMPLATELSTDESC ); item_list__to_desc( List3_P, &Ipcb.IPCB$R_OUTPUTLSTDESC ); /* * Get a connection. This call hangs until a client has initiated * a connection with us. */ Sts = SYS$IPCW( 0, IPC$K_FC_GET_CONNECTION, &Ipcb, 0, 0 ); VMS_CHECK( Sts ); IPC_CHECK( Ipcb ); /* * Update the item list from the IPCB output field. * Then print out the contents of the list. */ item_list__output( List3_P, &Ipcb ); printf( "Connection request received from node/user:\n\n" ); item_list__dump( List3_P ); /* * Clear list 2 and 3, and the IPCB template & output descriptors. */ item_list__clear( List2_P, &Ipcb.IPCB$R_TEMPLATELSTDESC ); item_list__clear( List3_P, &Ipcb.IPCB$R_OUTPUTLSTDESC ); /* * Accept the connection. */ Sts = SYS$IPCW( 0, IPC$K_FC_CONNECT_ACCEPT, &Ipcb, 0, 0 ); VMS_CHECK( Sts ); IPC_CHECK( Ipcb ); /* * Receive a buffer from the client, assume it's a printable * null-terminated string and print it out. */ Ipcb.IPCB$A_BUFFER = Receive_Buffer; Ipcb.IPCB$L_BUFFER_LENGTH = RECEIVE_BUFFER_SIZE; Sts = SYS$IPCW( 0, IPC$K_FC_RECEIVE, &Ipcb, 0, 0 ); VMS_CHECK( Sts ); IPC_CHECK( Ipcb ); printf( "\nReceived buffer: \n%s\n", Receive_Buffer ); /* * Transmit a buffer to the client. The buffer is the * command line argument (which is a null-terminated printable string). * Set up the IPCB so we send the null-terminator (for the sake of * the client). */ Ipcb.IPCB$A_BUFFER = argv[ 2 ]; Ipcb.IPCB$L_BUFFER_LENGTH = strlen( argv[ 2 ] ) + 1; Sts = SYS$IPCW( 0, IPC$K_FC_TRANSMIT, &Ipcb, 0, 0 ); VMS_CHECK( Sts ); IPC_CHECK( Ipcb ); /* * Wait on a network event. The client will disconnect, and we * will be notified. Since we specified only incoming disconnect * events to be received, there is no need to check the value of * IPCB$L_EVENT_TYPE. */ Ipcb.IPCB$A_BUFFER = NULL; Ipcb.IPCB$L_BUFFER_LENGTH = 0; Sts = SYS$IPCW( 0, IPC$K_FC_RECEIVE_EVENT, &Ipcb, 0, 0 ); VMS_CHECK( Sts ); IPC_CHECK( Ipcb ); /* * Close the association. */ Sts = SYS$IPCW( 0, IPC$K_FC_CLOSE_ASSOCIATION, &Ipcb, 0, 0 ); VMS_CHECK( Sts ); IPC_CHECK( Ipcb ); }