#include #include #include #include #include #include #include #include #include #include #include #include #define terminal_up "\x1b[A" char *default_port = "2345"; void error(char *msg) { perror(msg); exit(1); } void readsocket(FILE * sock) { char buffer[256]; while (1) { if (!fgets(buffer, sizeof(buffer), sock)) break; fputs(buffer, stdout); fflush(stdout); } fclose(sock); } void writesocket(FILE * sock, char nick[]) { char buffer[256]; fflush(stderr); fprintf(sock, "nick: %s\n\n", nick); fflush(sock); while (fgets(buffer, sizeof(buffer), stdin)) { fprintf(stderr, terminal_up); fputs(buffer, sock); fflush(sock); } fclose(sock); } char *user_env_vars[] = { "NICK", "nick", "USER", "LOGNAME", "USERNAME", "user", NULL }; char *guess_nick(void) { char **p; char *nick = NULL; for (p = user_env_vars; *p; ++p) { nick = getenv(*p); if (nick) break; } if (!nick) { fprintf(stderr, "can't guess nick from environment variables\n"); exit(1); } return nick; } int main(int argc, char *argv[]) { int sockfd; struct addrinfo *res, hints, *p; char *nick, *host, *port; if (argc < 1 || argc > 4 || (argc > 1 && argv[1][0] == '-')) { fprintf(stderr, "usage: chat [nick [host [port]]]\n"); exit(1); } nick = argc < 2 ? guess_nick() : argv[1]; host = argc < 3 ? "127.0.0.1" : argv[2]; port = argc < 4 ? default_port : argv[3]; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; // TODO put this getaddrinfo into a function int result = getaddrinfo(host, port, &hints, &res); if (result != 0) error("ERROR getaddrinfo\n"); for (p = res; p; p = p->ai_next) { sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd < 0) continue; if (connect(sockfd, p->ai_addr, p->ai_addrlen) < 0) error("ERROR connecting"); break; } FILE *io = fdopen(sockfd, "r+"); pid_t pid; pid = fork(); if (pid < 0) { perror("ERROR from fork()"); } else if (pid == 0) { readsocket(io); kill(getppid(), SIGTERM); } else { writesocket(io, nick); kill(pid, SIGTERM); waitpid(pid, NULL, 0); } return 0; }