/* * server_backend.c - network server socketing backend * * (c) 2001 Ondrej Jombik * * History * - 19/9/2001 - initial release * - 20/9/2001 - minor bugfixes * - waitpid() used as substitute of wait() * - 24/9/2001 - fork() after accept() change (parent <-> child) * - fnctl() removed * * TODO * - write debug infomations to STDERR * - ability to enter fake command on command line */ #include #include #include #include #include #include #include #include #include #include #include /* wait() */ #include /* struct timeval */ #include /* signal() */ #include #include "utils.h" #include "server-backend.h" int main(int argc, char *argv[]) { register int cur_arg; int port, f_interactive = 0; int listen_sock; char **process; if (argc < 3) { fprintf(stderr, "Usage:\n" " %s ... \n" " %s -i \n", PROG_NAME, PROG_NAME); return 1; } cur_arg = 1; if (! strcmp(argv[cur_arg], "-i")) { f_interactive = 1; cur_arg++; } port = get_port(argv[cur_arg]); cur_arg++; if (f_interactive && 0) { process = NULL; } else { if ((process = create_process_array(argc, argv, cur_arg)) == NULL) { perror(PROG_NAME); return 32; } } fake_command_line(argc, argv); if ((listen_sock = bind_to_port(port)) == -1) { perror(PROG_NAME); return 16; } if (1) { (void) setpgrp(); signal(SIGHUP, SIG_IGN); } if (0) fcntl(listen_sock,F_SETFL,O_NDELAY); switch (f_interactive ? 1 : fork()) { case -1: perror(PROG_NAME); return errno; break; case 0: break; default: fprintf(stderr, "%s: accepting connections on port %d\n", PROG_NAME, port); if (f_interactive) fprintf(stderr, "%s: interactive mode enabled," " waiting for first client\n", PROG_NAME); else return 0; break; } while (1) { struct sockaddr_in acc_addr; unsigned int size; int accept_sock; sleep(1); size = sizeof(struct sockaddr_in); accept_sock = accept(listen_sock, (struct sockaddr*) &acc_addr, &size); if (accept_sock < 0) { perror(PROG_NAME); return errno; } if (f_interactive) { fprintf(stderr, "%s: new client connected from %s\n", PROG_NAME, (char*)inet_ntoa(acc_addr.sin_addr)); fprintf(stderr, "%s: you can now communicate via socket no. %d\n", PROG_NAME, accept_sock); } if (accept_sock > 0) { switch (f_interactive ? 1 : fork()) { case -1: perror(PROG_NAME); return errno; break; case 0: /* child */ close(accept_sock); break; default: /* parent */ if (! f_interactive) { dup2(accept_sock, 0); dup2(accept_sock, 1); dup2(accept_sock, 2); close(listen_sock); close(accept_sock); execvp(process[0], process); write(accept_sock, "execlp() failure\n\r", 18); return 8; } if (do_interactive(accept_sock) < 0) { perror(PROG_NAME); return 8; } return 0; } } } /* while (1) */ return 0; }