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>
23 /*************************************************************************/
25 static int lastchar
= EOF
;
32 if (lastchar
!= EOF
) {
37 if (read(s
, &ch
, 1) != 1)
43 int sungetc(int c
, int s
)
48 /*************************************************************************/
50 /* Read a string, stopping with (and discarding) 0xFF as line terminator.
51 * If connection was broken, return NULL.
54 char *sgets(char *buf
, int len
, int s
)
57 unsigned char *ptr
= (unsigned char *) buf
;
62 while (--len
&& (*ptr
++ = c
) != 0xFF && (c
= sgetc(s
)) >= 0)
71 logfile
= fopen(logname
, "a");
74 gettimeofday(&tv
, NULL
);
75 fprintf(logfile
, "[%d.%03d] <<< %s\n",
76 (int) tv
.tv_sec
, (int) tv
.tv_usec
/1000, buf
);
83 /*************************************************************************/
85 /* Adds a 0xFF line terminator. */
87 int sputs(const char *str
, int s
)
89 unsigned char c
= 0xFF;
94 logfile
= fopen(logname
, "a");
97 gettimeofday(&tv
, NULL
);
98 fprintf(logfile
, "[%d.%03d] >>> %s\n",
99 (int) tv
.tv_sec
, (int) tv
.tv_usec
/1000, str
);
103 n
= write(s
, str
, strlen(str
));
107 if (write(s
, &c
, 1) <= 0)
112 /*************************************************************************/
114 /* Adds a 0xFF line terminator. */
116 int sockprintf(int s
, const char *fmt
, ...)
119 char buf
[16384]; /* Really huge, to try and avoid truncation */
122 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
123 return sputs(buf
, s
);
126 /*************************************************************************/
127 /*************************************************************************/
129 int conn(const char *host
, int port
, char ipbuf
[4])
132 char hbuf
[NI_MAXHOST
];
133 struct addrinfo hints
, *res
, *res0
;
137 struct sockaddr_in sa
;
142 snprintf(service
, sizeof(service
), "%d", port
);
143 memset(&hints
, 0, sizeof(hints
));
144 hints
.ai_family
= AF_UNSPEC
;
145 hints
.ai_socktype
= SOCK_STREAM
;
146 if (getaddrinfo(host
, service
, &hints
, &res0
))
148 for (res
= res0
; res
; res
= res
->ai_next
) {
150 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
153 getnameinfo(res
->ai_addr
, res
->ai_addrlen
, hbuf
, sizeof(hbuf
),
155 if (connect(sock
, res
->ai_addr
, res
->ai_addrlen
) == 0) {
157 if (res
->ai_family
== AF_INET6
) {
158 struct sockaddr_in6
*sin6
=
159 (struct sockaddr_in6
*)(res
->ai_addr
);
160 memcpy(ipbuf
, (char *)(&sin6
->sin6_addr
) + 12, 4);
162 struct sockaddr_in
*sin
=
163 (struct sockaddr_in
*)(res
->ai_addr
);
164 memcpy(ipbuf
, &sin
->sin_addr
, 4);
175 #else /* !HAVE_IPV6 */
176 memset(&sa
, 0, sizeof(sa
));
177 if (!(hp
= gethostbyname(host
)))
179 memcpy((char *)&sa
.sin_addr
, hp
->h_addr
, hp
->h_length
);
180 sa
.sin_family
= hp
->h_addrtype
;
181 sa
.sin_port
= htons((unsigned short)port
);
182 if ((sock
= socket(sa
.sin_family
, SOCK_STREAM
, 0)) < 0)
184 if (connect(sock
, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0) {
185 int errno_save
= errno
;
191 memcpy(ipbuf
, &sa
.sin_addr
, 4);
197 /*************************************************************************/
205 /*************************************************************************/