/*---------------------------------------------------------------------+ | Copyright (c) 1995, SAS Institute Inc. | | Unpublished - All Rights Reserved | | S A S / C S A M P L E | | | | NAME: TCPTSERV | | LANGUAGE: C | | PURPOSE: Demonstrate a TCP Server, attached by TCPLISTN. The | | "sub-task" will issue a takesocket(), and write to the | | remote client application. | | MVS - | | COMPILE, LINK: SUBMIT prefix.SAMPLE.AUX(TCPTSERV) | | where "prefix" is the installation defined high-level- | | qualifier for the SAS/C product. | | EXECUTE: N/A - TCPTSERV is "attached" by TCPLISTN | | NOTES: TCPTSERV assumes a working TCP/IP environment on both | | the local and remote hosts, refer to MISC NOTES. | | TSO - | | COMPILE: LC370 CLIST - options ENXREF EXTNAME RENT | | LINK: CLK370 CLIST | | EXECUTE: N/A - TCPTSERV is "attached" by TCPLISTN | | NOTES: TCPTSERV assumes a working TCP/IP environment on both | | the local and remote hosts. Refer to MISC NOTES: | | CMS - | | COMPILE: LC370 EXEC - options ENXREF EXTNAME RENT | | LINK: CLINK EXEC | | EXECUTE: TCPTSERV | | NOTES: TCPTSERV assumes a working TCP/IP environment on both | | the local and remote hosts. Refer to MISC NOTES: | | NOTES: TCPTSERV may be executed stand-alone. In this | | environment, customize TIMEPORT. A client application | | using TCPTSERV in this instance will only need to do a | | socket(), connect(), recv() and close(). The TCPCLNT | | may be modified to test TCPTSERV independently. | | MISC NOTES: Use TCPCLNT to test TCPLISTN and TCPTSERV | | MISC NOTES: TCPTSERV uses the following environment variables: | | TCP_SOCK - Socket descriptor passed to TCPTSERV | | TCP_DOMAIN - AF_INET = 2, passed to TCPTSERV | | TCP_NAME - Listener Jobname, passed to TCPTSERV | | TCP_SUBTASKNAME - taskname from getclientid() passed | | to TCPTSERV. | +---------------------------------------------------------------------*/ #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <options.h> #if __SASC__ == 550 #include <fcntl.h> #else #include <unistd.h> #endif int GetSocket(int *cs); #define TIMEPORT 0 /* default listen() port if NOT attached */ #define TCP_SOCK_FAILED -1 /* generic return for failed request */ main(int argc, void **argv) { int cs=0; int i; /* Variables used to obtain the time. */ char *p; int len; time_t t; /* Loop count */ int n_times; /* Buffer for outgoing time string. */ char outbuf[128]; /* If there were any arguments passed, echo them */ if (argc >1) { for (i=0; i<argc; i++) printf("argv[%d] = %s\n", i, argv[i]); } /* * Get a socket. If TIMESRV was attached by the LISTENER, then * GetSocket() calls takesocket(). Otherwise, GetSocket() will * open a new socket, bind, listen and accept before returning. */ if (GetSocket(&cs) == -1) exit(EXIT_FAILURE); /* Now, get the time and write it out to the client */ n_times = 2; while (n_times--) { /* Send the time to the client. clients */ /* expect the string to be in ASCII. */ time(&t); /* Machine readable time. */ p = ctime(&t); /* Human readable time. */ /* Convert to ASCII if necessary. */ for (len=0; len < sizeof(outbuf) && p[len] ; len++) outbuf[len] = htoncs(p[len]); if (write(cs, outbuf, len ) == -1) { perror("write() failed"); return EXIT_FAILURE; } } close(cs); return EXIT_SUCCESS; /* Avoid compilation warnings. */ } /*-------------------------------------------------------------- * Get the Socket either from a calling Main task of via a * Socket,bind, sequence. */ int GetSocket(int *cs) { /* struct for clientid information */ struct clientid clientid; char *buffer; /* Socket addresses for server and client. */ struct sockaddr_in sa_serv; struct sockaddr_in sa_clnt; int sa_len; int i; /* loop count */ int rc=0; int s; /* Working socket */ /* * If The Environment variable TCP_SOCK is not Null, we were attached * by the LISTENER and need to call takesocket to communicate. * Otherwise, we need to open a socket and accept a request on that. */ buffer = getenv("TCP_SOCK"); if (buffer != NULL) { /* * Build a clientid struct for takesocket */ memset(&clientid, 0, sizeof(clientid)); /* zero out client id */ s = atoi(buffer); buffer = getenv("TCP_DOMAIN"); clientid.domain = atoi(buffer); buffer = getenv("TCP_NAME"); memcpy(clientid.name, buffer, 8); /*Pad out the program name. */ for (i = 0; i < sizeof(clientid.name); i++) { if (clientid.name[i] < ' ') clientid.name[i] = ' '; else clientid.name[i] = toupper(clientid.name[i]); } buffer = getenv("TCP_SUBTASKNAME"); memcpy(clientid.subtaskname, buffer, 8); /*Pad out the Subtask name. */ for (i = 0; i < sizeof(clientid.subtaskname); i++) { if (clientid.subtaskname[i] < ' ') clientid.subtaskname[i] = ' '; } printf("info from ENV vars: " "Domain = <%d>, Socket# <%d> Name = <%.8s>, Task = <%.8s>\n", clientid.domain, s, clientid.name, clientid.subtaskname); /* Take the passed client socket; takesocket will return a local */ /* socket number enabling us to write to the client */ *cs = takesocket(&clientid, s); /* Check takesocket rc */ if (*cs == -1) { perror("takesock() call failed"); rc = TCP_SOCK_FAILED; } } else { /* * Since this instance is standalone (not invoked by LISTENER, * get a stream socket to communicate. */ s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) { perror("timesvr - socket() failed"); return (TCP_SOCK_FAILED); } /* Prepare a socket address for the server. */ memset(&sa_serv,'\0',sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = TIMEPORT; /* Bind our socket to the desired address. Now clients*/ /* specifying this address will reach this server. */ if (bind(s, &sa_serv, sizeof(sa_serv)) == -1) { perror("timesrv - bind() failed"); return (TCP_SOCK_FAILED); } /* Find out what port was choosen and report it. */ sa_len = sizeof(sa_serv); if (getsockname(s, &sa_serv, &sa_len) == -1) { perror("timesrv - getsockname() failed"); return (TCP_SOCK_FAILED); } printf("TIMESRV server port is: %d\n", (int) ntohs(sa_serv.sin_port)); /* Set up a queue for incoming connection requests. */ listen(s, SOMAXCONN); /* Accept a new request. Ask for client's address */ /* so that we can print it if there is an error. */ sa_len = sizeof(sa_clnt); *cs = accept(s, &sa_clnt, &sa_len); if (*cs==-1) { perror("timesrv - accept() failed"); return (TCP_SOCK_FAILED); } } return(rc); }