/* * tcp_util.c * * * by Eric Brown * 27 October '92 */ #include #include #include #include #include #include #include "lp.h" char *lp_printcap_server_lookup(char *printer) { return NULL; } /* lp_printcap_server_lookup() */ int lp_tcp_startup() { WSADATA WSAData; return WSAStartup(0x0001, &WSAData); } /* lp_tcp_startup() */ void lp_tcp_shutdown() { } /* lp_tcp_shutdown() */ /* * NOTES: * This code is modified from _UNIX_NETWORK_PROGRAMMING_ by W. Richard Stevens, * pp. 398-399. */ int lp_tcp_open(char *host) { struct sockaddr_in tcp_srv_addr; struct sockaddr_in tcp_my_addr; struct hostent tcp_host_info, *hp; unsigned long inaddr; int fd; int retries; int b_nolinger; struct linger linger; memset((void *)&tcp_srv_addr, 0, sizeof(tcp_srv_addr)); tcp_srv_addr.sin_family =AF_INET; tcp_srv_addr.sin_port = htons((short)PRINTER_PORT); /* * First try to convert the host name as a dotted-decimal number. * Only if that fails do we call gethostbyname() */ if ((inaddr = inet_addr(host)) != INADDR_NONE) { memcpy((void *)&tcp_srv_addr.sin_addr, (const void *)&inaddr, sizeof(inaddr)); tcp_host_info.h_name = NULL; } else { if ((hp = gethostbyname(host)) == NULL) { fprintf(stderr, "tcp_open: hst name error: %s\n", host); return -1; } /* if */ tcp_host_info = *hp; memcpy((void *)&tcp_srv_addr.sin_addr, (const void *)hp->h_addr, hp->h_length); } /* else */ /* * Create an internet domain socket */ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "tcp_open: can't get a reserved TCP port\n"); return -1; } /* if */ /* * Bind to a privledged port */ memset((void *)&tcp_my_addr, 0, sizeof(tcp_my_addr)); tcp_my_addr.sin_family = AF_INET; lp_randomize(); retries = BIND_RETRIES; while((tcp_my_addr.sin_port = htons((short)(rand() % MAX_PRIV_PORT)), bind(fd, (struct sockaddr *)&tcp_my_addr, sizeof(struct sockaddr)))) { if (WSAGetLastError() == WSAEADDRINUSE && retries-- > 0) continue; /* Try again */ else { fprintf(stderr, "tcp_open: Couldn't bind.\n"); closesocket(fd); return -1; } /* else */ } /* while */ if (retries == 0) { fprintf(stderr, "tcp_open: Tried %d ports, couldn't bind to any.\n", BIND_RETRIES); closesocket(fd); return -1; } /* if */ /* * Connect to the server */ if (connect(fd, (struct sockaddr *)&tcp_srv_addr, sizeof(struct sockaddr)) < 0) { fprintf(stderr, "tcp_open: can't connect to server\n"); closesocket(fd); return -1; } /* if */ /* * Let us linger for 1 AND ONLY 1 second! * Without this bit of code, I found that doing an lpq or lprm * immediately after an lpr would frequently fail! -Eric. */ b_nolinger = (int)FALSE; /* turn off DONTLINGER = turn on LINGER */ linger.l_onoff = 1; linger.l_linger = 1; /* 1 second */ setsockopt(fd, SOL_SOCKET, SO_DONTLINGER, (char *)&b_nolinger, sizeof(b_nolinger)); setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger)); return(fd); } /* tcp_open() */ void lp_randomize() { srand((unsigned)time(NULL)); } /* lp_randomize() */