diff --git a/direct/src/autorestart/Sources.pp b/direct/src/autorestart/Sources.pp deleted file mode 100644 index a85fc78a17..0000000000 --- a/direct/src/autorestart/Sources.pp +++ /dev/null @@ -1,8 +0,0 @@ -#begin bin_target - // This program only compiles on Unix. - #define BUILD_TARGET $[UNIX_PLATFORM] - #define C++FLAGS -DWITHIN_PANDA - - #define TARGET autorestart - #define SOURCES autorestart.c -#end bin_target diff --git a/direct/src/autorestart/autorestart.c b/direct/src/autorestart/autorestart.c deleted file mode 100644 index bfcad109de..0000000000 --- a/direct/src/autorestart/autorestart.c +++ /dev/null @@ -1,901 +0,0 @@ -/* Filename: autorestart.c - * Created by: drose (05Sep02) - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifdef WITHIN_PANDA -#include "dtoolbase.h" -#endif - -#include -#include -#include -#include /* for strerror */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_LIBCURL -#include -#endif - -/* The maximum number of seconds to wait for a process to go away - after issuing SIGTERM. This is only used in watchdog mode, when -W - is provided on the command line. */ -#define MAX_WAITTERM_SEC 10 - -char **params = NULL; -char *logfile_name = NULL; -char *pidfile_name = NULL; -int dont_fork = 0; -char *watchdog_url = NULL; -int watchdog_start_sec = 0; -int watchdog_cycle_sec = 0; -int watchdog_timeout_sec = 0; -char *startup_username = NULL; -char *startup_groupname = NULL; -char *startup_chdir = NULL; -int logfile_fd = -1; -int stop_on_terminate = 0; -int stop_always = 0; -char *respawn_script = NULL; -int respawn_count_time = 0; - -/* If requested, delay these many seconds between restart attempts */ -int respawn_delay_time = 5; - - -/* We shouldn't respawn more than (spam_respawn_count - 1) times over - spam_respawn_time seconds. */ -int spam_respawn_count = 5; -int spam_respawn_time = 60; -int spam_restart_delay_time = 600; /* Optionally, do not exit if we spam too much; simply sleep for this many seconds*/ - - - -pid_t child_pid = 0; -pid_t watchdog_pid = 0; - -#define TIME_BUFFER_SIZE 128 - -/* Keep track of the frequency with which we respawn, so we can report - this to our respawn script. */ -typedef struct respawn_record_struct { - time_t _time; - struct respawn_record_struct *_next; -} respawn_record; - -respawn_record *respawns = NULL; - -int -record_respawn(time_t now) { - /* Records the respawning event in the respawn_record, and returns - the number of respawns in the last respawn_count_time - interval. */ - respawn_record *rec; - respawn_record *next; - int count; - - if (respawn_count_time <= 0) { - /* We're not tracking respawns if respawn_count_time is 0. */ - return 0; - } - - rec = (respawn_record *)malloc(sizeof(respawn_record)); - rec->_time = now; - rec->_next = respawns; - respawns = rec; - - /* Now walk through the rest of the list and count up the number of - respawn events until we reach a record more than - respawn_count_time seconds old. */ - count = 0; - while (rec->_next != NULL && - (now - rec->_time) <= respawn_count_time) { - rec = rec->_next; - count++; - } - - /* The remaining respawn records get removed. */ - next = rec->_next; - rec->_next = NULL; - while (next != NULL) { - rec = next; - next = rec->_next; - free(rec); - } - - return count; -} - -void -invoke_respawn_script(time_t now) { - char buffer[32]; - char *new_command; - int new_command_length; - - /* The process is about to be respawned; run the script that we were - given on the command line. */ - if (respawn_count_time <= 0) { - /* We're not counting respawn times, so just run the script - directly. */ - system(respawn_script); - - } else { - /* We are counting respawn times, so append that information as a - parameter to the command. */ - sprintf(buffer, " %d", record_respawn(now)); - new_command_length = strlen(respawn_script) + strlen(buffer); - new_command = (char *)malloc(new_command_length + 1); - strcpy(new_command, respawn_script); - strcat(new_command, buffer); - assert(strlen(new_command) == new_command_length); - - system(new_command); - - free(new_command); - } -} - -/* A callback function passed to libcurl that simply discards the data - retrieved from the server. We only care about the HTTP status. */ -size_t -watchdog_bitbucket(void *ptr, size_t size, size_t nmemb, void *userdata) { - return size * nmemb; -} - -/* Waits up to timeout_ms for a particular child to terminate. - Returns 0 if the timeout expires. */ -pid_t -waitpid_timeout(pid_t child_pid, int *status_ptr, int timeout_ms) { - pid_t result; - struct timeval now, tv; - int now_ms, start_ms, elapsed_ms; - - gettimeofday(&now, NULL); - start_ms = now.tv_sec * 1000 + now.tv_usec / 1000; - - result = waitpid(child_pid, status_ptr, WNOHANG); - while (result == 0) { - gettimeofday(&now, NULL); - now_ms = now.tv_sec * 1000 + now.tv_usec / 1000; - elapsed_ms = now_ms - start_ms; - - if (elapsed_ms > timeout_ms) { - /* Tired of waiting. */ - return 0; - } - - /* Yield the timeslice and wait some more. */ - tv.tv_sec = 0; - tv.tv_usec = 1; - select(0, NULL, NULL, NULL, &tv); - result = waitpid(child_pid, status_ptr, WNOHANG); - } - if (result == -1) { - perror("waitpid"); - } - - return result; -} - - -/* Poll the requested URL until a failure or timeout occurs, or until - the child terminates on its own. Returns 1 on HTTP failure or - timeout, 0 on self-termination. In either case, *status_ptr is - filled in with the status value returned by waitpid().*/ -int -do_watchdog(int *status_ptr) { -#ifndef HAVE_LIBCURL - fprintf(stderr, "Cannot watchdog; no libcurl available.\n"); - return 0; -#else /* HAVE_LIBCURL */ - - CURL *curl; - CURLcode res; - char error_buffer[CURL_ERROR_SIZE]; - pid_t wresult; - - // Before we start polling the URL, wait at least start milliseconds. - wresult = waitpid_timeout(child_pid, status_ptr, watchdog_start_sec * 1000); - if (wresult == child_pid) { - // The child terminated on its own before we got started. - return 0; - } - - curl = curl_easy_init(); - if (!curl) { - fprintf(stderr, "Cannot watchdog; curl failed to init.\n"); - return 0; - } - - curl_easy_setopt(curl, CURLOPT_URL, watchdog_url); - /*curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);*/ - curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, watchdog_timeout_sec * 1000); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, watchdog_bitbucket); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); - curl_easy_setopt(curl, CURLOPT_USERAGENT, "autorestart"); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1); - curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1); - - res = curl_easy_perform(curl); - while (res == 0) { - /* 0: The HTTP request finished successfully (but might or might - not have returned an error code like a 404). */ - long http_response = 0; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response); - if ((http_response / 100) != 2) { - /* Anything in the 200 range is deemed success. Anything else - is deemed failure. */ - fprintf(stderr, "%s returned %ld\n", watchdog_url, http_response); - break; - } - - wresult = waitpid_timeout(child_pid, status_ptr, watchdog_cycle_sec * 1000); - if (wresult == child_pid) { - /* The process terminated on its own. Return 0 to indicate this. */ - return 0; - } - - res = curl_easy_perform(curl); - } - - curl_easy_cleanup(curl); - - /* Failed to retrieve the watchdog URL. */ - if (res != 0) { - fprintf(stderr, "Failed to contact %s: %s\n", watchdog_url, error_buffer); - } - - /* Kill the child process and wait for it to go away. */ - kill(child_pid, SIGTERM); - - pid_t result = waitpid_timeout(child_pid, status_ptr, MAX_WAITTERM_SEC * 1000); - if (result != child_pid) { - if (result == -1) { - perror("waitpid"); - } else { - /* SIGTERM didn't make the process die. Try SIGKILL. */ - fprintf(stderr, "Force-killing child process\n"); - kill(child_pid, SIGKILL); - result = waitpid_timeout(child_pid, status_ptr, MAX_WAITTERM_SEC * 1000); - if (result == -1) { - perror("waitpid"); - } - } - } - - /* Return 1 to indicate we killed the child due to an HTTP error. */ - return 1; -#endif /* HAVE_LIBCURL */ -} - -void -exec_process() { - /* First, output the command line to the log file. */ - char **p; - for (p = params; *p != NULL; ++p) { - fprintf(stderr, "%s ", *p); - } - fprintf(stderr, "\n"); - execvp(params[0], params); - fprintf(stderr, "Cannot exec %s: %s\n", params[0], strerror(errno)); - - /* Exit with a status of 0, to indicate to the parent process that - we should stop. */ - exit(0); -} - -int -spawn_process() { - /* Spawns the child process. Returns true if the process terminated - by itself and should be respawned, false if it was explicitly - killed (or some other error condition exists), and it should not - respawn any more. */ - pid_t wresult; - int status; - int error_exit; - - child_pid = fork(); - if (child_pid < 0) { - /* Fork error. */ - perror("fork"); - return 0; - } - - if (child_pid == 0) { - /* Child. Exec the process. */ - fprintf(stderr, "Child pid is %d.\n", getpid()); - exec_process(); - /* Shouldn't get here. */ - exit(1); - } - - /* Parent. */ - - error_exit = 0; - - if (watchdog_url != NULL) { - /* If we're watchdogging, then go check the URL. This function - won't return until the URL fails or the child exits. */ - error_exit = do_watchdog(&status); - - } else { - /* If we're not watchdogging, then just wait for the child to - terminate, and diagnose the reason. */ - wresult = waitpid(child_pid, &status, 0); - if (wresult < 0) { - perror("waitpid"); - return 0; - } - } - - /* Now that we've returned from waitpid, clear the child pid number - so our signal handler doesn't get too confused. */ - child_pid = 0; - - if (error_exit) { - /* An HTTP error exit is a reason to respawn. */ - return 1; - - } else if (WIFSIGNALED(status)) { - int signal = WTERMSIG(status); - fprintf(stderr, "\nprocess caught signal %d.\n\n", signal); - /* A signal exit is a reason to respawn unless the signal is TERM - or KILL. */ - return !stop_on_terminate || (signal != SIGTERM && signal != SIGKILL); - - } else { - int exit_status = WEXITSTATUS(status); - fprintf(stderr, "\nprocess exited with status %d.\n\n", WEXITSTATUS(status)); - /* Normal exit is a reason to respawn if the status indicates failure. */ - return !stop_on_terminate || (exit_status != 0); - } -} - -void -sigterm_handler() { - pid_t wresult; - int status; - time_t now; - char time_buffer[TIME_BUFFER_SIZE]; - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - - fprintf(stderr, "\nsigterm caught at %s; shutting down.\n", time_buffer); - if (child_pid == 0) { - fprintf(stderr, "no child process.\n\n"); - - } else { - kill(child_pid, SIGTERM); - - wresult = waitpid(child_pid, &status, 0); - if (wresult < 0) { - perror("waitpid"); - } else { - fprintf(stderr, "child process terminated.\n\n"); - } - } - exit(1); -} - -void -sighup_handler() { - time_t now; - char time_buffer[TIME_BUFFER_SIZE]; - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - - fprintf(stderr, "\nsighup caught at %s.\n", time_buffer); - if (child_pid == 0) { - fprintf(stderr, "no child process.\n\n"); - - } else { - kill(child_pid, SIGHUP); - } -} - -void -sigalarm_handler() { - fprintf(stderr, "sleep epoch was complete.\n"); -} - -void -do_autorestart() { - char time_buffer[TIME_BUFFER_SIZE]; - time_t now; - time_t *spam_respawn = NULL; - int sri, num_sri; - struct sigaction sa; - - if (spam_respawn_count > 1) { - spam_respawn = (time_t *)malloc(sizeof(time_t) * spam_respawn_count); - } - - /* Make our process its own process group. */ - setpgid(0, 0); - - /* Set up a signal handler to trap SIGTERM. */ - sa.sa_handler = sigterm_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(SIGTERM, &sa, NULL) < 0) { - perror("sigaction"); - } - - /* Set up a signal handler to trap SIGHUP. We pass this into the - child. */ - sa.sa_handler = sighup_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(SIGHUP, &sa, NULL) < 0) { - perror("sigaction"); - } - - if (logfile_fd >= 0) { - /* If we have a logfile, dup it onto stdout and stderr. */ - dup2(logfile_fd, STDOUT_FILENO); - dup2(logfile_fd, STDERR_FILENO); - close(logfile_fd); - } - - /* Make sure stdin is closed. */ - close(STDIN_FILENO); - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - fprintf(stderr, "autorestart begun at %s.\n", time_buffer); - - if (pidfile_name != NULL) { - unlink(pidfile_name); - FILE *pidfile = fopen(pidfile_name, "w"); - if (pidfile == NULL) { - fprintf(stderr, "Could not write pidfile %s\n", pidfile_name); - } else { - fprintf(pidfile, "%d\n", getpid()); - fclose(pidfile); - } - } - - sri = 1; - num_sri = 1; - if (spam_respawn_count > 1) { - spam_respawn[1] = now; - } - - while (spawn_process()) { - now = time(NULL); - - if (respawn_script != NULL) { - invoke_respawn_script(now); - } - - if (respawn_delay_time) { - sleep(respawn_delay_time); - } - - /* Make sure we're not respawning too fast. */ - if (spam_respawn_count > 1) { - sri = (sri + 1) % spam_respawn_count; - spam_respawn[sri] = now; - if (num_sri < spam_respawn_count) { - num_sri++; - } else { - time_t last = spam_respawn[(sri + 1) % spam_respawn_count]; - if (now - last < spam_respawn_time) - { - if(!spam_restart_delay_time) - { - fprintf(stderr, "respawning too fast, giving up.\n"); - break; - } - else - { - num_sri = 1; /* reset num_sri */ - fprintf(stderr, "respawning too fast, will sleep for %d seconds.\n", spam_restart_delay_time); - signal (SIGALRM, sigalarm_handler); - alarm(spam_restart_delay_time); - pause(); - signal (SIGALRM, SIG_IGN); - } - } - } - } - - if (stop_always) { - fprintf(stderr, "instructed to not autorestart, exiting.\n"); - break; - } - - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - fprintf(stderr, "respawning at %s.\n", time_buffer); - } - - now = time(NULL); - strftime(time_buffer, TIME_BUFFER_SIZE, "%T on %A, %d %b %Y", localtime(&now)); - fprintf(stderr, "autorestart terminated at %s.\n", time_buffer); - exit(0); -} - -void -double_fork() { - pid_t child, grandchild, wresult; - int status; - - /* Fork once, then again, to disassociate the child from the command - shell process group. */ - child = fork(); - if (child < 0) { - /* Failure to fork. */ - perror("fork"); - exit(1); - } - - if (child == 0) { - /* Child. Fork again. */ - grandchild = fork(); - if (grandchild < 0) { - perror("fork"); - exit(1); - } - - if (grandchild == 0) { - /* Grandchild. Begin useful work. */ - do_autorestart(); - /* Shouldn't get here. */ - exit(1); - } - - /* Child. Report the new pid, then terminate gracefully. */ - fprintf(stderr, "Spawned, monitoring pid is %d.\n", grandchild); - exit(0); - } - - /* Parent. Wait for the child to terminate, then return. */ - wresult = waitpid(child, &status, 0); - if (wresult < 0) { - perror("waitpid"); - exit(1); - } - - if (!WIFEXITED(status)) { - if (WIFSIGNALED(status)) { - fprintf(stderr, "child caught signal %d unexpectedly.\n", WTERMSIG(status)); - } else { - fprintf(stderr, "child exited with status %d.\n", WEXITSTATUS(status)); - } - exit(1); - } -} - -void -usage() { - fprintf(stderr, - "\n" - "autorestart [opts] program [args . . . ]\n" - "autorestart -h\n\n"); -} - -void -help() { - usage(); - fprintf(stderr, - "This program is used to run a program as a background task and\n" - "automatically restart it should it terminate for any reason other\n" - "than normal exit or explicit user kill.\n\n" - - "If the program exits with a status of 0, indicating successful\n" - "completion, it is not restarted.\n\n" - - "If the program is terminated via a TERM or KILL signal (e.g. via\n" - "kill [pid] or kill -9 [pid]), it is assumed the user meant for the\n" - "process to stop, and it is not restarted.\n\n" - - "Options:\n\n" - - " -l logfilename\n" - " Route stdout and stderr from the child process into the indicated\n" - " log file.\n\n" - - " -p pidfilename\n" - " Write the pid of the monitoring process to the indicated pidfile.\n\n" - " -f\n" - " Don't fork autorestart itself; run it as a foreground process. \n" - " (Normally, autorestart forks itself to run as a background process.)\n" - " In this case, the file named by -p is not used.\n\n" - - " -n\n" - " Do not attempt to restart the process under any circumstance.\n" - " The program can still be used to execute a script on abnormal\n" - " process termination.\n\n" - - " -t\n" - " Stop on terminate: don't restart if the child process exits\n" - " normally or is killed with a SIGTERM. With this flag, the\n" - " child process will be restarted only if it exits with a\n" - " non-zero exit status, or if it is killed with a signal other\n" - " than SIGTERM. Without this flag, the default behavior is to\n" - " restart the child process if it exits for any reason.\n\n" - - " -r count,secs,sleep\n" - " Sleep 'sleep' seconds if the process respawns 'count' times\n" - " within 'secs' seconds. This is designed to prevent respawning\n" - " from using too many system resources if something is wrong with\n" - " the child process. The default value is %d,%d,%d. Use -r 0,0,0\n" - " to disable this feature.\n\n" - - " -s \"command\"\n" - " Run the indicated command or script each time the process is\n" - " respawned, using the system() call. This may be useful, for\n" - " instance, to notify an operator via email each time a respawn\n" - " occurs. If -c is also specified, an additional parameter will\n" - " be appended to the command, indicating the number of times the\n" - " respawn has occurred in the given time interval.\n\n" - - " -c secs\n" - " Specifies the number of seconds over which to count respawn events\n" - " for the purposes of passing an argument to the script named with\n" - " -s.\n\n" - - " -d secs\n" - " Specifies the number of seconds to delay for between restarts.\n" - " The default is %d.\n\n" - -#ifdef HAVE_LIBCURL - " -W watchdog_url,start,cycle,timeout\n" - " Specifies an optional URL to watch while waiting for the process\n" - " to terminate. If this is specified, autorestart will start the process,\n" - " wait start seconds, and then repeatedly poll the indicated URL\n" - " every cycle seconds. If a HTTP failure code is detected,\n" - " or no response is received within timeout seconds, then the\n" - " child is terminated and restarted. The start, cycle, and timeout\n" - " parameters are all required.\n\n" -#endif /* HAVE_LIBCURL */ - - " -U username\n" - " Change to the indicated user upon startup. The logfile is still\n" - " created as the initial user.\n\n" - - " -G groupname\n" - " Change to the indicated group upon startup.\n\n" - - " -D dirname\n" - " Change to the indicated working directory upon startup. The logfile\n" - " is still created relative to the initial startup directory.\n\n" - - " -h\n" - " Output this help information.\n\n", - spam_respawn_count, spam_respawn_time, spam_restart_delay_time, respawn_delay_time); -} - -void -parse_int_triplet(char *param, int *a, int *b, int *c) { - char *comma; - char *comma2; - - comma = strchr(param, ','); - if (comma == NULL) { - fprintf(stderr, "Comma required: %s\n", param); - exit(1); - } - - comma2 = strchr(comma+1, ','); - if (comma2 == NULL) { - fprintf(stderr, "Second comma required: %s\n", param); - exit(1); - } - - *comma = '\0'; - *comma2 = '\0'; - - *a = atoi(param); - *b = atoi(comma + 1); - *c = atoi(comma2 + 1); -} - -void -parse_watchdog(char *param) { - char *comma; - char *comma2; - char *comma3; - -#ifndef HAVE_LIBCURL - fprintf(stderr, "-W requires autorestart to have been compiled with libcurl support.\n"); - exit(1); -#endif /* HAVE_LIBCURL */ - - comma = strrchr(param, ','); - if (comma == NULL) { - fprintf(stderr, "Comma required: %s\n", param); - exit(1); - } - *comma = '\0'; - - comma2 = strrchr(param, ','); - if (comma2 == NULL) { - *comma = ','; - fprintf(stderr, "Second comma required: %s\n", param); - exit(1); - } - *comma2 = '\0'; - - comma3 = strrchr(param, ','); - if (comma3 == NULL) { - *comma = ','; - *comma2 = ','; - fprintf(stderr, "Third comma required: %s\n", param); - exit(1); - } - *comma3 = '\0'; - - watchdog_url = param; - watchdog_start_sec = atoi(comma3 + 1); - watchdog_cycle_sec = atoi(comma2 + 1); - watchdog_timeout_sec = atoi(comma + 1); -} - - -int -main(int argc, char *argv[]) { - extern char *optarg; - extern int optind; - /* The initial '+' instructs GNU getopt not to reorder switches. */ - static const char *optflags = "+l:p:fntr:s:c:d:W:U:G:D:h"; - int flag; - - flag = getopt(argc, argv, optflags); - while (flag != EOF) { - switch (flag) { - case 'l': - logfile_name = optarg; - break; - - case 'p': - pidfile_name = optarg; - break; - - case 'f': - dont_fork = 1; - break; - - case 'n': - stop_always = 1; - break; - - case 't': - stop_on_terminate = 1; - break; - - case 'r': - parse_int_triplet(optarg, &spam_respawn_count, &spam_respawn_time, &spam_restart_delay_time); - break; - - case 's': - respawn_script = optarg; - break; - - case 'c': - respawn_count_time = atoi(optarg); - break; - - case 'd': - respawn_delay_time = atoi(optarg); - break; - - case 'W': - parse_watchdog(optarg); - break; - - case 'U': - startup_username = optarg; - break; - - case 'G': - startup_groupname = optarg; - break; - - case 'D': - startup_chdir = optarg; - break; - - case 'h': - help(); - return 1; - - case '?': - case '+': - usage(); - return 1; - - default: - fprintf(stderr, "Unhandled switch: -%c\n", flag); - return 1; - } - flag = getopt(argc, argv, optflags); - } - - argc -= (optind - 1); - argv += (optind - 1); - - if (argc < 2) { - fprintf(stderr, "No program to execute given.\n"); - usage(); - return 1; - } - - params = &argv[1]; - - if (logfile_name != NULL) { - logfile_fd = open(logfile_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (logfile_fd < 0) { - fprintf(stderr, "Cannot write to logfile %s: %s\n", - logfile_name, strerror(errno)); - return 1; - } - fprintf(stderr, "Generating output to %s.\n", logfile_name); - } - - if (startup_chdir != NULL) { - if (chdir(startup_chdir) != 0) { - perror(startup_chdir); - return 1; - } - } - - if (startup_groupname != NULL) { - struct group *grp; - grp = getgrnam(startup_groupname); - if (grp == NULL) { - perror(startup_groupname); - return 1; - } - - if (setgid(grp->gr_gid) != 0) { - perror(startup_groupname); - return 1; - } - } - - if (startup_username != NULL) { - struct passwd *pwd; - pwd = getpwnam(startup_username); - if (pwd == NULL) { - perror(startup_username); - return 1; - } - - if (setuid(pwd->pw_uid) != 0) { - perror(startup_username); - return 1; - } - } - - if (dont_fork) { - do_autorestart(); - } else { - double_fork(); - } - - return 0; -} - diff --git a/direct/src/directscripts/Doxyfile.python b/direct/src/directscripts/Doxyfile.python index 32ba23481d..81b68dc6b2 100644 --- a/direct/src/directscripts/Doxyfile.python +++ b/direct/src/directscripts/Doxyfile.python @@ -643,8 +643,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = built/direct/test \ - built/direct/plugin \ +EXCLUDE = built/direct/plugin \ built/direct/plugin_npapi \ built/direct/plugin_activex \ built/direct/plugin_installer \ diff --git a/direct/src/heapq/Sources.pp b/direct/src/heapq/Sources.pp deleted file mode 100755 index e072ecf367..0000000000 --- a/direct/src/heapq/Sources.pp +++ /dev/null @@ -1,29 +0,0 @@ -// DIR_TYPE "metalib" indicates we are building a shared library that -// consists mostly of references to other shared libraries. Under -// Windows, this directly produces a DLL (as opposed to the regular -// src libraries, which don't produce anything but a pile of OBJ files -// under Windows). - -#define DIR_TYPE metalib - -// This directory strictly contains a Python utility; therefore, only -// build it if we actually have Python. -#define BUILD_DIRECTORY $[HAVE_PYTHON] - - -#define OTHER_LIBS \ - pandaexpress:m \ - p3dconfig:c p3dtoolconfig:m \ - p3dtoolutil:c p3dtoolbase:c p3prc:c p3dtool:m - -#begin metalib_target - #define TARGET p3heapq - - // Tell ppremake to treat this file as if it had been generated via - // interrogate. On OSX, this will move it into the .so, instead of - // the .dylib, so that it can be imported into Python. - #define PYTHON_MODULE_ONLY 1 - - #define SOURCES heapq.cxx -#end metalib_target - diff --git a/direct/src/heapq/heapq.cxx b/direct/src/heapq/heapq.cxx deleted file mode 100755 index dcfe34f4bd..0000000000 --- a/direct/src/heapq/heapq.cxx +++ /dev/null @@ -1,240 +0,0 @@ - -/* Note: This module can probably go away when we upgrade to Python 2.4. - Python 2.3 has a heapq implementation, but it is in Python. This is - reported to be about 20x faster. In 2.4 they reimplemented heapq in C so - it should be comparable to this. At this time though, Python 2.4 is - still in alpha. - - Note: This code has been bastardized to only work on Tasks temporarily. - -*/ - -#include - -/* Prototypes */ -static PyObject * heappush(PyObject *self, PyObject *args); -static PyObject * heappop(PyObject *self, PyObject *args); -static PyObject * heapreplace(PyObject *self, PyObject *args); -static PyObject * heapify(PyObject *self, PyObject *args); -static int _siftdown(PyObject *list, int startpos, int pos); -static int _siftup(PyObject *list, int pos); - -#ifdef _WIN32 -extern "C" __declspec(dllexport) void initlibheapq(void); -extern "C" __declspec(dllexport) void initlibp3heapq(void); -#else -extern "C" void initlibheapq(); -extern "C" void initlibp3heapq(); -#endif - -static PyObject * -heappush(PyObject *self, PyObject *args) { - int len; - PyObject *list = NULL; - PyObject *node = NULL; - - if (!PyArg_ParseTuple(args,"O!O",&PyList_Type,&list,&node)) - return NULL; - - len = PyList_Size(list); - if (PyList_Append(list,node)) - return NULL; - - if (_siftdown(list,0,len)) - return NULL; - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -heappop(PyObject *self, PyObject *args) { - PyObject *list = NULL; - PyObject *node = NULL; - PyObject *returnNode = NULL; - int len; - - if (!PyArg_ParseTuple(args,"O!",&PyList_Type,&list)) - return NULL; - - len = PyList_Size(list); - if (len == 0) { - /* Special-case most common failure cause */ - PyErr_SetString(PyExc_IndexError, "pop from empty list"); - return NULL; - } - - node = PySequence_GetItem(list,-1); - PySequence_DelItem(list,-1); - - len -= 1; - if (len > 0) { - returnNode = PySequence_GetItem(list,0); - PyList_SetItem(list,0,node); - if (_siftup(list,0)) - return NULL; - } else { - returnNode = node; - } - - return returnNode; -} - -static PyObject * -heapreplace(PyObject *self, PyObject *args) { - PyObject *list = NULL; - PyObject *node = NULL; - PyObject *returnNode = NULL; - int len; - - if (!PyArg_ParseTuple(args,"O!O",&PyList_Type,&list,&node)) - return NULL; - - len = PyList_Size(list); - if (len == 0) { - /* Special-case most common failure cause */ - PyErr_SetString(PyExc_IndexError, "replace on an empty list"); - return NULL; - } - - returnNode = PySequence_GetItem(list,0); - PySequence_SetItem(list,0,node); - if (_siftup(list,0)) - return NULL; - - return returnNode; -} - -static PyObject * -heapify(PyObject *self, PyObject *args) { - int n, i; - PyObject *list; - - if (!PyArg_ParseTuple(args,"O!",&PyList_Type,&list)) - return NULL; - n = (PyList_Size(list)/2)-1; - - for (i=n;i>=0;i--) { - if (_siftup(list,i)) - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static int -_siftdown(PyObject *list, int startpos, int pos) { - PyObject *newitem, *parent; - int parentpos; - - newitem = PySequence_GetItem(list,pos); - - PyObject *newitem_wakeTime_obj = PyObject_GetAttrString(newitem, "wakeTime"); - double newitem_wakeTime = 0.0; - if (newitem_wakeTime_obj != NULL) { - newitem_wakeTime = PyFloat_AS_DOUBLE(newitem_wakeTime_obj); - Py_DECREF(newitem_wakeTime_obj); - } - - while (pos > startpos) { - parentpos = (pos - 1) >> 1; - parent = PyList_GetItem(list,parentpos); - - /* - cmp = PyObject_RichCompareBool(parent,newitem,Py_LE); - if (cmp > 0) - break; - else if (cmp < 0) - return -1; - */ - - PyObject *parent_wakeTime_obj = PyObject_GetAttrString(parent, "wakeTime"); - double parent_wakeTime = 0.0; - if (parent_wakeTime_obj != NULL) { - parent_wakeTime = PyFloat_AS_DOUBLE(parent_wakeTime_obj); - Py_DECREF(parent_wakeTime_obj); - } - - if (parent_wakeTime <= newitem_wakeTime) { - break; - } - - Py_INCREF(parent); - PyList_SetItem(list,pos,parent); - pos = parentpos; - } - PyList_SetItem(list,pos,newitem); - return 0; -} - -static int -_siftup(PyObject *list, int pos) { - PyObject *newitem, *right, *child; - int endpos, rightpos, childpos; - int startpos = pos; - - endpos = PyList_Size(list); - newitem = PySequence_GetItem(list,pos); - - childpos = (2*pos)+1; - while (childpos < endpos) { - rightpos = childpos + 1; - child = PySequence_Fast_GET_ITEM(list,childpos); - - PyObject *child_wakeTime_obj = PyObject_GetAttrString(child, "wakeTime"); - double child_wakeTime = 0.0; - if (child_wakeTime_obj != NULL) { - child_wakeTime = PyFloat_AS_DOUBLE(child_wakeTime_obj); - Py_DECREF(child_wakeTime_obj); - } - - - if (rightpos < endpos) { - right = PySequence_Fast_GET_ITEM(list,rightpos); - - PyObject *right_wakeTime_obj = PyObject_GetAttrString(right, "wakeTime"); - double right_wakeTime = 0.0; - if (right_wakeTime_obj != NULL) { - right_wakeTime = PyFloat_AS_DOUBLE(right_wakeTime_obj); - Py_DECREF(right_wakeTime_obj); - } - - /* - cmp = PyObject_RichCompareBool(right,child,Py_LE); - if (cmp > 0) - childpos = rightpos; - else if (cmp < 0) - return -1; - */ - - if (right_wakeTime <= child_wakeTime) { - childpos = rightpos; - } - } - child = PySequence_GetItem(list,childpos); - PyList_SetItem(list,pos,child); - pos = childpos; - childpos = (2*pos)+1; - } - PyList_SetItem(list,pos,newitem); - - return _siftdown(list,startpos,pos); -} - -static PyMethodDef heapqcMethods[] = { - {"heappush",heappush,METH_VARARGS}, - {"heappop",heappop,METH_VARARGS}, - {"heapreplace",heapreplace,METH_VARARGS}, - {"heapify",heapify,METH_VARARGS}, - {NULL, NULL} /* Sentinel */ -}; - -void initlibheapq(void) { - (void) Py_InitModule("libheapq", heapqcMethods); -}; - -void initlibp3heapq(void) { - (void) Py_InitModule("libp3heapq", heapqcMethods); -}; - diff --git a/direct/src/http/LandingPage.py b/direct/src/http/LandingPage.py index 927994d326..212e3a6e20 100755 --- a/direct/src/http/LandingPage.py +++ b/direct/src/http/LandingPage.py @@ -3,7 +3,7 @@ from direct.directnotify.DirectNotifyGlobal import directNotify from pandac.PandaModules import VirtualFileSystem from pandac.PandaModules import Filename from pandac.PandaModules import DSearchPath -from direct.showbase import ElementTree as ET +import xml.etree.ElementTree as ET import LandingPageHTML from StringIO import StringIO diff --git a/direct/src/http/LandingPageHTML.py b/direct/src/http/LandingPageHTML.py index b40eac6324..bc04caf80e 100755 --- a/direct/src/http/LandingPageHTML.py +++ b/direct/src/http/LandingPageHTML.py @@ -1,6 +1,6 @@ # -- Text content for the landing page. You should change these for yours! -- -from direct.showbase import ElementTree as ET +import xml.etree.ElementTree as ET title = "Landing Page" defaultTitle = title diff --git a/direct/src/http/WebRequest.py b/direct/src/http/WebRequest.py index 95b058ef5e..dc40be7e28 100755 --- a/direct/src/http/WebRequest.py +++ b/direct/src/http/WebRequest.py @@ -4,7 +4,7 @@ from direct.directnotify.DirectNotifyGlobal import directNotify from direct.task.TaskManagerGlobal import taskMgr from direct.task import Task from LandingPage import LandingPage -from direct.showbase import ElementTree as ET +import xml.etree.ElementTree as ET notify = directNotify.newCategory('WebRequestDispatcher') diff --git a/direct/src/pyinst/Builder.py b/direct/src/pyinst/Builder.py deleted file mode 100644 index b43f18172b..0000000000 --- a/direct/src/pyinst/Builder.py +++ /dev/null @@ -1,504 +0,0 @@ -import string -import pprint -import sys -import os -import ConfigParser -import pprint -import shutil -import tempfile -import ltoc -import tocfilter -import resource -import archive -import archivebuilder -import carchive - -logfile = None -autopath = [] -built = {} -copyFile = None - -class Target: - def __init__(self, cfg, sectnm, cnvrts): - self.children = [] - self._dependencies = ltoc.lTOC() # the stuff an outer package will need to use me - self.cfg = cfg - self.__name__ = 'joe' - for optnm in cfg.options(sectnm): - cnvrt = cnvrts.get(optnm, 'getstringlist') - if cnvrt: - f = getattr(self, cnvrt, None) - if f: - self.__dict__[optnm] = f(cfg.get(sectnm, optnm)) - if not hasattr(self, 'name'): - self.name = self.__name__ - print "Initializing", self.__name__ - self.pathprefix = autopath + self.pathprefix - self.pathprefix.append(os.path.join(pyinsthome, 'support')) - for z in self.zlib: - if z in self.cfg.sections(): - self.children.append(z) - else: - raise ValueError, "%s - zlib '%s' does not refer to a sections" \ - % (self.name, z) - for i in range(len(self.misc)): - x = self.misc[i] - if x in self.cfg.sections(): - if self.cfg.get(x, "type") == 'PYZ': - self.zlib.append(x) - self.misc[i] = None - self.children.append(x) - self.misc = filter(None, self.misc) - self.edit() - self.toc = ltoc.lTOC() - for thingie in self.excludes: - try: - fltr = tocfilter.makefilter(thingie, self.pathprefix) - except ValueError: - print "Warning: '%s' not found - no filter created" % thingie - else: - self.toc.addFilter(fltr) - if self.exstdlib: - self.toc.addFilter(tocfilter.StdLibFilter()) - if self.extypes: - self.toc.addFilter(tocfilter.ExtFilter(self.extypes)) - if self.expatterns: - self.toc.addFilter(tocfilter.PatternFilter(self.expatterns)) - - ##------utilities------## - def dump(self): - logfile.write("---- %s: %s -----\n" % (self.__class__.__name__, self.name)) - pprint.pprint(self.__dict__, logfile) - def getstringlist(self, opt): - tmp = string.split(opt, ',') - return filter(None, map(string.strip, tmp)) - def getstring(self, opt): - return opt - def getbool(self, opt): - if opt in ('0','f','F','n','N'): - return 0 - return 1 - ##-----framework-----## - def build(self): - print "Gathering components of %s" % self.name - self.gather() - logfile.write("Final Table of Contents for %s:\n" % self.name) - pprint.pprint(self.toc.toList(), logfile) - print "Creating %s" % self.name - self.assemble() - ##-----overrideables-----## - def edit(self): - pass - def gather(self): - pass - def assemble(self): - pass - -class PYZTarget(Target): - def __init__(self, cfg, sectnm, cnvrts): - Target.__init__(self, cfg, sectnm, cnvrts) - # to use a PYZTarget, you'll need imputil and archive - archivebuilder.GetCompiled([os.path.join(pyinsthome, 'imputil.py')]) - print "pyinsthome:", pyinsthome - imputil = resource.makeresource('imputil.py', [pyinsthome]) - self._dependencies.append(imputil) - archivebuilder.GetCompiled([os.path.join(pyinsthome, 'archive_rt.py')]) - archmodule = resource.makeresource('archive_rt.py', [pyinsthome]) - self._dependencies.merge(archmodule.dependencies()) - self._dependencies.append(archmodule) - self.toc.addFilter(archmodule) - self.toc.addFilter(imputil) - for mod in archmodule.modules: - self.toc.addFilter(mod) - def edit(self): - if self.extypes: - print "PYZ target %s ignoring extypes = %s" % (self.__name__, self.extypes) - - def gather(self): - for script in self.dependencies: - rsrc = resource.makeresource(script, self.pathprefix) - if not isinstance(rsrc, resource.scriptresource): - print "Bug alert - Made %s from %s!" % (rsrc, script) - self.toc.merge(rsrc.modules) - logfile.write("lTOC after expanding 'depends':\n") - pprint.pprint(self.toc.toList(), logfile) - for thingie in self.includes + self.directories + self.packages: - rsrc = resource.makeresource(thingie, self.pathprefix) -## if not isinstance(rsrc, resource.pythonresource): -## print "PYZ target %s ignoring include %s" % (self.name, thingie) -## else: - self.toc.merge(rsrc.contents()) - logfile.write("lTOC after includes, dir, pkgs:\n") - pprint.pprint(self.toc.toList(), logfile) - self.toc.addFilter(tocfilter.ExtFilter(['.py', '.pyc', '.pyo'], 1)) - logfile.write("Applying the following filters:\n") - pprint.pprint(self.toc.filters, logfile) - self.toc.filter() - - def assemble(self): - contents = self.toc.toList() - if contents: - lib = archive.ZlibArchive() - lib.build(self.name, archivebuilder.GetCompiled(self.toc.toList())) - -class CollectTarget(Target): - def __init__(self, cfg, sectnm, cnvrts): - Target.__init__(self, cfg, sectnm, cnvrts) - - _rsrcdict = {'COLLECT': resource.dirresource, 'PYZ': resource.zlibresource, 'CARCHIVE': resource.archiveresource} - - def gather(self): - if self.support: - # the bare minimum - self.toc.merge([resource.makeresource('python20.dll')]) - self.toc.merge([resource.makeresource('exceptions.pyc').asBinary()]) - # zlib, bindepends, misc, trees, destdir - for i in range(len(self.zlib)): - # z refers to the section name - z = self.zlib[i] - nm = self.cfg.get(z, 'name') - try: - self.toc.merge([resource.makeresource(nm, ['.'])]) - except ValueError: - # zlibs aren't written if they turn out to be empty - self.zlib[i] = None - self.zlib = filter(None, self.zlib) - if self.zlib: - target = built.get(self.zlib[0], None) - if target: - self.toc.merge(target._dependencies) - for script in self.bindepends: - rsrc = resource.makeresource(script, self.pathprefix) - self.toc.merge(rsrc.binaries) - logfile.write('ltoc after bindepends:\n') - pprint.pprint(self.toc.toList(), logfile) - for thingie in self.misc: - if thingie in self.cfg.sections(): - name = self.cfg.get(thingie, "name") - typ = self.cfg.get(thingie, "type") - klass = self._rsrcdict.get(typ, resource.dataresource) - rsrc = apply(klass, (name, name)) - #now make sure we have the stuff the resource requires - target = built.get(thingie, None) - if target: - self.toc.merge(target._dependencies) - else: - rsrc = resource.makeresource(thingie, self.pathprefix) - self.toc.merge(rsrc.contents()) - logfile.write('ltoc after misc:\n') - pprint.pprint(self.toc.toList(), logfile) - for script in self.script: - if string.find(script, '.') == -1: - script = script + '.py' - rsrc = resource.makeresource(script, self.pathprefix) - if rsrc.typ == 'm': - rsrc.typ = 's' - self.toc.merge([rsrc]) - logfile.write('ltoc after scripts:\n') - pprint.pprint(self.toc.toList(), logfile) - for tree in self.trees: - try: - rsrc = resource.treeresource('.', tree) - except ValueError: - print "tree %s not found" % tree - else: - self.toc.merge(rsrc.contents()) - logfile.write('ltoc after trees:\n') - pprint.pprint(self.toc.toList(), logfile) - self.toc.addFilter(tocfilter.TypeFilter(['d'])) - logfile.write("Applying the following filters:\n") - pprint.pprint(self.toc.filters, logfile) - self.toc.filter() - #don't dupe stuff in a zlib that's part of this target - if self.zlib: - ztoc = ltoc.lTOC() - for zlibnm in self.zlib: - target = built.get(zlibnm, None) - if target: - ztoc.merge(target.toc) - for i in range(len(self.toc)-1, -1, -1): - rsrc = self.toc[i] - if isinstance(rsrc, resource.moduleresource) and rsrc in ztoc: - del self.toc[i] - - def assemble(self): - if os.path.exists(self.name): - if os.path.isdir(self.name): - for fnm in os.listdir(self.name): - try: - os.remove(os.path.join(self.name, fnm)) - except: - print "Could not delete file %s" % os.path.join(self.name, fnm) - else: - os.makedirs(self.name) - mysite = [] - for nm, path, typ in self.toc.toList(): - shutil.copy2(path, self.name) - if typ == 'z': - mysite.append('imputil.FuncImporter(archive.ZlibArchive("%s", 0).get_code).install()' % nm) - if mysite: - mysite.insert(0, 'import archive, imputil') - open(os.path.join(self.name, 'site.py'),'w').write(string.join(mysite, '\n')) - - -class ArchiveTarget(CollectTarget): - usefullname = 1 - def __init__(self, cfg, sectnm, cnvrts): - CollectTarget.__init__(self, cfg, sectnm, cnvrts) - archivebuilder.GetCompiled([os.path.join(pyinsthome, 'carchive_rt.py')]) - carchmodule = resource.makeresource('carchive_rt.py', [pyinsthome]) - self._dependencies.merge(carchmodule.dependencies()) - self._dependencies.append(carchmodule) - - def edit(self): - if self.destdir: - print "Warning 'destdir = %s' ignored for %s" % (self.destdir, self.name) - - def gather(self): - CollectTarget.gather(self) - - _cdict = {'s':2,'m':1,'b':1,'x':1,'a':0,'z':0, 'p':1} - - def assemble(self, pkgnm=None): - if pkgnm is None: - pkgnm = self.name - arch = carchive.CArchive() - toc = [] - pytoc = [] - for nm, path, typ in self.toc.toList(): - compress = self._cdict[typ] - if typ == 'b' or (self.usefullname and typ in 'ms'): - nm = os.path.basename(path) - if typ == 'm': - pytoc.append((nm, path, compress, typ)) - else: - toc.append((nm, path, compress, typ)) - toc = toc + archivebuilder.GetCompiled(pytoc) - arch.build(pkgnm, toc) - return arch - -class FullExeTarget(ArchiveTarget): - usefullname = 0 - def __init__(self, cfg, sectnm, cnvrts): - ArchiveTarget.__init__(self, cfg, sectnm, cnvrts) - - def gather(self): - for script in self.script: - #print "FullExeTarget.gather: script is", repr(script) - rsrc = resource.makeresource(script, self.pathprefix) - rsrc = resource.scriptresource(rsrc.name, rsrc.path) - #print " resource is", repr(rsrc) - self.toc.merge(rsrc.binaries) - ArchiveTarget.gather(self) - if not self.zlib: - self.toc.merge(rsrc.modules) - self._dependencies = ltoc.lTOC() - - _cdict = {'s':2,'m':0,'b':1,'x':0,'a':0,'z':0} - _edict = { (1, 1):'Runw_d.exe', (1, 0):'Runw.exe', (0, 1):'Run_d.exe', (0, 0):'Run.exe'} - - def assemble(self): - pkgname = tempfile.mktemp() - arch = ArchiveTarget.assemble(self, pkgname) - exe = self._edict[(self.userunw, self.debug)] - exe = os.path.normpath(os.path.join(pyinsthome, 'support', exe)) -## copyFile([exe, pkgname], self.name) -## os.remove(pkgname) - # Thomas Heller's icon code - # my version - if self.icon: - myexe = tempfile.mktemp() - copyFile (exe, myexe) - try: - from icon import CopyIcons - CopyIcons(myexe, self.icon) - except ImportError: - print "win32api is required for updating icons" - print "You should have win32api.pyd and PyWinTypes20.dll" - print "in the installation directory." - print "Please copy them to Python's DLLS subdirectory" - print "(or install Mark Hammond's Win32 extensions)." -## iconfile = None -## for name in self.cfg.sections(): -## if self.cfg.get (name, "type") == "STANDALONE": -## try: -## iconfile = self.cfg.get (name, "iconfile") -## except: -## pass -## if iconfile: -## from icon import CopyIcons -## CopyIcons (myexe, iconfile) - copyFile ([myexe, pkgname], self.name) - os.remove(myexe) - else: - copyFile([exe, pkgname], self.name) - #os.remove(pkgname) - -class ExeTarget(FullExeTarget): - def __init__(self, cfg, sectnm, cnvrts): - FullExeTarget.__init__(self, cfg, sectnm, cnvrts) - - def edit(self): - if not self.script: - raise ValueError, "EXE target %s requires 'script=