1/* 2 * $FreeBSD$ 3 * 4 * Jordan Hubbard 5 * 6 * My contributions are in the public domain. 7 * 8 * Parts of this file are also blatently stolen from Poul-Henning Kamp's 9 * previous version of sysinstall, and as such fall under his "BEERWARE license" 10 * so buy him a beer if you like it! Buy him a beer for me, too! 11 * Heck, get him completely drunk and send me pictures! :-) 12 */ 13 14#include "sade.h" 15#include <signal.h> 16#include <termios.h> 17#include <sys/param.h> 18#include <sys/reboot.h> 19#include <sys/consio.h> 20#include <sys/fcntl.h> 21#include <sys/ioctl.h> 22#include <sys/mount.h> 23#include <sys/stat.h> 24#include <sys/sysctl.h> 25#include <ufs/ufs/ufsmount.h> 26 27 28/* Where we stick our temporary expanded doc file */ 29#define DOC_TMP_DIR "/tmp/.doc" 30#define DOC_TMP_FILE "/tmp/.doc/doc.tmp" 31 32/* 33 * Handle interrupt signals - this probably won't work in all cases 34 * due to our having bogotified the internal state of dialog or curses, 35 * but we'll give it a try. 36 */ 37static int 38intr_continue(dialogMenuItem *self) 39{ 40 return DITEM_LEAVE_MENU; 41} 42 43static int 44intr_restart(dialogMenuItem *self) 45{ 46 int ret, fd, fdmax; 47 48 free_variables(); 49 fdmax = getdtablesize(); 50 for (fd = 3; fd < fdmax; fd++) 51 close(fd); 52 ret = execl(StartName, StartName, "-restart", (char *)NULL); 53 msgDebug("execl failed (%s)\n", strerror(errno)); 54 /* NOTREACHED */ 55 return -1; 56} 57 58static dialogMenuItem intrmenu[] = { 59 { "Restart", "Restart the program", NULL, intr_restart, NULL, NULL, 0, 0, 0, 0 }, 60 { "Continue", "Continue without restarting", NULL, intr_continue, NULL, NULL, 0, 0, 0, 0 }, 61}; 62 63 64static void 65handle_intr(int sig) 66{ 67 WINDOW *save = savescr(); 68 69 use_helpline(NULL); 70 use_helpfile(NULL); 71 if (OnVTY) { 72 ioctl(0, VT_ACTIVATE, 1); /* Switch back */ 73 msgInfo(NULL); 74 } 75 (void)dialog_menu("Installation interrupt", 76 "Do you want to abort the installation?", 77 -1, -1, 2, -2, intrmenu, NULL, NULL, NULL); 78 restorescr(save); 79} 80 81/* Expand a file into a convenient location, nuking it each time */ 82static char * 83expand(char *fname) 84{ 85 char *gunzip = "/usr/bin/gunzip"; 86 87 if (!directory_exists(DOC_TMP_DIR)) { 88 Mkdir(DOC_TMP_DIR); 89 if (chown(DOC_TMP_DIR, 0, 0) < 0) 90 return NULL; 91 if (chmod(DOC_TMP_DIR, S_IRWXU) < 0) 92 return NULL; 93 } 94 else 95 unlink(DOC_TMP_FILE); 96 if (!file_readable(fname) || vsystem("%s < %s > %s", gunzip, fname, DOC_TMP_FILE)) 97 return NULL; 98 return DOC_TMP_FILE; 99} 100 101/* Initialize system defaults */ 102void 103systemInitialize(int argc, char **argv) 104{ 105 size_t i; 106 int boothowto; 107 sigset_t signalset; 108 109 signal(SIGINT, SIG_IGN); 110 globalsInit(); 111 112 i = sizeof(boothowto); 113 if (!sysctlbyname("debug.boothowto", &boothowto, &i, NULL, 0) && 114 (i == sizeof(boothowto)) && (boothowto & RB_VERBOSE)) 115 variable_set2(VAR_DEBUG, "YES", 0); 116 117 if (set_termcap() == -1) { 118 printf("Can't find terminal entry\n"); 119 exit(-1); 120 } 121 122 /* XXX - libdialog has particularly bad return value checking */ 123 init_dialog(); 124 125 /* If we haven't crashed I guess dialog is running ! */ 126 DialogActive = TRUE; 127 128 /* Make sure HOME is set for those utilities that need it */ 129 signal(SIGINT, handle_intr); 130 /* 131 * Make sure we can be interrupted even if we were re-executed 132 * from an interrupt. 133 */ 134 sigemptyset(&signalset); 135 sigaddset(&signalset, SIGINT); 136 sigprocmask(SIG_UNBLOCK, &signalset, NULL); 137 138 (void)vsystem("rm -rf %s", DOC_TMP_DIR); 139} 140 141/* Run some general command */ 142int 143systemExecute(char *command) 144{ 145 int status; 146 struct termios foo; 147 WINDOW *w = savescr(); 148 149 dialog_clear(); 150 dialog_update(); 151 end_dialog(); 152 DialogActive = FALSE; 153 if (tcgetattr(0, &foo) != -1) { 154 foo.c_cc[VERASE] = '\010'; 155 tcsetattr(0, TCSANOW, &foo); 156 } 157 if (!Fake) 158 status = system(command); 159 else { 160 status = 0; 161 msgDebug("systemExecute: Faked execution of `%s'\n", command); 162 } 163 DialogActive = TRUE; 164 restorescr(w); 165 return status; 166} 167 168/* suspend/resume libdialog/curses screen */ 169static WINDOW *oldW; 170 171void 172systemSuspendDialog(void) 173{ 174 175 oldW = savescr(); 176 dialog_clear(); 177 dialog_update(); 178 end_dialog(); 179 DialogActive = FALSE; 180} 181 182void 183systemResumeDialog(void) 184{ 185 186 DialogActive = TRUE; 187 restorescr(oldW); 188} 189 190/* Display a help file in a filebox */ 191int 192systemDisplayHelp(char *file) 193{ 194 char *fname = NULL; 195 char buf[FILENAME_MAX]; 196 int ret = 0; 197 WINDOW *w = savescr(); 198 199 printf("zzz"); 200 fname = systemHelpFile(file, buf); 201 if (!fname) { 202 snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file); 203 use_helpfile(NULL); 204 use_helpline(NULL); 205 dialog_mesgbox("Sorry!", buf, -1, -1); 206 ret = 1; 207 } 208 else { 209 use_helpfile(NULL); 210 use_helpline(NULL); 211 dialog_textbox(file, fname, LINES, COLS); 212 } 213 restorescr(w); 214 return ret; 215} 216 217char * 218systemHelpFile(char *file, char *buf) 219{ 220 if (!file) 221 return NULL; 222 if (file[0] == '/') 223 return file; 224 snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp.gz", file); 225 if (file_readable(buf)) 226 return expand(buf); 227 snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp", file); 228 if (file_readable(buf)) 229 return expand(buf); 230 snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT.gz", file); 231 if (file_readable(buf)) 232 return expand(buf); 233 snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT", file); 234 if (file_readable(buf)) 235 return expand(buf); 236 snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/%s/help/%s.hlp", ProgName, 237 file); 238 if (file_readable(buf)) 239 return buf; 240 snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/%s/help/%s.TXT", ProgName, 241 file); 242 if (file_readable(buf)) 243 return buf; 244 return NULL; 245} 246 247int 248vsystem(const char *fmt, ...) 249{ 250 va_list args; 251 int pstat; 252 pid_t pid; 253 int omask; 254 sig_t intsave, quitsave; 255 char *cmd; 256 int i; 257 struct stat sb; 258 259 cmd = (char *)alloca(FILENAME_MAX); 260 cmd[0] = '\0'; 261 va_start(args, fmt); 262 vsnprintf(cmd, FILENAME_MAX, fmt, args); 263 va_end(args); 264 265 omask = sigblock(sigmask(SIGCHLD)); 266 if (Fake) { 267 msgDebug("vsystem: Faked execution of `%s'\n", cmd); 268 return 0; 269 } 270 if (isDebug()) 271 msgDebug("Executing command `%s'\n", cmd); 272 pid = fork(); 273 if (pid == -1) { 274 (void)sigsetmask(omask); 275 i = 127; 276 } 277 else if (!pid) { /* Junior */ 278 (void)sigsetmask(omask); 279 if (DebugFD != -1) { 280 dup2(DebugFD, 0); 281 dup2(DebugFD, 1); 282 dup2(DebugFD, 2); 283 } 284 else { 285 close(1); open("/dev/null", O_WRONLY); 286 dup2(1, 2); 287 } 288 if (stat("/stand/sh", &sb) == 0) 289 execl("/stand/sh", "/stand/sh", "-c", cmd, (char *)NULL); 290 else 291 execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL); 292 exit(1); 293 } 294 else { 295 intsave = signal(SIGINT, SIG_IGN); 296 quitsave = signal(SIGQUIT, SIG_IGN); 297 pid = waitpid(pid, &pstat, 0); 298 (void)sigsetmask(omask); 299 (void)signal(SIGINT, intsave); 300 (void)signal(SIGQUIT, quitsave); 301 i = (pid == -1) ? -1 : WEXITSTATUS(pstat); 302 if (isDebug()) 303 msgDebug("Command `%s' returns status of %d\n", cmd, i); 304 } 305 return i; 306} 307 308