static void* signal_thread(void* arg) { pthread_attr_t tattr; /* Used to set thread to detached mode */ int err; /* Indicates an error from sigwait */ int signo; /* The signal number that has been caught */ pthread_t tid; /* ID of the thread that has been spawnned */ // Make sure any threads that are spawned are detached, so the OS // can reclaim the resources in a timely fashion pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); for (;; ) { // Check directory for updates alarm(gperiod); // Block until signal has been caught err = sigwait(&mask, &signo); if (err != 0) { syslog(LOG_ERR, "sigwait failed"); exit(1); } switch (signo) { case SIGHUP: // Finish transfers, remove all clients syslog(LOG_INFO, "Received SIGHUP"); kill_clients(remove_client_pipes[1], "Server received SIGHUP; Disconnect all clients."); break; case SIGALRM: // See if directory has updated syslog(LOG_INFO, "Received SIGALRM"); pthread_create(&tid, &tattr, send_updates, NULL); break; case SIGINT: // Mainly used when not running in daemon mode syslog(LOG_INFO, "Received SIGINT"); kill_clients(remove_client_pipes[1], "Server received SIGINT; Disconnect all clients."); exit(0); case SIGTERM: syslog(LOG_INFO, "Received SIGTERM"); kill_clients(remove_client_pipes[1], "Server received SIGTERM; Disconnect all clients."); exit(0); default: syslog(LOG_ERR, "Unexpected signal: %d", signo); break; } } }
static void do_listen(char *port) { struct addrinfo hints; struct addrinfo *result, *rp; int sfd, s, cfd; struct sockaddr_storage peer_addr; socklen_t peer_addr_len; int pid; if (!debug) signal_setup(SIGCHLD, clean_up); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; s = getaddrinfo(NULL, port, &hints, &result); if (s != 0) pdie("getaddrinfo: error opening %s", port); for (rp = result; rp != NULL; rp = rp->ai_next) { sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sfd < 0) continue; if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) break; close(sfd); } if (rp == NULL) pdie("Could not bind"); freeaddrinfo(result); if (listen(sfd, backlog) < 0) pdie("listen"); peer_addr_len = sizeof(peer_addr); do { cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len); printf("connected!\n"); if (cfd < 0 && errno == EINTR) continue; if (cfd < 0) pdie("connecting"); pid = do_connection(cfd, &peer_addr, peer_addr_len); if (pid > 0) add_process(pid); } while (!done); kill_clients(); }
/* Handles the SIGINT, dispatching it to the clients */ static void sigint_signal_handler () { kill_clients(); wait(5); int i = 0; for(; i < MAX_CLIENTS; i++){ if(registered_clients[i] != 0){ int p_status; kill(registered_clients[i], SIGINT); waitpid(registered_clients[i], &p_status, WUNTRACED); /* Close message queue */ msgctl(client_msqid_from_pid(registered_clients[i]), IPC_RMID,0); } } fprintf(stdout, "[auctioneer] \x1b[31mQuitting... \x1b[0m \n"); fflush(stdout); _exit(EXIT_SUCCESS); }
int exploredir(struct direntrylist* list, const char* path) { struct stat fattr; /* Used to store attributes of a file entry */ struct direntry* list_entry; /* Used to capture information about file entry */ struct dirent** entries; /* Stores each file entry's name and stuff */ int n; /* How many file entries are in the directory */ int i; /* Used to traverse file entries */ // Alphabetize the entries in the directory since Linux is stupid // and doesn't do this by default, which Mac OS X does... if ((n = scandir(path, &entries, 0, alphasort)) < 0) { // Send error message to all clients and then exit kill_clients(remove_client_pipes[1], "Cannot open directory! ; Exiting now!"); syslog(LOG_ERR, "Cannot open directory: %s", path); exit(1); } // Delete reference to current directory (.) free(entries[0]); // Delete reference to parent directory (..) free(entries[1]); // Start after . and .. i = 2; while (i < n) { list_entry = (struct direntry*)mempool_alloc(direntry_pool, sizeof(struct direntry)); list_entry->next = NULL; memset(list_entry, 0, sizeof(list_entry)); if (list_entry == NULL) { // Mempool has no free nodes and malloc failed kill_clients(remove_client_pipes[1], "Unrecoverable server error! ; Exiting now!"); syslog(LOG_ERR, "Cannot malloc direntry"); exit(1); } // Make sure absolute path is not too long if ((strlen(path) + strlen(entries[i]->d_name) + 1) >= PATH_MAX) { kill_clients(remove_client_pipes[1], "Unrecoverable server error! ; Exiting now!"); syslog(LOG_ERR, "Path is too long."); exit(1); } else { strcpy(abspath, path); strcat(abspath, "/"); strcat(abspath, entries[i]->d_name); } // Get the attributes of the file entry if (stat(abspath, &fattr) < 0) { kill_clients(remove_client_pipes[1], "Unrecoverable server error! ; Exiting now!"); syslog(LOG_ERR, "Cannot get stats on file: %s", entries[i]->d_name); exit(1); } // Make sure just the file name is not too long if (strlen(entries[i]->d_name) > MAX_FILENAME) { syslog(LOG_ERR, "Filename is too long to be saved."); exit(1); } // Copy the file entry name into direntry representation strcpy(list_entry->filename, entries[i]->d_name); list_entry->attrs = fattr; // Add the list entry now add_direntry(list, list_entry); free(entries[i]); i++; } free(entries); return 0; }