/* * Restart * Author: Linh Ngo (Swiftest@Copperdiku) * Date : 4/10/92 * Restarts dmserver in the event of a crash. Only root and group * dmserver should have access to run it. * * Restart also performs a copy-over (copy new files from working * directory to /usr/games/diku directory) if given the copyover flag * * Should be setuid, and owned by user root, and group dmserver like this: * * -rws--x--- 1 root dmserver 51539 Apr 10 20:15 restart* * * Restart will also redirect stderr into the SYSLOG file and * do a chdir() to the /usr/games/diku directory so we don't have * to define the library path like before. * * Define DEBUG when testing as we don't want to corrupt the real * data files, or just do a kill -9 pid so that the autosave is not * invoked. * * Define NO_STRDUP if the library call strdup() is missing. * * TO DO: * 1. zero out the IFS environment flag (or change it to space? colon?) * This for security measures (needed for older shells). * * ---------- * CHANGE LOG * ---------- * 6/2 Added chdir() so that we don't have to define the library path * 9/17 Added copy-over capability with copyover flag */ #include <stdio.h> /* printf(), etc. */ #include <string.h> /* for strdup(), etc. */ #include <pwd.h> #include <ctype.h> /* for isnum() */ #define CRASH_SCRIPT "scripts/crash.csh" #define INSTALLFILE "scripts/diku.install" #define MIN_PORT 4000 /* port must be equal or higher than this */ #if !defined(DEBUG) #define CHDIR "<path to run mud from>" #define BINFULL "<path to run mud from>/dmserver" #define BINSHORT "dmserver" #define SYSLOG "<path to run mud from>/syslog" #define DEFAULT_PORT "4000" /* No port specified defaults to port 4000 */ #else /* DEBUG */ #define LIBPATH "./lib" #define BINFULL "dmserver" #define BINSHORT "dmserver" #define SYSLOG "syslogtest" #define DEFAULT_PORT "4444" #endif /* DEBUG */ #ifdef NO_STRDUP char * strdup( char *str) { char *tmp = (char*)malloc(strlen(str)+1); if(tmp == (char*)0 ) { perror(str), exit(1); } strcpy(tmp, str); return tmp; } #endif /* NO_STRDUP */ main(int argc, char **argv) { int copyover = 0; /* 0 == restart the mud, 1 == copyover */ char *port; int ruid, euid; int pid; struct passwd *pswd; /* Check args */ #ifdef DEBUG printf("DEBUG flag set\n"); #endif if(argc == 1){ port = strdup( DEFAULT_PORT ); } else if(argc==2 ){ if( !strcmp( argv[1], "copyover") ){ copyover = 1; } else { port = strdup(argv[1]); if( atoi(port) < MIN_PORT ){ fprintf(stderr, "Error: Port argument [%s] must be greater than or equal to 4000\n",port); exit(-1); } } } else { fprintf(stderr,"usage: restart [ port | copyover ]\n"); exit(1); } if( !copyover ) { printf("Restart: Selected port number is %s\n", port); } else { printf("Restart: Attempting copyover\n"); } /* Fork to go into the background */ if((pid=fork())== -1) { perror("fork"); exit(1); } else if(pid!=0){ /* Parent dies */ exit(0); } /* Child continues */ ruid = getuid(); euid = geteuid(); pswd = getpwuid(ruid); /* * This sets the real user id to be the effective one * so we are really root. This is required to run dmserver. */ if (setreuid(euid, euid) != 0 ) { perror("setreuid"); exit(1); } /* * Run CRASH_SCRIPT to clean up the log files first */ switch( pid=fork() ){ case -1: perror("fork"); exit(1); case 0: /* child executes script */ fprintf(stderr,"Restart: Executing %s\n", CRASH_SCRIPT); execl(CRASH_SCRIPT, CRASH_SCRIPT, (char*)0 ); perror(CRASH_SCRIPT); /* never get here if works */ exit(1); default: /* parent */ wait(); /* parent waits for shell script to finish */ fprintf(stderr,"Restart: Parent done waiting for crash_script\n"); break; } /* If we used the copyover switch, then execute the * diku.install Bourne script. */ if( copyover ) { fprintf(stderr,"Copyover: executing %s\n",INSTALLFILE); execl(INSTALLFILE, INSTALLFILE, (char*)0); perror("execl installfile"); exit(1); } /* Change directory to CHDIR */ fprintf(stderr,"Restart: changing directory to %s\n",CHDIR); if( chdir(CHDIR) == -1 ) { perror(CHDIR); exit(1); } /* Append stderr to SYSLOG so we can continue logging */ if(freopen(SYSLOG, "w", stderr) == (FILE*)0){ perror(SYSLOG); exit(1); } /* Execute our binary file securely (hopefully) */ execl(BINFULL, BINSHORT, port, (char*)0 ); perror("execl dmserver"); exit(1); }