void qmp_guest_set_time(int64_t time_ns, Error **errp) { int ret; int status; pid_t pid; Error *local_err = NULL; struct timeval tv; /* year-2038 will overflow in case time_t is 32bit */ if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) { error_setg(errp, "Time %" PRId64 " is too large", time_ns); return; } tv.tv_sec = time_ns / 1000000000; tv.tv_usec = (time_ns % 1000000000) / 1000; ret = settimeofday(&tv, NULL); if (ret < 0) { error_setg_errno(errp, errno, "Failed to set time to guest"); return; } /* Set the Hardware Clock to the current System Time. */ pid = fork(); if (pid == 0) { setsid(); reopen_fd_to_null(0); reopen_fd_to_null(1); reopen_fd_to_null(2); execle("/sbin/hwclock", "hwclock", "-w", NULL, environ); _exit(EXIT_FAILURE); } else if (pid < 0) { error_setg_errno(errp, errno, "failed to create child process"); return; } ga_wait_child(pid, &status, &local_err); if (error_is_set(&local_err)) { error_propagate(errp, local_err); return; } if (!WIFEXITED(status)) { error_setg(errp, "child process has terminated abnormally"); return; } if (WEXITSTATUS(status)) { error_setg(errp, "hwclock failed to set hardware clock to system time"); return; } }
void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) { const char *shutdown_flag; Error *local_err = NULL; pid_t pid; int status; slog("guest-shutdown called, mode: %s", mode); if (!has_mode || strcmp(mode, "powerdown") == 0) { shutdown_flag = "-P"; } else if (strcmp(mode, "halt") == 0) { shutdown_flag = "-H"; } else if (strcmp(mode, "reboot") == 0) { shutdown_flag = "-r"; } else { error_setg(err, "mode is invalid (valid values are: halt|powerdown|reboot"); return; } pid = fork(); if (pid == 0) { /* child, start the shutdown */ setsid(); reopen_fd_to_null(0); reopen_fd_to_null(1); reopen_fd_to_null(2); execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0", "hypervisor initiated shutdown", (char*)NULL, environ); _exit(EXIT_FAILURE); } else if (pid < 0) { error_setg_errno(err, errno, "failed to create child process"); return; } ga_wait_child(pid, &status, &local_err); if (error_is_set(&local_err)) { error_propagate(err, local_err); return; } if (!WIFEXITED(status)) { error_setg(err, "child process has terminated abnormally"); return; } if (WEXITSTATUS(status)) { error_setg(err, "child process has failed to shutdown"); return; } /* succeded */ }
void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) { const char *shutdown_flag; pid_t rpid, pid; int status; slog("guest-shutdown called, mode: %s", mode); if (!has_mode || strcmp(mode, "powerdown") == 0) { shutdown_flag = "-P"; } else if (strcmp(mode, "halt") == 0) { shutdown_flag = "-H"; } else if (strcmp(mode, "reboot") == 0) { shutdown_flag = "-r"; } else { error_set(err, QERR_INVALID_PARAMETER_VALUE, "mode", "halt|powerdown|reboot"); return; } pid = fork(); if (pid == 0) { /* child, start the shutdown */ setsid(); reopen_fd_to_null(0); reopen_fd_to_null(1); reopen_fd_to_null(2); execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0", "hypervisor initiated shutdown", (char*)NULL, environ); _exit(EXIT_FAILURE); } else if (pid < 0) { goto exit_err; } do { rpid = waitpid(pid, &status, 0); } while (rpid == -1 && errno == EINTR); if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) { return; } exit_err: error_set(err, QERR_UNDEFINED_ERROR); }
static void become_daemon(const char *pidfile) { #ifndef _WIN32 pid_t pid, sid; pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } if (pid > 0) { exit(EXIT_SUCCESS); } if (pidfile) { if (!ga_open_pidfile(pidfile)) { g_critical("failed to create pidfile"); exit(EXIT_FAILURE); } } umask(S_IRWXG | S_IRWXO); sid = setsid(); if (sid < 0) { goto fail; } if ((chdir("/")) < 0) { goto fail; } reopen_fd_to_null(STDIN_FILENO); reopen_fd_to_null(STDOUT_FILENO); reopen_fd_to_null(STDERR_FILENO); return; fail: if (pidfile) { unlink(pidfile); } g_critical("failed to daemonize"); exit(EXIT_FAILURE); #endif }