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));
}
|