improve the completion facility and fix some bugs.

This commit is contained in:
okuji 1999-06-01 14:59:50 +00:00
parent b1c1211adb
commit 8b55b165f2
11 changed files with 212 additions and 28 deletions

View file

@ -1,3 +1,40 @@
1999-06-01 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* grub/asmstub.c: Do not use I_AM_VERY_BRAVE any more.
(grub_stage2): Delete first_scsi_disk and add a variable
num_hd, which is used for counting how many drives are
detected.
Initialize the flags member of each element of disks to -1
instead of 0, and check if it is equal to -1 instead of 0 when
close it.
(get_diskinfo): Treat -1 as non-caching state instead of 0.
1999-06-01 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
Reported from Klaus Reichl <a8709182@unet.univie.ac.at>:
* docs/.cvsignore: New file.
* shared_src/disk_io.c (print_a_completion): New function
which saves what has been printed to UNIQUE_STRING and printf
it.
(unique) [!STAGE1_5]: New variable.
(unique_string): Likewise.
(print_completions): Use print_a_completion, and improve the
completion facility.
* shared_src/fsys_ext2fs.c (ext2fs_dir) [!STAGE1_5]: Use
print_a_completion instead of just printf.
* shared_src/fsys_ffs.c (ffs_dir) [!STAGE1_5]: Likewise.
* shared_src/fsys_fat.c (fat_dir) [!STAGE1_5]: Likewise.
* shared_src/shared.h (print_a_completion): Declared.
* shared_src/cmdline.c (enter_cmdline): Explicitly cast
int to pointer to char for grub_read.
* grub/asmstub.c (grub_stage2) [__linux__]: Don't use /dev/fd1.
Probe 4 IDE drives instead of 2.
(biosdisk) [__linux__]: Add a prototype for _llseek.
* shared_src/char_io.c (get_cmdline): Update LPOS and LLEN_OLD
when the functon print_completion modifies CMDLINE.
* shared_src/stage2.c (get_line_from_config): Fix LITERAL
handling.
1999-05-25 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp> 1999-05-25 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* grub/asmstub.c (grub_stage2): Fix a memory leak that FP is * grub/asmstub.c (grub_stage2): Fix a memory leak that FP is

3
docs/.cvsignore Normal file
View file

@ -0,0 +1,3 @@
*.info*
version.texi
stamp-vti

View file

@ -38,6 +38,7 @@ int grub_stage2 (void);
#include <fcntl.h> #include <fcntl.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <string.h>
#ifdef __linux__ #ifdef __linux__
# include <sys/ioctl.h> /* ioctl */ # include <sys/ioctl.h> /* ioctl */
@ -78,8 +79,7 @@ grub_stage2 (void)
/* These need to be static, because they survive our stack transitions. */ /* These need to be static, because they survive our stack transitions. */
static int status = 0; static int status = 0;
static char *realstack; static char *realstack;
int i; int i, num_hd = 0;
int first_scsi_disk;
char *scratch, *simstack; char *scratch, *simstack;
/* We need a nested function so that we get a clean stack frame, /* We need a nested function so that we get a clean stack frame,
@ -119,7 +119,7 @@ grub_stage2 (void)
assert (disks); assert (disks);
/* Initialize DISKS. */ /* Initialize DISKS. */
for (i = 0; i < NUM_DISKS; i++) for (i = 0; i < NUM_DISKS; i++)
disks[i].flags = 0; disks[i].flags = -1;
assert (device_map == 0); assert (device_map == 0);
device_map = malloc (NUM_DISKS * sizeof (char *)); device_map = malloc (NUM_DISKS * sizeof (char *));
@ -132,10 +132,14 @@ grub_stage2 (void)
/* Floppies. */ /* Floppies. */
device_map[0] = strdup ("/dev/fd0"); device_map[0] = strdup ("/dev/fd0");
#ifndef __linux__
/* FIXME: leave linux out for now /dev/fd1 blocks for long time
if there is no second floppy ? */
device_map[1] = strdup ("/dev/fd1"); device_map[1] = strdup ("/dev/fd1");
#endif
/* IDE disks. */ /* IDE disks. */
for (i = 0; i < 2; i++) for (i = 0; i < 4; i++)
{ {
char name[10]; char name[10];
FILE *fp; FILE *fp;
@ -149,7 +153,30 @@ grub_stage2 (void)
sprintf (name, "/dev/hd%c", unit); sprintf (name, "/dev/hd%c", unit);
fp = fopen (name, "r"); fp = fopen (name, "r");
if (! fp) if (! fp)
{
switch (errno)
{
#ifdef ENOMEDIUM
case ENOMEDIUM:
#if 0
/* At the moment, this finds only CDROMs, which can't be
read anyway, so leave it out. Code should be
reactivated if `removable disks' and CDROMs are
supported. */
/* register it, it may be inserted. */
device_map[num_hd++ + 0x80] = strdup (name);
#endif
break; break;
#endif /* ENOMEDIUM */
default:
/* break case and leave */
break;
}
/* continue: there may be more disks sitting sparse on the
controllers */
continue;
}
/* Attempt to read the first sector. */ /* Attempt to read the first sector. */
if (fread (buf, 1, 512, fp) != 512) if (fread (buf, 1, 512, fp) != 512)
{ {
@ -158,9 +185,8 @@ grub_stage2 (void)
} }
fclose (fp); fclose (fp);
device_map[i + 0x80] = strdup (name); device_map[num_hd++ + 0x80] = strdup (name);
} }
first_scsi_disk = i + 0x80;
/* The rest is SCSI disks. */ /* The rest is SCSI disks. */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
@ -173,7 +199,7 @@ grub_stage2 (void)
#else #else
sprintf (name, "/dev/sd%d", i); sprintf (name, "/dev/sd%d", i);
#endif #endif
device_map[i + first_scsi_disk] = name; device_map[num_hd++ + 0x80] = name;
} }
/* Check some invariants. */ /* Check some invariants. */
@ -208,7 +234,7 @@ grub_stage2 (void)
/* Close off the file descriptors we used. */ /* Close off the file descriptors we used. */
for (i = 0; i < NUM_DISKS; i ++) for (i = 0; i < NUM_DISKS; i ++)
if (disks[i].flags) if (disks[i].flags != -1)
close (disks[i].flags); close (disks[i].flags);
/* Release memory. */ /* Release memory. */
@ -473,7 +499,7 @@ get_diskinfo (int drive, struct geometry *geometry)
or my reputation would be ruined. --Gord */ or my reputation would be ruined. --Gord */
/* See if we have a cached device. */ /* See if we have a cached device. */
if (! disks[drive].flags) if (disks[drive].flags == -1)
{ {
/* The unpartitioned device name: /dev/XdX */ /* The unpartitioned device name: /dev/XdX */
char *devname = device_map[drive]; char *devname = device_map[drive];
@ -484,18 +510,27 @@ get_diskinfo (int drive, struct geometry *geometry)
/* Open read/write, or read-only if that failed. */ /* Open read/write, or read-only if that failed. */
disks[drive].flags = open (devname, O_RDWR); disks[drive].flags = open (devname, O_RDWR);
if (! disks[drive].flags) if (disks[drive].flags == -1)
{
if (errno == EACCES || errno == EROFS)
{
disks[drive].flags = open (devname, O_RDONLY); disks[drive].flags = open (devname, O_RDONLY);
if (disks[drive].flags == -1)
return -1;
}
else
return -1;
}
/* Attempt to read the first sector. */ /* Attempt to read the first sector. */
if (read (disks[drive].flags, buf, 512) != 512) if (read (disks[drive].flags, buf, 512) != 512)
{ {
close (disks[drive].flags); close (disks[drive].flags);
disks[drive].flags = 0; disks[drive].flags = -1;
return -1; return -1;
} }
if (disks[drive].flags) if (disks[drive].flags != -1)
{ {
#ifdef __linux__ #ifdef __linux__
struct hd_geometry hdg; struct hd_geometry hdg;
@ -538,7 +573,7 @@ get_diskinfo (int drive, struct geometry *geometry)
} }
} }
if (! disks[drive].flags) if (disks[drive].flags == -1)
return -1; return -1;
*geometry = disks[drive]; *geometry = disks[drive];
@ -613,6 +648,7 @@ biosdisk (int subfunc, int drive, struct geometry *geometry,
/* FIXME: only use this section if libc doesn't have large file support */ /* FIXME: only use this section if libc doesn't have large file support */
{ {
loff_t offset, result; loff_t offset, result;
static int _llseek (uint fd, ulong hi, ulong lo, loff_t *res, uint wh);
_syscall5 (int, _llseek, uint, fd, ulong, hi, ulong, lo, _syscall5 (int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh); loff_t *, res, uint, wh);
@ -633,15 +669,10 @@ biosdisk (int subfunc, int drive, struct geometry *geometry,
if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE) if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
return -1; return -1;
break; break;
/* For now, I don't want to turn on this write code by default,
because a bug that I haven't known yet may destroy all disks
in the world. */
#ifdef I_AM_VERY_BRAVE
case BIOSDISK_WRITE: case BIOSDISK_WRITE:
if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE) if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
return -1; return -1;
break; break;
#endif
default: default:
grub_printf ("unknown subfunc %d\n", subfunc); grub_printf ("unknown subfunc %d\n", subfunc);
break; break;

View file

@ -276,6 +276,10 @@ get_cmdline (char *prompt, char *commands, char *cmdline, int maxlen,
i = j + 1; i = j + 1;
/* print possible completions */ /* print possible completions */
print_completions (cmdline + i); print_completions (cmdline + i);
/* if somebody in print_completions has added something,
account for that */
while (cmdline[lpos])
lpos++, llen_old++;
} }
else if (commands) else if (commands)
printf (commands); printf (commands);

View file

@ -466,7 +466,7 @@ returnit:
while ((*(str++) = *(ptr++)) != 0); /* do copy */ while ((*(str++) = *(ptr++)) != 0); /* do copy */
} }
grub_read (RAW_ADDR (0x100000), -1); grub_read ((char *) RAW_ADDR (0x100000), -1);
buf_track = -1; buf_track = -1;

View file

@ -574,6 +574,10 @@ open_partition (void)
/* XX used for device completion in 'set_device' and 'print_completions' */ /* XX used for device completion in 'set_device' and 'print_completions' */
static int incomplete, disk_choice; static int incomplete, disk_choice;
#ifndef STAGE1_5
static int unique;
static char unique_string[128]; /* XXX Don't know yet */
#endif
static enum static enum
{ {
PART_UNSPECIFIED = 0, PART_UNSPECIFIED = 0,
@ -595,12 +599,31 @@ set_device (char *device)
current_drive = saved_drive; current_drive = saved_drive;
current_partition = 0xFFFFFF; current_partition = 0xFFFFFF;
if (*device == '(' && !*(device + 1))
/* user has given '(' only, let disk_choice handle what disks we have */
return device + 1;
if (*device == '(' && *(++device)) if (*device == '(' && *(++device))
{ {
if (*device != ',' && *device != ')') if (*device != ',' && *device != ')')
{ {
char ch = *device; char ch = *device;
if (*device == 'f' || *device == 'h')
{
/* user has given '([fh]', check for resp. add 'd' and
let disk_choice handle what disks we have */
if (!*(device + 1))
{
device++;
*device++ = 'd';
*device = '\0';
return device;
}
else if (*(device + 1) == 'd' && !*(device + 2))
return device + 2;
}
if ((*device == 'f' || *device == 'h') if ((*device == 'f' || *device == 'h')
&& (device += 2, (*(device - 1) != 'd'))) && (device += 2, (*(device - 1) != 'd')))
errnum = ERR_NUMBER_PARSING; errnum = ERR_NUMBER_PARSING;
@ -879,6 +902,35 @@ print_fsys_type (void)
#endif /* STAGE1_5 */ #endif /* STAGE1_5 */
#ifndef STAGE1_5 #ifndef STAGE1_5
/*
* print_a_completion saves what has been printed to unique_string
* printf's with a leading ' '.
*/
void
print_a_completion (char *filename)
{
char *f = filename;
char *u = unique_string;
if (! *u && unique == 0)
{
/* copy first string, this is unique. */
while ((*u++ = *f++))
;
}
else
{
while (*u && (*u == *f))
u++, f++;
/* mismatch, strip it. */
*u = '\0';
}
unique++;
printf (" %s", filename);
}
/* /*
* This lists the possible completions of a device string, filename, or * This lists the possible completions of a device string, filename, or
* any sane combination of the two. * any sane combination of the two.
@ -889,6 +941,9 @@ print_completions (char *filename)
{ {
char *ptr = filename; char *ptr = filename;
*unique_string = '\0';
unique = 0;
if (*filename == '/' || (ptr = set_device (filename)) || incomplete) if (*filename == '/' || (ptr = set_device (filename)) || incomplete)
{ {
errnum = 0; errnum = 0;
@ -903,16 +958,44 @@ print_completions (char *filename)
printf (" Possible disks are: "); printf (" Possible disks are: ");
for (i = 0; i < 2; i++) for (i = (ptr && (*(ptr-2) == 'h' && *(ptr-1) == 'd') ? 1 : 0);
i < (ptr && (*(ptr-2) == 'f' && *(ptr-1) == 'd') ? 1 : 2);
i++)
{ {
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
{ {
disk_no = (i * 0x80) + j; disk_no = (i * 0x80) + j;
if ((disk_choice || disk_no == current_drive) && if ((disk_choice || disk_no == current_drive) &&
! get_diskinfo (disk_no, &geom)) ! get_diskinfo (disk_no, &geom))
printf (" %cd%d", (i ? 'h' : 'f'), j); {
char dev_name[4];
dev_name[0] = (i ? 'h' : 'f');
dev_name[1] = 'd';
dev_name[2] = '0' + j;
dev_name[3] = '\0';
print_a_completion (dev_name);
} }
} }
}
ptr = filename;
while (*ptr != '(')
ptr--;
ptr++;
{
char *u = unique_string;
while ((*ptr++ = *u++))
;
ptr--;
}
ptr--;
if ((*(ptr - 2) == 'h') && (*(ptr - 1) == 'd')
&& ('0' <= *ptr && *ptr <= '8'))
*(ptr + 1) = ',', *(ptr + 2) = '\0';
if ((*(ptr - 2) == 'f') && (*(ptr - 1) == 'd')
&& ('0' <= *ptr && *ptr <= '8'))
*(ptr + 1) = ')', *(ptr + 2) = '\0';
putchar ('\n'); putchar ('\n');
} }
@ -927,7 +1010,18 @@ print_completions (char *filename)
else else
{ {
if (open_partition ()) if (open_partition ())
{
check_and_print_mount (); check_and_print_mount ();
/* FIXME: Can talk about linux only, do we need
to know about syntax here? */
ptr = filename;
while (*ptr)
ptr++;
if (*(ptr - 1) != ')')
*ptr++ = ')';
*ptr++ = '/';
*ptr = '\0';
}
} }
} }
} }
@ -936,6 +1030,20 @@ print_completions (char *filename)
/* filename completions */ /* filename completions */
printf (" Possible files are:"); printf (" Possible files are:");
dir (filename); dir (filename);
{
char *u = unique_string;
if (*u)
{
while (*ptr++)
;
while (*ptr != '/')
ptr--;
ptr++;
while ((*ptr++ = *u++))
;
}
}
} }
else else
errnum = ERR_BAD_FILENAME; errnum = ERR_BAD_FILENAME;

View file

@ -757,7 +757,7 @@ ext2fs_dir (char *dirname)
{ {
if (print_possibilities > 0) if (print_possibilities > 0)
print_possibilities = -print_possibilities; print_possibilities = -print_possibilities;
printf (" %s", dp->name); print_a_completion (dp->name);
} }
# endif # endif

View file

@ -240,7 +240,7 @@ loop:
{ {
if (print_possibilities > 0) if (print_possibilities > 0)
print_possibilities = -print_possibilities; print_possibilities = -print_possibilities;
printf (" %s", filename); print_a_completion (filename);
} }
# endif /* STAGE1_5 */ # endif /* STAGE1_5 */
} }

View file

@ -252,7 +252,7 @@ loop:
if (print_possibilities > 0) if (print_possibilities > 0)
print_possibilities = -print_possibilities; print_possibilities = -print_possibilities;
printf (" %s", dp->d_name); print_a_completion (dp->d_name);
} }
#endif /* STAGE1_5 */ #endif /* STAGE1_5 */
} }

View file

@ -512,6 +512,7 @@ int set_bootdev (int hdbias);
void print_fsys_type (void); void print_fsys_type (void);
/* Display device and filename completions. */ /* Display device and filename completions. */
void print_a_completion (char *filename);
void print_completions (char *filename); void print_completions (char *filename);
/* Copies the current partition data to the desired address. */ /* Copies the current partition data to the desired address. */

View file

@ -470,7 +470,7 @@ get_line_from_config(char *cmdline, int maxlen)
while (grub_read (&c, 1)) while (grub_read (&c, 1))
{ {
/* translate characters first! */ /* translate characters first! */
if (c == '\\') if (c == '\\' && ! literal)
{ {
literal = 1; literal = 1;
continue; continue;