static void start_one_job(const char *user, CronLine *line) { const char *shell; struct passwd *pas; pid_t pid; pas = getpwnam(user); if (!pas) { bb_error_msg("can't get uid for %s", user); goto err; } /* Prepare things before vfork */ shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL; set_env_vars(pas, shell); /* Fork as the user in question and run program */ pid = vfork(); if (pid == 0) { /* CHILD */ /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */ change_user(pas); log5("child running %s", shell); /* crond 3.0pl1-100 puts tasks in separate process groups */ bb_setpgrp(); execl(shell, shell, "-c", line->cl_cmd, (char *) NULL); bb_error_msg_and_die("can't execute '%s' for user %s", shell, user); } if (pid < 0) { bb_perror_msg("vfork"); err: pid = 0; } line->cl_pid = pid; }
void test_signal_task_group() { printf("\nTesting group signal_task\n"); fflush(stdout); fflush(stderr); pid_t child = fork(); if (child == -1) { printf("FAIL: fork failed\n"); exit(1); } else if (child == 0) { setpgrp(); if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { exit(1); } sleep(3600); exit(0); } printf("Child task launched as %d\n", child); if (signal_user_task(username, child, SIGKILL) != 0) { exit(1); } int status = 0; if (waitpid(child, &status, 0) == -1) { printf("FAIL: waitpid failed - %s\n", strerror(errno)); exit(1); } if (!WIFSIGNALED(status)) { printf("FAIL: child wasn't signalled - %d\n", status); exit(1); } if (WTERMSIG(status) != SIGKILL) { printf("FAIL: child was killed with %d instead of %d\n", WTERMSIG(status), SIGKILL); exit(1); } }
void test_signal_container() { printf("\nTesting signal_container\n"); fflush(stdout); fflush(stderr); pid_t child = fork(); if (child == -1) { printf("FAIL: fork failed\n"); exit(1); } else if (child == 0) { if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { exit(1); } sleep(3600); exit(0); } else { printf("Child container launched as %" PRId64 "\n", (int64_t)child); if (signal_container_as_user(yarn_username, child, SIGQUIT) != 0) { exit(1); } int status = 0; if (waitpid(child, &status, 0) == -1) { printf("FAIL: waitpid failed - %s\n", strerror(errno)); exit(1); } if (!WIFSIGNALED(status)) { printf("FAIL: child wasn't signalled - %d\n", status); exit(1); } if (WTERMSIG(status) != SIGQUIT) { printf("FAIL: child was killed with %d instead of %d\n", WTERMSIG(status), SIGQUIT); exit(1); } } }
/* * Function used to launch a task as the provided user. It does the following : * 1) Creates attempt work dir and log dir to be accessible by the child * 2) Copies the script file from the TT to the work directory * 3) Sets up the environment * 4) Does an execlp on the same in order to replace the current image with * task image. */ int run_task_as_user(const char *user, const char * good_local_dirs, const char *job_id, const char *task_id, const char *work_dir, const char *script_name) { int exit_code = -1; char *task_script_path = NULL; if (create_attempt_directories(user, good_local_dirs, job_id, task_id) != 0) { goto cleanup; } int task_file_source = open_file_as_task_tracker(script_name); if (task_file_source == -1) { goto cleanup; } task_script_path = get_task_launcher_file(work_dir); if (task_script_path == NULL) { exit_code = OUT_OF_MEMORY; goto cleanup; } if (copy_file(task_file_source, script_name,task_script_path,S_IRWXU) != 0) { goto cleanup; } //change the user // dlai blocked 12/29/2012 fcloseall(); // dlai added ditto fflush(stdin); fflush(stdout); fflush(stderr); fclose(stdin); fclose(stdout); fclose(stderr); umask(0027); if (chdir(work_dir) != 0) { fprintf(LOGFILE, "Can't change directory to %s -%s\n", work_dir, strerror(errno)); goto cleanup; } if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { exit_code = SETUID_OPER_FAILED; goto cleanup; } // dlai blocked `1/19/10`1 if (execlp(task_script_path, task_script_path, NULL) != 0) { if (execlp(task_script_path, task_script_path, (char*) 0) != 0) { fprintf(LOGFILE, "Couldn't execute the task jvm file %s - %s", task_script_path, strerror(errno)); exit_code = UNABLE_TO_EXECUTE_TASK_SCRIPT; goto cleanup; } exit_code = 0; cleanup: free(task_script_path); return exit_code; }
int kill_user_task(const char *user, const char *jobid, const char *taskid, const char *tt_root) { int pid = 0; int i = 0; char *pid_path = NULL; FILE *file_handle = NULL; #ifdef DEBUG fprintf(LOGFILE,"kill_user_task : Job id : %s \n", jobid); fprintf(LOGFILE,"kill_user_task : task id : %s \n", taskid); fprintf(LOGFILE,"kill_user_task : tt_root : %s \n", tt_root); fflush(LOGFILE); #endif if (check_tt_root(tt_root) < 0) { fprintf(LOGFILE, "invalid tt root specified"); cleanup(); return INVALID_TT_ROOT; } get_pid_path(jobid, taskid, tt_root, &pid_path); if (pid_path == NULL) { cleanup(); return INVALID_PID_PATH; } #ifdef DEBUG fprintf(LOGFILE,"kill_user_task : task-pid path :%s \n",pid_path); fflush(LOGFILE); #endif file_handle = fopen(pid_path, "r"); if (file_handle == NULL) { fprintf(LOGFILE, "unable to open task-pid file :%s \n", pid_path); free(pid_path); cleanup(); return UNABLE_TO_OPEN_PID_FILE_READ_MODE; } fscanf(file_handle, "%d", &pid); fclose(file_handle); free(pid_path); if (pid == 0) { fprintf(LOGFILE, "Unable to read task-pid from path: %s \n", pid_path); cleanup(); return UNABLE_TO_READ_PID; } if (change_user(user) != 0) { cleanup(); return SETUID_OPER_FAILED; } if (kill(pid, SIGTERM) < 0) { fprintf(LOGFILE, "%s\n", strerror(errno)); cleanup(); return UNABLE_TO_KILL_TASK; } cleanup(); return 0; }
/* * General server example: accept a client connection and do something. * This program just outputs a short HTML page, but can be easily adapted * to do other things. * * This server creates a constant number of processes ("virtual processors" * or VPs) and replaces them when they die. Each virtual processor manages * its own independent set of state threads (STs), the number of which varies * with load against the server. Each state thread listens to exactly one * listening socket. The initial process becomes the watchdog, waiting for * children (VPs) to die or for a signal requesting termination or restart. * Upon receiving a restart signal (SIGHUP), all VPs close and then reopen * log files and reload configuration. All currently active connections remain * active. It is assumed that new configuration affects only request * processing and not the general server parameters such as number of VPs, * thread limits, bind addresses, etc. Those are specified as command line * arguments, so the server has to be stopped and then started again in order * to change them. * * Each state thread loops processing connections from a single listening * socket. Only one ST runs on a VP at a time, and VPs do not share memory, * so no mutual exclusion locking is necessary on any data, and the entire * server is free to use all the static variables and non-reentrant library * functions it wants, greatly simplifying programming and debugging and * increasing performance (for example, it is safe to ++ and -- all global * counters or call inet_ntoa(3) without any mutexes). The current thread on * each VP maintains equilibrium on that VP, starting a new thread or * terminating itself if the number of spare threads exceeds the lower or * upper limit. * * All I/O operations on sockets must use the State Thread library's I/O * functions because only those functions prevent blocking of the entire VP * process and perform state thread scheduling. */ int main(int argc, char *argv[]) { /* Parse command-line options */ parse_arguments(argc, argv); /* Allocate array of server pids */ if ((vp_pids = calloc(vp_count, sizeof(pid_t))) == NULL) err_sys_quit(errfd, "ERROR: calloc failed"); /* Start the daemon */ if (!interactive_mode) start_daemon(); /* Initialize the ST library */ if (st_init() < 0) err_sys_quit(errfd, "ERROR: initialization failed: st_init"); /* Set thread throttling parameters */ set_thread_throttling(); /* Create listening sockets */ create_listeners(); /* Change the user */ if (username) change_user(); /* Open log files */ open_log_files(); /* Start server processes (VPs) */ start_processes(); /* Turn time caching on */ st_timecache_set(1); /* Install signal handlers */ install_sighandlers(); /* Load configuration from config files */ load_configs(); /* Start all threads */ start_threads(); /* Become a signal processing thread */ process_signals(NULL); /* NOTREACHED */ return 1; }
/** * run command as user */ int run_command_as_user(const char *user, char* const* args) { if (user == NULL) { fprintf(LOGFILE, "The user passed is null.\n"); return INVALID_ARGUMENT_NUMBER; } // give up root privs if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { return -1; } execvp(args[0], args); fprintf(LOGFILE, "Failure to exec command - %s\n", strerror(errno)); return -1; }
int main(int argc, char **argv){ // set up the logging stream if (!LOGFILE){ LOGFILE=stdout; } if (!ERRORFILE){ ERRORFILE=stderr; } if (argc < 3) { fprintf(ERRORFILE, "Requires at least 3 variables: ./execute-as-user uid command [args]"); return INVALID_INPUT; } char *uid = argv[1]; // gather information about user struct passwd *user_info = getpwnam(uid); if (user_info == NULL){ fprintf(LOGFILE, "user does not exist: %s", uid); return USER_NOT_FOUND; } // try to change user fprintf(LOGFILE, "Changing user: user: %s, uid: %d, gid: %d\n", uid, user_info->pw_uid, user_info->pw_gid); int retval = change_user(user_info->pw_uid, user_info->pw_gid); if (retval != 0){ fprintf(LOGFILE, "Error changing user to %s\n", uid); return SETUID_OPER_FAILED; } // execute the command char **user_argv = &argv[2]; fprintf(LOGFILE, "user command starting from: %s\n", user_argv[0]); fflush(LOGFILE); retval = execvp(*user_argv, user_argv); fprintf(LOGFILE, "system call return value: %d\n", retval); // sometimes system(cmd) returns 256, which is interpreted to 0, making a failed job a successful job // hence this goofy piece of if statement. if (retval != 0){ return 1; } else{ return 0; } }
static int c_init(void) { int r; /* TODO: configurable */ change_user("buxton"); r = direct_init(MODULE_DIR, confpath ? confpath : CONFPATH); if (r == -1) { bxt_err("Init: %s", strerror(errno)); return -1; } return 0; }
void engine_init (engine_t *E, const char *const pwd_filename, int index_mode) { E->sfd = 0; struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = sigusr1_handler; sigemptyset (&sa.sa_mask); sigaction (SIGUSR1, &sa, NULL); sa.sa_handler = sigrtmax_handler; sigaction (SIGRTMAX, &sa, NULL); if (!index_mode && port < PRIVILEGED_TCP_PORTS) { E->sfd = server_socket (port, E->settings_addr, backlog, 0); if (E->sfd < 0) { kprintf ("cannot open server socket at port %d: %m\n", port); exit (1); } } const int gap = 16; if (getuid ()) { struct rlimit rlim; if (getrlimit (RLIMIT_NOFILE, &rlim) < 0) { kprintf ("%s: getrlimit (RLIMIT_NOFILE) fail. %m\n", __func__); exit (1); } if (maxconn > rlim.rlim_cur - gap) { maxconn = rlim.rlim_cur - gap; } } else { if (raise_file_rlimit (maxconn + gap) < 0) { kprintf ("fatal: cannot raise open file limit to %d\n", maxconn + gap); exit (1); } } aes_load_pwd_file (pwd_filename); if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } init_dyn_data (); if (udp_enabled) { init_server_PID (get_my_ipv4 (), port); } }
int fork_as_user(const char * working_dir, const char * script_file) { char *script_file_dest = NULL; script_file_dest = get_container_launcher_file(working_dir); if (script_file_dest == NULL) { return OUT_OF_MEMORY; } // open launch script int script_file_source = open_file_as_wl(script_file); if (script_file_source == -1) { return -1; } setsid(); // give up root privs if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { return SETUID_OPER_FAILED; } if (copy_file(script_file_source, script_file, script_file_dest, S_IRWXU) != 0) { return -1; } fcloseall(); umask(0027); if (chdir(working_dir) != 0) { fprintf(LOGFILE, "Can't change directory to %s -%s\n", working_dir, strerror(errno)); return -1; } int pid = fork(); if (pid == 0 && execlp(script_file_dest, script_file_dest, NULL) != 0) { fprintf(LOGFILE, "Couldn't execute the container launch file %s - %s", script_file_dest, strerror(errno)); return UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; } else { fprintf(LOGFILE, "Launched the process from the container launch file %s - with pid %d", script_file_dest, pid); return 0; } //Unreachable return -1; }
int main (int argc, char *argv[]) { int i; while ((i = getopt (argc, argv, "1H:mtuv")) != -1) { switch (i) { case 'H': http_port = atoi (optarg); break; case 'm': memory_repairing = 1; break; case 't': test_mode = 1; break; case 'u': username = optarg; break; case 'v': verbosity++; break; case '1': exit_on_file_body_error = 0; break; } } if (argc < optind + 2) { usage (); return 1; } if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } if (memory_repairing) { if (storage_memory_repair (argv[optind], argv[optind+1]) < 0) { unlink (argv[optind+1]); return 1; } return 0; } storage_binlog_append (argv[optind], argv[optind+1]); return 0; }
int main (int argc, char *argv[]) { int i; set_debug_handlers (); progname = argv[0]; if (argc == 1) { usage(); return 2; } while ((i = getopt (argc, argv, "hu:")) != -1) { switch (i) { case 'h': usage (); return 2; case 'u': username = optarg; break; } } if (argc != optind + 2) { usage(); return 2; } if (change_user (username) < 0) { fprintf (stderr, "fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } init_files (3); open_file (0, argv[optind], 0); open_file (1, argv[optind + 1], 0); fd[2] = 1; run(); flush_w_buff(); fsync (fd[2]); // assert (fsync (fd[2]) >= 0); // fails when stdout is a pipe return 0; }
int signal_container_as_user(const char *user, int pid, int sig) { if(pid <= 0) { return INVALID_CONTAINER_PID; } if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { return SETUID_OPER_FAILED; } //Don't continue if the process-group is not alive anymore. int has_group = 1; if (kill(-pid,0) < 0) { if (kill(pid, 0) < 0) { if (errno == ESRCH) { return INVALID_CONTAINER_PID; } fprintf(LOGFILE, "Error signalling container %d with %d - %s\n", pid, sig, strerror(errno)); return -1; } else { has_group = 0; } } if (kill((has_group ? -1 : 1) * pid, sig) < 0) { if(errno != ESRCH) { fprintf(LOGFILE, "Error signalling process group %d with signal %d - %s\n", -pid, sig, strerror(errno)); fprintf(stderr, "Error signalling process group %d with signal %d - %s\n", -pid, sig, strerror(errno)); fflush(LOGFILE); return UNABLE_TO_SIGNAL_CONTAINER; } else { return INVALID_CONTAINER_PID; } } fprintf(LOGFILE, "Killing process %s%d with %d\n", (has_group ? "group " :""), pid, sig); return 0; }
void test_signal_container_group() { printf("\nTesting group signal_container\n"); fflush(stdout); fflush(stderr); pid_t child = fork(); if (child == -1) { printf("FAIL: fork failed\n"); exit(1); } else if (child == 0) { setpgid(0,0); if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { exit(1); } sleep(3600); exit(0); } printf("Child container launched as %" PRId64 "\n", (int64_t)child); // there's a race condition for child calling change_user and us // calling signal_container_as_user, hence sleeping sleep(3); if (signal_container_as_user(yarn_username, child, SIGKILL) != 0) { exit(1); } int status = 0; if (waitpid(child, &status, 0) == -1) { printf("FAIL: waitpid failed - %s\n", strerror(errno)); exit(1); } if (!WIFSIGNALED(status)) { printf("FAIL: child wasn't signalled - %d\n", status); exit(1); } if (WTERMSIG(status) != SIGKILL) { printf("FAIL: child was killed with %d instead of %d\n", WTERMSIG(status), SIGKILL); exit(1); } }
static void edit_file(const struct passwd *pas, const char *file) { const char *ptr; int pid = vfork(); if (pid < 0) /* failure */ bb_perror_msg_and_die("vfork"); if (pid) { /* parent */ wait4pid(pid); return; } /* CHILD - change user and run editor */ change_user(pas); ptr = getenv("VISUAL"); if (!ptr) { ptr = getenv("EDITOR"); if (!ptr) ptr = "vi"; } BB_EXECLP(ptr, ptr, file, NULL); bb_perror_msg_and_die("exec %s", ptr); }
int launch_container_as_user(const char *user, const char *app_id, const char *container_id, const char *work_dir, const char *script_name, const char *cred_file, const char* pid_file, char* const* local_dirs, char* const* log_dirs, const char *resources_key, char* const* resources_values) { int exit_code = -1; char *script_file_dest = NULL; char *cred_file_dest = NULL; char *exit_code_file = NULL; script_file_dest = get_container_launcher_file(work_dir); if (script_file_dest == NULL) { exit_code = OUT_OF_MEMORY; goto cleanup; } cred_file_dest = get_container_credentials_file(work_dir); if (NULL == cred_file_dest) { exit_code = OUT_OF_MEMORY; goto cleanup; } exit_code_file = get_exit_code_file(pid_file); if (NULL == exit_code_file) { exit_code = OUT_OF_MEMORY; goto cleanup; } // open launch script int container_file_source = open_file_as_nm(script_name); if (container_file_source == -1) { goto cleanup; } // open credentials int cred_file_source = open_file_as_nm(cred_file); if (cred_file_source == -1) { goto cleanup; } pid_t child_pid = fork(); if (child_pid != 0) { // parent exit_code = wait_and_write_exit_code(child_pid, exit_code_file); goto cleanup; } // setsid pid_t pid = setsid(); if (pid == -1) { exit_code = SETSID_OPER_FAILED; goto cleanup; } // write pid to pidfile if (pid_file == NULL || write_pid_to_file_as_nm(pid_file, pid) != 0) { exit_code = WRITE_PIDFILE_FAILED; goto cleanup; } // cgroups-based resource enforcement if (resources_key != NULL && ! strcmp(resources_key, "cgroups")) { // write pid to cgroups char* const* cgroup_ptr; for (cgroup_ptr = resources_values; cgroup_ptr != NULL && *cgroup_ptr != NULL; ++cgroup_ptr) { if (strcmp(*cgroup_ptr, "none") != 0 && write_pid_to_cgroup_as_root(*cgroup_ptr, pid) != 0) { exit_code = WRITE_CGROUP_FAILED; goto cleanup; } } } // create the user directory on all disks int result = initialize_user(user, local_dirs); if (result != 0) { return result; } // initializing log dirs int log_create_result = create_log_dirs(app_id, log_dirs); if (log_create_result != 0) { return log_create_result; } // give up root privs if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { exit_code = SETUID_OPER_FAILED; goto cleanup; } // Create container specific directories as user. If there are no resources // to localize for this container, app-directories and log-directories are // also created automatically as part of this call. if (create_container_directories(user, app_id, container_id, local_dirs, log_dirs, work_dir) != 0) { fprintf(LOGFILE, "Could not create container dirs"); goto cleanup; } // 700 if (copy_file(container_file_source, script_name, script_file_dest,S_IRWXU) != 0) { goto cleanup; } // 600 if (copy_file(cred_file_source, cred_file, cred_file_dest, S_IRUSR | S_IWUSR) != 0) { goto cleanup; } #if HAVE_FCLOSEALL fcloseall(); #else // only those fds are opened assuming no bug fclose(LOGFILE); fclose(ERRORFILE); fclose(stdin); fclose(stdout); fclose(stderr); #endif umask(0027); if (chdir(work_dir) != 0) { fprintf(LOGFILE, "Can't change directory to %s -%s\n", work_dir, strerror(errno)); goto cleanup; } if (execlp(script_file_dest, script_file_dest, NULL) != 0) { fprintf(LOGFILE, "Couldn't execute the container launch file %s - %s", script_file_dest, strerror(errno)); exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; goto cleanup; } exit_code = 0; cleanup: free(exit_code_file); free(script_file_dest); free(cred_file_dest); return exit_code; }
/** * Function to prepare the job directories for the task JVM. */ int initialize_job(const char *user, const char *jobid, const char* credentials, const char* job_xml, char* const* args) { if (jobid == NULL || user == NULL) { fprintf(LOGFILE, "Either jobid is null or the user passed is null.\n"); return INVALID_ARGUMENT_NUMBER; } // create the user directory int result = initialize_user(user); if (result != 0) { return result; } // create the log directory for the job char *job_log_dir = get_job_log_directory(jobid); if (job_log_dir == NULL) { return -1; } result = create_directory_for_user(job_log_dir); free(job_log_dir); if (result != 0) { return -1; } // open up the credentials file int cred_file = open_file_as_task_tracker(credentials); if (cred_file == -1) { return -1; } int job_file = open_file_as_task_tracker(job_xml); if (job_file == -1) { return -1; } // give up root privs if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { return -1; } // 750 mode_t permissions = S_IRWXU | S_IRGRP | S_IXGRP; char **tt_roots = get_values(TT_SYS_DIR_KEY); if (tt_roots == NULL) { return INVALID_CONFIG_FILE; } char **tt_root; char *primary_job_dir = NULL; for(tt_root=tt_roots; *tt_root != NULL; ++tt_root) { char *job_dir = get_job_directory(*tt_root, user, jobid); if (job_dir == NULL) { // try the next one } else if (mkdirs(job_dir, permissions) != 0) { free(job_dir); } else if (primary_job_dir == NULL) { primary_job_dir = job_dir; } else { free(job_dir); } } free_values(tt_roots); if (primary_job_dir == NULL) { fprintf(LOGFILE, "Did not create any job directories\n"); return -1; } char *cred_file_name = concatenate("%s/%s", "cred file", 2, primary_job_dir, CREDENTIALS_FILENAME); if (cred_file_name == NULL) { return -1; } if (copy_file(cred_file, credentials, cred_file_name, S_IRUSR|S_IWUSR) != 0){ return -1; } char *job_file_name = concatenate("%s/%s", "job file", 2, primary_job_dir, JOB_FILENAME); if (job_file_name == NULL) { return -1; } if (copy_file(job_file, job_xml, job_file_name, S_IRUSR|S_IWUSR|S_IRGRP) != 0) { return -1; } fclose(stdin); fflush(LOGFILE); if (LOGFILE != stdout) { fclose(stdout); } fclose(stderr); if (chdir(primary_job_dir)) { fprintf(LOGFILE, "Failure to chdir to job dir - %s\n", strerror(errno)); return -1; } execvp(args[0], args); fprintf(LOGFILE, "Failure to exec job initialization process - %s\n", strerror(errno)); return -1; }
int main(int argc, char *argv[]) { pa_core *c = NULL; pa_strbuf *buf = NULL; pa_daemon_conf *conf = NULL; pa_mainloop *mainloop = NULL; char *s; char *configured_address; int r = 0, retval = 1, d = 0; pa_bool_t valid_pid_file = FALSE; pa_bool_t ltdl_init = FALSE; int passed_fd = -1; const char *e; #ifdef HAVE_FORK int daemon_pipe[2] = { -1, -1 }; int daemon_pipe2[2] = { -1, -1 }; #endif #ifdef OS_IS_WIN32 pa_time_event *win32_timer; struct timeval win32_tv; #endif int autospawn_fd = -1; pa_bool_t autospawn_locked = FALSE; #ifdef HAVE_DBUS pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */ pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */ pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */ pa_bool_t start_server; #endif pa_log_set_ident("pulseaudio"); pa_log_set_level(PA_LOG_NOTICE); pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET); #if defined(__linux__) && defined(__OPTIMIZE__) /* Disable lazy relocations to make usage of external libraries more deterministic for our RT threads. We abuse __OPTIMIZE__ as a check whether we are a debug build or not. This all is admittedly a bit snake-oilish. */ if (!getenv("LD_BIND_NOW")) { char *rp; char *canonical_rp; /* We have to execute ourselves, because the libc caches the * value of $LD_BIND_NOW on initialization. */ pa_set_env("LD_BIND_NOW", "1"); if ((canonical_rp = pa_realpath(PA_BINARY))) { if ((rp = pa_readlink("/proc/self/exe"))) { if (pa_streq(rp, canonical_rp)) pa_assert_se(execv(rp, argv) == 0); else pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); pa_xfree(rp); } else pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); pa_xfree(canonical_rp); } else pa_log_warn("Couldn't canonicalize binary path, cannot self execute."); } #endif if ((e = getenv("PULSE_PASSED_FD"))) { passed_fd = atoi(e); if (passed_fd <= 2) passed_fd = -1; } /* We might be autospawned, in which case have no idea in which * context we have been started. Let's cleanup our execution * context as good as possible */ pa_reset_personality(); pa_drop_root(); pa_close_all(passed_fd, -1); pa_reset_sigs(-1); pa_unblock_sigs(-1); pa_reset_priority(); setlocale(LC_ALL, ""); pa_init_i18n(); conf = pa_daemon_conf_new(); if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; if (pa_daemon_conf_env(conf) < 0) goto finish; if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { pa_log(_("Failed to parse command line.")); goto finish; } pa_log_set_level(conf->log_level); pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target); if (conf->log_meta) pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET); if (conf->log_time) pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET); pa_log_set_show_backtrace(conf->log_backtrace); #ifdef HAVE_DBUS /* conf->system_instance and conf->local_server_type control almost the * same thing; make them agree about what is requested. */ switch (conf->local_server_type) { case PA_SERVER_TYPE_UNSET: conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER; break; case PA_SERVER_TYPE_USER: case PA_SERVER_TYPE_NONE: conf->system_instance = FALSE; break; case PA_SERVER_TYPE_SYSTEM: conf->system_instance = TRUE; break; default: pa_assert_not_reached(); } start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM); if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) { pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service.")); conf->system_instance = FALSE; } #endif LTDL_SET_PRELOADED_SYMBOLS(); pa_ltdl_init(); ltdl_init = TRUE; if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); #ifdef OS_IS_WIN32 { WSADATA data; WSAStartup(MAKEWORD(2, 0), &data); } #endif pa_random_seed(); switch (conf->cmd) { case PA_CMD_DUMP_MODULES: pa_dump_modules(conf, argc-d, argv+d); retval = 0; goto finish; case PA_CMD_DUMP_CONF: { if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } s = pa_daemon_conf_dump(conf); fputs(s, stdout); pa_xfree(s); retval = 0; goto finish; } case PA_CMD_DUMP_RESAMPLE_METHODS: { int i; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } for (i = 0; i < PA_RESAMPLER_MAX; i++) if (pa_resample_method_supported(i)) printf("%s\n", pa_resample_method_to_string(i)); retval = 0; goto finish; } case PA_CMD_HELP : pa_cmdline_help(argv[0]); retval = 0; goto finish; case PA_CMD_VERSION : if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); retval = 0; goto finish; case PA_CMD_CHECK: { pid_t pid; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) pa_log_info(_("Daemon not running")); else { pa_log_info(_("Daemon running as PID %u"), pid); retval = 0; } goto finish; } case PA_CMD_KILL: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0) pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno)); else retval = 0; goto finish; case PA_CMD_CLEANUP_SHM: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_shm_cleanup() >= 0) retval = 0; goto finish; default: pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START); } if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } #ifdef HAVE_GETUID if (getuid() == 0 && !conf->system_instance) pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); #ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */ else if (getuid() != 0 && conf->system_instance) { pa_log(_("Root privileges required.")); goto finish; } #endif #endif /* HAVE_GETUID */ if (conf->cmd == PA_CMD_START && conf->system_instance) { pa_log(_("--start not supported for system instances.")); goto finish; } if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) { /* There is an server address in our config, but where did it come from? * By default a standard X11 login will load module-x11-publish which will * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end * up hitting this code path. So we have to check to see if our configured_address * is the same as the value that would go into this property so that we can * recover (i.e. autospawn) from a crash. */ char *ufn; pa_bool_t start_anyway = FALSE; if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { char *id; if ((id = pa_machine_id())) { pa_strlist *server_list; char formatted_ufn[256]; pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn); pa_xfree(id); if ((server_list = pa_strlist_parse(configured_address))) { char *u = NULL; /* We only need to check the first server */ server_list = pa_strlist_pop(server_list, &u); pa_strlist_free(server_list); start_anyway = (u && pa_streq(formatted_ufn, u)); pa_xfree(u); } } pa_xfree(ufn); } if (!start_anyway) { pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address); pa_xfree(configured_address); retval = 0; goto finish; } pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address); pa_xfree(configured_address); } if (conf->system_instance && !conf->disallow_exit) pa_log_warn(_("Running in system mode, but --disallow-exit not set!")); if (conf->system_instance && !conf->disallow_module_loading) pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!")); if (conf->system_instance && !conf->disable_shm) { pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!")); conf->disable_shm = TRUE; } if (conf->system_instance && conf->exit_idle_time >= 0) { pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!")); conf->exit_idle_time = -1; } if (conf->cmd == PA_CMD_START) { /* If we shall start PA only when it is not running yet, we * first take the autospawn lock to make things * synchronous. */ if ((autospawn_fd = pa_autospawn_lock_init()) < 0) { pa_log("Failed to initialize autospawn lock"); goto finish; } if ((pa_autospawn_lock_acquire(TRUE) < 0)) { pa_log("Failed to acquire autospawn lock"); goto finish; } autospawn_locked = TRUE; } if (conf->daemonize) { #ifdef HAVE_FORK pid_t child; #endif if (pa_stdio_acquire() < 0) { pa_log(_("Failed to acquire stdio.")); goto finish; } #ifdef HAVE_FORK if (pipe(daemon_pipe) < 0) { pa_log(_("pipe() failed: %s"), pa_cstrerror(errno)); goto finish; } if ((child = fork()) < 0) { pa_log(_("fork() failed: %s"), pa_cstrerror(errno)); pa_close_pipe(daemon_pipe); goto finish; } if (child != 0) { ssize_t n; /* Father */ pa_assert_se(pa_close(daemon_pipe[1]) == 0); daemon_pipe[1] = -1; if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) { if (n < 0) pa_log(_("read() failed: %s"), pa_cstrerror(errno)); retval = 1; } if (retval) pa_log(_("Daemon startup failed.")); else pa_log_info(_("Daemon startup successful.")); goto finish; } if (autospawn_fd >= 0) { /* The lock file is unlocked from the parent, so we need * to close it in the child */ pa_autospawn_lock_release(); pa_autospawn_lock_done(TRUE); autospawn_locked = FALSE; autospawn_fd = -1; } pa_assert_se(pa_close(daemon_pipe[0]) == 0); daemon_pipe[0] = -1; #endif if (conf->auto_log_target) pa_log_set_target(PA_LOG_SYSLOG); #ifdef HAVE_SETSID if (setsid() < 0) { pa_log(_("setsid() failed: %s"), pa_cstrerror(errno)); goto finish; } #endif #ifdef HAVE_FORK /* We now are a session and process group leader. Let's fork * again and let the father die, so that we'll become a * process that can never acquire a TTY again, in a session and * process group without leader */ if (pipe(daemon_pipe2) < 0) { pa_log(_("pipe() failed: %s"), pa_cstrerror(errno)); goto finish; } if ((child = fork()) < 0) { pa_log(_("fork() failed: %s"), pa_cstrerror(errno)); pa_close_pipe(daemon_pipe2); goto finish; } if (child != 0) { ssize_t n; /* Father */ pa_assert_se(pa_close(daemon_pipe2[1]) == 0); daemon_pipe2[1] = -1; if ((n = pa_loop_read(daemon_pipe2[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) { if (n < 0) pa_log(_("read() failed: %s"), pa_cstrerror(errno)); retval = 1; } /* We now have to take care of signalling the first fork with * the return value we've received from this fork... */ pa_assert(daemon_pipe[1] >= 0); pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); pa_close(daemon_pipe[1]); daemon_pipe[1] = -1; goto finish; } pa_assert_se(pa_close(daemon_pipe2[0]) == 0); daemon_pipe2[0] = -1; /* We no longer need the (first) daemon_pipe as it's handled in our child above */ pa_close_pipe(daemon_pipe); #endif #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif pa_nullify_stdfds(); } pa_set_env_and_record("PULSE_INTERNAL", "1"); pa_assert_se(chdir("/") == 0); umask(0022); #ifdef HAVE_SYS_RESOURCE_H set_all_rlimits(conf); #endif pa_rtclock_hrtimer_enable(); pa_raise_priority(conf->nice_level); if (conf->system_instance) if (change_user() < 0) goto finish; pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0"); pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION); pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST); pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS); s = pa_uname_string(); pa_log_debug(_("Running on host: %s"), s); pa_xfree(s); pa_log_debug(_("Found %u CPUs."), pa_ncpus()); pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE); #ifdef HAVE_VALGRIND_MEMCHECK_H pa_log_debug(_("Compiled with Valgrind support: yes")); #else pa_log_debug(_("Compiled with Valgrind support: no")); #endif pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind())); pa_log_debug(_("Running in VM: %s"), pa_yes_no(pa_running_in_vm())); #ifdef __OPTIMIZE__ pa_log_debug(_("Optimized build: yes")); #else pa_log_debug(_("Optimized build: no")); #endif #ifdef NDEBUG pa_log_debug(_("NDEBUG defined, all asserts disabled.")); #elif defined(FASTPATH) pa_log_debug(_("FASTPATH defined, only fast path asserts disabled.")); #else pa_log_debug(_("All asserts enabled.")); #endif if (!(s = pa_machine_id())) { pa_log(_("Failed to get machine ID")); goto finish; } pa_log_info(_("Machine ID is %s."), s); pa_xfree(s); if ((s = pa_session_id())) { pa_log_info(_("Session ID is %s."), s); pa_xfree(s); } if (!(s = pa_get_runtime_dir())) goto finish; pa_log_info(_("Using runtime directory %s."), s); pa_xfree(s); if (!(s = pa_get_state_dir())) goto finish; pa_log_info(_("Using state directory %s."), s); pa_xfree(s); pa_log_info(_("Using modules directory %s."), conf->dl_search_path); pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode())); if (pa_in_system_mode()) pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n" "If you do it nonetheless then it's your own fault if things don't work as expected.\n" "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea.")); if (conf->use_pid_file) { int z; if ((z = pa_pid_file_create("pulseaudio")) != 0) { if (conf->cmd == PA_CMD_START && z > 0) { /* If we are already running and with are run in * --start mode, then let's return this as success. */ retval = 0; goto finish; } pa_log(_("pa_pid_file_create() failed.")); goto finish; } valid_pid_file = TRUE; } pa_disable_sigpipe(); if (pa_rtclock_hrtimer()) pa_log_info(_("Fresh high-resolution timers available! Bon appetit!")); else pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!")); if (conf->lock_memory) { #ifdef HAVE_SYS_MMAN_H if (mlockall(MCL_FUTURE) < 0) pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno)); else pa_log_info("Successfully locked process into memory."); #else pa_log_warn("Memory locking requested but not supported on platform."); #endif } pa_memtrap_install(); pa_assert_se(mainloop = pa_mainloop_new()); if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) { pa_log(_("pa_core_new() failed.")); goto finish; } c->default_sample_spec = conf->default_sample_spec; c->alternate_sample_rate = conf->alternate_sample_rate; c->default_channel_map = conf->default_channel_map; c->default_n_fragments = conf->default_n_fragments; c->default_fragment_size_msec = conf->default_fragment_size_msec; c->deferred_volume_safety_margin_usec = conf->deferred_volume_safety_margin_usec; c->deferred_volume_extra_delay_usec = conf->deferred_volume_extra_delay_usec; c->exit_idle_time = conf->exit_idle_time; c->scache_idle_time = conf->scache_idle_time; c->resample_method = conf->resample_method; c->realtime_priority = conf->realtime_priority; c->realtime_scheduling = !!conf->realtime_scheduling; c->disable_remixing = !!conf->disable_remixing; c->disable_lfe_remixing = !!conf->disable_lfe_remixing; c->deferred_volume = !!conf->deferred_volume; c->running_as_daemon = !!conf->daemonize; c->disallow_exit = conf->disallow_exit; c->flat_volumes = conf->flat_volumes; #ifdef HAVE_DBUS c->server_type = conf->local_server_type; #endif c->cpu_info.cpu_type = PA_CPU_UNDEFINED; if (!getenv("PULSE_NO_SIMD")) { if (pa_cpu_init_x86(&(c->cpu_info.flags.x86))) c->cpu_info.cpu_type = PA_CPU_X86; if (pa_cpu_init_arm(&(c->cpu_info.flags.arm))) c->cpu_info.cpu_type = PA_CPU_ARM; pa_cpu_init_orc(c->cpu_info); } pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); pa_signal_new(SIGTERM, signal_callback, c); #ifdef SIGUSR1 pa_signal_new(SIGUSR1, signal_callback, c); #endif #ifdef SIGUSR2 pa_signal_new(SIGUSR2, signal_callback, c); #endif #ifdef SIGHUP pa_signal_new(SIGHUP, signal_callback, c); #endif #ifdef OS_IS_WIN32 win32_timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL); #endif if (!conf->no_cpu_limit) pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0); buf = pa_strbuf_new(); #ifdef HAVE_DBUS pa_assert_se(dbus_threads_init_default()); if (start_server) { #endif if (conf->load_default_script_file) { FILE *f; if ((f = pa_daemon_conf_open_default_script_file(conf))) { r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); fclose(f); } } if (r >= 0) r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); pa_xfree(s); if (r < 0 && conf->fail) { pa_log(_("Failed to initialize daemon.")); goto finish; } if (!c->modules || pa_idxset_size(c->modules) == 0) { pa_log(_("Daemon startup without any loaded modules, refusing to work.")); goto finish; } #ifdef HAVE_DBUS } else { /* When we just provide the D-Bus server lookup service, we don't want * any modules to be loaded. We haven't loaded any so far, so one might * think there's no way to contact the server, but receiving certain * signals could still cause modules to load. */ conf->disallow_module_loading = TRUE; } #endif /* We completed the initial module loading, so let's disable it * from now on, if requested */ c->disallow_module_loading = !!conf->disallow_module_loading; #ifdef HAVE_DBUS if (!conf->system_instance) { if ((server_lookup = pa_dbusobj_server_lookup_new(c))) { if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.PulseAudio1"))) goto finish; } } if (start_server) server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server"); #endif #ifdef HAVE_FORK if (daemon_pipe2[1] >= 0) { int ok = 0; pa_loop_write(daemon_pipe2[1], &ok, sizeof(ok), NULL); pa_close(daemon_pipe2[1]); daemon_pipe2[1] = -1; } #endif pa_log_info(_("Daemon startup complete.")); retval = 0; if (pa_mainloop_run(mainloop, &retval) < 0) goto finish; pa_log_info(_("Daemon shutdown initiated.")); finish: #ifdef HAVE_DBUS if (server_bus) pa_dbus_connection_unref(server_bus); if (lookup_service_bus) pa_dbus_connection_unref(lookup_service_bus); if (server_lookup) pa_dbusobj_server_lookup_free(server_lookup); #endif if (autospawn_fd >= 0) { if (autospawn_locked) pa_autospawn_lock_release(); pa_autospawn_lock_done(FALSE); } #ifdef OS_IS_WIN32 if (mainloop && win32_timer) pa_mainloop_get_api(mainloop)->time_free(win32_timer); #endif if (c) { /* Ensure all the modules/samples are unloaded when the core is still ref'ed, * as unlink callback hooks in modules may need the core to be ref'ed */ pa_module_unload_all(c); pa_scache_free_all(c); pa_core_unref(c); pa_log_info(_("Daemon terminated.")); } if (!conf->no_cpu_limit) pa_cpu_limit_done(); pa_signal_done(); #ifdef HAVE_FORK /* If we have daemon_pipe[1] still open, this means we've failed after * the first fork, but before the second. Therefore just write to it. */ if (daemon_pipe[1] >= 0) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); else if (daemon_pipe2[1] >= 0) pa_loop_write(daemon_pipe2[1], &retval, sizeof(retval), NULL); pa_close_pipe(daemon_pipe2); pa_close_pipe(daemon_pipe); #endif if (mainloop) pa_mainloop_free(mainloop); if (conf) pa_daemon_conf_free(conf); if (valid_pid_file) pa_pid_file_remove(); /* This has no real purpose except making things valgrind-clean */ pa_unset_env_recorded(); #ifdef OS_IS_WIN32 WSACleanup(); #endif if (ltdl_init) pa_ltdl_done(); #ifdef HAVE_DBUS dbus_shutdown(); #endif return retval; }
int main (int argc, char *argv[]) { int i; set_debug_handlers (); while ((i = getopt (argc, argv, "vrb:u:a:l:")) != -1) { switch (i) { case 'v': verbosity++; break; case 'r': read_only = 1; break; case 'h': usage(); return 2; case 'b': backlog = atoi(optarg); if (backlog <= 0) backlog = BACKLOG; break; case 'u': username = optarg; break; case 'a': binlogname = optarg; break; case 'l': logname = optarg; break; } } if (argc != optind + 1 && argc != optind + 2) { usage(); return 2; } if (change_user (username) < 0) { fprintf (stderr, "fatal: cannot change user to %s\n", username ? username : "******"); exit(1); } init_dyn_data (); if (engine_preload_filelist (argv[optind], binlogname) < 0) { fprintf (stderr, "cannot open binlog files for %s\n", binlogname ? binlogname : argv[optind]); exit (1); } Snapshot = open_recent_snapshot (engine_snapshot_replica); if (!Snapshot) { fprintf (stderr, "No snapshots found. Nothing to do\n"); return 0; } else { int t[5]; assert (read (Snapshot->fd, t, 20) == 20); if (t[0] != RPC_PROXY_INDEX_MAGIC) { fprintf (stderr, "Snapshot is not from rpc-proxy\n"); return 1; } long long binlog_pos = *(long long *)(t + 1); if (verbosity > 0) { fprintf (stderr, "log_pos = %lld\n", binlog_pos); } for (i = 0; i < engine_replica->binlog_num - 1; i++) { struct kfs_file_info *FI = engine_replica->binlogs[i]; int fd = preload_file_info (FI); assert (fd >= 0); if (FI->log_pos + FI->file_size <= binlog_pos) { if (read_only) { fprintf (stderr, "Would delete file %s\n", engine_replica->binlogs[i]->filename); } else { if (verbosity > 0) { fprintf (stderr, "Deleting file %s\n", engine_replica->binlogs[i]->filename); } int r = unlink (engine_replica->binlogs[i]->filename); if (r < 0) { fprintf (stderr, "Error deleting file %s: %m\n", engine_replica->binlogs[i]->filename); } } } if (fd >= 0) { close (fd); } } return 0; } }
int main (int argc, char *argv[]) { int i; progname = argv[0]; while ((i = getopt (argc, argv, "hvu:m:s:t:p")) != -1) { switch (i) { case 'p': fits = positive_counter_fits; break; case 'v': verbosity = 1; break; case 'h': usage(); return 2; case 'u': username = optarg; break; case 'm': if (sscanf (optarg, "%d,%d", ©_rem, ©_mod) != 2 || copy_rem < 0 || copy_rem >= copy_mod) { usage(); return 2; } break; case 's': jump_log_pos = atoll (optarg); break; case 't': log_limit_pos = atoll (optarg); break; } } if (copy_mod < 0) { usage (); return 2; } if (optind >= argc || optind + 2 < argc) { usage(); return 2; } if (log_limit_pos >= 0) { if (jump_log_pos > log_limit_pos) { fprintf (stderr, "fatal: log start position %lld after stop position %lld\n", jump_log_pos, log_limit_pos); return 2; } } if (username && change_user (username) < 0) { fprintf (stderr, "fatal: cannot change user to %s\n", username ? username : "******"); return 1; } if (engine_preload_filelist (argv[optind], binlogname) < 0) { fprintf (stderr, "cannot open binlog files for %s\n", binlogname ? binlogname : argv[optind]); exit (1); } Binlog = open_binlog (engine_replica, jump_log_pos); if (!Binlog) { fprintf (stderr, "fatal: cannot find binlog for %s, log position %lld\n", engine_replica->replica_prefix, 0LL); exit (1); } binlogname = Binlog->info->filename; if (verbosity) { fprintf (stderr, "replaying binlog file %s (size %lld)\n", binlogname, Binlog->info->file_size); } clear_log(); init_log_data (jump_log_pos, 0, 0); if (jump_log_pos > 0) { init_stats_data (0); } if (optind + 1 < argc) { targ_fname = argv[optind+1]; targ_fd = open (targ_fname, O_WRONLY | O_APPEND | O_CREAT, 0644); if (targ_fd < 0) { fprintf (stderr, "cannot create %s: %m\n", targ_fname); return 1; } targ_orig_size = lseek (targ_fd, 0, SEEK_END); targ_existed = (targ_orig_size > 0); } else { targ_fname = "stdout"; targ_fd = 1; } i = replay_log (0, 1); if (i < 0) { fprintf (stderr, "fatal: error reading binlog\n"); exit (1); } if (log_limit_pos >= 0 && log_readto_pos != log_limit_pos) { fprintf (stderr, "fatal: binlog read up to position %lld instead of %lld\n", log_readto_pos, log_limit_pos); exit (1); } flush_out (); if (targ_fd != 1) { if (fdatasync (targ_fd) < 0) { fprintf (stderr, "error syncing %s: %m", targ_fname); exit (1); } close (targ_fd); } if (verbosity > 0) { output_stats (); } return 0; }
void server_init (engine_t *E, server_functions_t *F, conn_type_t *listen_connection_type, void *listen_connection_extra) { if (F != NULL) { if (F->sighup) { sf.sighup = F->sighup; } if (F->sigusr1) { sf.sigusr1 = F->sigusr1; } if (F->save_index) { sf.save_index = F->save_index; } if (F->cron) { sf.cron = F->cron; } } init_epoll (); init_netbuffers (); if (udp_enabled) { init_msg_buffers (0); } if (daemonize) { setsid (); reopen_logs (); } if (!E->sfd) { E->sfd = server_socket (port, E->settings_addr, backlog, 0); } if (E->sfd < 0) { kprintf ("cannot open server socket at port %d: %m\n", port); exit (1); } if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } if (binlogname && !binlog_disabled) { assert (append_to_binlog (Binlog) == log_readto_pos); } init_listening_connection (E->sfd, listen_connection_type, listen_connection_extra); if (udp_enabled) { add_udp_socket (port, 0); } if (binlog_disabled && binlog_fd >= 0) { epoll_pre_event = read_new_events; } struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = sigint_handler; sigemptyset (&sa.sa_mask); sigaddset (&sa.sa_mask, SIGTERM); sigaction (SIGINT, &sa, NULL); sa.sa_handler = sigterm_handler; sigemptyset (&sa.sa_mask); sigaddset (&sa.sa_mask, SIGINT); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); sigaction (SIGPOLL, &sa, NULL); if (daemonize) { sa.sa_handler = sighup_handler; sigemptyset (&sa.sa_mask); sigaction (SIGHUP, &sa, NULL); } }
/** * Function to prepare the application directories for the container. */ int initialize_app(const char *user, const char *app_id, const char* nmPrivate_credentials_file, char* const* local_dirs, char* const* log_roots, char* const* args) { if (app_id == NULL || user == NULL) { fprintf(LOGFILE, "Either app_id is null or the user passed is null.\n"); return INVALID_ARGUMENT_NUMBER; } // create the user directory on all disks int result = initialize_user(user, local_dirs); if (result != 0) { return result; } ////////////// create the log directories for the app on all disks char* const* log_root; char *any_one_app_log_dir = NULL; for(log_root=log_roots; *log_root != NULL; ++log_root) { char *app_log_dir = get_app_log_directory(*log_root, app_id); if (app_log_dir == NULL) { // try the next one } else if (create_directory_for_user(app_log_dir) != 0) { free(app_log_dir); return -1; } else if (any_one_app_log_dir == NULL) { any_one_app_log_dir = app_log_dir; } else { free(app_log_dir); } } if (any_one_app_log_dir == NULL) { fprintf(LOGFILE, "Did not create any app-log directories\n"); return -1; } free(any_one_app_log_dir); ////////////// End of creating the log directories for the app on all disks // open up the credentials file int cred_file = open_file_as_nm(nmPrivate_credentials_file); if (cred_file == -1) { return -1; } // give up root privs if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { return -1; } // 750 mode_t permissions = S_IRWXU | S_IRGRP | S_IXGRP; char* const* nm_root; char *primary_app_dir = NULL; for(nm_root=local_dirs; *nm_root != NULL; ++nm_root) { char *app_dir = get_app_directory(*nm_root, user, app_id); if (app_dir == NULL) { // try the next one } else if (mkdirs(app_dir, permissions) != 0) { free(app_dir); } else if (primary_app_dir == NULL) { primary_app_dir = app_dir; } else { free(app_dir); } } if (primary_app_dir == NULL) { fprintf(LOGFILE, "Did not create any app directories\n"); return -1; } char *nmPrivate_credentials_file_copy = strdup(nmPrivate_credentials_file); // TODO: FIXME. The user's copy of creds should go to a path selected by // localDirAllocatoir char *cred_file_name = concatenate("%s/%s", "cred file", 2, primary_app_dir, basename(nmPrivate_credentials_file_copy)); if (cred_file_name == NULL) { free(nmPrivate_credentials_file_copy); return -1; } if (copy_file(cred_file, nmPrivate_credentials_file, cred_file_name, S_IRUSR|S_IWUSR) != 0){ free(nmPrivate_credentials_file_copy); return -1; } free(nmPrivate_credentials_file_copy); fclose(stdin); fflush(LOGFILE); if (LOGFILE != stdout) { fclose(stdout); } if (ERRORFILE != stderr) { fclose(stderr); } if (chdir(primary_app_dir) != 0) { fprintf(LOGFILE, "Failed to chdir to app dir - %s\n", strerror(errno)); return -1; } execvp(args[0], args); fprintf(ERRORFILE, "Failure to exec app initialization process - %s\n", strerror(errno)); return -1; }
int main(int argc, char **argv) { int opt; extern char *optarg; extern int optind; int loop_status; signal(SIGHUP, &handle_signal); signal(SIGINT, &handle_signal); /* Process command line arguments */ while ((opt = getopt(argc, argv, "b:df:Fhpqi:l:m:n:o:P:r:st:u:S:")) != -1) { switch (opt) { case 'b': use_dumpfile = optarg; break; case 'd': daemon_mode = 1; use_syslog = 1; break; case 'f': format_str = optarg; break; case 'F': force_flush = 1; break; case 'h': display_usage(); break; case 'i': interface = optarg; break; case 'l': rate_threshold = atoi(optarg); break; case 'm': methods_str = optarg; break; case 'n': parse_count = atoi(optarg); break; case 'o': use_outfile = optarg; break; case 'p': set_promisc = 0; break; case 'P': pid_filename = optarg; break; case 'q': quiet_mode = 1; break; case 'r': use_infile = optarg; break; case 's': rate_stats = 1; break; case 't': rate_interval = atoi(optarg); break; case 'u': new_user = optarg; break; case 'S': eth_skip_bits = atoi(optarg); break; default: display_usage(); } } display_banner(); if (daemon_mode && !use_outfile) LOG_DIE("Daemon mode requires an output file"); if (parse_count < 0) LOG_DIE("Invalid -n value, must be 0 or greater"); if (rate_interval < 1) LOG_DIE("Invalid -t value, must be 1 or greater"); if (rate_threshold < 1) LOG_DIE("Invalid -l value, must be 1 or greater"); if (argv[optind] && *(argv[optind])) { capfilter = argv[optind]; } else { capfilter = default_capfilter; } if (!format_str) format_str = default_format; if (rate_stats) format_str = rate_format; parse_format_string(format_str); if (!methods_str) methods_str = default_methods; parse_methods_string(methods_str); if (force_flush) { if (setvbuf(stdout, NULL, _IONBF, 0) != 0) LOG_WARN("Cannot disable buffering on stdout"); } if (!pid_filename) pid_filename = PID_FILENAME; pcap_hnd = prepare_capture(interface, set_promisc, use_infile, capfilter); open_outfiles(); if (daemon_mode) runas_daemon(); if (new_user) change_user(new_user); if ((buf = malloc(BUFSIZ + 1)) == NULL) LOG_DIE("Cannot allocate memory for packet data buffer"); if (rate_stats) init_rate_stats(rate_interval, use_infile, rate_threshold); start_time = time(0); loop_status = pcap_loop(pcap_hnd, -1, &parse_http_packet, NULL); if (loop_status == -1) { LOG_DIE("Problem reading packets from interface: %s", pcap_geterr(pcap_hnd)); } else if (loop_status == -2) { PRINT("Loop halted, shutting down..."); } print_stats(); cleanup(); return loop_status == -1 ? EXIT_FAILURE : EXIT_SUCCESS; }
int main(int argc, char **argv) { int opt; extern char *optarg; extern int optind; int loop_status; signal(SIGINT, &handle_signal); /* Process command line arguments */ while ((opt = getopt(argc, argv, "b:df:hpqi:m:n:o:r:u:")) != -1) { switch (opt) { case 'b': use_dumpfile = optarg; break; case 'd': daemon_mode = 1; use_syslog = 1; break; case 'f': format_str = optarg; break; case 'h': display_usage(); break; case 'i': interface = optarg; break; case 'm': methods_str = optarg; break; case 'n': parse_count = atoi(optarg); break; case 'o': use_outfile = optarg; break; case 'p': set_promisc = 0; break; case 'q': quiet_mode = 1; break; case 'r': use_infile = optarg; break; case 'u': new_user = optarg; break; default: display_usage(); } } display_banner(); if (daemon_mode && !use_outfile) LOG_DIE("Daemon mode requires an output file"); if (parse_count < 0) LOG_DIE("Invalid -n value, must be 0 or greater"); if (argv[optind] && *(argv[optind])) { capfilter = argv[optind]; } else { capfilter = default_capfilter; } if (!format_str) format_str = default_format; parse_format_string(format_str); if (!methods_str) methods_str = default_methods; parse_methods_string(methods_str); pcap_hnd = prepare_capture(interface, set_promisc, use_infile, capfilter); open_outfiles(); if (daemon_mode) runas_daemon(); if (new_user) change_user(new_user); if ((buf = malloc(BUFSIZ + 1)) == NULL) LOG_DIE("Cannot allocate memory for packet data buffer"); start_time = time(0); loop_status = pcap_loop(pcap_hnd, -1, &parse_http_packet, NULL); if (loop_status == -1) { LOG_DIE("Problem reading packets from interface: %s", pcap_geterr(pcap_hnd)); } else if (loop_status == -2) { PRINT("Loop halted, shutting down..."); } cleanup(); return loop_status == -1 ? EXIT_FAILURE : EXIT_SUCCESS; }
int launch_container_as_user(const char *user, const char *app_id, const char *container_id, const char *work_dir, const char *script_name, const char *cred_file, const char* pid_file, char* const* local_dirs, char* const* log_dirs, const char *resources_key, char* const* resources_values) { int exit_code = -1; char *script_file_dest = NULL; char *cred_file_dest = NULL; script_file_dest = get_container_launcher_file(work_dir); if (script_file_dest == NULL) { exit_code = OUT_OF_MEMORY; goto cleanup; } cred_file_dest = get_container_credentials_file(work_dir); if (NULL == cred_file_dest) { exit_code = OUT_OF_MEMORY; goto cleanup; } // open launch script int container_file_source = open_file_as_nm(script_name); if (container_file_source == -1) { goto cleanup; } // open credentials int cred_file_source = open_file_as_nm(cred_file); if (cred_file_source == -1) { goto cleanup; } // setsid pid_t pid = setsid(); if (pid == -1) { exit_code = SETSID_OPER_FAILED; goto cleanup; } // write pid to pidfile if (pid_file == NULL || write_pid_to_file_as_nm(pid_file, pid) != 0) { exit_code = WRITE_PIDFILE_FAILED; goto cleanup; } // cgroups-based resource enforcement if (resources_key != NULL && ! strcmp(resources_key, "cgroups")) { // write pid to cgroups char* const* cgroup_ptr; for (cgroup_ptr = resources_values; cgroup_ptr != NULL && *cgroup_ptr != NULL; ++cgroup_ptr) { if (strcmp(*cgroup_ptr, "none") != 0 && write_pid_to_cgroup_as_root(*cgroup_ptr, pid) != 0) { exit_code = WRITE_CGROUP_FAILED; goto cleanup; } } } // give up root privs if (change_user(user_detail->pw_uid, user_detail->pw_gid) != 0) { exit_code = SETUID_OPER_FAILED; goto cleanup; } if (create_container_directories(user, app_id, container_id, local_dirs, log_dirs, work_dir) != 0) { fprintf(LOGFILE, "Could not create container dirs"); goto cleanup; } // 700 if (copy_file(container_file_source, script_name, script_file_dest,S_IRWXU) != 0) { goto cleanup; } // 600 if (copy_file(cred_file_source, cred_file, cred_file_dest, S_IRUSR | S_IWUSR) != 0) { goto cleanup; } fcloseall(); umask(0027); if (chdir(work_dir) != 0) { fprintf(LOGFILE, "Can't change directory to %s -%s\n", work_dir, strerror(errno)); goto cleanup; } if (execlp(script_file_dest, script_file_dest, NULL) != 0) { fprintf(LOGFILE, "Couldn't execute the container launch file %s - %s", script_file_dest, strerror(errno)); exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; goto cleanup; } exit_code = 0; cleanup: free(script_file_dest); free(cred_file_dest); return exit_code; }
int run_task_as_user(const char * user, const char *jobid, const char *taskid, const char *tt_root) { char *task_script_path = NULL; char *pid_path = NULL; char *task_script = NULL; FILE *file_handle = NULL; int exit_code = 0; int i = 0; #ifdef DEBUG fprintf(LOGFILE,"run_task_as_user : Job id : %s \n", jobid); fprintf(LOGFILE,"run_task_as_user : task id : %s \n", taskid); fprintf(LOGFILE,"run_task_as_user : tt_root : %s \n", tt_root); fflush(LOGFILE); #endif if (check_tt_root(tt_root) < 0) { fprintf(LOGFILE, "invalid tt root passed %s\n", tt_root); cleanup(); return INVALID_TT_ROOT; } get_pid_path(jobid, taskid, tt_root, &pid_path); if (pid_path == NULL) { fprintf(LOGFILE, "Invalid task-pid path provided"); cleanup(); return INVALID_PID_PATH; } errno = 0; file_handle = fopen(pid_path, "w"); if (file_handle == NULL) { fprintf(LOGFILE, "Error opening task-pid file %s :%s\n", pid_path, strerror(errno)); exit_code = UNABLE_TO_OPEN_PID_FILE_WRITE_MODE; goto cleanup; } errno = 0; if (fprintf(file_handle, "%d\n", getpid()) < 0) { fprintf(LOGFILE, "Error writing to task-pid file :%s\n", strerror(errno)); exit_code = UNABLE_TO_WRITE_TO_PID_FILE; goto cleanup; } fflush(file_handle); fclose(file_handle); //change the permissions of the file errno = 0; //setting permission to 777 if (chmod(pid_path, S_IREAD | S_IEXEC | S_IWRITE | S_IROTH | S_IWOTH | S_IXOTH | S_IRGRP | S_IWGRP | S_IXGRP) < 0) { fprintf(LOGFILE, "Error changing permission of %s task-pid file : %s", pid_path, strerror(errno)); errno = 0; if (remove(pid_path) < 0) { fprintf(LOGFILE, "Error deleting %s task-pid file : %s", pid_path, strerror(errno)); exit_code = UNABLE_TO_CHANGE_PERMISSION_AND_DELETE_PID_FILE; } else { exit_code = UNABLE_TO_CHANGE_PERMISSION_OF_PID_FILE; } goto cleanup; } #ifdef DEBUG fprintf(LOGFILE,"changing file ownership\n"); fprintf(LOGFILE, "run_task_as_user : uid id %d \n", getuid()); fprintf(LOGFILE, "run_task_as_user : gid id %d \n", getgid()); #endif //change the owner ship of the file to the launching user. if(chown(pid_path, getuid(), getgid()) <0 ) { fprintf(LOGFILE, "Error changing ownership of %s task-pid file : %s", pid_path, strerror(errno)); if(remove(pid_path) < 0) { fprintf(LOGFILE, "Error deleting %s task-pid file : %s", pid_path, strerror(errno)); exit_code = UNABLE_TO_CHANGE_OWNERSHIP_OF_PID_FILE_AND_DELETE_PID_FILE; } else { exit_code = UNABLE_TO_CHANGE_OWNERSHIP_OF_PID_FILE; } goto cleanup; } //free pid_t path which is allocated free(pid_path); //change the user fcloseall(); fclose(LOGFILE); umask(0); if (change_user(user) != 0) { cleanup(); return SETUID_OPER_FAILED; } get_task_file_path(jobid, taskid, tt_root, &task_script_path); if (task_script_path == NULL) { fprintf(LOGFILE, "Unable to locate task script"); cleanup(); return INVALID_TASK_SCRIPT_PATH; } errno = 0; cleanup(); execlp(task_script_path, task_script_path, NULL); if (errno != 0) { fprintf(LOGFILE, "Error execing script %s", strerror(errno)); free(task_script_path); exit_code = UNABLE_TO_EXECUTE_TASK_SCRIPT; } return exit_code; cleanup: if (pid_path != NULL) { free(pid_path); } if (task_script_path != NULL) { free(task_script_path); } if (file_handle != NULL) { fclose(file_handle); } // free configurations cleanup(); return exit_code; }
static pid_t fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail) { struct passwd *pas; const char *shell, *prog; smallint sv_logmode; pid_t pid; /* prepare things before vfork */ pas = getpwnam(user); if (!pas) { bb_error_msg("can't get uid for %s", user); goto err; } shell = line->cl_shell ? line->cl_shell : DEFAULT_SHELL; prog = run_sendmail ? SENDMAIL : shell; set_env_vars(pas, shell); sv_logmode = logmode; pid = vfork(); if (pid == 0) { /* CHILD */ /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */ change_user(pas); log5("child running %s", prog); if (mailFd >= 0) { xmove_fd(mailFd, run_sendmail ? 0 : 1); dup2(1, 2); } /* crond 3.0pl1-100 puts tasks in separate process groups */ bb_setpgrp(); if (!run_sendmail) execlp(prog, prog, "-c", line->cl_cmd, (char *) NULL); else execlp(prog, prog, SENDMAIL_ARGS, (char *) NULL); /* * I want this error message on stderr too, * even if other messages go only to syslog: */ logmode |= LOGMODE_STDIO; bb_error_msg_and_die("can't execute '%s' for user %s", prog, user); } logmode = sv_logmode; if (pid < 0) { bb_perror_msg("vfork"); err: pid = 0; } /* else: PARENT, FORK SUCCESS */ /* * Close the mail file descriptor.. we can't just leave it open in * a structure, closing it later, because we might run out of descriptors */ if (mailFd >= 0) { close(mailFd); } return pid; }
int main (int argc, char *argv[]) { int i; progname = argv[0]; while ((i = getopt (argc, argv, "hvu:m:f:g:o:")) != -1) { switch (i) { case 'v': verbosity = 1; break; case 'h': usage(); return 2; case 'm': assert (sscanf(optarg, "%d,%d", &split_rem, &split_mod) == 2); assert (split_mod > 0 && split_mod <= 1000 && split_rem >= 0 && split_rem < split_mod); break; case 'f': table_format = get_dump_format(optarg); if (!table_format) { fprintf (stderr, "fatal: unsupported table dump format: %s\n", optarg); return 2; } break; case 'g': groups_fname = optarg; break; case 'o': output_format = atol (optarg); break; case 'u': username = optarg; break; } } if (optind >= argc || optind + 2 < argc) { usage(); return 2; } src_fname = argv[optind]; if (username && change_user (username) < 0) { fprintf (stderr, "fatal: cannot change user to %s\n", username ? username : "******"); return 1; } src_fd = open (src_fname, O_RDONLY); if (src_fd < 0) { fprintf (stderr, "cannot open %s: %m\n", src_fname); return 1; } if (!table_format) { table_format = get_dump_format (fname_last (src_fname)); if (!table_format) { fprintf (stderr, "fatal: cannot determine table type from filename %s\n", src_fname); } } if (optind + 1 < argc) { targ_fname = argv[optind+1]; targ_fd = open (targ_fname, O_WRONLY | O_APPEND | O_CREAT, 0644); if (targ_fd < 0) { fprintf (stderr, "cannot create %s: %m\n", targ_fname); return 1; } } else { targ_fname = "stdout"; targ_fd = 1; } switch (table_format) { case TF_AUDIO: Args_per_line = au_END; start_binlog(SEARCH_SCHEMA_V1, "audio_search"); while (read_record() > 0) { process_audio_row(); } break; case TF_VIDEO: Args_per_line = vi_END; start_binlog(SEARCH_SCHEMA_V1, "video_search"); while (read_record() > 0) { process_video_row(); } break; case TF_APPS: Args_per_line = ap_END; start_binlog(SEARCH_SCHEMA_V1, "apps_search"); while (read_record() > 0) { process_applications_row(); } break; case TF_GROUPS: Args_per_line = gr_END; start_binlog(SEARCH_SCHEMA_V1, "group_search"); while (read_record() > 0) { process_groups_row(); } break; case TF_EVENTS: Args_per_line = gr_END; start_binlog(SEARCH_SCHEMA_V1, "event_search"); while (read_record() > 0) { process_events_row(); } break; case TF_BLOG_POSTS: Args_per_line = bp_END; start_binlog(SEARCH_SCHEMA_V1, "blog_posts_search"); while (read_record() > 0) { process_blog_posts_row(); } break; case TF_MEMLITE: Args_per_line = ml_END; start_binlog(SEARCH_SCHEMA_V1, "member_name_search"); while (read_record() > 0) { process_memlite_row(); } break; case TF_MARKET_ITEMS: Args_per_line = mi_END; start_binlog(SEARCH_SCHEMA_V1, "market_search"); while (read_record() > 0) { process_market_row(); } break; case TF_QUESTIONS: Args_per_line = qu_END; start_binlog(SEARCH_SCHEMA_V1, "question_search"); while (read_record() > 0) { process_questions_row(); } break; case TF_TOPICS: load_map (1); Args_per_line = to_END; start_binlog(SEARCH_SCHEMA_V1, "topic_search"); while (read_record() > 0) { process_topics_row(); } break; case TF_MINIFEED: Args_per_line = mf_END; start_binlog(SEARCH_SCHEMA_V1, "status_search"); while (read_record() > 0) { process_minifeed_row(); } break; default: fprintf (stderr, "unknown table type\n"); exit(1); } flush_out(); if (targ_fd != 1) { if (fdatasync(targ_fd) < 0) { fprintf (stderr, "error syncing %s: %m", targ_fname); exit (1); } close (targ_fd); } if (map_size > 0 && map_changes > 0 && groups_fname) { map_fd = open (groups_fname, O_WRONLY | O_CREAT | O_TRUNC, 0640); if (map_fd < 0) { fprintf (stderr, "cannot create map file %s: %m\n", groups_fname); exit (1); } assert (write (map_fd, Map, map_size) == map_size); close (map_fd); if (verbosity > 0) { fprintf (stderr, "%d bytes written to map file %s\n", map_size, groups_fname); } } if (verbosity > 0) { output_stats(); } return 0; }
int main (int argc, char *argv[]) { int i; progname = argv[0]; while ((i = getopt (argc, argv, "fhvu:m:s:t:M:F")) != -1) { switch (i) { case 'F': filter_member_fan = 1; break; case 'v': verbosity += 1; break; case 'f': // vkprintf(2, "setting skip_rotate\n"); skip_rotate = 1; break; case 'h': usage (); return 2; case 'u': username = optarg; break; case 'm': if (sscanf (optarg, "%d,%d", ©_rem, ©_mod) != 2 || copy_rem < 0 || copy_rem >= copy_mod) { usage(); return 2; } break; case 's': jump_log_pos = atoll (optarg); break; case 't': keep_log_limit_pos = log_limit_pos = atoll (optarg); break; case 'M': if (!strncmp(optarg, "firstint", 9)) { split_mode = SPLIT_FIRSTINT; } else if (!strncmp(optarg, "liked", 6)) { split_mode = SPLIT_LIKED; } else { usage(); return 2; } break; default: assert (0); return 2; } } if (optind >= argc || optind + 2 < argc) { usage(); return 2; } if (filter_member_fan) { vkprintf (1, "fix member_fans, fan_members mode\n"); char *p = strrchr (argv[optind], '/'); p = (p == NULL) ? argv[optind] : (p + 1); if (!strncmp (p, "member_fans", 11)) { want_write = member_fans_want_write; } else if (!strncmp (p, "fan_members", 11)) { want_write = fan_members_want_write; } else { kprintf ("binlogname should starts from member_fans of fan_members when command line switch -F used.\n"); exit (1); } } if (log_limit_pos >= 0) { if (jump_log_pos > log_limit_pos) { fprintf (stderr, "fatal: log start position %lld after stop position %lld\n", jump_log_pos, log_limit_pos); return 2; } } if (username && change_user (username) < 0) { fprintf (stderr, "fatal: cannot change user to %s\n", username ? username : "******"); return 1; } if (engine_preload_filelist (argv[optind], binlogname) < 0) { fprintf (stderr, "cannot open binlog files for %s\n", binlogname ? binlogname : argv[optind]); exit (1); } Binlog = open_binlog (engine_replica, 0); if (!Binlog) { fprintf (stderr, "fatal: cannot find binlog for %s, log position %lld\n", engine_replica->replica_prefix, 0LL); exit (1); } binlogname = Binlog->info->filename; if (verbosity) { fprintf (stderr, "replaying binlog file %s (size %lld)\n", binlogname, Binlog->info->file_size); } clear_log(); init_log_data (0, 0, 0); if (optind + 1 < argc) { targ_fname = argv[optind+1]; targ_fd = open (targ_fname, O_WRONLY | O_APPEND | O_CREAT, 0644); if (targ_fd < 0) { fprintf (stderr, "cannot create %s: %m\n", targ_fname); return 1; } targ_orig_size = lseek (targ_fd, 0, SEEK_END); targ_existed = (targ_orig_size > 0); } else { targ_fname = "stdout"; targ_fd = 1; } if (jump_log_pos > 0) { log_limit_pos = 256; immediate_exit = 1; i = replay_log (0, 1); if (!list_id_ints) { fprintf (stderr, "fatal: cannot parse first LEV_START entry"); exit (1); } log_limit_pos = keep_log_limit_pos; immediate_exit = 0; clear_log (); close_binlog (Binlog, 1); Binlog = 0; Binlog = open_binlog (engine_replica, jump_log_pos); if (!Binlog) { fprintf (stderr, "fatal: cannot find binlog for %s, log position %lld\n", engine_replica->replica_prefix, jump_log_pos); exit (1); } binlogname = Binlog->info->filename; if (verbosity) { fprintf (stderr, "replaying binlog file %s (size %lld) from log position %lld\n", binlogname, Binlog->info->file_size, jump_log_pos); } init_log_data (jump_log_pos, 0, 0); } i = replay_log (0, 1); if (i < 0) { fprintf (stderr, "fatal: error reading binlog\n"); exit (1); } if (log_limit_pos >= 0 && log_readto_pos != log_limit_pos) { fprintf (stderr, "fatal: binlog read up to position %lld instead of %lld\n", log_readto_pos, log_limit_pos); exit (1); } if (!targ_orig_size && !jump_log_pos) { vkprintf (1, "Writing CRC32 to the end of target binlog.\n"); struct lev_crc32 *C = write_alloc (20); C->type = LEV_CRC32; C->timestamp = last_timestamp; C->pos = wr_bytes; C->crc32 = ~wr_crc32_complement; wr_bytes += 20; wr_rec++; } flush_out (); if (targ_fd != 1) { if (fdatasync (targ_fd) < 0) { fprintf (stderr, "error syncing %s: %m", targ_fname); exit (1); } close (targ_fd); } if (verbosity > 0) { output_stats (); } return 0; }