/* Copyright (C) 2019 C. McEnroe * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "term.h" int main(void) { int error; setlocale(LC_CTYPE, ""); // TODO: Read info from file. const char *path = "example.sock"; struct Term *term = termAlloc(24, 80); int server = socket(PF_LOCAL, SOCK_STREAM, 0); if (server < 0) err(EX_OSERR, "socket"); struct sockaddr_un addr = { .sun_family = AF_LOCAL }; strncpy(addr.sun_path, path, sizeof(addr.sun_path)); error = bind(server, (struct sockaddr *)&addr, SUN_LEN(&addr)); if (error) err(EX_CANTCREAT, "%s", path); error = listen(server, 0); if (error) err(EX_OSERR, "listen"); int maxClient = server; struct pollfd fds[2] = { { .events = POLLIN, .fd = STDIN_FILENO }, { .events = POLLIN, .fd = server }, }; for (;;) { int nfds = poll(fds, 2, 60 * 1000); if (nfds < 0) err(EX_IOERR, "poll"); if (!nfds) { // TODO: Increment idle time in info. } if (fds[0].revents) { char buf[4096]; ssize_t rlen = read(STDIN_FILENO, buf, sizeof(buf)); if (rlen < 0) err(EX_IOERR, "read"); int client = server + 1; while (client <= maxClient) { ssize_t wlen = write(client, buf, rlen); if (wlen == rlen) { client++; continue; } close(client); if (client < maxClient) { int fd = dup(maxClient); assert(fd == client); close(maxClient); } maxClient--; } ssize_t pos = 0; while (pos < rlen) { wchar_t ch; int n = mbtowc(&ch, &buf[pos], rlen - pos); if (n <= 0) break; termUpdate(term, ch); pos += n; } } if (fds[1].revents) { int client = accept(server, NULL, NULL); if (client < 0) continue; fcntl(client, F_SETFL, O_NONBLOCK); int yes = 1; error = setsockopt(client, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof(yes)); if (error) { close(client); continue; } error = termSnapshot(term, client); if (error) { close(client); continue; } maxClient++; assert(client == maxClient); } } }