#include <errno.h>
#include <unistd.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
pid_t pid(_not(pid_t));
#endif
+ const char *host(NULL);
+ const char *port(NULL);
+
apr_getopt_t *state;
_aprcall(apr_getopt_init(&state, pool, argc, argv));
#ifdef CY_ATTACH
"p:"
#endif
+ "r:"
"s"
, &opt, &arg));
#ifdef CY_ATTACH
" [-p <pid|name>]"
#endif
+ " [-r <host:port>]"
" [<script> [<arg>...]]\n"
);
return 1;
} break;
#endif
+ case 'r': {
+ //size_t size(strlen(arg));
+
+ char *colon(strrchr(arg, ':'));
+ if (colon == NULL) {
+ fprintf(stderr, "missing colon in hostspec\n");
+ return 1;
+ }
+
+ /*char *end;
+ port = strtoul(colon + 1, &end, 10);
+ if (end != arg + size) {
+ fprintf(stderr, "invalid port in hostspec\n");
+ return 1;
+ }*/
+
+ host = arg;
+ *colon = '\0';
+ port = colon + 1;
+ } break;
+
case 's':
strict_ = true;
break;
client_ = -1;
#endif
+ if (client_ == -1 && host != NULL && port != NULL) {
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ hints.ai_flags = 0;
+
+ struct addrinfo *infos;
+ _syscall(getaddrinfo(host, port, &hints, &infos));
+
+ _assert(infos != NULL); try {
+ for (struct addrinfo *info(infos); info != NULL; info = info->ai_next) {
+ int client(_syscall(socket(info->ai_family, info->ai_socktype, info->ai_protocol))); try {
+ _syscall(connect(client, info->ai_addr, info->ai_addrlen));
+ client_ = client;
+ break;
+ } catch (...) {
+ _syscall(close(client));
+ throw;
+ }
+ }
+ } catch (...) {
+ freeaddrinfo(infos);
+ throw;
+ }
+ }
+
if (script == NULL && tty)
Console(options);
else {
fprintf(stderr, "%s\n", error.PoolCString(pool));
}
}
+
+struct CYServer {
+ pthread_t thread_;
+ uint16_t port_;
+ int socket_;
+
+ CYServer(uint16_t port) :
+ port_(port),
+ socket_(-1)
+ {
+ }
+
+ ~CYServer() {
+ if (socket_ != -1)
+ _syscall(close(socket_));
+ }
+
+ void Listen() {
+ socket_ = _syscall(::socket(PF_INET, SOCK_STREAM, 0)); try {
+ sockaddr_in address;
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = INADDR_ANY;
+ address.sin_port = htons(port_);
+ _syscall(::bind(socket_, reinterpret_cast<sockaddr *>(&address), sizeof(address)));
+
+ _syscall(::listen(socket_, -1));
+
+ for (;;) {
+ socklen_t length(sizeof(address));
+ int socket(_syscall(::accept(socket_, reinterpret_cast<sockaddr *>(&address), &length)));
+ CYHandleClient(socket);
+ }
+ } catch (const CYException &error) {
+ CYPool pool;
+ fprintf(stderr, "%s\n", error.PoolCString(pool));
+ }
+ }
+};
+
+static void *OnServer(void *data) {
+ CYServer *server(reinterpret_cast<CYServer *>(data));
+ server->Listen();
+ delete server;
+ return NULL;
+}
+
+extern "C" void CYListenServer(short port) {
+ CYInitializeDynamic();
+
+ CYServer *server(new CYServer(port));
+ _assert(pthread_create(&server->thread_, NULL, &OnServer, server) == 0);
+}