xref: /plan9/sys/src/cmd/postscript/tcpostio/dial.c (revision 14f51593fd82e19ba95969a8c07ff71131015979)
1 #define _BSD_EXTENSION
2 #define _NET_EXTENSION
3 #define _POSIX_SOURCE
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <ctype.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <netdb.h>
14 #include <sys/time.h>
15 
16 #define	DIALTIMEOUT	30
17 
18 /* This is a dummy routine for non Plan9 systems.
19  * No attempt has been made to be clever, it's just
20  * supposed to work in this program.
21  */
22 int dial_debug = 0;
23 
24 int
dial(char * dest,char * local,char * dir,int * cfdp)25 dial(char *dest, char *local, char *dir, int *cfdp) {
26 	int sockconn, lport;
27 	struct hostent *hp;		/* Pointer to host info */
28 	struct sockaddr_in sin;		/* Socket address, Internet style */
29 	struct servent *sp = 0;
30 	char *tdest, *netname, *hostname, *servname;
31 	int sock_type;
32 #ifndef plan9
33 #define	USED(x)	if(x); else
34 	int sockoption, sockoptsize;
35 #endif
36 
37 	USED(dir);
38 	USED(cfdp);
39 	if ((tdest = malloc(strlen(dest)+1)) == NULL) {
40 		if (dial_debug) fprintf(stderr, "dial: could not allocate memory\n");
41 		return(-1);
42 	}
43 	strcpy(tdest, dest);
44 
45 	if ((netname = strtok(tdest, "!")) == NULL) {
46 		fprintf(stderr, "dial: no network name\n");
47 		return(-1);
48 	}
49 	if (strcmp(netname, "tcp") == 0) {
50 		sock_type = SOCK_STREAM;
51 	} else if (strcmp(netname, "udp") == 0) {
52 		sock_type = SOCK_DGRAM;
53 	} else {
54 		fprintf(stderr, "dial: network protocol name `%s' is invalid; must be `tcp' or `udp'\n", netname);
55 		return(-1);
56 	}
57 	if ((hostname = strtok(0, "!")) == NULL) {
58 		fprintf(stderr, "dial: no host name or number\n");
59 		return(-1);
60 	}
61 	if ((servname = strtok(0, "!")) == NULL) {
62 		fprintf(stderr, "dial: no service name or number\n");
63 		return(-1);
64 	}
65 	hp = gethostbyname(hostname);
66 	if (hp == (struct hostent *)NULL) {
67 		if (dial_debug) fprintf(stderr, "host `%s' unknown by local host\n", hostname);
68 		return(-1);
69 	}
70 	if (!isdigit(servname[0]))
71 		sp = getservbyname(servname, netname);
72 	sin.sin_addr.s_addr = *(unsigned long*)hp->h_addr;
73 	sin.sin_port	= htons((sp==0)?atoi(servname):sp->s_port);
74 	sin.sin_family	= AF_INET;
75 	if (local == NULL) {
76 		if ((sockconn = socket(AF_INET, sock_type, 0)) < 0) {
77 			if (dial_debug) perror("dial:socket():");
78 			return(-1);
79 		}
80 		if (dial_debug) fprintf(stderr, "socket FD=%d\n", sockconn);
81 	} else {
82 		lport = atoi(local);
83 		if ((lport < 512) || (lport >= 1024)) {
84 			fprintf(stderr, "dial:invalid local port %d\n", lport);
85 			return(-1);
86 		}
87 		if ((sockconn = rresvport(&lport)) < 0) {
88 			if (dial_debug) perror("dial:rresvport():");
89 			return(-1);
90 		}
91 	}
92 	if (dial_debug) {
93 		fprintf(stderr, "sin size=%d\n", sizeof(sin));
94 	}
95 	alarm(DIALTIMEOUT);
96 	if ((connect(sockconn, (struct sockaddr *) &sin, sizeof(sin)) < 0)) {
97 		if (dial_debug) perror("dial:connect():");
98 		return(-1);
99 	}
100 	alarm(0);
101 #ifndef plan9
102 	sockoptsize = sizeof(sockoption);
103 	if (getsockopt(sockconn, SOL_SOCKET, SO_KEEPALIVE, &sockoption, &sockoptsize) < 0) {
104 		if (dial_debug) perror("dial:getsockopt():");
105 		return(-1);
106 	}
107 	if (sockoptsize == sizeof(sockoption) && !sockoption) {
108 		if (setsockopt(sockconn, SOL_SOCKET, SO_KEEPALIVE, &sockoption, sockoptsize) < 0) {
109 			if (dial_debug) perror("dial:getsockopt():");
110 			return(-1);
111 		}
112 	}
113 #endif
114 	return(sockconn);
115 }
116