2 * Miscellaneous support routines..
4 * $FreeBSD: src/release/sysinstall/misc.c,v 1.40.2.1 2001/09/27 06:51:09 murray Exp $
7 * Jordan Hubbard. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer,
14 * verbatim and that no modifications are made prior to this
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "sysinstall.h"
38 #include <sys/errno.h>
40 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/mount.h>
45 #include <ufs/ufs/ufsmount.h>
46 #include <sys/reboot.h>
47 #include <sys/disklabel.h>
49 /* Quick check to see if a file is readable */
51 file_readable(char *fname)
53 if (!access(fname, F_OK))
58 /* Quick check to see if a file is executable */
60 file_executable(char *fname)
62 if (!access(fname, X_OK))
67 /* Concatenate two strings into static storage */
69 string_concat(char *one, char *two)
71 static char tmp[FILENAME_MAX];
73 /* Yes, we're deliberately cavalier about not checking for overflow */
79 /* sane strncpy() function */
81 sstrncpy(char *dst, const char *src, int size)
84 return strncpy(dst, src, size);
87 /* Concatenate three strings into static storage */
89 string_concat3(char *one, char *two, char *three)
91 static char tmp[FILENAME_MAX];
93 /* Yes, we're deliberately cavalier about not checking for overflow */
100 /* Clip the whitespace off the end of a string */
102 string_prune(char *str)
104 int len = str ? strlen(str) : 0;
106 while (len && isspace(str[len - 1]))
111 /* run the whitespace off the front of a string */
113 string_skipwhite(char *str)
115 while (*str && isspace(*str))
120 /* copy optionally and allow second arg to be null */
122 string_copy(char *s1, char *s2)
133 /* convert an integer to a string, using a static buffer */
139 snprintf(buf, 12, "%d", value);
144 directory_exists(const char *dirname)
150 if (!strlen(dirname))
153 tptr = opendir(dirname);
162 pathBaseName(const char *path)
165 char *ret = (char *)path;
167 pt = strrchr(path,(int)'/');
169 if (pt != 0) /* if there is a slash */
171 ret = ++pt; /* start the file after it */
177 /* A free guaranteed to take NULL ptrs */
185 /* A malloc that checks errors */
187 safe_malloc(size_t size)
192 msgFatal("Invalid malloc size of %ld!", (long)size);
195 msgFatal("Out of memory!");
200 /* A realloc that checks errors */
202 safe_realloc(void *orig, size_t size)
207 msgFatal("Invalid realloc size of %ld!", (long)size);
208 ptr = realloc(orig, size);
210 msgFatal("Out of memory!");
214 /* Create a path biased from the VAR_INSTALL_ROOT variable (if not /) */
216 root_bias(char *path)
218 static char tmp[FILENAME_MAX];
219 char *cp = variable_get(VAR_INSTALL_ROOT);
221 if (!strcmp(cp, "/"))
223 strcpy(tmp, variable_get(VAR_INSTALL_ROOT));
229 * These next routines are kind of specialized just for building item lists
233 /* Add an item to an item list */
235 item_add(dialogMenuItem *list, char *prompt, char *title,
236 int (*checked)(dialogMenuItem *self),
237 int (*fire)(dialogMenuItem *self),
238 void (*selected)(dialogMenuItem *self, int is_selected),
239 void *data, int aux, int *curr, int *max)
245 list = (dialogMenuItem *)realloc(list, sizeof(dialogMenuItem) * *max);
247 d = &list[(*curr)++];
248 bzero(d, sizeof(*d));
249 d->prompt = prompt ? strdup(prompt) : NULL;
250 d->title = title ? strdup(title) : NULL;
251 d->checked = checked;
253 d->selected = selected;
259 /* Toss the items out */
261 items_free(dialogMenuItem *list, int *curr, int *max)
265 for (i = 0; list[i].prompt; i++) {
266 safe_free(list[i].prompt);
267 safe_free(list[i].title);
280 if (file_readable(ipath) || Fake)
281 return DITEM_SUCCESS;
283 path = strcpy(alloca(strlen(ipath) + 1), ipath);
285 msgDebug("mkdir(%s)\n", path);
287 if (p[0] == '/') /* Skip leading '/'. */
289 for (final = FALSE; !final; ++p) {
290 if (p[0] == '\0' || (p[0] == '/' && p[1] == '\0'))
292 else if (p[0] != '/')
295 if (stat(path, &sb)) {
296 if (errno != ENOENT) {
297 msgConfirm("Couldn't stat directory %s: %s", path, strerror(errno));
298 return DITEM_FAILURE;
301 msgDebug("mkdir(%s..)\n", path);
302 if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
303 msgConfirm("Couldn't create directory %s: %s", path,strerror(errno));
304 return DITEM_FAILURE;
309 return DITEM_SUCCESS;
313 Mount(char *mountp, void *dev)
315 struct ufs_args ufsargs;
317 char mountpoint[FILENAME_MAX];
320 return DITEM_SUCCESS;
322 if (*((char *)dev) != '/') {
323 sprintf(device, "%s/dev/%s", RunningAsInit ? "/mnt" : "", (char *)dev);
324 sprintf(mountpoint, "%s%s", RunningAsInit ? "/mnt" : "", mountp);
328 strcpy(mountpoint, mountp);
330 memset(&ufsargs,0,sizeof ufsargs);
332 if (Mkdir(mountpoint)) {
333 msgConfirm("Unable to make directory mountpoint for %s!", mountpoint);
334 return DITEM_FAILURE;
337 msgDebug("mount %s %s\n", device, mountpoint);
339 ufsargs.fspec = device;
340 if (mount("ufs", mountpoint, RunningAsInit ? MNT_ASYNC | MNT_NOATIME : 0,
341 (caddr_t)&ufsargs) == -1) {
342 msgConfirm("Error mounting %s on %s : %s", device, mountpoint, strerror(errno));
343 return DITEM_FAILURE;
345 return DITEM_SUCCESS;
349 openLayoutDialog(char *helpfile, char *title, int x, int y, int width, int height)
352 static char help[FILENAME_MAX];
354 /* We need a curses window */
355 win = newwin(LINES, COLS, 0, 0);
357 /* Say where our help comes from */
359 use_helpline("Press F1 for more information on this screen.");
360 use_helpfile(systemHelpFile(helpfile, help));
362 /* Setup a nice screen for us to splat stuff onto */
363 draw_box(win, y, x, height, width, dialog_attr, border_attr);
364 wattrset(win, dialog_attr);
365 mvwaddstr(win, y, x + (COLS - strlen(title)) / 2, title);
371 initLayoutDialog(WINDOW *win, Layout *layout, int x, int y, int *max)
373 ComposeObj *obj = NULL, *first;
376 /* Loop over the layout list, create the objects, and add them
377 onto the chain of objects that dialog uses for traversal*/
380 while (layout[n].help != NULL) {
381 int t = TYPE_OF_OBJ(layout[n].type);
385 layout[n].obj = NewStringObj(win, layout[n].prompt, layout[n].var,
386 layout[n].y + y, layout[n].x + x, layout[n].len, layout[n].maxlen);
387 ((StringObj *)layout[n].obj)->attr_mask = ATTR_OF_OBJ(layout[n].type);
391 layout[n].obj = NewButtonObj(win, layout[n].prompt, layout[n].var, layout[n].y + y, layout[n].x + x);
395 msgFatal("Don't support this object yet!");
397 AddObj(&obj, t, (void *) layout[n].obj);
401 /* Find the first object in the list */
402 for (first = obj; first->prev; first = first->prev);
407 layoutDialogLoop(WINDOW *win, Layout *layout, ComposeObj **obj, int *n, int max, int *cbutton, int *cancel)
410 int ret, i, len = strlen(layout[*n].help);
412 /* Display the help line at the bottom of the screen */
413 for (i = 0; i < 79; i++)
414 help_line[i] = (i < len) ? layout[*n].help[i] : ' ';
416 use_helpline(help_line);
417 display_helpline(win, LINES - 1, COLS - 1);
420 /* Ask for libdialog to do its stuff */
422 /* Handle special case stuff that libdialog misses. Sigh */
424 case SEL_ESC: /* Bail out */
428 /* This doesn't work for list dialogs. Oh well. Perhaps
429 should special case the move from the OK button ``up''
430 to make it go to the interface list, but then it gets
431 awkward for the user to go back and correct screw up's
432 in the per-interface section */
442 /* The user has pressed enter over a button object */
444 if (cbutton && *cbutton)
461 /* They tried some key combination we don't support - tootle them forcefully! */
478 restorescr(WINDOW *w)