1 /* Tetrinet for Linux, by Andrew Church <achurch@achurch.org>
2 * This program is public domain.
11 #include <sys/types.h>
13 #include <netinet/in.h>
14 #include <sys/socket.h>
22 /*************************************************************************/
24 static int lastchar
= EOF
;
31 if (lastchar
!= EOF
) {
36 if (read(s
, &ch
, 1) != 1)
42 int sungetc(int c
, int s
)
47 /*************************************************************************/
49 /* Read a string, stopping with (and discarding) 0xFF as line terminator.
50 * If connection was broken, return NULL.
53 char *sgets(char *buf
, int len
, int s
)
56 unsigned char *ptr
= (unsigned char *) buf
;
61 while (--len
&& (*ptr
++ = c
) != 0xFF && (c
= sgetc(s
)) >= 0)
70 logfile
= fopen(logname
, "a");
73 gettimeofday(&tv
, NULL
);
74 fprintf(logfile
, "[%d.%03d] <<< %s\n",
75 (int) tv
.tv_sec
, (int) tv
.tv_usec
/1000, buf
);
82 /*************************************************************************/
84 /* Adds a 0xFF line terminator. */
86 int sputs(const char *str
, int s
)
88 unsigned char c
= 0xFF;
93 logfile
= fopen(logname
, "a");
96 gettimeofday(&tv
, NULL
);
97 fprintf(logfile
, "[%d.%03d] >>> %s\n",
98 (int) tv
.tv_sec
, (int) tv
.tv_usec
/1000, str
);
102 n
= write(s
, str
, strlen(str
));
106 if (write(s
, &c
, 1) <= 0)
111 /*************************************************************************/
113 /* Adds a 0xFF line terminator. */
115 int sockprintf(int s
, const char *fmt
, ...)
118 char buf
[16384]; /* Really huge, to try and avoid truncation */
121 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
122 return sputs(buf
, s
);
125 /*************************************************************************/
126 /*************************************************************************/
128 int conn(const char *host
, int port
, char ipbuf
[4])
131 char hbuf
[NI_MAXHOST
];
132 struct addrinfo hints
, *res
, *res0
;
136 struct sockaddr_in sa
;
141 snprintf(service
, sizeof(service
), "%d", port
);
142 memset(&hints
, 0, sizeof(hints
));
143 hints
.ai_family
= AF_UNSPEC
;
144 hints
.ai_socktype
= SOCK_STREAM
;
145 if (getaddrinfo(host
, service
, &hints
, &res0
))
147 for (res
= res0
; res
; res
= res
->ai_next
) {
149 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
152 getnameinfo(res
->ai_addr
, res
->ai_addrlen
, hbuf
, sizeof(hbuf
),
154 if (connect(sock
, res
->ai_addr
, res
->ai_addrlen
) == 0) {
156 if (res
->ai_family
== AF_INET6
) {
157 struct sockaddr_in6
*sin6
=
158 (struct sockaddr_in6
*)(res
->ai_addr
);
159 memcpy(ipbuf
, (char *)(&sin6
->sin6_addr
) + 12, 4);
161 struct sockaddr_in
*sin
=
162 (struct sockaddr_in
*)(res
->ai_addr
);
163 memcpy(ipbuf
, &sin
->sin_addr
, 4);
174 #else /* !HAVE_IPV6 */
175 memset(&sa
, 0, sizeof(sa
));
176 if (!(hp
= gethostbyname(host
)))
178 memcpy((char *)&sa
.sin_addr
, hp
->h_addr
, hp
->h_length
);
179 sa
.sin_family
= hp
->h_addrtype
;
180 sa
.sin_port
= htons((unsigned short)port
);
181 if ((sock
= socket(sa
.sin_family
, SOCK_STREAM
, 0)) < 0)
183 if (connect(sock
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0) {
184 int errno_save
= errno
;
190 memcpy(retbuf
, &sa
.sin_addr
, 4);
196 /*************************************************************************/
204 /*************************************************************************/