static int mdns_external_avahi_register(char *apname, int port) { char mdns_port[6]; sprintf(mdns_port, "%d", config.port); char *argv[] = { NULL, apname, "_raop._tcp", mdns_port, MDNS_RECORD, NULL }; argv[0] = "avahi-publish-service"; int pid = fork_execvp(argv[0], argv); if (pid >= 0) { mdns_pid = pid; return 0; } else debug(1, "Calling %s failed, trying next method", argv[0]); argv[0] = "mDNSPublish"; pid = fork_execvp(argv[0], argv); if (pid >= 0) { mdns_pid = pid; return 0; } else warn("Calling %s failed !", argv[0]); // If we reach here, both execvp calls failed. return -1; }
static int mdns_external_dns_sd_register(char *apname, int port) { char mdns_port[6]; sprintf(mdns_port, "%d", config.port); char *argvwithoutmetadata[] = {NULL, apname, config.regtype, mdns_port, MDNS_RECORD_WITHOUT_METADATA, NULL}; #ifdef CONFIG_METADATA char *argvwithmetadata[] = {NULL, apname, config.regtype, mdns_port, MDNS_RECORD_WITH_METADATA, NULL}; #endif char **argv; #ifdef CONFIG_METADATA if (config.metadata_enabled) argv = argvwithmetadata; else #endif argv = argvwithoutmetadata; int pid = fork_execvp(argv[0], argv); if (pid >= 0) { mdns_pid = pid; return 0; } else warn("Calling %s failed !", argv[0]); return -1; }
static int mdns_external_avahi_register(char *apname, int port) { char mdns_port[6]; sprintf(mdns_port, "%d", config.port); char *argvwithoutmetadata[] = {NULL, apname, config.regtype, mdns_port, MDNS_RECORD_WITHOUT_METADATA, NULL}; #ifdef CONFIG_METADATA char *argvwithmetadata[] = {NULL, apname, config.regtype, mdns_port, MDNS_RECORD_WITH_METADATA, NULL}; #endif char **argv; #ifdef CONFIG_METADATA if (config.metadata_enabled) argv = argvwithmetadata; else #endif argv = argvwithoutmetadata; argv[0] = "avahi-publish-service"; int pid = fork_execvp(argv[0], argv); if (pid >= 0) { mdns_pid = pid; return 0; } else warn("Calling %s failed !", argv[0]); argv[0] = "mDNSPublish"; pid = fork_execvp(argv[0], argv); if (pid >= 0) { mdns_pid = pid; return 0; } else warn("Calling %s failed !", argv[0]); // If we reach here, both execvp calls failed. return -1; }
int fork_execlp(const char *file, ...) { const char *argv[1024]; unsigned int i; va_list args; va_start (args, file); i = 0; do argv[i] = va_arg (args, const char *); while (argv[i++] != NULL); va_end (args); return fork_execvp (file, (char **) argv); }
static int mdns_external_dns_sd_register(char *apname, int port) { char mdns_port[6]; sprintf(mdns_port, "%d", config.port); char *argv[] = {"dns-sd", "-R", apname, "_raop._tcp", ".", mdns_port, MDNS_RECORD, NULL}; int pid = fork_execvp(argv[0], argv); if (pid >= 0) { mdns_pid = pid; return 0; } else warn("Calling %s failed !", argv[0]); return -1; }
int run_receiver(UDR_Options * udr_options) { int orig_ppid = getppid(); UDT::startup(); addrinfo hints; addrinfo* res; set_verbosity(udr_options->verbose); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; char receiver_port[NI_MAXSERV]; UDTSOCKET serv; bool bad_port = false; for(int port_num = udr_options->start_port; port_num < udr_options->end_port; port_num++) { bad_port = false; snprintf(receiver_port, sizeof(receiver_port), "%d", port_num); if (0 != getaddrinfo(NULL, receiver_port, &hints, &res)) { bad_port = true; } else { serv = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (UDT::ERROR == UDT::bind(serv, res->ai_addr, res->ai_addrlen)) { bad_port = true; } } freeaddrinfo(res); if(!bad_port) break; } if(bad_port){ fprintf(stderr, "[udr receiver] ERROR: could not bind to any port in range %d - %d\n", udr_options->start_port, udr_options->end_port); return 0; } unsigned char rand_pp[PASSPHRASE_SIZE]; if (!RAND_bytes((unsigned char *) rand_pp, PASSPHRASE_SIZE)) { fprintf(stderr, "Couldn't generate random key: %ld\n", ERR_get_error()); exit(EXIT_FAILURE); } //stdout port number and password -- to send back to the client printf("%s ", receiver_port); for(int i = 0; i < PASSPHRASE_SIZE; i++) { printf("%02x", rand_pp[i]); } printf(" \n"); fflush(stdout); verbose_print("[udr receiver] server is ready at port %s\n", receiver_port); if (UDT::ERROR == UDT::listen(serv, 10)) { cerr << "[udr receiver] listen: " << UDT::getlasterror().getErrorMessage() << endl; return 0; } sockaddr_storage clientaddr; int addrlen = sizeof(clientaddr); UDTSOCKET recver; if (UDT::INVALID_SOCK == (recver = UDT::accept(serv, (sockaddr*)&clientaddr, &addrlen))) { fprintf(stderr, "[udr receiver] accept: %s\n", UDT::getlasterror().getErrorMessage()); return 0; } char clienthost[NI_MAXHOST]; char clientservice[NI_MAXSERV]; getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV); string cmd_str = udt_recv_string(recver); const char * cmd = cmd_str.c_str(); //perhaps want to at least check that starts with rsync? if(strncmp(cmd, "rsync ", 5) != 0){ exit(1); } char * rsync_cmd; if(udr_options->server_connect){ verbose_print("[udr receiver] server connect mode\n"); rsync_cmd = (char *)malloc(100); if(strlen(udr_options->server_config) > 0){ sprintf(rsync_cmd, "%s%s %s", "rsync --config=", udr_options->server_config, " --server --daemon ."); } else{ strcpy(rsync_cmd, "rsync --server --daemon ."); } } else{ rsync_cmd = (char *)malloc(strlen(cmd) + 1); strcpy(rsync_cmd, cmd); } verbose_print("[udr receiver] rsync cmd: %s\n", rsync_cmd); char ** sh_cmd = (char **)malloc(sizeof(char *) * 4); sh_cmd[0] = udr_options->shell_program; sh_cmd[1] = "-c"; sh_cmd[2] = rsync_cmd; sh_cmd[3] = NULL; //now fork and exec the rsync on the remote side using sh (so that wildcards will be expanded properly) int child_to_parent, parent_to_child; int rsync_pid = fork_execvp(udr_options->shell_program, sh_cmd, &parent_to_child, &child_to_parent); //now if we're in server mode need to drop privileges if specified if(udr_options->rsync_gid > 0){ setgid(udr_options->rsync_gid); } if(udr_options->rsync_uid > 0){ setuid(udr_options->rsync_uid); } verbose_print("[udr receiver] rsync pid: %d\n", rsync_pid); struct thread_data recv_to_udt; recv_to_udt.udt_socket = &recver; recv_to_udt.fd = child_to_parent; //stdout of rsync server process recv_to_udt.id = 2; recv_to_udt.is_complete = false; struct thread_data udt_to_recv; udt_to_recv.udt_socket = &recver; udt_to_recv.fd = parent_to_child; //stdin of rsync server process udt_to_recv.id = 3; udt_to_recv.is_complete = false; if(udr_options->encryption){ crypto encrypt(EVP_ENCRYPT, PASSPHRASE_SIZE, rand_pp, udr_options->encryption_type); crypto decrypt(EVP_DECRYPT, PASSPHRASE_SIZE, rand_pp, udr_options->encryption_type); recv_to_udt.crypt = &encrypt; udt_to_recv.crypt = &decrypt; } else{ recv_to_udt.crypt = NULL; udt_to_recv.crypt = NULL; } pthread_t recv_to_udt_thread; pthread_create(&recv_to_udt_thread, NULL, handle_to_udt, (void *)&recv_to_udt); pthread_t udt_to_recv_thread; pthread_create(&udt_to_recv_thread, NULL, udt_to_handle, (void*)&udt_to_recv); verbose_print("[udr receiver] waiting to join on recv_to_udt_thread\n"); verbose_print("[udr receiver] ppid %d pid %d\n", getppid(), getpid()); //going to poll if the ppid changes then we know it's exited and then we exit all of our threads and exit as well //also going to check if either thread is complete, if one is then the other should also be killed //bit of a hack to deal with the pthreads while(true){ if(getppid() != orig_ppid){ pthread_kill(recv_to_udt_thread, SIGUSR1); pthread_kill(udt_to_recv_thread, SIGUSR1); break; } if(recv_to_udt.is_complete && udt_to_recv.is_complete){ verbose_print("[udr receiver] both threads are complete: recv_to_udt.is_complete %d udt_to_recv.is_complete %d\n", recv_to_udt.is_complete, udt_to_recv.is_complete); break; } else if(recv_to_udt.is_complete){ verbose_print("[udr receiver] recv_to_udt is complete: recv_to_udt.is_complete %d udt_to_recv.is_complete %d\n", recv_to_udt.is_complete, udt_to_recv.is_complete); break; } else if(udt_to_recv.is_complete){ verbose_print("[udr receiver] udt_to_recv is complete: recv_to_udt.is_complete %d udt_to_recv.is_complete %d\n", recv_to_udt.is_complete, udt_to_recv.is_complete); break; } sleep(ppid_poll); } verbose_print("[udr receiver] Trying to close recver\n"); UDT::close(recver); verbose_print("[udr receiver] Closed recver\n"); UDT::close(serv); verbose_print("[udr receiver] Closed serv\n"); UDT::cleanup(); verbose_print("[udr receiver] UDT cleaned up\n"); return 0; }