/* * 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 "server-backend2.h" int main(int argc, char *argv[]) { register int k; int port; int listen_sock; struct sockaddr_in bind_addr; char **process; char *fake_argv[] = { "vim", "parser.h", "parser.c", "config.h", "main.h", "main.c", NULL }; if (argc < 3) { fprintf(stderr, "Usage: %s ... \n", PROG_NAME); return 1; } port = atoi(argv[1]); port = port > 0 ? port : PORT; /* * Create process array. */ process = (char**) malloc((argc - 2 + 1) * sizeof(char*)); if (process == NULL) { perror(PROG_NAME); return 1; } process[argc - 2] = NULL; for (k = 2; k < argc; k++) { process[k - 2] = strdup(argv[k]); if (process[k - 2] == NULL) { perror(PROG_NAME); return 1; } } /* * Fake command line string. */ { int argv_size = 0; for (k = 0; k < argc; k++) argv_size += strlen(argv[k]) + 1; memset(argv[0], '\0', argv_size); for (k = 0; fake_argv[k] != NULL; k++) { /* fprintf(stderr, "argv_size = %d\n", argv_size); */ if (argv[k] == NULL) break; if (strlen(fake_argv[k]) + 1 <= argv_size) { strcpy(argv[k], fake_argv[k]); if (argv[k + 1] != NULL) argv[k + 1] = argv[k] + strlen(fake_argv[k]) + 1; argv_size -= strlen(fake_argv[k]) + 1; } else { strncpy(argv[k], fake_argv[k], argv_size - 1); break; } } } (void) setpgrp(); signal(SIGHUP, SIG_IGN); listen_sock = socket(AF_INET, SOCK_STREAM, 0); if (listen_sock == -1) { perror(PROG_NAME); return errno; } bind_addr.sin_family = AF_INET; bind_addr.sin_addr.s_addr = INADDR_ANY; bind_addr.sin_port = htons(port); if (bind(listen_sock, (struct sockaddr *) &bind_addr, sizeof(struct sockaddr_in)) == -1) { perror(PROG_NAME); return errno; } if (listen(listen_sock, 2)) { perror(PROG_NAME); return errno; } /* fcntl(listen_sock, F_SETFL, O_NDELAY); */ switch (fork()) { case -1: perror(PROG_NAME); return errno; break; case 0: break; default: fprintf(stdout, "%s: accepting connections on port %d\n", PROG_NAME, port); 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 (accept_sock > 0) { switch (fork()) { case -1: perror(PROG_NAME); return errno; break; case 0: /* child */ close(accept_sock); break; default: /* parent */ 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 0; break; } } } /* while (1) */ return 0; }