system.c revision 43811
1/* 2 * The new sysinstall program. 3 * 4 * This is probably the last program in the `sysinstall' line - the next 5 * generation being essentially a complete rewrite. 6 * 7 * $Id: system.c,v 1.88 1999/02/05 22:15:52 jkh Exp $ 8 * 9 * Jordan Hubbard 10 * 11 * My contributions are in the public domain. 12 * 13 * Parts of this file are also blatently stolen from Poul-Henning Kamp's 14 * previous version of sysinstall, and as such fall under his "BEERWARE license" 15 * so buy him a beer if you like it! Buy him a beer for me, too! 16 * Heck, get him completely drunk and send me pictures! :-) 17 */ 18 19#include "sysinstall.h" 20#include <signal.h> 21#include <sys/reboot.h> 22#include <machine/console.h> 23#include <sys/fcntl.h> 24#include <sys/ioctl.h> 25#include <sys/stat.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 32static pid_t ehs_pid; 33 34/* 35 * Handle interrupt signals - this probably won't work in all cases 36 * due to our having bogotified the internal state of dialog or curses, 37 * but we'll give it a try. 38 */ 39static void 40handle_intr(int sig) 41{ 42 WINDOW *save = savescr(); 43 44 if (!msgYesNo("Are you sure you want to abort the installation?")) 45 systemShutdown(-1); 46 else 47 restorescr(save); 48} 49 50/* Expand a file into a convenient location, nuking it each time */ 51static char * 52expand(char *fname) 53{ 54 char *gunzip = RunningAsInit ? "/stand/gunzip" : "/usr/bin/gunzip"; 55 56 if (!directory_exists(DOC_TMP_DIR)) { 57 Mkdir(DOC_TMP_DIR); 58 if (chown(DOC_TMP_DIR, 0, 0) < 0) 59 return NULL; 60 if (chmod(DOC_TMP_DIR, S_IRWXU) < 0) 61 return NULL; 62 } 63 else 64 unlink(DOC_TMP_FILE); 65 if (!file_readable(fname) || vsystem("%s < %s > %s", gunzip, fname, DOC_TMP_FILE)) 66 return NULL; 67 return DOC_TMP_FILE; 68} 69 70/* Initialize system defaults */ 71void 72systemInitialize(int argc, char **argv) 73{ 74 int i; 75 76 signal(SIGINT, SIG_IGN); 77 globalsInit(); 78 79 /* Are we running as init? */ 80 if (getpid() == 1) { 81 int fd, type; 82 83 RunningAsInit = 1; 84 setsid(); 85 close(0); 86 fd = open("/dev/ttyv0", O_RDWR); 87 if (fd == -1) 88 fd = open("/dev/console", O_RDWR); /* fallback */ 89 else 90 OnVTY = TRUE; 91 /* 92 * To make _sure_ we're on a VTY and don't have /dev/console switched 93 * away to a serial port or something, attempt to set the cursor appearance. 94 */ 95 type = 0; /* normal */ 96 if (OnVTY) { 97 int fd2; 98 99 if ((fd2 = open("/dev/console", O_RDWR)) != -1) { 100 if (ioctl(fd2, CONS_CURSORTYPE, &type) == -1) { 101 OnVTY = FALSE; 102 close(fd); close(fd2); 103 open("/dev/console", O_RDWR); 104 } 105 else 106 close(fd2); 107 } 108 } 109 close(1); dup(0); 110 close(2); dup(0); 111 printf("%s running as init on %s\n", argv[0], OnVTY ? "vty0" : "serial console"); 112 i = ioctl(0, TIOCSCTTY, (char *)NULL); 113 setlogin("root"); 114 setenv("PATH", "/stand:/bin:/sbin:/usr/sbin:/usr/bin:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin:/usr/X11R6/bin", 1); 115 setbuf(stdin, 0); 116 setbuf(stderr, 0); 117 } 118 else { 119 char hname[256]; 120 121 /* Initalize various things for a multi-user environment */ 122 if (!gethostname(hname, sizeof hname)) 123 variable_set2(VAR_HOSTNAME, hname, 1); 124 } 125 126 if (set_termcap() == -1) { 127 printf("Can't find terminal entry\n"); 128 exit(-1); 129 } 130 131 /* XXX - libdialog has particularly bad return value checking */ 132 init_dialog(); 133 134 /* If we haven't crashed I guess dialog is running ! */ 135 DialogActive = TRUE; 136 137 /* Make sure HOME is set for those utilities that need it */ 138 if (!getenv("HOME")) 139 setenv("HOME", "/", 1); 140 signal(SIGINT, handle_intr); 141 (void)vsystem("rm -rf %s", DOC_TMP_DIR); 142} 143 144/* Close down and prepare to exit */ 145void 146systemShutdown(int status) 147{ 148 /* If some media is open, close it down */ 149 if (status >=0 && mediaDevice) 150 mediaDevice->shutdown(mediaDevice); 151 152 /* write out any changes to rc.conf .. */ 153 configRC_conf(); 154 155 /* Shut down the dialog library */ 156 if (DialogActive) { 157 end_dialog(); 158 DialogActive = FALSE; 159 } 160 161 /* Shut down curses */ 162 endwin(); 163 164 /* If we have a temporary doc dir lying around, nuke it */ 165 (void)vsystem("rm -rf %s", DOC_TMP_DIR); 166 167 /* REALLY exit! */ 168 if (RunningAsInit) { 169 /* Put the console back */ 170 ioctl(0, VT_ACTIVATE, 2); 171#ifdef __alpha__ 172 reboot(RB_HALT); 173#else 174 reboot(0); 175#endif 176 } 177 else 178 exit(status); 179} 180 181/* Run some general command */ 182int 183systemExecute(char *command) 184{ 185 int status; 186 struct termios foo; 187 188 dialog_update(); 189 end_dialog(); 190 DialogActive = FALSE; 191 if (tcgetattr(0, &foo) != -1) { 192 foo.c_cc[VERASE] = '\010'; 193 tcsetattr(0, TCSANOW, &foo); 194 } 195 if (!Fake) 196 status = system(command); 197 else { 198 status = 0; 199 msgDebug("systemExecute: Faked execution of `%s'\n", command); 200 } 201 DialogActive = TRUE; 202 return status; 203} 204 205/* Display a help file in a filebox */ 206int 207systemDisplayHelp(char *file) 208{ 209 char *fname = NULL; 210 char buf[FILENAME_MAX]; 211 int ret = 0; 212 213 fname = systemHelpFile(file, buf); 214 if (!fname) { 215 snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file); 216 use_helpfile(NULL); 217 use_helpline(NULL); 218 dialog_mesgbox("Sorry!", buf, -1, -1); 219 ret = 1; 220 } 221 else { 222 use_helpfile(NULL); 223 use_helpline(NULL); 224 dialog_textbox(file, fname, LINES, COLS); 225 } 226 return ret; 227} 228 229char * 230systemHelpFile(char *file, char *buf) 231{ 232 if (!file) 233 return NULL; 234 235 snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp.gz", file); 236 if (file_readable(buf)) 237 return expand(buf); 238 snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT.gz", file); 239 if (file_readable(buf)) 240 return expand(buf); 241 snprintf(buf, FILENAME_MAX, "/usr/src/release/sysinstall/help/%s.hlp", file); 242 if (file_readable(buf)) 243 return buf; 244 snprintf(buf, FILENAME_MAX, "/usr/src/release/sysinstall/help/%s.TXT", file); 245 if (file_readable(buf)) 246 return buf; 247 return NULL; 248} 249 250void 251systemChangeTerminal(char *color, const u_char c_term[], 252 char *mono, const u_char m_term[]) 253{ 254 extern void init_acs(void); 255 256 if (OnVTY) { 257 if (ColorDisplay) { 258 setenv("TERM", color, 1); 259 setenv("TERMCAP", c_term, 1); 260 reset_shell_mode(); 261 setterm(color); 262 init_acs(); 263 cbreak(); noecho(); 264 } 265 else { 266 setenv("TERM", mono, 1); 267 setenv("TERMCAP", m_term, 1); 268 reset_shell_mode(); 269 setterm(mono); 270 init_acs(); 271 cbreak(); noecho(); 272 } 273 } 274 clear(); 275 refresh(); 276 dialog_clear(); 277} 278 279int 280vsystem(char *fmt, ...) 281{ 282 va_list args; 283 int pstat; 284 pid_t pid; 285 int omask; 286 sig_t intsave, quitsave; 287 char *cmd; 288 int i; 289 290 cmd = (char *)alloca(FILENAME_MAX); 291 cmd[0] = '\0'; 292 va_start(args, fmt); 293 vsnprintf(cmd, FILENAME_MAX, fmt, args); 294 va_end(args); 295 296 omask = sigblock(sigmask(SIGCHLD)); 297 if (Fake) { 298 msgDebug("vsystem: Faked execution of `%s'\n", cmd); 299 return 0; 300 } 301 if (isDebug()) 302 msgDebug("Executing command `%s'\n", cmd); 303 pid = fork(); 304 if (pid == -1) { 305 (void)sigsetmask(omask); 306 i = 127; 307 } 308 else if (!pid) { /* Junior */ 309 (void)sigsetmask(omask); 310 if (DebugFD != -1) { 311 dup2(DebugFD, 0); 312 dup2(DebugFD, 1); 313 dup2(DebugFD, 2); 314 } 315 else { 316 close(1); open("/dev/null", O_WRONLY); 317 dup2(1, 2); 318 } 319 if (!RunningAsInit) 320 execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL); 321 else 322 execl("/stand/sh", "/stand/sh", "-c", cmd, (char *)NULL); 323 exit(1); 324 } 325 else { 326 intsave = signal(SIGINT, SIG_IGN); 327 quitsave = signal(SIGQUIT, SIG_IGN); 328 pid = waitpid(pid, &pstat, 0); 329 (void)sigsetmask(omask); 330 (void)signal(SIGINT, intsave); 331 (void)signal(SIGQUIT, quitsave); 332 i = (pid == -1) ? -1 : WEXITSTATUS(pstat); 333 if (isDebug()) 334 msgDebug("Command `%s' returns status of %d\n", cmd, i); 335 } 336 return i; 337} 338 339void 340systemCreateHoloshell(void) 341{ 342 if (OnVTY && RunningAsInit) { 343 344 if (ehs_pid != 0) { 345 int pstat; 346 347 if (kill(ehs_pid, 0) == 0) { 348 349 if (msgYesNo("There seems to be an emergency holographic shell\n" 350 "already running von VTY 4.\n" 351 "Kill it and start a new one?")) 352 return; 353 354 /* try cleaning up as much as possible */ 355 (void) kill(ehs_pid, SIGHUP); 356 sleep(1); 357 (void) kill(ehs_pid, SIGKILL); 358 } 359 360 /* avoid too many zombies */ 361 (void) waitpid(ehs_pid, &pstat, WNOHANG); 362 } 363 364 if ((ehs_pid = fork()) == 0) { 365 int i, fd; 366 struct termios foo; 367 extern int login_tty(int); 368 369 ioctl(0, TIOCNOTTY, NULL); 370 for (i = getdtablesize(); i >= 0; --i) 371 close(i); 372 fd = open("/dev/ttyv3", O_RDWR); 373 ioctl(0, TIOCSCTTY, &fd); 374 dup2(0, 1); 375 dup2(0, 2); 376 DebugFD = 2; 377 if (login_tty(fd) == -1) 378 msgDebug("Doctor: I can't set the controlling terminal.\n"); 379 signal(SIGTTOU, SIG_IGN); 380 if (tcgetattr(fd, &foo) != -1) { 381 foo.c_cc[VERASE] = '\010'; 382 if (tcsetattr(fd, TCSANOW, &foo) == -1) 383 msgDebug("Doctor: I'm unable to set the erase character.\n"); 384 } 385 else 386 msgDebug("Doctor: I'm unable to get the terminal attributes!\n"); 387 execlp("sh", "-sh", 0); 388 msgDebug("Was unable to execute sh for Holographic shell!\n"); 389 exit(1); 390 } 391 else { 392 msgNotify("Starting an emergency holographic shell on VTY4"); 393 sleep(2); 394 } 395 } 396} 397