diff options
Diffstat (limited to 'usr.sbin/sysinstall/devices.c')
-rw-r--r-- | usr.sbin/sysinstall/devices.c | 505 |
1 files changed, 229 insertions, 276 deletions
diff --git a/usr.sbin/sysinstall/devices.c b/usr.sbin/sysinstall/devices.c index c1f4b94b1ab76..aa63d8d0e0ad4 100644 --- a/usr.sbin/sysinstall/devices.c +++ b/usr.sbin/sysinstall/devices.c @@ -4,7 +4,7 @@ * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * - * $Id: devices.c,v 1.13 1995/05/11 06:10:45 jkh Exp $ + * $Id: devices.c,v 1.14 1995/05/11 06:47:42 jkh Exp $ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. @@ -42,324 +42,277 @@ */ #include "sysinstall.h" + #include <sys/fcntl.h> -#include <ctype.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/ioctl.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <netinet/in.h> +#include <netinet/in_var.h> +#include <arpa/inet.h> + +#define NSIP +#include <netns/ns.h> +#include <netns/ns_if.h> +#include <netdb.h> + +#define EON +#include <netiso/iso.h> +#include <netiso/iso_var.h> +#include <sys/protosw.h> -/* Where we start displaying chunk information on the screen */ -#define CHUNK_START_ROW 5 +#include <ctype.h> -static char *cdrom_table[] = { - "cd0a", "cd1a", /* SCSI */ - "mcd0a", "mcd1a", /* Mitsumi (old model) */ - "scd0a", "scd1a", /* Sony CDROM */ - "matcd0a", "matcd1a", /* Matsushita (SB) */ - NULL, +static Device *Devices[DEV_MAX]; +static int numDevs; + +#define CHECK_DEVS \ + if (numDevs == DEV_MAX) msgFatal("Too many devices found!") + +static struct { + DeviceType type; + char *name; + char *description; +} device_names[] = { + { DEVICE_TYPE_CDROM, "cd0a", "SCSI CDROM drive" }, + { DEVICE_TYPE_CDROM, "cd1a", "SCSI CDROM drive (2nd unit)" }, + { DEVICE_TYPE_CDROM, "mcd0a", "Mitsumi (old model) CDROM drive" }, + { DEVICE_TYPE_CDROM, "mcd1a", "Mitsumi (old model) CDROM drive (2nd unit)" }, + { DEVICE_TYPE_CDROM, "scd0a", "Sony CDROM drive - CDU31/33A type", } + { DEVICE_TYPE_CDROM, "scd1a", "Sony CDROM drive - CDU31/33A type (2nd unit)" }, + { DEVICE_TYPE_CDROM, "matcd0a", "Matsushita CDROM ("sound blaster" type)" }, + { DEVICE_TYPE_CDROM, "matcd1a", "Matsushita CDROM ("sound blaster" type - 2nd unit)" }, + { DEVICE_TYPE_TAPE, "rst0", "SCSI tape drive" }, + { DEVICE_TYPE_TAPE, "rst1", "SCSI tape drive (2nd unit)" }, + { DEVICE_TYPE_TAPE, "ft0", "Floppy tape drive (QIC-02)" }, + { DEVICE_TYPE_TAPE, "wt0", "Wangtek tape drive" }, + { DEVICE_TYPE_DISK, "sd", "SCSI disk device" }, + { DEVICE_TYPE_DISK, "wd", "IDE/ESDI/MFM/ST506 disk device" }, + { DEVICE_TYPE_NETWORK, "lo", "Loop-back (local) network interface" }, + { DEVICE_TYPE_NETWORK, "sl", "Serial-line IP (SLIP) interface" }, + { DEVICE_TYPE_NETWORK, "ppp", "Point-to-Point Protocol (PPP) interface" }, + { DEVICE_TYPE_NETWORK, "tun", "Tunneling IP driver (not for direct use)" }, + { DEVICE_TYPE_NETWORK, "ed", "WD/SMC 80xx; Novell NE1000/2000; 3Com 3C503 cards" }, + { DEVICE_TYPE_NETWORK, "ep", "3Com 3C509 interface card" }, + { DEVICE_TYPE_NETWORK, "el", "3Com 3C501 interface card" }, + { DEVICE_TYPE_NETWORK, "fe", "Fujitsu MB86960A/MB86965A Ethernet" }, + { DEVICE_TYPE_NETWORK, "ie", "AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210" }, + { DEVICE_TYPE_NETWORK, "le", "DEC EtherWorks 2 and 3" }, + { DEVICE_TYPE_NETWORK, "lnc", "Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL)" }, + { DEVICE_TYPE_NETWORK, "ze", "IBM/National Semiconductor PCMCIA ethernet controller" }, + { DEVICE_TYPE_NETWORK, "zp", "3Com PCMCIA Etherlink III" }, + { NULL }, }; -/* Get all device information for a given device class */ static Device * -device_get_all(DeviceType which, int *ndevs) +new_device(char *name) { - char **names; - Device *devs = NULL; - - *ndevs = 0; - if (which == DEVICE_TYPE_DISK || which == DEVICE_TYPE_ANY) { - if ((names = Disk_Names()) != NULL) { - int i; - - for (i = 0; names[i]; i++) - ++*ndevs; - devs = safe_malloc(sizeof(Device) * (*ndevs + 1)); - for (i = 0; names[i]; i++) { - strcpy(devs[i].name, names[i]); - devs[i].type = DEVICE_TYPE_DISK; - } - free(names); - } - } - if (which == DEVICE_TYPE_CDROM || which == DEVICE_TYPE_ANY) { - char try[FILENAME_MAX]; - int i, fd; - - for (i = 0; cdrom_table[i]; i++) { - snprintf(try, FILENAME_MAX, "/mnt/dev/%s", cdrom_table[i]); - fd = open(try, O_RDWR); - if (fd > 0) { - close(fd); - devs = safe_realloc(devs, sizeof(Device) * (*ndevs + 2)); - strcpy(devs[*ndevs].name, cdrom_table[i]); - devs[(*ndevs)++].type = DEVICE_TYPE_CDROM; - break; - } - } - } - /* Terminate the devices array */ - devs[*ndevs].name[0] = '\0'; - return devs; + Device *dev; + + dev = safe_malloc(sizeof(Device)); + if (name) + strcpy(dev->name, name); + else + dev->name[0] = '\0'; + return dev; } -static struct chunk *chunk_info[10]; -static int current_chunk; - -static void -record_chunks(struct disk *d) +static int +deviceTry(char *name) { - struct chunk *c1; - int i = 0; - int last_free = 0; - if (!d->chunks) - msgFatal("No chunk list found for %s!", d->name); - c1 = d->chunks->part; - current_chunk = 0; - while (c1) { - if (c1->type == unused && c1->size > last_free) { - last_free = c1->size; - current_chunk = i; - } - chunk_info[i++] = c1; - c1 = c1->next; - } - chunk_info[i] = NULL; -} - -static void -print_chunks(struct disk *d) -{ - int row; - int i; - - attrset(A_NORMAL); - mvaddstr(0, 0, "Disk name:\t"); - attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); - attrset(A_REVERSE); mvaddstr(0, 55, "Master Partition Editor"); attrset(A_NORMAL); - mvprintw(1, 0, - "BIOS Geometry:\t%lu cyls/%lu heads/%lu sectors", - d->bios_cyl, d->bios_hd, d->bios_sect); - mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s", - "Offset", "Size", "End", "Name", "PType", "Desc", - "Subtype", "Flags"); - for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { - if (i == current_chunk) - attrset(A_REVERSE); - mvprintw(row, 2, "%10lu %10lu %10lu %8s %8d %8s %8d %6lx", - chunk_info[i]->offset, chunk_info[i]->size, - chunk_info[i]->end, chunk_info[i]->name, - chunk_info[i]->type, chunk_n[chunk_info[i]->type], - chunk_info[i]->subtype, chunk_info[i]->flags); - if (i == current_chunk) - attrset(A_NORMAL); - } + char try[FILENAME_MAX]; + + snprintf(try, FILENAME_MAX, "/dev/%s", name); + fd = open(try, O_RDWR); + if (fd > 0) + return fd; + snprintf(try, FILENAME_MAX, "/mnt/dev/%s", name); + fd = open(try, O_RDWR); + return fd; } static void -print_command_summary() +deviceDiskFree(Device *dev) { - mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); - mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Partition"); - mvprintw(17, 0, "D = Delete Partition G = Set BIOS Geometry S = Set Bootable"); - mvprintw(18, 0, "U = Undo All Changes W = `Wizard' Mode ESC = Proceed to next screen"); - mvprintw(20, 0, "The currently selected partition is displayed in "); - attrset(A_REVERSE); addstr("reverse video."); attrset(A_NORMAL); - mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to move."); - move(0, 0); + Disk_Close(dev->private); } -struct disk * -device_slice_disk(struct disk *d) +/* Get all device information for devices we have attached */ +void +deviceGetAll(Boolean disksOnly) { - char *p; - int key = 0; - Boolean chunking; - char *msg = NULL; - char name[40]; + int i, fd, s; + struct ifconf ifc; + struct ifreq *ifptr, *end; + int ifflags, selectflag = -1; + char buffer[INTERFACES_MAX * sizeof(struct ifreq)]; - dialog_clear(); - chunking = TRUE; - strncpy(name, d->name, 40); - keypad(stdscr, TRUE); + /* We do this at the very beginning */ + if (disksOnly) { + char **names = Disk_names(); - record_chunks(d); - while (chunking) { - clear(); - print_chunks(d); - print_command_summary(); - if (msg) { - standout(); mvprintw(23, 0, msg); standend(); - beep(); - msg = NULL; + if (names) { + int i; + + for (i = 0; names[i]; i++) { + CHECK_DEVS; + Devices[numDevs] = new_device(names[i]); + Devices[numDevs]->type = DEVICE_TYPE_DISK; + Devices[numDevs]->ignore = TRUE; + Devices[numDevs]->init = NULL; + Devices[numDevs]->get = mediaUFSGet; + Devices[numDevs]->close = deviceDiskFree; + Devices[numDevs]->private = Open_Disk(names[i]); + if (!Devices[numDevs]->private) + msgFatal("Unable to open device for %s!", names[i]); + msgDebug("Found a device of type disk named: %s\n", + names[i]); + ++numDevs; + } + free(names); } - refresh(); - - key = toupper(getch()); - switch (key) { - case KEY_UP: - case '-': - if (current_chunk != 0) - --current_chunk; - break; - - case KEY_DOWN: - case '+': - case '\r': - case '\n': - if (chunk_info[current_chunk + 1]) - ++current_chunk; - break; - - case KEY_HOME: - current_chunk = 0; - break; - - case KEY_END: - while (chunk_info[current_chunk + 1]) - ++current_chunk; - break; - - case KEY_F(1): - case '?': - systemDisplayFile("slice.hlp"); - break; - - case 'A': - All_FreeBSD(d); - record_chunks(d); - break; - - case 'B': - if (chunk_info[current_chunk]->type != freebsd) - msg = "Can only scan for bad blocks in FreeBSD partition."; - else if (strncmp(name, "sd", 2) || - !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\nAre you sure you want to do this on a SCSI disk?")) - chunk_info[current_chunk]->flags |= CHUNK_BAD144; - break; - - case 'C': - if (chunk_info[current_chunk]->type != unused) - msg = "Partition in use, delete it first or move to an unused one."; - else { - char *val, tmp[20]; - int size; + return; + } - snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size); - val = msgGetInput(tmp, "Please specify size for new FreeBSD partition"); - if (val && (size = strtol(val, 0, 0)) > 0) { - Create_Chunk(d, chunk_info[current_chunk]->offset, - size, - freebsd, - 3, - (chunk_info[current_chunk]->flags & - CHUNK_ALIGN)); - record_chunks(d); - } + /* + * Try to get all the types of devices it makes sense to get at the + * second stage of the installation. + */ + for (i = 0; device_names[i].name; i++) { + switch(device_names[i].type) { + case DEVICE_TYPE_CDROM: + fd = deviceTry(device_names[i].name); + if (fd > 0) { + close(fd); + CHECK_DEVS; + Devices[numDevs] = new_devices(device_names[i].name); + Devices[numDevs]->type = DEVICE_TYPE_CDROM; + Devices[numDevs]->description = devices_names[i].description; + Devices[numDevs]->ignore = FALSE; + Devices[numDevs]->init = NULL; + Devices[numDevs]->get = mediaCDROMGet; + Devices[numDevs]->close = NULL; + Devices[numDevs]->private = NULL; + msgDebug("Found a device of type CDROM named: %s\n", + cdrom_table[i]); + ++numDevs; } break; - case 'D': - if (chunk_info[current_chunk]->type == unused) - msg = "Partition is already unused!"; - else { - Delete_Chunk(d, chunk_info[current_chunk]); - record_chunks(d); + case DEVICE_TYPE_TAPE: + fd = deviceTry(device_names[i].name); + if (fd > 0) { + close(fd); + CHECK_DEVS; + Devices[numDevs] = new_devices(device_names[i].name); + Devices[numDevs]->type = DEVICE_TYPE_TAPE; + Devices[numDevs]->ignore = FALSE; + Devices[numDevs]->init = mediaTapeInit; + Devices[numDevs]->get = mediaTapeGet; + Devices[numDevs]->close = mediaTapeClose; + Devices[numDevs]->private = NULL; + msgDebug("Found a device of type TAPE named: %s\n", + tape_table[i]); + ++numDevs; } break; - - case 'G': { - char *val, geometry[80]; - - snprintf(geometry, 80, "%lu/%lu/%lu", - d->bios_cyl, d->bios_hd, d->bios_sect); - val = msgGetInput(geometry, -"Please specify the new geometry in cyl/hd/sect format.\nDon't forget to use the two slash (/) separator characters!\nIt's not possible to parse the field without them."); - if (val) { - d->bios_cyl = strtol(val, &val, 0); - d->bios_hd = strtol(val + 1, &val, 0); - d->bios_sect = strtol(val + 1, 0, 0); - } } - break; - - case 'S': - /* Set Bootable */ - chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; - break; - - case 'U': - Free_Disk(d); - d = Open_Disk(name); - if (!d) - msgFatal("Can't reopen disk %s!", name); - record_chunks(d); - break; - - case 'W': - if (!msgYesNo("Are you sure you want to go into Wizard mode?\nNo seat belts whatsoever are provided!")) { - clear(); - dialog_clear(); - end_dialog(); - DialogActive = FALSE; - slice_wizard(d); - clear(); - dialog_clear(); - DialogActive = TRUE; - record_chunks(d); - } - else - msg = "Wise choice!"; - break; - - case 27: /* ESC */ - chunking = FALSE; - break; + } - default: - beep(); - msg = "Type F1 or ? for help"; - break; + /* + * Now go for the network interfaces dynamically. Stolen shamelessly + * from ifconfig! + */ + ifc.ifc_len = sizeof(buffer); + ifc.ifc_buf = buffer; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + msgConfirm("ifconfig: socket"); + return; + } + if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) { + msgConfirm("ifconfig (SIOCGIFCONF)"); + return; + } + ifflags = ifc.ifc_req->ifr_flags; + end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); + ifptr = ifc.ifc_req; + while (ifptr < end) { + CHECK_DEVS; + Devices[numDevs] = new_devices(ifptr->ifr_name); + Devices[numDevs]->type = DEVICE_TYPE_NETWORK; + Devices[numDevs]->ignore = FALSE; + Devices[numDevs]->init = mediaNetworkInit; + Devices[numDevs]->get = mediaNetworkGet; + Devices[numDevs]->close = mediaNetworkClose; + Devices[numDevs]->private = NULL; + msgDebug("Found a device of type network named: %s\n", + ifptr->ifr_name); + ++numDevs; + close(s); + if ((s = socket(af, SOCK_DGRAM, 0)) < 0) { + msgConfirm("ifconfig: socket"); + continue; } + if (ifptr->ifr_addr.sa_len) /* Dohw! */ + ifptr = (struct ifreq *)((caddr_t)ifptr + ifptr->ifr_addr.sa_len + - sizeof(struct sockaddr)); + ifptr++; } - p = CheckRules(d); - if (p) { - msgConfirm(p); - free(p); + /* Terminate the devices array */ + Devices[numDevs] = NULL; +} + +/* + * Find all devices that match the criteria, allowing "wildcarding" as well + * by allowing NULL or ANY values to match all. + */ +Device ** +deviceFind(char *name, DeviceType class) +{ + static Device *found[DEV_MAX]; + int i, j; + + for (i = 0, j = 0; i < numDevs; i++) { + if ((!name || !strcmp(Devices[i]->name, name)) && + (class == DEVICE_TYPE_ANY || class == Devices[i]->type)) + found[j++] = Devices[i]; } - clear(); - refresh(); - return d; + found[j] = NULL; + return j ? found : NULL; } /* - * Create a menu listing all the devices in the system. The pass-in menu - * is expected to be a "prototype" from which the new menu is cloned. + * Create a menu listing all the devices of a certain type in the system. + * The passed-in menu is expected to be a "prototype" from which the new + * menu is cloned. */ DMenu * -device_create_disk_menu(DMenu *menu, Device **rdevs, int (*hook)()) +deviceCreateMenu(DMenu *menu, DeviceType type, int (*hook)()) { - Device *devices; - int numdevs; + Device **devs; - devices = device_get_all(DEVICE_TYPE_DISK, &numdevs); - *rdevs = devices; - if (!devices) { - msgConfirm("No devices suitable for installation found!\n\nPlease verify that your disk controller (and attached drives) were detected properly. This can be done by selecting the ``Bootmsg'' option on the main menu and reviewing the boot messages carefully."); - return NULL; - } - else { - Device *start; + devs = deviceFind(NULL, type); + if (devs) { DMenu *tmp; - int i; + int i, j; tmp = (DMenu *)safe_malloc(sizeof(DMenu) + (sizeof(DMenuItem) * (numdevs + 1))); bcopy(menu, tmp, sizeof(DMenu)); - for (start = devices, i = 0; start->name[0]; start++, i++) { - tmp->items[i].title = start->name; - if (!strncmp(start->name, "sd", 2)) - tmp->items[i].prompt = "SCSI disk"; - else if (!strncmp(start->name, "wd", 2)) - tmp->items[i].prompt = "IDE/ESDI/MFM/ST506 disk"; - else - msgFatal("Unknown disk type: %s!", start->name); + for (i = 0; *devs; i++, devs++) { + tmp->items[i].title = *devs->name; + for (j = 0; device_names[j].name; j++) { + if (!strncmp(*devs->name, device_names[j].name, + strlen(device_names[j].name))) + tmp->items[i].prompt = devices_names[j].description; + } + if (!device_names[j].name) + tmp->items[i].prompt = "<unknown device type>"; tmp->items[i].type = DMENU_CALL; tmp->items[i].ptr = hook; tmp->items[i].disabled = FALSE; |