#include #include #include #include #include #include #include #include #include #include #include #include #include #define USE_IPC //define BIND_AFTER_FORK #define BUFFERLEN 256 struct database { int shmid; int semid; int test1; int test2; } *wdb; int get_shared_memory(char *path_key) { key_t key; int shmid; int shmflg; char file[BUFFERLEN]; snprintf(file, BUFFERLEN-1, "%s.exe", path_key); if ((key = ftok(file, 'Z')) == -1) { perror("Getting key for shared memory"); exit(1); } shmflg = IPC_CREAT|0600; if ((shmid = shmget(key, sizeof(struct database), shmflg)) == -1) { perror ("Getting shared memory"); exit(1); } fprintf(stderr,"shmid: %i\n", shmid); return (shmid); } int get_semaphores(char *path_key) { key_t key; int semid; struct sembuf op; int semflg; char file[BUFFERLEN]; snprintf(file, BUFFERLEN-1, "%s.exe", path_key); if ((key = ftok(file, 'Z')) == -1) { perror ("Getting key for semaphores"); exit(1); } semflg = IPC_CREAT|0600; if ((semid = semget(key, 1, semflg)) == -1) { perror ("Getting semaphores"); exit(1); } if (semctl(semid, 0, SETVAL, 1) == -1) { perror ("semctl SETVAL -> 1"); exit(1); } if (semctl(semid, 0, GETVAL) == 0) { op.sem_num = 0; op.sem_op = 1; op.sem_flg = 0; if (semop(semid, &op, 1) == -1) { perror ("semaphore_release"); exit(1); } } fprintf(stderr,"semval: %i semid: %i\n", semctl (semid, 0, GETVAL), semid); return (semid); } void *attach_shared_memory(int shmid) { void *rv; // return value if ((rv = shmat(shmid, 0, 0)) == (void *) -1) { perror ("master shmat"); return ((void *) -1); } return (rv); } void set_signal_handlers (void) { struct sigaction ignore; ignore.sa_handler = SIG_IGN; sigemptyset(&ignore.sa_mask); ignore.sa_flags = 0; sigaction(SIGHUP, &ignore, NULL); // So we keep running as a daemon } int get_socket(short port) { int sfd; //socket file descriptor struct sockaddr_in addr; int opt; opt = 1; sfd = socket(PF_INET, SOCK_STREAM, 0); if (sfd == -1) { perror("socket"); exit(1); } else { if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (int *) &opt, sizeof(opt)) == -1) perror ("setsockopt"); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sfd, (struct sockaddr *) &addr, sizeof (addr)) == -1) { perror("bind"); sfd = -1; } else { listen (sfd, 5); } } return (sfd); } int accept_socket (int sfd, struct sockaddr_in *addr) { int fd; int len = sizeof(struct sockaddr_in); if ((fd = accept(sfd, (struct sockaddr *) addr, &len)) == -1) { perror("Accepting connection\n"); exit(1); } return (fd); } int main(int argc, char *argv[]) { int sfd; // socket file descriptor int csfd; // child sfd, the socket once accepted int shmid; // shared memory id struct sockaddr_in addr; // Address of the remote host pid_t child; pid_t child_wait; int n_children; int rc; // Return code int i; // For loops n_children = 0; set_signal_handlers(); #ifdef USE_IPC shmid = get_shared_memory(argv[0]); if ((wdb = attach_shared_memory (shmid)) == (void *) -1) exit (1); wdb->shmid = shmid; wdb->semid = get_semaphores(argv[0]); #endif #ifndef BIND_AFTER_FORK if ((sfd = get_socket(1234)) == -1) exit(0); #endif printf ("Waiting for connections...\n"); while (1) { if (n_children < 1) { if ((child = fork()) == 0) { #ifdef BIND_AFTER_FORK if ((sfd = get_socket(1234)) == -1) exit(0); #endif if ((csfd = accept_socket(sfd, &addr)) != -1) { close(sfd); // handle connection here close(csfd); } else perror("Accepting connection\n"); exit(0); } else if (child != -1) n_children++; else perror("Forking\n"); } else { if ((child_wait = wait (&rc)) != -1) n_children--; } } exit(0); }