#include #include #include #include main(argc, argv) int argc; char **argv; { int verbose; int lfd, sfd; struct sockaddr_in myaddr, claddr; struct in_addr ia; int inane; int pid; FILE *sfp; verbose = 0; if (argc > 1 && strcmp(argv[1], "-v") == 0) { verbose = 1; argc--; argv++; } if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } myaddr.sin_family = AF_INET; myaddr.sin_port = 0; myaddr.sin_addr.s_addr = INADDR_ANY; if (bind(lfd, &myaddr, sizeof(myaddr)) < 0) { perror("bind"); exit(1); } inane = sizeof(myaddr); if (getsockname(lfd, &myaddr, &inane) < 0) { perror("getsockname"); exit(1); } if (listen(lfd, 5) < 0) { perror("listen"); exit(1); } fprintf(stderr, "listening on %d\n", ntohs(myaddr.sin_port)); fflush(stdout); while (inane = sizeof(claddr), (sfd = accept(lfd, &claddr, &inane)) >= 0) { if ((pid = fork()) < 0) { perror("fork"); continue; } if (pid == 0) { /* child: copy in */ if ((sfp = fdopen(sfd, "r")) == NULL) { fprintf(stderr, "child can't fdopen connection for reading\n"); exit(1); } copydata(sfp, stdout, verbose); exit(0); } else { /* parent: copy out */ if (verbose) fprintf(stderr, "accept %s:%d, pid %d\n", inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port), pid); if ((sfp = fdopen(sfd, "w")) == NULL) { fprintf(stderr, "parent can't fdopen connection for writing\n"); continue; /* leave child running */ } copydata(stdin, sfp, 0); fclose(sfp); kill(pid, SIGTERM); /* kill child, so connection closes */ clearerr(stdin); /* clear EOF flag */ } close(sfd); } exit(0); } copydata(frfp, tofp, verbose) FILE *frfp, *tofp; int verbose; { char buf[200]; int mypid; mypid = getpid(); while (fgets(buf, sizeof(buf), frfp)) { if (verbose) fprintf(tofp, "%d: ", mypid); if (fputs(buf, tofp) == EOF || fflush(tofp) == EOF) { perror("write"); break; } } }