26 |
#include <grub/disk.h> |
#include <grub/disk.h> |
27 |
#include <grub/file.h> |
#include <grub/file.h> |
28 |
|
|
|
/* The disk that is used for grub_partition_iterate. */ |
|
|
static grub_device_t disk_dev; |
|
|
|
|
29 |
/* The current word. */ |
/* The current word. */ |
30 |
static char *current_word; |
static char *current_word; |
31 |
|
|
38 |
/* The string to be appended. */ |
/* The string to be appended. */ |
39 |
static const char *suffix; |
static const char *suffix; |
40 |
|
|
41 |
|
/* The callback function to print items. */ |
42 |
|
static void (*print_func) (const char *, grub_completion_type_t, int); |
|
static void |
|
|
print_simple_completion (const char *str) |
|
|
{ |
|
|
grub_printf (" %s", str); |
|
|
} |
|
43 |
|
|
44 |
static void |
|
|
print_partition_completion (const char *str) |
|
|
{ |
|
|
grub_print_partinfo (disk_dev, (char *) str); |
|
|
grub_errno = GRUB_ERR_NONE; |
|
|
} |
|
45 |
|
|
46 |
/* Add a string to the list of possible completions. COMPLETION is the |
/* Add a string to the list of possible completions. COMPLETION is the |
47 |
string that should be added. EXTRA will be appended if COMPLETION |
string that should be added. EXTRA will be appended if COMPLETION |
48 |
matches uniquely. The string WHAT contains a description of the |
matches uniquely. The type TYPE specifies what kind of data is added. */ |
|
kind of data that is added. Use PRINT to show the completions |
|
|
if there are multiple matches. */ |
|
49 |
static int |
static int |
50 |
add_completion (const char *completion, const char *extra, const char *what, |
add_completion (const char *completion, const char *extra, |
51 |
void (*print) (const char *)) |
grub_completion_type_t type) |
52 |
{ |
{ |
53 |
if (grub_strncmp (current_word, completion, grub_strlen (current_word)) == 0) |
if (grub_strncmp (current_word, completion, grub_strlen (current_word)) == 0) |
54 |
{ |
{ |
64 |
break; |
break; |
65 |
|
|
66 |
case 2: |
case 2: |
67 |
grub_printf ("\nPossible %s are:\n", what); |
if (print_func) |
68 |
print (match); |
print_func (match, type, 0); |
69 |
|
|
70 |
/* Fall through. */ |
/* Fall through. */ |
71 |
|
|
73 |
{ |
{ |
74 |
char *s = match; |
char *s = match; |
75 |
const char *t = completion; |
const char *t = completion; |
76 |
|
|
77 |
print (completion); |
if (print_func) |
78 |
|
print_func (completion, type, num_found - 1); |
79 |
|
|
80 |
/* Detect the matched portion. */ |
/* Detect the matched portion. */ |
81 |
while (*s && *t && *s == *t) |
while (*s && *t && *s == *t) |
94 |
} |
} |
95 |
|
|
96 |
static int |
static int |
97 |
iterate_partition (const grub_partition_t p) |
iterate_partition (grub_disk_t disk, const grub_partition_t p) |
98 |
{ |
{ |
99 |
return add_completion (grub_partition_get_name (p), ")", "partitions", |
const char *disk_name = disk->name; |
100 |
print_partition_completion); |
char *partition_name = grub_partition_get_name (p); |
101 |
|
char *name; |
102 |
|
int ret; |
103 |
|
|
104 |
|
if (! partition_name) |
105 |
|
return 1; |
106 |
|
|
107 |
|
name = grub_malloc (grub_strlen (disk_name) + 1 |
108 |
|
+ grub_strlen (partition_name) + 1); |
109 |
|
if (! name) |
110 |
|
{ |
111 |
|
grub_free (partition_name); |
112 |
|
return 1; |
113 |
|
} |
114 |
|
|
115 |
|
grub_sprintf (name, "%s,%s", disk_name, partition_name); |
116 |
|
grub_free (partition_name); |
117 |
|
|
118 |
|
ret = add_completion (name, ")", GRUB_COMPLETION_TYPE_PARTITION); |
119 |
|
grub_free (name); |
120 |
|
return ret; |
121 |
} |
} |
122 |
|
|
123 |
static int |
static int |
125 |
{ |
{ |
126 |
if (! dir) |
if (! dir) |
127 |
{ |
{ |
128 |
if (add_completion (filename, " ", "files", print_simple_completion)) |
if (add_completion (filename, " ", GRUB_COMPLETION_TYPE_FILE)) |
129 |
return 1; |
return 1; |
130 |
} |
} |
131 |
else |
else |
133 |
char fname[grub_strlen (filename) + 2]; |
char fname[grub_strlen (filename) + 2]; |
134 |
|
|
135 |
grub_sprintf (fname, "%s/", filename); |
grub_sprintf (fname, "%s/", filename); |
136 |
if (add_completion (fname, "", "files", print_simple_completion)) |
if (add_completion (fname, "", GRUB_COMPLETION_TYPE_FILE)) |
137 |
return 1; |
return 1; |
138 |
} |
} |
139 |
|
|
152 |
{ |
{ |
153 |
if (dev->disk && dev->disk->has_partitions) |
if (dev->disk && dev->disk->has_partitions) |
154 |
{ |
{ |
155 |
if (add_completion (devname, ",", "devices", |
if (add_completion (devname, ",", GRUB_COMPLETION_TYPE_DEVICE)) |
|
print_simple_completion)) |
|
156 |
return 1; |
return 1; |
157 |
} |
} |
158 |
else |
else |
159 |
{ |
{ |
160 |
if (add_completion (devname, ")", "devices", |
if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_DEVICE)) |
|
print_simple_completion)) |
|
161 |
return 1; |
return 1; |
162 |
} |
} |
163 |
} |
} |
173 |
{ |
{ |
174 |
if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE) |
if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE) |
175 |
{ |
{ |
176 |
if (add_completion (cmd->name, " ", "commands", |
if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) |
|
print_simple_completion)) |
|
177 |
return 1; |
return 1; |
178 |
} |
} |
179 |
} |
} |
187 |
{ |
{ |
188 |
/* Check if this is a device or a partition. */ |
/* Check if this is a device or a partition. */ |
189 |
char *p = grub_strchr (++current_word, ','); |
char *p = grub_strchr (++current_word, ','); |
190 |
|
grub_device_t dev; |
191 |
|
|
192 |
if (! p) |
if (! p) |
193 |
{ |
{ |
199 |
{ |
{ |
200 |
/* Complete the partition part. */ |
/* Complete the partition part. */ |
201 |
*p = '\0'; |
*p = '\0'; |
202 |
disk_dev = grub_device_open (current_word); |
dev = grub_device_open (current_word); |
203 |
*p = ','; |
*p = ','; |
204 |
grub_errno = GRUB_ERR_NONE; |
grub_errno = GRUB_ERR_NONE; |
205 |
|
|
206 |
if (disk_dev) |
if (dev) |
207 |
{ |
{ |
208 |
if (disk_dev->disk && disk_dev->disk->has_partitions) |
if (dev->disk && dev->disk->has_partitions) |
209 |
{ |
{ |
210 |
current_word = p + 1; |
if (grub_partition_iterate (dev->disk, iterate_partition)) |
|
|
|
|
if (grub_partition_iterate (disk_dev->disk, iterate_partition)) |
|
211 |
{ |
{ |
212 |
grub_device_close (disk_dev); |
grub_device_close (dev); |
213 |
return 1; |
return 1; |
214 |
} |
} |
215 |
} |
} |
216 |
|
|
217 |
grub_device_close (disk_dev); |
grub_device_close (dev); |
218 |
} |
} |
219 |
else |
else |
220 |
return 1; |
return 1; |
305 |
|
|
306 |
/* Try to complete the string in BUF. Return the characters that |
/* Try to complete the string in BUF. Return the characters that |
307 |
should be added to the string. This command outputs the possible |
should be added to the string. This command outputs the possible |
308 |
completions, in that case set RESTORE to 1 so the caller can |
completions by calling HOOK, in that case set RESTORE to 1 so the |
309 |
restore the prompt. */ |
caller can restore the prompt. */ |
310 |
char * |
char * |
311 |
grub_normal_do_completion (char *buf, int *restore) |
grub_normal_do_completion (char *buf, int *restore, |
312 |
|
void (*hook) (const char *, grub_completion_type_t, int)) |
313 |
{ |
{ |
314 |
char *first_word; |
char *first_word; |
315 |
|
|
316 |
/* Initialize variables. */ |
/* Initialize variables. */ |
|
disk_dev = 0; |
|
317 |
match = 0; |
match = 0; |
318 |
num_found = 0; |
num_found = 0; |
319 |
suffix = ""; |
suffix = ""; |
320 |
|
print_func = hook; |
321 |
|
|
322 |
*restore = 1; |
*restore = 1; |
323 |
|
|
379 |
|
|
380 |
grub_free (match); |
grub_free (match); |
381 |
|
|
382 |
|
if (*ret == '\0') |
383 |
|
{ |
384 |
|
grub_free (ret); |
385 |
|
return 0; |
386 |
|
} |
387 |
|
|
388 |
return ret; |
return ret; |
389 |
} |
} |
390 |
|
|