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>
21 /*************************************************************************/
23 static int lastchar
= EOF
;
30 if (lastchar
!= EOF
) {
35 if (read(s
, &ch
, 1) != 1)
41 int sungetc(int c
, int s
)
46 /*************************************************************************/
48 /* Read a string, stopping with (and discarding) 0xFF as line terminator.
49 * If connection was broken, return NULL.
52 char *sgets(char *buf
, int len
, int s
)
55 unsigned char *ptr
= (unsigned char *) buf
;
60 while (--len
&& (*ptr
++ = c
) != 0xFF && (c
= sgetc(s
)) >= 0)
69 logfile
= fopen(logname
, "a");
72 gettimeofday(&tv
, NULL
);
73 fprintf(logfile
, "[%d.%03d] <<< %s\n",
74 tv
.tv_sec
, tv
.tv_usec
/1000, buf
);
81 /*************************************************************************/
83 /* Adds a 0xFF line terminator. */
85 int sputs(const char *str
, int s
)
87 unsigned char c
= 0xFF;
92 logfile
= fopen(logname
, "a");
95 gettimeofday(&tv
, NULL
);
96 fprintf(logfile
, "[%d.%03d] >>> %s\n",
97 tv
.tv_sec
, tv
.tv_usec
/1000, str
);
101 n
= write(s
, str
, strlen(str
));
105 if (write(s
, &c
, 1) <= 0)
110 /*************************************************************************/
112 /* Adds a 0xFF line terminator. */
114 int sockprintf(int s
, const char *fmt
, ...)
117 char buf
[16384]; /* Really huge, to try and avoid truncation */
120 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
121 return sputs(buf
, s
);
124 /*************************************************************************/
125 /*************************************************************************/
127 int conn(const char *host
, int port
, char ipbuf
[4])
130 char hbuf
[NI_MAXHOST
];
131 struct addrinfo hints
, *res
, *res0
;
135 struct sockaddr_in sa
;
140 snprintf(service
, sizeof(service
), "%d", port
);
141 memset(&hints
, 0, sizeof(hints
));
142 hints
.ai_family
= AF_UNSPEC
;
143 hints
.ai_socktype
= SOCK_STREAM
;
144 if (getaddrinfo(host
, service
, &hints
, &res0
))
146 for (res
= res0
; res
; res
= res
->ai_next
) {
148 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
151 getnameinfo(res
->ai_addr
, res
->ai_addrlen
, hbuf
, sizeof(hbuf
),
153 if (connect(sock
, res
->ai_addr
, res
->ai_addrlen
) == 0) {
155 if (res
->ai_family
== AF_INET6
) {
156 struct sockaddr_in6
*sin6
=
157 (struct sockaddr_in6
*)(res
->ai_addr
);
158 memcpy(ipbuf
, (char *)(&sin6
->sin6_addr
) + 12, 4);
160 struct sockaddr_in
*sin
=
161 (struct sockaddr_in
*)(res
->ai_addr
);
162 memcpy(ipbuf
, &sin
->sin_addr
, 4);
173 #else /* !HAVE_IPV6 */
174 memset(&sa
, 0, sizeof(sa
));
175 if (!(hp
= gethostbyname(host
)))
177 memcpy((char *)&sa
.sin_addr
, hp
->h_addr
, hp
->h_length
);
178 sa
.sin_family
= hp
->h_addrtype
;
179 sa
.sin_port
= htons((unsigned short)port
);
180 if ((sock
= socket(sa
.sin_family
, SOCK_STREAM
, 0)) < 0)
182 if (connect(sock
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0) {
183 int errno_save
= errno
;
189 memcpy(retbuf
, &sa
.sin_addr
, 4);
195 /*************************************************************************/
203 /*************************************************************************/