/* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $Id: apache.c,v 1.10 1995/11/03 12:02:22 jkh Exp $ * * Copyright (c) 1995 * Coranth Gryphon. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Coranth Gryphon * for the FreeBSD Project. * 4. The name of Coranth Gryphon or the FreeBSD project may not be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY CORANTH GRYPHON ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL CORANTH GRYPHON OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include "ui_objects.h" #include "dir.h" #include "dialog.priv.h" #include "colors.h" #include "sysinstall.h" #define APACHE_HELPFILE "apache" #define APACHE_PACKAGE "apache-0.8.14" #define FREEBSD_GIF "/stand/power.gif" /* These change if the package uses different defaults */ #define APACHE_BASE "/usr/local/www" #define DATA_SUBDIR "htdocs" #define CONFIG_SUBDIR "config" /* Set up the structure to hold configuration information */ /* Note that this is only what we could fit onto the one screen */ typedef struct { char docroot[128]; /* DocumentRoot */ char userdir[128]; /* UserDir */ char welcome[32]; /* Welcome Doc */ char email[64]; /* ServerAdmin */ char hostname[64]; /* ServerName */ char user[32]; /* User */ char group[32]; /* Group */ char maxcon[8]; /* Max Connections */ } ApacheConf; static ApacheConf tconf; #define APACHE_DOCROOT_LEN 128 #define APACHE_USERDIR_LEN 128 #define APACHE_WELCOME_LEN 32 #define APACHE_EMAIL_LEN 64 #define APACHE_HOSTNAME_LEN 64 #define APACHE_USER_LEN 32 #define APACHE_GROUP_LEN 32 #define APACHE_MAXCON_LEN 8 static int okbutton, cancelbutton; /* What the screen size is meant to be */ #define APACHE_DIALOG_Y 0 #define APACHE_DIALOG_X 8 #define APACHE_DIALOG_WIDTH COLS - 16 #define APACHE_DIALOG_HEIGHT LINES - 2 /* The screen layout structure */ typedef struct _layout { int y; /* x & Y co-ordinates */ int x; int len; /* The size of the dialog on the screen */ int maxlen; /* How much the user can type in ... */ char *prompt; /* The string for the prompt */ char *help; /* The display for the help line */ void *var; /* The var to set when this changes */ int type; /* The type of the dialog to create */ void *obj; /* The obj pointer returned by libdialog */ } Layout; static Layout layout[] = { { 1, 2, 24, HOSTNAME_FIELD_LEN - 1, "Host Name:", "What name to report this host as to client browsers", tconf.hostname, STRINGOBJ, NULL }, #define LAYOUT_HOSTNAME 0 { 1, 30, 30, APACHE_EMAIL_LEN - 1, "Email Address:", "The email address of the site maintainer, e.g. webmaster@bar.com", tconf.email, STRINGOBJ, NULL }, #define LAYOUT_EMAIL 1 { 5, 3, 15, APACHE_USER_LEN - 1, "Default User:", "Default username for access to web pages", tconf.user, STRINGOBJ, NULL }, #define LAYOUT_USER 2 { 5, 22, 15, APACHE_GROUP_LEN - 1, "Default Group:", "Default group name for access to web pages", tconf.group, STRINGOBJ, NULL }, #define LAYOUT_GROUP 3 { 5, 46, 13, APACHE_MAXCON_LEN - 1, "Max Connect:", "Maximum number of concurrent http connections", tconf.maxcon, STRINGOBJ, NULL }, #define LAYOUT_MAXCON 4 { 10, 10, 43, APACHE_DOCROOT_LEN - 1, "Root Document Path:", "The top directory that holds the system web pages", tconf.docroot, STRINGOBJ, NULL }, #define LAYOUT_DOCROOT 5 { 14, 10, 18, APACHE_USERDIR_LEN - 1, "User Directory:", "Personal sub-directory that holds users' web pages (eg. ~/Web)", tconf.userdir, STRINGOBJ, NULL }, #define LAYOUT_USERDIR 6 { 14, 35, 18, APACHE_WELCOME_LEN - 1, "Default Document:", "The name of the default document found in each directory", tconf.welcome, STRINGOBJ, NULL }, #define LAYOUT_WELCOME 7 { 19, 15, 0, 0, "OK", "Select this if you are happy with these settings", &okbutton, BUTTONOBJ, NULL }, #define LAYOUT_OKBUTTON 8 { 19, 35, 0, 0, "CANCEL", "Select this if you wish to cancel this screen", &cancelbutton, BUTTONOBJ, NULL }, #define LAYOUT_CANCELBUTTON 9 { NULL }, }; DMenu MenuApacheLanguages = { DMENU_MULTIPLE_TYPE | DMENU_SELECTION_RETURNS, "Apache Languages Menu", "This allows you to specify which languages are known by your httpd server.", NULL, NULL, { { "English", "English", DMENU_SET_VARIABLE, "APACHE_English=en", 0, 0 }, { "French", "French", DMENU_SET_VARIABLE, "APACHE_French=fr", 0, 0 }, { "German", "German", DMENU_SET_VARIABLE, "APACHE_German=de", 0, 0 }, { "Italian", "Italian", DMENU_SET_VARIABLE, "APACHE_Italian=it", 0, 0 }, { "Japanese", "Japanese", DMENU_SET_VARIABLE, "APACHE_Japanese=jp", 0, 0 }, { NULL } }, }; /* This is it - how to get Apache setup values */ int apacheOpenDialog() { WINDOW *ds_win; ComposeObj *obj = NULL; ComposeObj *first, *last; int n=0, quit=FALSE, cancel=FALSE, ret; int max; char *tmp; char help[FILENAME_MAX]; char title[80]; /* We need a curses window */ ds_win = newwin(LINES, COLS, 0, 0); if (ds_win == 0) { beep(); msgConfirm("Cannot open apache dialog window!!"); return(RET_SUCCESS); } /* Say where our help comes from */ systemHelpFile(APACHE_HELPFILE, help); use_helpfile(help); /* Setup a nice screen for us to splat stuff onto */ draw_box(ds_win, APACHE_DIALOG_Y, APACHE_DIALOG_X, APACHE_DIALOG_HEIGHT, APACHE_DIALOG_WIDTH, dialog_attr, border_attr); wattrset(ds_win, dialog_attr); mvwaddstr(ds_win, APACHE_DIALOG_Y, APACHE_DIALOG_X + 20, " Apache HTTPD Configuration "); draw_box(ds_win, APACHE_DIALOG_Y + 9, APACHE_DIALOG_X + 8, APACHE_DIALOG_HEIGHT - 13, APACHE_DIALOG_WIDTH - 17, dialog_attr, border_attr); wattrset(ds_win, dialog_attr); sprintf(title, " Path Configuration "); mvwaddstr(ds_win, APACHE_DIALOG_Y + 9, APACHE_DIALOG_X + 22, title); /** Initialize the config Data Structure **/ bzero(&tconf, sizeof(tconf)); tmp = variable_get(VAR_DOMAINNAME); if (tmp) { sprintf(tconf.email, "webmaster@%s", tmp); sprintf(tconf.hostname, "www.%s", tmp); } strcpy(tconf.user, "guest"); strcpy(tconf.group, "guest"); strcpy(tconf.userdir, "public_html"); strcpy(tconf.welcome, "index.html"); strcpy(tconf.maxcon, "150"); sprintf(tconf.docroot, "%s/%s", APACHE_BASE,DATA_SUBDIR); /* Loop over the layout list, create the objects, and add them onto the chain of objects that dialog uses for traversal*/ n = 0; #define lt layout[n] while (lt.help != NULL) { switch (lt.type) { case STRINGOBJ: lt.obj = NewStringObj(ds_win, lt.prompt, lt.var, lt.y + APACHE_DIALOG_Y, lt.x + APACHE_DIALOG_X, lt.len, lt.maxlen); break; case BUTTONOBJ: lt.obj = NewButtonObj(ds_win, lt.prompt, lt.var, lt.y + APACHE_DIALOG_Y, lt.x + APACHE_DIALOG_X); break; default: msgFatal("Don't support this object yet!"); } AddObj(&obj, lt.type, (void *) lt.obj); n++; } max = n - 1; /* Find the last object we can traverse to */ last = obj; while (last->next) last = last->next; /* Find the first object in the list */ first = obj; while (first->prev) first = first->prev; /* Some more initialisation before we go into the main input loop */ n = 0; cancelbutton = 0; cancel = FALSE; okbutton = 0; /* Incoming user data - DUCK! */ while (!quit) { char help_line[80]; int i, len = strlen(lt.help); /* Display the help line at the bottom of the screen */ for (i = 0; i < 79; i++) help_line[i] = (i < len) ? lt.help[i] : ' '; help_line[i] = '\0'; use_helpline(help_line); display_helpline(ds_win, LINES - 1, COLS - 1); /* Ask for libdialog to do its stuff */ ret = PollObj(&obj); /* We are in the Hostname field - calculate the e-mail addr */ if (n == LAYOUT_HOSTNAME) { if ((tmp = index(tconf.hostname, '.')) != NULL) { sprintf(tconf.email,"webmaster@%s",tmp+1); RefreshStringObj(layout[LAYOUT_EMAIL].obj); } } /* Handle special case stuff that libdialog misses. Sigh */ switch (ret) { /* Bail out */ case SEL_ESC: quit = TRUE, cancel=TRUE; break; /* This doesn't work for list dialogs. Oh well. Perhaps should special case the move from the OK button ``up'' to make it go to the interface list, but then it gets awkward for the user to go back and correct screw up's in the per-interface section */ case KEY_UP: if (obj->prev !=NULL ) { obj = obj->prev; --n; } else { obj = last; n = max; } break; case KEY_DOWN: if (obj->next != NULL) { obj = obj->next; ++n; } else { obj = first; n = 0; } break; case SEL_TAB: if (n < max) ++n; else n = 0; break; /* The user has pressed enter over a button object */ case SEL_BUTTON: quit = TRUE; if (cancelbutton) cancel = TRUE; break; /* Generic CR handler */ case SEL_CR: if (n < max) ++n; else n = 0; break; case SEL_BACKTAB: if (n) --n; else n = max; break; case KEY_F(1): display_helpfile(); /* They tried some key combination we don't support - tell them! */ default: beep(); } } /* Clear this crap off the screen */ dialog_clear(); refresh(); use_helpfile(NULL); if (cancel) return RET_FAIL; return RET_SUCCESS; } int configApache(char *unused) { int i, maxcon; char company[64], file[128]; char *tptr; FILE *fptr; /* Be optimistic */ i = RET_SUCCESS; dialog_clear(); msgConfirm("Since you elected to install the WEB server, we'll now add the\n" "Apache HTTPD package and set up a few configuration files."); i = package_add(APACHE_PACKAGE); if (i != RET_SUCCESS) { dialog_clear(); msgConfirm("Hmmmmm. Looks like we weren't able to fetch the Apache WEB server\n" "package. You may wish to fetch and configure it by hand by looking\n" "in /usr/ports/net/apache (in the ports collection) or looking for the\n" "precompiled apache package in packages/networking/%s.", APACHE_PACKAGE); return (i); } i = apacheOpenDialog(); if (i != RET_SUCCESS) { dialog_clear(); msgConfirm("Configuration of the Apache WEB server was cancelled per\n" "user request."); return i; } /*** Fix defaults for invalid value ***/ maxcon = atoi(tconf.maxcon); if (maxcon <= 0) maxcon = 150; if (! tconf.group[0]) strcpy(tconf.group, "guest"); if (! tconf.user[0]) strcpy(tconf.user, "nobody"); if (! tconf.welcome[0]) strcpy(tconf.welcome, "index.html"); if (! tconf.userdir[0]) strcpy(tconf.userdir, "public_html"); /*** If the user did not specify a directory, use default ***/ if (tconf.docroot[strlen(tconf.docroot)-1] == '/') tconf.docroot[strlen(tconf.docroot)-1] = '\0'; if (!tconf.docroot[0]) sprintf(tconf.docroot,"%s/%s",APACHE_BASE,DATA_SUBDIR); /*** If DocRoot does not exist, create it ***/ if (!directoryExists(tconf.docroot)) vsystem("mkdir -p %s", tconf.docroot); if (directoryExists(tconf.docroot)) { sprintf(file,"%s/index.html", tconf.docroot); if (!file_readable(file)) { dialog_clear(); tptr = msgGetInput(NULL, "What is your company name?"); if (tptr && strlen(tptr)) strcpy(company, tptr); else strcpy(company, "our Web Page"); msgNotify("Creating sample web page..."); fptr = fopen(file,"w"); if (fptr) { fprintf(fptr,"
\nWelcome Page\n"); fprintf(fptr,"

Welcome to %s

\n
\n",company); fprintf(fptr,"


\n
\n"); fprintf(fptr,"\n"); fprintf(fptr,"\"Powered\n"); if (! tconf.email[0]) { if ((tptr = variable_get(VAR_DOMAINNAME))) sprintf(tconf.email,"root@%s",tptr); } if (tconf.email[0]) { fprintf(fptr,"

\n"); fprintf(fptr," For questions or comments, please send mail to:\n"); fprintf(fptr," %s\n", tconf.email, tconf.email); fprintf(fptr,"

\n"); } fprintf(fptr,"
\n\n"); fclose(fptr); if (file_readable(FREEBSD_GIF)) vsystem("cp %s %s", FREEBSD_GIF, tconf.docroot); } else { msgConfirm("Unable to create sample Web Page."); i = RET_FAIL; } } } else { dialog_clear(); msgConfirm("Unable to create Document Root Directory."); i = RET_FAIL; } msgNotify("Writing configuration files...."); (void)vsystem("mkdir -p %s/config", APACHE_BASE); sprintf(file, "%s/%s/access.conf", APACHE_BASE,CONFIG_SUBDIR); if (file_readable(file)) vsystem("mv -f %s %s.ORIG", file, file); fptr = fopen(file,"w"); if (fptr) { fprintf(fptr,"\n", APACHE_BASE); fprintf(fptr,"Options Indexes FollowSymLinks\n\n\n"); fprintf(fptr,"\n", tconf.docroot); fprintf(fptr,"Options Indexes FollowSymLinks\nAllowOverride All\n"); fprintf(fptr,"\n\n"); fclose(fptr); } else { dialog_clear(); msgConfirm("Could not create %s",file); i = RET_FAIL; } sprintf(file, "%s/%s/httpd.conf", APACHE_BASE,CONFIG_SUBDIR); if (file_readable(file)) vsystem("mv -f %s %s.ORIG", file, file); fptr = fopen(file,"w"); if (fptr) { fprintf(fptr,"ServerType standalone\nPort 80\nTimeOut 400\n"); fprintf(fptr,"ErrorLog logs/error_log\nTransferLog logs/access_log\n"); fprintf(fptr,"PidFile /var/run/httpd.pid\n\nStartServers 5\n"); fprintf(fptr,"MinSpareServers 5\nMaxSpareServers 10\n"); fprintf(fptr,"MaxRequestsPerChild 30\nMaxClients %d\n\n",maxcon); fprintf(fptr,"User %s\nGroup %s\n\n",tconf.user,tconf.group); if (tconf.email[0]) fprintf(fptr,"ServerAdmin %s\n",tconf.email); if (tconf.hostname[0]) fprintf(fptr,"ServerName %s\n",tconf.hostname); fclose(fptr); } else { dialog_clear(); msgConfirm("Could not create %s",file); i = RET_FAIL; } sprintf(file, "%s/%s/srm.conf", APACHE_BASE,CONFIG_SUBDIR); if (file_readable(file)) vsystem("mv -f %s %s.ORIG", file, file); fptr = fopen(file,"w"); if (fptr) { fprintf(fptr,"FancyIndexing on\nDefaultType text/plain\n"); fprintf(fptr,"IndexIgnore */.??* *~ *# */HEADER* */README* */RCS\n"); fprintf(fptr,"HeaderName HEADER\nReadmeName README\n"); fprintf(fptr,"AccessFileName .htaccess\n\n"); fprintf(fptr,"AddEncoding x-compress Z\nAddEncoding x-gzip gz\n"); fprintf(fptr,"DefaultIcon /icons/unknown.gif\n\n"); fprintf(fptr, "AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip\n"); fprintf(fptr,"AddIconByType (TXT,/icons/text.gif) text/*\n"); fprintf(fptr,"AddIconByType (IMG,/icons/image2.gif) image/*\n"); fprintf(fptr,"AddIconByType (SND,/icons/sound2.gif) audio/*\n"); fprintf(fptr,"AddIconByType (VID,/icons/movie.gif) video/*\n\n"); fprintf(fptr,"AddIcon /icons/text.gif .ps .shtml\n"); fprintf(fptr,"AddIcon /icons/movie.gif .mpg .qt\n"); fprintf(fptr,"AddIcon /icons/binary.gif .bin\n"); fprintf(fptr,"AddIcon /icons/burst.gif .wrl\n"); fprintf(fptr,"AddIcon /icons/binhex.gif .hqx .sit\n"); fprintf(fptr,"AddIcon /icons/uu.gif .uu\n"); fprintf(fptr,"AddIcon /icons/tar.gif .tar\n"); fprintf(fptr,"AddIcon /icons/back.gif ..\n"); fprintf(fptr,"AddIcon /icons/dir.gif ^^DIRECTORY^^\n"); fprintf(fptr,"AddIcon /icons/blank.gif ^^BLANKICON^^\n\n"); fprintf(fptr,"ScriptAlias /cgi_bin/ %s/cgi_bin/\n",APACHE_BASE); fprintf(fptr,"Alias /icons/ %s/icons/\n",APACHE_BASE); fprintf(fptr,"DocumentRoot %s\n",tconf.docroot); fprintf(fptr,"UserDir %s\nDirectoryIndex %s\n\n", tconf.userdir, tconf.welcome); fclose(fptr); } else { dialog_clear(); msgConfirm("Could not create %s",file); i = RET_FAIL; } if (i != RET_FAIL) variable_set2("apache_httpd", "YES"); return i; }