Cover V03, I03
Article
Figure 1
Figure 2
Figure 3
Figure 4
Listing 1
Listing 2
Listing 3
Sidebar 1

may94.tar


Listing 2: Remote DCL (rdcl)program

/*====================================================
AUTHOR: Dave Brillhart
FILE:   rdcl.c
-----------------------------------------------------
This C program will allow a DECnet capable UNIX
host to execute a remote DECnet object much like
the "rsh" command available via TCP/IP. This code
can execute a single DCL command (batch) or a series
of interactive commands. In interactive mode, a
blank line will terminate the program.
-----------------------------------------------------
Compile this program on an Ultrix host using:
# cc rdcl.c -ldnet -o rdcl
-----------------------------------------------------
Use this program as follows (authenication depends
on proxey setup):
# rdcl <nodename>[/<username>/[<password>]] [cmd]
====================================================*/

/*--------------------------------------------------*/
#include <stdio.h>
#include <sys/types.h>        /* dnet_conn & select */
#include <sys/socket.h>                /* dnet_conn */
#include <netdnet/dn.h>                /* dnet_conn */
#include <sys/time.h>                     /* select */
/*--------------------------------------------------*/
#define BUFSIZE   2048    /* read/write buffer size */
#define READWAIT  3.0    /* read timeout in seconds */
#define OBJECT    "dnet_cmd"  /* DECnet object name */
#define NODESIZE  16   /* max DECnet node name size */
#define E_F       '\004'               /* EOF == ^D */
/*--------------------------------------------------*/
int main(argc,argv)
int argc; char *argv[];
{
int sock;                /* socket for connection */
char node[NODESIZE];          /* DECnet node name */
int i;                      /* local loop counter */
char buff[BUFSIZE];            /* buffer for data */

if (argc < 2) {
printf("Usage: %s nodename [cmd]\n",argv[0]);
exit(1);
}
/*------------------------------------------------*/
/* Connect with the remote DECnet object. These   */
/* 'dnet_conn' and 'nerror' calls are the only    */
/* ones that depend on the "dnet" library         */
/*------------------------------------------------*/
strcpy(node,argv[1]);
if ((sock=dnet_conn(node,OBJECT,0,0,0,0,0)) < 0) {
nerror(argv[0]);         /* DECnet error mapper */
exit(1);
}
/*------------------------------------------------*/
/* If ARGC >=3 then a batch command was issued.   */
/* If ARGC < 3 then interactive mode is desired.  */
/*------------------------------------------------*/
buff[0] = '\0';   /* initialize buffer for strcat */
if (argc >= 3) {   /* construct the batch command */
for (i=3; i<=argc; i++) {
strcat(buff,argv[i-1]);      /* append tokens */
if (i != argc) strcat(buff," "); /* insert WS */
}
execute_batch_cmd(sock,node,buff,'b');
}
else        /* prompt loop - interactive commands */
while(1) {
printf("\nEnter Command: "); gets(buff);
if (execute_batch_cmd(sock,node,buff,'i') < 0)
break;
}
/*------------------------------------------------*/
/* Finished - Close network connection and exit   */
/*------------------------------------------------*/
puts("Exiting...\n");
close(sock);
exit(0);
}

/*--------------------------------------------------*/
/* Execute this single VMS command, close the       */
/* connection, and terminate.                       */
/*--------------------------------------------------*/
int execute_batch_cmd(sock,node,buff,mode)
int sock; char *node,*buff,mode;
{
int len;                        /* length of data */
int selRtn;            /* return value for select */
char EOFstr[2];             /* EOF str for socket */

sprintf(EOFstr,"%c%c",E_F,'\0');

if ((len=strlen(buff)) <= 0) { /* empty - snd EOF */
strcpy(buff,EOFstr); len=1;
}
else
printf("\nSENDING CMD: %s to %s\n",buff,node);
if(write(sock,buff,len) < 0) {
perror("Error: can't send cmd across network");
return(-1);
}
if (mode == 'b') write(sock,EOFstr,1); /* snd EOF */

/*------------------------------------------------*/
/* Read data coming back from the VMS host        */
/*------------------------------------------------*/
do {
selRtn = config_select(sock);
switch(selRtn) {
case -1:                     /* select failed */
printf("Error: select failed.\n");
return(-2);
case 0:                   /* socket timed out */
printf("Warning: select timed out.\n");
return(-3);
default:          /* socket ready for read... */
if ((len=read(sock,buff,BUFSIZE)) < 0) {
perror("Error: can't read from network");
return(-4);
}
buff[len]='\0'; /* return string needs null */
if (strcmp(buff,"EOC") == 0 && mode == 'i')
return(0);     /* return for next command */
if (strcmp(buff,"EOC") != 0 && len > 0)
puts(buff);    /* print appropriate lines */
}
} while (len > 0);
return(-5);
}

/*--------------------------------------------------*/
/* configure "select" for a short timeout and have  */
/* it watch the socket file descriptor for activity */
/*--------------------------------------------------*/
int config_select(int socket)
{
struct timeval timer;  /* timeout struct - select */
fd_set rset;    /* file descriptor set for select */

timer.tv_sec = READWAIT; timer.tv_usec = 0.0;
FD_ZERO(&rset); FD_SET(socket,&rset);

return(select(getdtablesize(),&rset,0,0,&timer));
}