QI_SOCKET 1-SEP-1993 10:04:16 VAX C V3.2-044 Page 1 V1.0 22-AUG-1993 19:43:04 X$SRC:[CSO]QI_SOCKET.C;1 (1) 1 /* TCP/IP routines stolen from the VMS GOPHERD */ 2 3 #include stdio 265 #include socket 467 #include in 626 #include netdb 691 692 #if defined(UCX) 693 X #include 694 #endif 695 696 #define MULTINET 697 698 #if defined(VMS) && (defined(WOLLONGONG) || defined(MULTINET)) 699 /* Multinet and Wollongong (non UCX-emulation) use channel numbers */ 700 /* for sockets, which are small multiples of 16. The first 5 */ 701 /* channels can be assumed to be already used, so we assume that */ 702 /* sockets start at 64, and that only 64 VAXC fds are simultaneously */ 703 /* open in the program. Actually, the first socket is likely to be */ 704 /* more like 176! */ 705 #define IS_SOCKET(s) ((s)>=64) 706 707 /* Close a socket. 708 * Note that in old Wollongong and Multinet implementations close() 709 * works only on fds, not sockets. 710 * For UCX and Unix, closenet() is #defined to be close() 711 */ 712 int closenet(s) 713 int s; 714 { 715 1 if (IS_SOCKET(s)) { 716 2 #ifdef MULTINET 717 2 return (socket_close(s)); 718 2 #else /* WOLLONGONG */ 719 X return (netclose(s)); 720 2 #endif 721 2 } 722 1 else 723 1 close(s); /* shouldn't be calling this routine */ 724 1 } 725 #endif /* WOLLANGONG or MULTINET */ 726 727 728 /* Read "n" bytes from a descriptor. 729 * Use in place of read() when fd is a stream socket 730 * 731 * Returns the number of total bytes read. 732 */ 733 734 int readn(fd, ptr, nbytes) 735 int fd; 736 char *ptr; 737 int nbytes; 738 { 739 1 int nleft, nread; QI_SOCKET 1-SEP-1993 10:04:16 VAX C V3.2-044 Page 2 V1.0 22-AUG-1993 19:43:04 X$SRC:[CSO]QI_SOCKET.C;1 (1) 740 1 741 1 nleft = nbytes; 742 1 while (nleft > 0) { 743 2 #if defined(VMS) && defined(WOLLONGONG) 744 X nread = IS_SOCKET(fd) ? netread(fd, ptr, nleft) : read(fd, ptr, nleft); 745 2 #else 746 2 #if defined(VMS) && defined(MULTINET) 747 2 nread = IS_SOCKET(fd) ? socket_read(fd, ptr, nleft) : read(fd, ptr, nleft); 748 2 #else 749 X nread = read(fd, ptr, nleft); 750 2 #endif 751 2 #endif 752 2 #if defined(VMS) && defined(UCX) 753 X if (nread < 0 && errno == EPIPE) 754 X break; 755 2 #endif 756 2 if (nread < 0) 757 2 return(nread); /* error, return <0 */ 758 2 else if (nread == 0) /* EOF */ 759 2 break; 760 2 761 2 nleft -= nread; 762 2 ptr += nread; 763 2 } 764 1 return(nbytes - nleft); /* return >= 0) */ 765 1 } 766 767 768 769 /* 770 * Write "n" bytes to a descriptor. 771 * Use in place of write() when fd is a stream socket 772 * 773 * We return the number of bytes written 774 */ 775 776 int 777 writen(fd, ptr, nbytes) 778 int fd; 779 char *ptr; 780 int nbytes; 781 { 782 1 int nleft, nwritten; 783 1 784 1 nleft = nbytes; 785 1 while(nleft > 0) { 786 2 #if defined(VMS) && defined(WOLLONGONG) 787 X nwritten = IS_SOCKET(fd) ? netwrite(fd, ptr, nleft) : write(fd, ptr, nleft); 788 2 #else 789 2 #if defined(VMS) && defined(MULTINET) 790 2 nwritten = IS_SOCKET(fd) ? socket_write(fd, ptr, nleft) : write(fd, ptr, nleft); 791 2 #else 792 X nwritten = write(fd, ptr, nleft); 793 2 #endif 794 2 #endif 795 2 if (nwritten <= 0) 796 2 return(nwritten); /* error */ QI_SOCKET 1-SEP-1993 10:04:16 VAX C V3.2-044 Page 3 V1.0 22-AUG-1993 19:43:04 X$SRC:[CSO]QI_SOCKET.C;1 (1) 797 2 798 2 nleft -= nwritten; 799 2 ptr += nwritten; 800 2 } 801 1 return(nbytes - nleft); 802 1 } 803 804 805 /* 806 * Writestring uses the writen and strlen calls to write a 807 * string to the file descriptor fd. If the write fails 808 * a -1 is returned. Otherwise zero is returned. 809 */ 810 811 int writestring(fd, stringptr) 812 int fd; 813 char *stringptr; 814 { 815 1 int length; 816 1 817 1 if (stringptr == NULL) 818 1 return(0); 819 1 820 1 length = strlen(stringptr); 821 1 if (writen(fd, stringptr, length) != length) { 822 2 return(-1); 823 2 } 824 1 else 825 1 return(0); 826 1 } 827 828 /* 829 * Read from the socket into a buffer. Mucho more efficent in terms of 830 * system calls.. 831 * 832 * returns bytes read, or <0 for an error 833 */ 834 835 #define RECVSIZE 4096 836 837 int readrecvbuf(sockfd, buf, len) 838 int sockfd; 839 char *buf; 840 int len; 841 { 842 1 static char recvbuf[RECVSIZE]; 843 1 static int recvbufptr = 0; 844 1 static int recvbufsize = 0; 845 1 static int Oldsockfd = 0; 846 1 int bytesread = 0; 847 1 848 1 if (recvbufptr == 0 || Oldsockfd != sockfd) { 849 2 #if defined(VMS) && defined(WOLLONGONG) 850 X recvbufsize = IS_SOCKET(sockfd) ? 851 X netread(sockfd, recvbuf, RECVSIZE) : read(sockfd, recvbuf, RECVSIZE); 852 2 #else 853 2 #if defined(VMS) && defined(MULTINET) QI_SOCKET 1-SEP-1993 10:04:16 VAX C V3.2-044 Page 4 V1.0 22-AUG-1993 19:43:04 X$SRC:[CSO]QI_SOCKET.C;1 (1) 854 2 recvbufsize = IS_SOCKET(sockfd) ? 855 2 socket_read(sockfd, recvbuf, RECVSIZE) : read(sockfd, recvbuf, RECVSIZE); 856 2 #else 857 X recvbufsize = read(sockfd, recvbuf, RECVSIZE); 858 2 #endif 859 2 #endif 860 2 Oldsockfd = sockfd; 861 2 recvbufptr = 0; 862 2 if (recvbufsize == 0) 863 2 return(0); 864 2 #if defined(VMS) && defined(UCX) 865 X if (recvbufsize < 0 && errno == EPIPE) 866 X return(0); 867 2 #endif 868 2 869 2 } 870 1 871 1 while (len--) { 872 2 *buf++ = recvbuf[recvbufptr++]; 873 2 bytesread++; 874 2 875 2 if (recvbufptr == recvbufsize && len != 0) { 876 3 recvbufsize = readn(sockfd, recvbuf, RECVSIZE); 877 3 recvbufptr = 0; 878 3 if (recvbufsize == 0) 879 3 return(bytesread); 880 3 if (recvbufsize < 0) 881 3 return(recvbufsize); 882 3 883 3 } else if (recvbufptr >= recvbufsize) 884 2 recvbufptr = 0; 885 2 } 886 1 return(bytesread); 887 1 } 888 889 890 /* 891 * Read a line from a descriptor. Read the line one byte at a time, 892 * looking for the newline. We store the newline in the buffer, 893 * then follow it with a null (the same as fgets(3)). 894 * We return the number of characters up to, but not including, 895 * the null (the same as strlen(3)) 896 */ 897 898 int readline(fd, ptr, maxlen) 899 int fd; 900 char *ptr; 901 int maxlen; 902 { 903 1 int n; 904 1 int rc; 905 1 char c; 906 1 907 1 908 1 for (n=1; n < maxlen; n++) { 909 2 if ( (rc = readrecvbuf(fd, &c, 1)) == 1) { 910 3 *ptr++ = c; QI_SOCKET 1-SEP-1993 10:04:16 VAX C V3.2-044 Page 5 V1.0 22-AUG-1993 19:43:04 X$SRC:[CSO]QI_SOCKET.C;1 (1) 911 3 if (c == '\n') 912 3 break; 913 3 } 914 2 else if (rc == 0) { 915 3 if (n == 1) 916 3 return(0); /* EOF, no data read */ 917 3 else 918 3 break; /* EOF, some data was read */ 919 3 } 920 2 else 921 2 return(-1); /* error */ 922 2 } 923 1 924 1 *ptr = 0; /* Tack a NULL on the end */ 925 1 926 1 return(n); 927 1 } 928 929 930 /* 931 * ZapCRLF removes all carriage returns and linefeeds from a C-string. 932 */ 933 934 void 935 ZapCRLF(inputline) 936 char *inputline; 937 { 938 1 char *cp; 939 1 940 1 cp = strchr(inputline, '\r'); /* Zap CR-LF */ 941 1 if (cp != NULL) 942 1 *cp = '\0'; 943 1 else { 944 2 cp = strchr(inputline, '\n'); 945 2 if (cp != NULL) 946 2 *cp = '\0'; 947 2 } 948 1 } 949 950 951 void inet_netnames(int sock, char *host_name) 952 { 953 1 struct sockaddr_in sa; 954 1 int length; 955 1 u_long net_addr; 956 1 struct hostent *hp; 957 1 958 1 length = sizeof(sa); 959 1 getpeername(sock, &sa, &length); 960 1 strcpy(host_name, inet_ntoa(sa.sin_addr)); 961 1 962 1 hp = gethostbyaddr((char *) &sa.sin_addr, 963 1 sizeof (sa.sin_addr.s_addr), AF_INET); 964 1 965 1 if (hp != NULL) 966 1 strcpy(host_name, hp->h_name); 967 1 } QI_SOCKET 1-SEP-1993 10:04:16 VAX C V3.2-044 Page 6 V1.0 22-AUG-1993 19:43:04 X$SRC:[CSO]QI_SOCKET.C;1 (1) Command Line ------------ CC/DEBUG/NOOP/LIST QI_SOCKET .