]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/sade/system.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.sbin / sade / system.c
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  */
37 static int
38 intr_continue(dialogMenuItem *self)
39 {
40     return DITEM_LEAVE_MENU;
41 }
42
43 static int
44 intr_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
58 static 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
64 static void
65 handle_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 */
82 static char *
83 expand(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 */
102 void
103 systemInitialize(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 */
142 int
143 systemExecute(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 */
169 static    WINDOW *oldW;
170
171 void
172 systemSuspendDialog(void)
173 {
174
175     oldW  = savescr();
176     dialog_clear();
177     dialog_update();
178     end_dialog();
179     DialogActive = FALSE;
180 }
181
182 void
183 systemResumeDialog(void)
184 {
185
186     DialogActive = TRUE;
187     restorescr(oldW);
188 }
189
190 /* Display a help file in a filebox */
191 int
192 systemDisplayHelp(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
217 char *
218 systemHelpFile(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
247 int
248 vsystem(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