/* -------------------- SAS/C Sample Program -------------------- * * MODULE: rexeccmd.c - Main routine for sample rexec command * SYNTAX: rexec host username password cmd-words * * NOTE: This command does not support sending input to the remote * program. Non-UNIX implementations often restrict * select() to sockets. Thus, there is no portable * way to wait for sockets and "stdin" simultaneously. */ #include #include #include #include #include #include #ifdef __SASC__ Static void to_ebcdic(char *buf, size_t n); #endif #define EXEC_PORT 512 /* Well-known port for exec server. */ Main(int argc, char *argv[]) { int primary; /* Socket for stdin/stdout. */ int secondary; /* Socket for stderr. */ fd_set recv_set; /* Set of sockets we will wait on. */ char buf[256]; /* Set of buffer for incoming data. */ char *host; /* Pointer to hostname. */ int port; /* Port for exec server */ char cmd[512]; /* Command string. */ struct servent *serv; /* exec server information. */ int i, n, rc; /* * Handle command line arguments. * argv[1] = hostname * argv[2] = username * argv[3] = password * argv[4] = first command word * ... * argv[argc-1] = last command word */ if ((argc < 5) || (*argv[1] == '?') || (strcmp(argv[1], "-?") == 0)) { printf("Usage: %s hostname username password cmd-words\n", Argv[0]); exit(EXIT_FAILURE); } host = argv[1]; /* Pointer can be modified by rexec() call. */ /* Build up command string from remaining arguments. */ strcpy(cmd, argv[4]); for (i = 5; i < argc; i++) { strcat(cmd, " "); strcat(cmd, argv[i]); } /* Lookup standard REXEC server port. */ serv = getservbyname("exec","tcp"); if (serv == NULL) { perror("getservbyname failed"); port = EXEC_PORT; /* Assume the usual. */ } else port = serv->s_port; primary = rexec(&host, port, argv[2], argv[3], cmd, &secondary); if (primary < 0) return EXIT_FAILURE; FD_ZERO(&recv_set); while ((primary >= 0) || (secondary >= 0)) { /* * Wait for incoming data on both sockets. * select() clears bits from the mask, so we must reset * the bits each time through the loop. */ if (primary >= 0) FD_SET(primary, &recv_set); if (secondary >= 0) FD_SET(secondary, &recv_set); rc = select(FD_SETSIZE, &recv_set, NULL, NULL, NULL); if (rc < 0) { perror("select failed"); exit(EXIT_FAILURE); } /* * If incoming data available on primary... */ if ((primary >= 0) /* Not end of file yet. */ && (FD_ISSET(primary, &recv_set))) { /* recv it (or at least some of it). */ n = recv(primary, buf, sizeof(buf), 0); if (n == 0) primary = -1; /* Flag end-of-file on primary. */ else if (n < 0) { perror("recv failed on remote program's standard output"); exit(EXIT_FAILURE); } else { #ifdef __SASC__ to_ebcdic(buf, n); #endif fwrite(buf, n, 1, stdout); /* Write to local stdout */ } } /* * If incoming data available on secondary... */ if ((secondary >= 0) /* Not end of file yet. */ && (FD_ISSET(secondary, &recv_set))) { n = recv(secondary, buf, sizeof(buf)-1, 0); if (n == 0) secondary = -1; /* Flag end-of-file on secondary. */ else if (n < 0) { perror("recv failed on remote program's standard error"); exit(EXIT_FAILURE); } else { #ifdef __SASC__ to_ebcdic(buf, n); #endif fwrite(buf, n, 1, stderr); /* Write to local stderr */ } } } /* End of while loop. */ return EXIT_SUCCESS; } #ifdef __SASC__ /* Need conversion to EBCDIC */ /* * htoncs() is a SAS/C specific function which converts * a character from ASCII to EBCDIC. */ #include /* prototype for htoncs(). */ static void to_ebcdic(char *buf, size_t n) { int i; for (i = 0; i < n; i++) buf[i] = ntohcs(buf[i]); return; } #endif