X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fsetup.c;h=91a979411d51f959aae51290dd3fcfa263f23a34;hb=8e165dd308679f195af8614d62dbdb4e43238495;hp=18938e80a28b88dda92ab7a206d2879b93fe0046;hpb=5f8562aa6e7314bf14b177081aac0016e9aabbcd;p=citadel.git diff --git a/webcit/setup.c b/webcit/setup.c index 18938e80a..91a979411 100644 --- a/webcit/setup.c +++ b/webcit/setup.c @@ -2,45 +2,51 @@ * $Id$ * * WebCit setup utility + * + * (This is basically just an install wizard. It's not required.) * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - +#include "sysdep.h" #include "webcit.h" - -#ifdef HAVE_NEWT -#include -#endif +#include "webserver.h" #define UI_TEXT 0 /* Default setup type -- text only */ +#define UI_DIALOG 2 /* Use the 'dialog' program */ #define UI_SILENT 3 /* Silent running, for use in scripts */ -#define UI_NEWT 4 /* Use the "newt" window library */ int setup_type; char setup_directory[SIZ]; -char init_entry[SIZ]; - +int using_web_installer = 0; +char suggested_url[SIZ]; + +/* some copies... */ +int lprintf(int loglevel, const char *format, ...){return 0;} +void wc_printf(const char *format,...){} + +void RegisterNS(const char *NSName, long len, + int nMinArgs, + int nMaxArgs, + WCHandlerFunc HandlerFunc, + WCPreevalFunc PreEvalFunc, + int ContextRequired){} +pthread_key_t MyConKey; + +#ifdef ENABLE_NLS + +#ifdef HAVE_USELOCALE +int localeoffset = 1; +#else +int localeoffset = 0; +#endif +#endif /* - * Set an entry in inittab to the desired state + * Delete an entry from /etc/inittab */ -void set_init_entry(char *which_entry, char *new_state) { +void delete_init_entry(char *which_entry) +{ char *inittab = NULL; FILE *fp; char buf[SIZ]; @@ -58,15 +64,13 @@ void set_init_entry(char *which_entry, char *new_state) { while(fgets(buf, sizeof buf, fp) != NULL) { if (num_tokens(buf, ':') == 4) { - extract_token(entry, buf, 0, ':'); - extract_token(levels, buf, 1, ':'); - extract_token(state, buf, 2, ':'); - extract_token(prog, buf, 3, ':'); /* includes 0x0a LF */ + extract_token(entry, buf, 0, ':', sizeof entry); + extract_token(levels, buf, 1, ':', sizeof levels); + extract_token(state, buf, 2, ':', sizeof state); + extract_token(prog, buf, 3, ':', sizeof prog); /* includes 0x0a LF */ if (!strcmp(entry, which_entry)) { - strcpy(state, new_state); - sprintf(buf, "%s:%s:%s:%s", - entry, levels, state, prog); + strcpy(state, "off"); /* disable it */ } } @@ -92,23 +96,26 @@ void set_init_entry(char *which_entry, char *new_state) { /* - * Shut down the Citadel service if necessary, during setup. + * Remove any /etc/inittab entries for webcit, because we don't + * start it that way anymore. */ -void shutdown_service(void) { +void delete_the_old_way(void) { FILE *infp; - char buf[SIZ]; - char looking_for[SIZ]; + char buf[1024]; + char looking_for[1024]; int have_entry = 0; - char entry[SIZ]; - char prog[SIZ]; + char entry[1024]; + char prog[1024]; + char init_entry[1024]; + strcpy(init_entry, ""); - /* Determine the fully qualified path name of citserver */ - snprintf(looking_for, sizeof looking_for, "%s/citserver ", WEBCITDIR); + /* Determine the fully qualified path name of webcit */ + snprintf(looking_for, sizeof looking_for, "%s/webcit ", setup_directory); /* Pound through /etc/inittab line by line. Set have_entry to 1 if - * an entry is found which we believe starts citserver. + * an entry is found which we believe starts webcit. */ infp = fopen("/etc/inittab", "r"); if (infp == NULL) { @@ -116,8 +123,8 @@ void shutdown_service(void) { } else { while (fgets(buf, sizeof buf, infp) != NULL) { buf[strlen(buf) - 1] = 0; - extract_token(entry, buf, 0, ':'); - extract_token(prog, buf, 3, ':'); + extract_token(entry, buf, 0, ':', sizeof entry); + extract_token(prog, buf, 3, ':', sizeof prog); if (!strncasecmp(prog, looking_for, strlen(looking_for))) { ++have_entry; @@ -130,28 +137,13 @@ void shutdown_service(void) { /* Bail out if there's nothing to do. */ if (!have_entry) return; - set_init_entry(init_entry, "off"); -} - - -/* - * Start the Citadel service. - */ -void start_the_service(void) { - if (strlen(init_entry) > 0) { - set_init_entry(init_entry, "respawn"); - } + delete_init_entry(init_entry); } void cleanup(int exitcode) { -#ifdef HAVE_NEWT - newtCls(); - newtRefresh(); - newtFinished(); -#endif exit(exitcode); } @@ -166,71 +158,63 @@ void title(char *text) -int yesno(char *question) + +int yesno(char *question, int default_value) { -#ifdef HAVE_NEWT - newtComponent form = NULL; - newtComponent yesbutton = NULL; - newtComponent nobutton = NULL; int i = 0; -#endif int answer = 0; - char buf[SIZ]; + char buf[SIZ] = ""; switch (setup_type) { case UI_TEXT: do { - printf("%s\nYes/No --> ", question); - fgets(buf, sizeof buf, stdin); - answer = tolower(buf[0]); - if (answer == 'y') - answer = 1; - else if (answer == 'n') - answer = 0; + printf("%s\nYes/No [%s] --> ", + question, + ( default_value ? "Yes" : "No" ) + ); + if (fgets(buf, sizeof buf, stdin)) + { + answer = tolower(buf[0]); + if ((buf[0]==0) || (buf[0]==13) || (buf[0]==10)) + answer = default_value; + else if (answer == 'y') + answer = 1; + else if (answer == 'n') + answer = 0; + } + } while ((answer < 0) || (answer > 1)); break; -#ifdef HAVE_NEWT - case UI_NEWT: - newtCenteredWindow(76, 10, "Question"); - form = newtForm(NULL, NULL, 0); - for (i=0; i%s", + getenv("CTDL_DIALOG"), + prompt, + str, + dialog_result); + system(buf); + fp = fopen(dialog_result, "r"); + if (fp != NULL) { + if (fgets(str, sizeof buf, fp)){ + if (str[strlen(str)-1] == 10) { + str[strlen(str)-1] = 0; + } + } + fclose(fp); + unlink(dialog_result); } - newtFormAddComponent(form, newtEntry(1, 8, str, 74, &result, - NEWT_FLAG_RETURNEXIT)); - newtRunForm(form); - strcpy(str, result); - - newtPopWindow(); - newtFormDestroy(form); + break; -#endif } } -void important_message(char *title, char *msgtext) +extern const char *AvailLang[]; +int GetLocalePrefs(void) { -#ifdef HAVE_NEWT - newtComponent form = NULL; + int nLocales; + StrBuf *Buf; + char buf[SIZ]; + char dialog_result[PATH_MAX]; + FILE *fp; int i = 0; + int offs = 0; + + + nLocales = 0; + while (!IsEmptyStr(AvailLang[nLocales])) + nLocales++; + + Buf = NewStrBuf(); + + StrBufAppendBufPlain(Buf, HKEY("Select the locale webcit should use : \n"), 0); +#ifdef HAVE_USELOCALE + StrBufAppendBufPlain(Buf, HKEY(" 0 Let the user select it at the login prompt (default)\n"), 0); + offs ++; #endif + for (i = 0; i < nLocales; i++) { + StrBufAppendPrintf(Buf, " %ld: %s\n", i + offs, AvailLang[i]); + + } + + switch (setup_type) { + case UI_TEXT: + title("WebCit setup"); + printf("\n%s\n", ChrPtr(Buf)); + printf("This is currently set to:\n%ld\n", 0L); + printf("Enter new value or press return to leave unchanged:\n"); + if (fgets(buf, sizeof buf, stdin)) + return atoi(buf); + break; + + case UI_DIALOG: + CtdlMakeTempFileName(dialog_result, sizeof dialog_result); + sprintf(buf, "exec %s --inputbox '%s' 19 72 '%ld' 2>%s", + getenv("CTDL_DIALOG"), + ChrPtr(Buf), + 0L, + dialog_result); + system(buf); + fp = fopen(dialog_result, "r"); + if (fp != NULL) { + char *str = &buf[0]; + if (fgets(str, sizeof buf, fp)){ + if (str[strlen(str)-1] == 10) { + str[strlen(str)-1] = 0; + } + } + fclose(fp); + unlink(dialog_result); + return atoi(buf); + } + break; + + } + return 0; +} + +void important_message(char *title, char *msgtext) +{ char buf[SIZ]; switch (setup_type) { @@ -280,24 +327,15 @@ void important_message(char *title, char *msgtext) printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); printf(" %s \n\n%s\n\n", title, msgtext); printf("Press return to continue..."); - fgets(buf, sizeof buf, stdin); + if (fgets(buf, sizeof buf, stdin)); break; -#ifdef HAVE_NEWT - case UI_NEWT: - newtCenteredWindow(76, 10, title); - form = newtForm(NULL, NULL, 0); - for (i=0; i 0) && (curr <= cmax)) { - newtScaleSet(scale, curr); - newtRefresh(); + sprintf(buf, "exec %s --gauge '%s' 7 72 0", + getenv("CTDL_DIALOG"), + text); + fp = popen(buf, "w"); + if (fp != NULL) { + fprintf(fp, "0\n"); + fflush(fp); + } + } + else if (curr == cmax) { + if (fp != NULL) { + fprintf(fp, "100\n"); + pclose(fp); + fp = NULL; + } } - if (curr == cmax) { - newtFormDestroy(form); - newtPopWindow(); - newtRefresh(); + else { + a = (curr * 100) / cmax; + if (fp != NULL) { + fprintf(fp, "%ld\n", a); + fflush(fp); + } } break; -#endif - } } @@ -375,100 +409,233 @@ void progress(char *text, long int curr, long int cmax) /* - * check_inittab_entry() -- Make sure "webserver" is in /etc/inittab + * install_init_scripts() -- Create and deploy SysV init scripts. * */ -void check_inittab_entry(void) +void install_init_scripts(void) { - FILE *infp; - char buf[SIZ]; - char looking_for[SIZ]; - char question[128]; - char entryname[5]; - char listenport[128]; +#ifdef ENABLE_NLS + int localechoice; +#endif + char question[1024]; + char buf[256]; + char http_port[128]; +#ifdef HAVE_OPENSSL + char https_port[128]; +#endif char hostname[128]; char portname[128]; + char command[SIZ]; + struct utsname my_utsname; + struct stat etcinitd; + FILE *fp; + char *initfile = "/etc/init.d/webcit"; - /* Determine the fully qualified path name of citserver */ - snprintf(looking_for, sizeof looking_for, "%s/webserver ", WEBCITDIR); - - /* If there's already an entry, then we have nothing left to do. */ - if (strlen(init_entry) > 0) { - return; + fp = fopen(initfile, "r"); + if (fp != NULL) { + if (yesno("WebCit already appears to be configured to start at boot.\n" + "Would you like to keep your boot configuration as is?\n", 1) == 1) { + return; + } + fclose(fp); + } /* Otherwise, prompt the user to create an entry. */ snprintf(question, sizeof question, - "There is no '%s' entry in /etc/inittab.\n" - "Would you like to add one?", - looking_for); - if (yesno(question) == 0) + "Would you like to automatically start WebCit at boot?" + ); + if (yesno(question, 1) == 0) return; - snprintf(question, sizeof question, - "On which port do you want WebCit to listen for HTTP " - "requests?\n\nYou can use the standard port (80) if you are " - "not running another web server\n(such as Apache), otherwise " - "select another port."); - sprintf(listenport, "2000"); - set_value(question, listenport); - /* Find out where Citadel is. */ - snprintf(question, sizeof question, - "Is the Citadel service running on the same host as WebCit?"); - if (yesno(question)) { - sprintf(hostname, "uds"); - sprintf(portname, "/usr/local/citadel"); - set_value("In what directory is Citadel installed?", portname); - } - else { - sprintf(hostname, "127.0.0.1"); - sprintf(portname, "504"); - set_value("Enter the host name or IP address of your " - "Citadel server.", hostname); - set_value("Enter the port number on which Citadel is " - "running (usually 504)", portname); +#ifdef ENABLE_NLS + + localechoice = GetLocalePrefs(); + +#endif + /* Defaults */ + sprintf(http_port, "2000"); +#ifdef HAVE_OPENSSL + sprintf(https_port, "443"); +#endif + sprintf(hostname, "uds"); + sprintf(portname, "/usr/local/citadel"); + + /* This is a very hackish way of learning the port numbers used + * in a previous install, if we are upgrading: read them out of + * the existing init script. + */ + if ((stat("/etc/init.d/", &etcinitd) == -1) && + (errno == ENOENT)) + { + if ((stat("/etc/rc.d/init.d/", &etcinitd) == -1) && + (errno == ENOENT)) + initfile = WEBCITDIR"/webcit.init"; + else + initfile = "/etc/rc.d/init.d/webcit"; } - /* Generate a unique entry name for /etc/inittab */ - snprintf(entryname, sizeof entryname, "c0"); - do { - ++entryname[1]; - if (entryname[1] > '9') { - entryname[1] = 0; - ++entryname[0]; - if (entryname[0] > 'z') { - display_error( - "Can't generate a unique entry name"); - return; + fp = fopen(initfile, "r"); + if (fp != NULL) { + while (fgets(buf, sizeof buf, fp) != NULL) { + if (strlen(buf) > 0) { + buf[strlen(buf)-1] = 0; /* strip trailing cr */ + } + if (!strncasecmp(buf, "HTTP_PORT=", 10)) { + safestrncpy(http_port, &buf[10], sizeof http_port); + } +#ifdef HAVE_OPENSSL + if (!strncasecmp(buf, "HTTPS_PORT=", 11)) { + safestrncpy(https_port, &buf[11], sizeof https_port); + } +#endif + if (!strncasecmp(buf, "CTDL_HOSTNAME=", 14)) { + safestrncpy(hostname, &buf[14], sizeof hostname); + } + if (!strncasecmp(buf, "CTDL_PORTNAME=", 14)) { + safestrncpy(portname, &buf[14], sizeof portname); } } - snprintf(buf, sizeof buf, - "grep %s: /etc/inittab >/dev/null 2>&1", entryname); - } while (system(buf) == 0); + fclose(fp); + } - /* Now write it out to /etc/inittab */ - infp = fopen("/etc/inittab", "a"); - if (infp == NULL) { - display_error(strerror(errno)); - } else { - fprintf(infp, "# Start the WebCit server...\n"); - fprintf(infp, "%s:2345:respawn:%s %s %s\n", - entryname, looking_for, hostname, portname); - fclose(infp); - strcpy(init_entry, entryname); + /* Now ask for the port numbers */ + snprintf(question, sizeof question, + "On which port do you want WebCit to listen for HTTP " + "requests?\n\nYou can use the standard port (80) if you are " + "not running another\nweb server (such as Apache), otherwise " + "select another port."); + set_value(question, http_port); + uname(&my_utsname); + sprintf(suggested_url, "http://%s:%s/", my_utsname.nodename, http_port); + +#ifdef HAVE_OPENSSL + snprintf(question, sizeof question, + "On which port do you want WebCit to listen for HTTPS " + "requests?\n\nYou can use the standard port (443) if you are " + "not running another\nweb server (such as Apache), otherwise " + "select another port."); + set_value(question, https_port); +#endif + + /* Find out where Citadel is. */ + if ( (using_web_installer) && (getenv("CITADEL") != NULL) ) { + strcpy(hostname, "uds"); + strcpy(portname, getenv("CITADEL")); + } + else { + snprintf(question, sizeof question, + "Is the Citadel service running on the same host as WebCit?"); + if (yesno(question, ((!strcasecmp(hostname, "uds")) ? 1 : 0))) { + strcpy(hostname, "uds"); + if (atoi(portname) != 0) strcpy(portname, "/usr/local/citadel"); + set_value("In what directory is Citadel installed?", portname); + } + else { + if (!strcasecmp(hostname, "uds")) strcpy(hostname, "127.0.0.1"); + if (atoi(portname) == 0) strcpy(portname, "504"); + set_value("Enter the host name or IP address of your " + "Citadel server.", hostname); + set_value("Enter the port number on which Citadel is " + "running (usually 504)", portname); + } } -} + fp = fopen(initfile, "w"); + + fprintf(fp, "#!/bin/sh\n" + "\n" + "# uncomment this to create coredumps as described in\n" + "# http://www.citadel.org/doku.php/faq:mastering_your_os:gdb#how.do.i.make.my.system.produce.core-files\n" + "# ulimit -c unlimited\n" + "WEBCIT_DIR=%s\n", setup_directory); + fprintf(fp, "HTTP_PORT=%s\n", http_port); +#ifdef HAVE_OPENSSL + fprintf(fp, "HTTPS_PORT=%s\n", https_port); +#endif + fprintf(fp, "CTDL_HOSTNAME=%s\n", hostname); + fprintf(fp, "CTDL_PORTNAME=%s\n", portname); + +#ifdef ENABLE_NLS + + if (localechoice == 0) { +#ifdef HAVE_USELOCALE + fprintf(fp, "unset LANG\n"); +#else + fprintf(fp, "export WEBCIT_LANG=c\n"); +#endif + } + else { + fprintf(fp, "export WEBCIT_LANG=%s\n", AvailLang[localechoice - localeoffset]); + } +#else + fprintf(fp, "# your system doesn't support locales\n"); +#endif + fprintf(fp, "\n" + "\n" + "case \"$1\" in\n" + "\n" + "start) echo -n \"Starting WebCit... \"\n" + " if $WEBCIT_DIR/webcit " + "-D/var/run/webcit.pid " + "-p$HTTP_PORT $CTDL_HOSTNAME $CTDL_PORTNAME\n" + " then\n" + " echo \"ok\"\n" + " else\n" + " echo \"failed\"\n" + " fi\n"); +#ifdef HAVE_OPENSSL + fprintf(fp, " echo -n \"Starting WebCit SSL... \"\n" + " if $WEBCIT_DIR/webcit " + "-D/var/run/webcit-ssl.pid " + "-s -p$HTTPS_PORT $CTDL_HOSTNAME $CTDL_PORTNAME\n" + " then\n" + " echo \"ok\"\n" + " else\n" + " echo \"failed\"\n" + " fi\n"); +#endif + fprintf(fp, " ;;\n" + "stop) echo -n \"Stopping WebCit... \"\n" + " if kill `cat /var/run/webcit.pid 2>/dev/null` 2>/dev/null\n" + " then\n" + " echo \"ok\"\n" + " else\n" + " echo \"failed\"\n" + " fi\n" + " rm -f /var/run/webcit.pid 2>/dev/null\n"); +#ifdef HAVE_OPENSSL + fprintf(fp, " echo -n \"Stopping WebCit SSL... \"\n" + " if kill `cat /var/run/webcit-ssl.pid 2>/dev/null` 2>/dev/null\n" + " then\n" + " echo \"ok\"\n" + " else\n" + " echo \"failed\"\n" + " fi\n" + " rm -f /var/run/webcit-ssl.pid 2>/dev/null\n"); +#endif + fprintf(fp, " ;;\n" + "restart) $0 stop\n" + " $0 start\n" + " ;;\n" + "*) echo \"Usage: $0 {start|stop|restart}\"\n" + " exit 1\n" + " ;;\n" + "esac\n" + ); -/* - * Check to see if our server really works. Returns 0 on success. - */ -int test_server(void) { + fclose(fp); + chmod(initfile, 0755); - return 0; /* FIXME ... stubbed out */ + /* Set up the run levels. */ + system("/bin/rm -f /etc/rc?.d/[SK]??webcit 2>/dev/null"); + snprintf(command, sizeof(command), "for x in 2 3 4 5 ; do [ -d /etc/rc$x.d ] && ln -s %s /etc/rc$x.d/S84webcit ; done 2>/dev/null", initfile); + system(command); + snprintf(command, sizeof(command), "for x in 0 6 S; do [ -d /etc/rc$x.d ] && ln -s %s /etc/rc$x.d/K15webcit ; done 2>/dev/null", initfile); + system(command); } @@ -481,12 +648,11 @@ int test_server(void) { int discover_ui(void) { -#ifdef HAVE_NEWT - newtInit(); - newtCls(); - newtDrawRootText(0, 0, "WebCit Setup"); - return UI_NEWT; -#endif + /* Use "dialog" if we have it */ + if (getenv("CTDL_DIALOG") != NULL) { + return UI_DIALOG; + } + return UI_TEXT; } @@ -497,12 +663,18 @@ int discover_ui(void) int main(int argc, char *argv[]) { int a; - char aaa[128]; + char aaa[256]; int info_only = 0; + strcpy(suggested_url, "http://:/"); /* set an invalid setup type */ setup_type = (-1); + /* Check to see if we're running the web installer */ + if (getenv("CITADEL_INSTALLER") != NULL) { + using_web_installer = 1; + } + /* parse command line args */ for (a = 0; a < argc; ++a) { if (!strncmp(argv[a], "-u", 2)) { @@ -532,30 +704,26 @@ int main(int argc, char *argv[]) /* Get started in a valid setup directory. */ strcpy(setup_directory, WEBCITDIR); - set_value("FIXME enter your setup directory, dumbass.", - setup_directory); + if ( (using_web_installer) && (getenv("WEBCIT") != NULL) ) { + strcpy(setup_directory, getenv("WEBCIT")); + } + else { + set_value("In what directory is WebCit installed?", + setup_directory); + } if (chdir(setup_directory) != 0) { important_message("WebCit Setup", "The directory you specified does not exist."); cleanup(errno); } - /* See if we need to shut down the WebCit service. */ - for (a=0; a<=3; ++a) { - progress("Shutting down the WebCit service...", a, 3); - if (a == 0) shutdown_service(); - sleep(1); - } - - /* Make sure it's stopped. FIXME put back in - if (test_server() == 0) { - important_message("WebCit Setup", - "The WebCit service is still running.\n" - "Please stop the service manually and run " - "setup again."); - cleanup(1); - } - */ + /* + * We used to start WebCit by putting it directly into /etc/inittab. + * Since some systems are moving away from init, we can't do this anymore. + */ + progress("Removing obsolete /etc/inittab entries...", 0, 1); + delete_the_old_way(); + progress("Removing obsolete /etc/inittab entries...", 1, 1); /* Now begin. */ switch (setup_type) { @@ -567,26 +735,24 @@ int main(int argc, char *argv[]) } - check_inittab_entry(); /* Check /etc/inittab */ + /* + * If we're running on SysV, install init scripts. + */ + if (!access("/var/run", W_OK)) { + install_init_scripts(); - /* See if we can start the WebCit service. */ - if (strlen(init_entry) > 0) { - for (a=0; a<=3; ++a) { - progress("Starting the WebCit service...", a, 3); - if (a == 0) start_the_service(); - sleep(1); - } - if (test_server() == 0) { - important_message("Setup finished", - "Setup is finished. You may now log in."); - } - else { - important_message("Setup finished", - "Setup is finished, but the WebCit service " - "failed to start.\n" - "Go back and check your configuration."); + if (!access("/etc/init.d/webcit", X_OK)) { + system("/etc/init.d/webcit stop"); + system("/etc/init.d/webcit start"); } + + sprintf(aaa, + "Setup is finished. You may now log in.\n" + "Point your web browser at %s\n", suggested_url + ); + important_message("Setup finished", aaa); } + else { important_message("Setup finished", "Setup is finished. You may now start the server.");