#include #include #include //for strlen, strspn #include //for fork #include //for socket, fork, wait #include //for socket, shutdown #include #include //for gethostbyname, getservbyname #include //for inet_ntop #include //for inet_ntop int main(int argc, char **argv) { struct hostent *host; int s; struct sockaddr_in echo; char buffer[INET6_ADDRSTRLEN]; pid_t pid; int status; int i; /* getchar requires an int: KR p. 16 */ char c; /* write requires a char: KR p. 170 */ if (argc < 2 || argc > 3) { fprintf(stderr, "%s: requires hostname and optional port number\n", argv[0]); return 1; } host = gethostbyname(argv[1]); if (host == NULL) { fprintf(stderr, "%s: %s: Unknown host\n", argv[0], argv[1]); return 2; } s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror(argv[0]); return 3; } bzero((char *)&echo, sizeof echo); echo.sin_family = AF_INET; echo.sin_addr.s_addr = *(in_addr_t *)*host->h_addr_list; if (argc < 3) { struct servent *server = getservbyname("telnet", "tcp"); if (server == NULL) { perror(argv[0]); return 4; } echo.sin_port = htons(server->s_port); } else { const size_t length = strlen(argv[2]); if (length <= 0) { fprintf(stderr, "%s: second argument must be port number\n", argv[0]); return 5; } if (strspn(argv[2], "0123456789") != length) { fprintf(stderr, "%s: second argument must be all digits\n", argv[0]); return 6; } echo.sin_port = htons(atoi(argv[2])); } if (inet_ntop(AF_INET, &echo.sin_addr, buffer, sizeof buffer) == NULL) { perror(argv[0]); return 7; } printf("Trying %s...\n", buffer); if (connect(s, (struct sockaddr *)&echo, sizeof echo) != 0) { perror(argv[0]); return 8; } printf("Connected to %s.\n" "Escape character is '^d'.\n", buffer); pid = fork(); if (pid < 0) { perror(argv[0]); return 9; } if (pid == 0) { /* The child will copy from the server to the stdout. */ while (read(s, &c, 1) == 1) { putchar(c); } fprintf(stderr, "Connection closed by foreign host.\n"); return EXIT_SUCCESS; } /* The parent will copy from the stdin to the server. */ while ((i = getchar()) != EOF) { c = i; if (write(s, &c, 1) != 1) { perror(argv[0]); return 10; } } if (shutdown(s, SHUT_RDWR) != 0) { /* terminate while loop in line 95 */ perror(argv[0]); return 11; } wait(&status); if (WIFEXITED(status)) { printf("My child's exit status was %d.\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("My child was terminated by signal number%d.\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { printf("My child was stopped by signal number%d.\n", WSTOPSIG(status)); } else { fprintf(stderr, "%s: couldn't find out how child ended up.\n", argv[0]); } return EXIT_SUCCESS; }