2 * Copyright (c)2004 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
16 * Neither the name of the DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Disk functions for installer.
37 * $Id: fn_disk.c,v 1.40 2005/03/13 01:53:58 cpressey Exp $
46 #define _(String) gettext (String)
48 #define _(String) (String)
51 #include "libaura/mem.h"
52 #include "libaura/fspred.h"
54 #include "libdfui/dfui.h"
55 #include "libdfui/system.h"
57 #include "libinstaller/commands.h"
58 #include "libinstaller/diskutil.h"
59 #include "libinstaller/functions.h"
60 #include "libinstaller/uiutil.h"
63 #include "pathnames.h"
65 /*** DISK-RELATED FUNCTIONS ***/
68 * Ask the user which physical disk they want.
69 * Changes ss->selected_disk if successful.
72 fn_select_disk(struct i_fn_args *a)
75 struct dfui_action *k;
76 struct dfui_response *r;
86 "p", "special", "dfinstaller_select_disk",
91 for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
92 dfui_form_action_add(f, disk_get_device_name(d),
93 dfui_info_new(disk_get_desc(d), "", ""));
96 k = dfui_form_action_add(f, "cancel",
97 dfui_info_new(a->cancel_desc, "", ""));
98 dfui_action_property_set(k, "accelerator", "ESC");
100 if (!dfui_be_present(a->c, f, &r))
103 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
106 d = disk_find(a->s, dfui_response_get_action_id(r));
108 inform(a->c, _("Internal error - response from frontend "
109 "should be a valid device name."));
112 storage_set_selected_disk(a->s, d);
118 dfui_response_free(r);
122 * Ask the user which slice on a the selected disk they want.
123 * Changes ss->selected_slice.
126 fn_select_slice(struct i_fn_args *a)
129 struct dfui_action *k;
130 struct dfui_response *r;
134 f = dfui_form_create(
136 _("Select Primary Partition"),
141 "p", "special", "dfinstaller_select_slice",
146 for (s = disk_slice_first(storage_get_selected_disk(a->s));
147 s != NULL; s = slice_next(s)) {
148 snprintf(string, 16, "%d", slice_get_number(s));
149 dfui_form_action_add(f, string,
150 dfui_info_new(slice_get_desc(s), "", ""));
153 k = dfui_form_action_add(f, "cancel",
154 dfui_info_new(a->cancel_desc, "", ""));
155 dfui_action_property_set(k, "accelerator", "ESC");
157 if (!dfui_be_present(a->c, f, &r))
160 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
163 s = slice_find(storage_get_selected_disk(a->s),
164 atoi(dfui_response_get_action_id(r)));
166 inform(a->c, _("Internal error - response from frontend "
167 "should be a valid slice number."));
170 storage_set_selected_slice(a->s, s);
176 dfui_response_free(r);
180 * If ss->selected_disk == NULL, user will be asked for which disk.
181 * Returns 1 if disk was formatted, 0 if it wasn't.
182 * If it was, ss->selected_disk and ss->selected_slice are set to it.
185 fn_format_disk_mbr(struct i_fn_args *a)
187 struct commands *cmds;
188 char *selected_disk_string;
190 if (storage_get_selected_disk(a->s) == NULL) {
191 a->short_desc = _("Select a disk to format.");
192 a->cancel_desc = _("Return to Utilities Menu");
194 if (!a->result || storage_get_selected_disk(a->s) == NULL) {
200 if (confirm_dangerous_action(a->c,
201 _("WARNING! ALL data in ALL partitions on the disk\n\n"
202 "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
203 "SURE you wish to take this action? This is your "
204 "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
205 cmds = commands_new();
208 "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
209 a->os_root, cmd_name(a, "DD"),
210 disk_get_device_name(storage_get_selected_disk(a->s)));
211 command_add(cmds, "%s%s -BI %s",
212 a->os_root, cmd_name(a, "FDISK"),
213 disk_get_device_name(storage_get_selected_disk(a->s)));
215 if (!commands_execute(a, cmds)) {
216 inform(a->c, _("The disk\n\n%s\n\nwas "
217 "not correctly formatted, and may "
218 "now be in an inconsistent state. "
219 "We recommend re-formatting it "
220 "before attempting to install "
222 disk_get_desc(storage_get_selected_disk(a->s)),
223 OPERATING_SYSTEM_NAME);
231 * Since one of the disks has now changed, we must
232 * refresh our view of them and re-select the disk
233 * since the selected_disk pointer will be invalidated.
235 selected_disk_string = aura_strdup(
236 disk_get_device_name(storage_get_selected_disk(a->s)));
237 if (!survey_storage(a)) {
238 inform(a->c, _("Errors occurred while probing "
239 "the system for its storage capabilities."));
241 storage_set_selected_disk(a->s, disk_find(a->s, selected_disk_string));
242 free(selected_disk_string);
245 * Note that we formatted this disk and that we want
246 * to use the first (and only) slice of it.
248 disk_set_formatted(storage_get_selected_disk(a->s), 1);
249 storage_set_selected_slice(a->s, disk_slice_first(storage_get_selected_disk(a->s)));
251 if (!format_slice(a)) {
252 inform(a->c, _("The sole primary partition of "
253 "the disk\n\n%s\n\nwas "
254 "not correctly formatted, and may "
255 "now be in an inconsistent state. "
256 "We recommend re-formatting the "
257 "disk before attempting to install "
259 disk_get_desc(storage_get_selected_disk(a->s)),
260 OPERATING_SYSTEM_NAME);
264 inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
265 disk_get_desc(storage_get_selected_disk(a->s)));
268 inform(a->c, _("Action cancelled - no disks were formatted."));
274 fn_format_disk_uefi(struct i_fn_args *a)
276 struct commands *cmds;
277 char *selected_disk_string;
279 if (storage_get_selected_disk(a->s) == NULL) {
280 a->short_desc = _("Select a disk to format.");
281 a->cancel_desc = _("Return to Utilities Menu");
283 if (!a->result || storage_get_selected_disk(a->s) == NULL) {
289 if (confirm_dangerous_action(a->c,
290 _("WARNING! ALL data in ALL partitions on the disk\n\n"
291 "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
292 "SURE you wish to take this action? This is your "
293 "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
294 cmds = commands_new();
297 "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
298 a->os_root, cmd_name(a, "DD"),
299 disk_get_device_name(storage_get_selected_disk(a->s)));
300 command_add(cmds, "%s%s destroy %s",
301 a->os_root, cmd_name(a, "GPT"),
302 disk_get_device_name(storage_get_selected_disk(a->s)));
303 command_add(cmds, "%s%s create -f %s",
304 a->os_root, cmd_name(a, "GPT"),
305 disk_get_device_name(storage_get_selected_disk(a->s)));
306 command_add(cmds, "%s%s add -i 0 -s 262144 -t efi %s",
307 a->os_root, cmd_name(a, "GPT"),
308 disk_get_device_name(storage_get_selected_disk(a->s)));
309 command_add(cmds, "%s%s add -i 1 -t dragonfly %s",
310 a->os_root, cmd_name(a, "GPT"),
311 disk_get_device_name(storage_get_selected_disk(a->s)));
312 command_add(cmds, "%s%s -F 32 -c 2 -L EFI -m 0xf8 %ss0",
313 a->os_root, cmd_name(a, "NEWFS_MSDOS"),
314 disk_get_device_name(storage_get_selected_disk(a->s)));
315 command_add(cmds, "%s%s /dev/%ss0 %smnt",
316 a->os_root, cmd_name(a, "MOUNT_MSDOS"),
317 disk_get_device_name(storage_get_selected_disk(a->s)),
319 command_add(cmds, "%s%s -p %smnt/EFI/BOOT",
320 a->os_root, cmd_name(a, "MKDIR"), a->os_root);
322 "%s%s %s/boot/boot1.efi %smnt/EFI/BOOT/BOOTX64.EFI",
323 a->os_root, cmd_name(a, "CP"),
324 a->os_root, a->os_root);
325 command_add(cmds, "%s%s %smnt",
326 a->os_root, cmd_name(a, "UMOUNT"), a->os_root);
328 if (!commands_execute(a, cmds)) {
329 inform(a->c, _("The disk\n\n%s\n\nwas "
330 "not correctly formatted, and may "
331 "now be in an inconsistent state. "
332 "We recommend re-formatting it "
333 "before attempting to install "
335 disk_get_desc(storage_get_selected_disk(a->s)),
336 OPERATING_SYSTEM_NAME);
344 * Since one of the disks has now changed, we must
345 * refresh our view of them and re-select the disk
346 * since the selected_disk pointer will be invalidated.
348 selected_disk_string = aura_strdup(
349 disk_get_device_name(storage_get_selected_disk(a->s)));
350 if (!survey_storage(a)) {
351 inform(a->c, _("Errors occurred while probing "
352 "the system for its storage capabilities."));
354 storage_set_selected_disk(a->s,
355 disk_find(a->s, selected_disk_string));
356 free(selected_disk_string);
359 * Note that we formatted this disk and that we want
360 * to use the first (and only) slice of it.
362 disk_set_formatted(storage_get_selected_disk(a->s), 1);
363 storage_set_selected_slice(a->s,
364 disk_slice_first(storage_get_selected_disk(a->s)));
366 inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
367 disk_get_desc(storage_get_selected_disk(a->s)));
370 inform(a->c, _("Action cancelled - no disks were formatted."));
376 * Wipes the start of the selected disk.
379 fn_wipe_start_of_disk(struct i_fn_args *a)
381 struct commands *cmds;
383 a->short_desc = _("If you are having problems formatting a disk, "
384 "it may be because of junk that has accumulated "
385 "in the boot block and the partition table. "
386 "A cure for this is to wipe out everything on "
387 "the first few sectors of the disk. However, this "
388 "is a rather drastic action to take, so it is not "
389 "recommended unless you are otherwise "
390 "encountering problems.");
391 a->cancel_desc = _("Return to Utilities Menu");
396 /* XXX check to make sure no slices on this disk are mounted first? */
397 if (storage_get_selected_disk(a->s) != NULL && confirm_dangerous_action(a->c,
398 _("WARNING! ALL data in ALL partitions on the disk\n\n"
399 "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
400 "SURE you wish to take this action? This is your "
401 "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
402 cmds = commands_new();
404 "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
405 a->os_root, cmd_name(a, "DD"),
406 disk_get_device_name(storage_get_selected_disk(a->s)));
407 if (commands_execute(a, cmds)) {
408 inform(a->c, _("Start of disk was successfully wiped."));
410 inform(a->c, _("Some errors occurred. "
411 "Start of disk was not successfully wiped."));
418 * Wipes the start of the selected slice.
421 fn_wipe_start_of_slice(struct i_fn_args *a)
423 struct commands *cmds;
426 _("If you are having problems formatting a primary partition, "
427 "it may be because of junk that has accumulated in the "
428 "partition's `disklabel'. A cure for this is to wipe out "
429 "everything on the first few sectors of the primary partition. "
430 "However, this is a rather drastic action to take, so it is not "
431 "recommended unless you are otherwise encountering problems.");
432 a->cancel_desc = _("Return to Utilities Menu");
437 if (confirm_dangerous_action(a->c,
438 _("WARNING! ALL data in primary partition #%d,\n\n%s\n\non the "
439 "disk\n\n%s\n\n will be IRREVOCABLY ERASED!\n\nAre you "
440 "ABSOLUTELY SURE you wish to take this action? This is "
441 "your LAST CHANCE to cancel!"),
442 slice_get_number(storage_get_selected_slice(a->s)),
443 slice_get_desc(storage_get_selected_slice(a->s)),
444 disk_get_desc(storage_get_selected_disk(a->s)))) {
445 /* XXX check to make sure this slice is not mounted first */
446 cmds = commands_new();
447 command_add(cmds, "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
448 a->os_root, cmd_name(a, "DD"),
449 slice_get_device_name(storage_get_selected_slice(a->s)));
450 if (commands_execute(a, cmds)) {
451 inform(a->c, _("Start of primary partition was successfully wiped."));
453 inform(a->c, _("Some errors occurred. "
454 "Start of primary partition was not successfully wiped."));
461 ask_to_wipe_boot_sector(struct i_fn_args *a, struct commands *fcmds)
463 struct commands *cmds;
467 for (cmd = command_get_first(fcmds); cmd != NULL;
468 cmd = command_get_next(cmd)) {
469 disk = command_get_tag(cmd);
471 command_get_result(cmd) > 0 &&
472 command_get_result(cmd) < 256) {
473 switch (dfui_be_present_dialog(a->c,
474 _("Bootblock Install Failed"),
475 _("Re-Initialize Bootblock|Cancel"),
476 _("Warning: bootblocks were not successfully "
477 "installed on the disk `%s'. This may be "
478 "because the disk is new and not yet "
479 "formatted. If this is the case, it might "
480 "help to re-initialize the boot sector, "
481 "then try installing the bootblock again. "
482 "Note that this should not affect the "
483 "partition table of the disk."),
486 cmds = commands_new();
488 "%s%s | %s%s -B /dev/%s",
489 a->os_root, cmd_name(a, "YES"),
490 a->os_root, cmd_name(a, "FDISK"),
492 if (commands_execute(a, cmds)) {
493 inform(a->c, _("Boot sector successfully initialized."));
495 inform(a->c, _("Some errors occurred. "
496 "Boot sector was not successfully initialized."));
508 fn_install_bootblocks(struct i_fn_args *a, const char *device)
511 struct dfui_response *r;
512 struct dfui_dataset *ds;
514 struct commands *cmds;
516 char disk[64], boot0cfg[32], packet[32];
517 char msg_buf[1][1024];
519 snprintf(msg_buf[0], sizeof(msg_buf[0]),
520 "'Packet Mode' refers to using newer BIOS calls to boot "
521 "from a partition of the disk. It is generally not "
522 "required unless:\n\n"
523 "- your BIOS does not support legacy mode; or\n"
524 "- your %s primary partition resides on a "
525 "cylinder of the disk beyond cylinder 1024; or\n"
526 "- you just can't get it to boot without it.",
527 OPERATING_SYSTEM_NAME);
529 f = dfui_form_create(
531 _("Install Bootblock(s)"),
536 "p", "special", "dfinstaller_install_bootstrap",
538 "f", "disk", _("Disk Drive"),
539 _("The disk on which you wish to install a bootblock"), "",
540 "p", "editable", "false",
541 "f", "boot0cfg", _("Install Bootblock?"),
542 _("Install a bootblock on this disk"), "",
543 "p", "control", "checkbox",
544 "f", "packet", _("Packet Mode?"),
545 _("Select this to use 'packet mode' to boot the disk"), "",
546 "p", "control", "checkbox",
548 "a", "ok", _("Accept and Install Bootblocks"), "", "",
549 "a", "cancel", a->cancel_desc, "", "",
550 "p", "accelerator", "ESC",
555 dfui_form_set_multiple(f, 1);
557 if (device != NULL) {
558 ds = dfui_dataset_new();
559 dfui_dataset_celldata_add(ds, "disk", device);
560 dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
561 dfui_dataset_celldata_add(ds, "packet", "Y");
562 dfui_form_dataset_add(f, ds);
564 for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
565 ds = dfui_dataset_new();
566 dfui_dataset_celldata_add(ds, "disk",
567 disk_get_device_name(d));
568 dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
569 dfui_dataset_celldata_add(ds, "packet", "Y");
570 dfui_form_dataset_add(f, ds);
574 if (!dfui_be_present(a->c, f, &r))
578 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
579 cmds = commands_new();
581 for (ds = dfui_response_dataset_get_first(r); ds != NULL;
582 ds = dfui_dataset_get_next(ds)) {
583 strlcpy(disk, dfui_dataset_get_value(ds, "disk"), 64);
584 strlcpy(boot0cfg, dfui_dataset_get_value(ds, "boot0cfg"), 32);
585 strlcpy(packet, dfui_dataset_get_value(ds, "packet"), 32);
587 if (strcasecmp(boot0cfg, "Y") == 0) {
588 cmd = command_add(cmds, "%s%s -B -o %spacket %s",
589 a->os_root, cmd_name(a, "BOOT0CFG"),
590 strcasecmp(packet, "Y") == 0 ? "" : "no",
592 command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
593 command_set_tag(cmd, "%s", disk);
594 cmd = command_add(cmds, "%s%s -v %s",
595 a->os_root, cmd_name(a, "BOOT0CFG"),
597 command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
598 command_set_tag(cmd, "%s", disk);
602 if (!commands_execute(a, cmds)) {
603 ask_to_wipe_boot_sector(a, cmds);
605 inform(a->c, _("Bootblocks were successfully installed!"));
612 dfui_response_free(r);
616 fn_format_msdos_floppy(struct i_fn_args *a)
618 struct commands *cmds;
620 switch (dfui_be_present_dialog(a->c, _("Format MSDOS Floppy"),
621 _("Format Floppy|Return to Utilities Menu"),
622 _("Please insert the floppy to be formatted "
623 "in unit 0 (``drive A:'')."))) {
625 cmds = commands_new();
626 command_add(cmds, "%s%s -y -f 1440 /dev/fd0",
627 a->os_root, cmd_name(a, "FDFORMAT"));
628 command_add(cmds, "%s%s -f 1440 fd0",
629 a->os_root, cmd_name(a, "NEWFS_MSDOS"));
630 if (commands_execute(a, cmds))
631 inform(a->c, _("Floppy successfully formatted!"));
633 inform(a->c, _("Floppy was not successfully formatted."));
643 fn_create_cdboot_floppy(struct i_fn_args *a)
645 struct commands *cmds;
646 char msg_buf[1][1024];
648 snprintf(msg_buf[0], sizeof(msg_buf[0]),
649 "%s cannot be installed from a floppy; "
650 "it must be installed from a booted CD-ROM. "
651 "However, many older systems do not support booting "
652 "from a CD-ROM. For these systems, a boot disk can be "
653 "created. This boot disk contains the Smart Boot "
654 "Manager program, which can boot a CD-ROM even "
655 "on systems with BIOSes which do not support booting "
656 "from the CD-ROM.\n\n"
657 "Smart Boot Manager is not a part of %s; "
658 "the Smart Boot Manager project can be found here:\n\n"
659 "http://btmgr.sourceforge.net/\n\n"
660 "To create a CDBoot floppy, insert a blank floppy "
661 "in unit 0 (``drive A:'') before proceeding."
663 OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
665 switch (dfui_be_present_dialog(a->c, _("Create CDBoot Floppy"),
666 _("Create CDBoot Floppy|Return to Utilities Menu"),
669 cmds = commands_new();
670 command_add(cmds, "%s%s -c %sboot/cdboot.flp.bz2 | "
671 "%s%s of=/dev/fd0 bs=32k",
672 a->os_root, cmd_name(a, "BUNZIP2"),
674 a->os_root, cmd_name(a, "DD"));
675 if (commands_execute(a, cmds))
676 inform(a->c, _("CDBoot floppy successfully created!"));
678 inform(a->c, _("CDBoot floppy was not successfully created."));
687 /**** NON-fn_ FUNCTIONS ***/
690 format_slice(struct i_fn_args *a)
692 struct commands *cmds;
697 cmds = commands_new();
700 * The information in a->s NEEDS to be accurate here!
701 * Presumably we just did a survey_storage() recently.
702 * XXX should we do another one here anyway just to be paranoid?
706 * Make sure the survey did get disk info correctly or fail
708 if ((storage_get_selected_disk(a->s) == NULL) ||
709 (storage_get_selected_slice(a->s) == NULL))
713 * Set the slice's sysid to 108.
715 disk_get_geometry(storage_get_selected_disk(a->s), &cyl, &hd, &sec);
716 command_add(cmds, "%s%s 'g c%d h%d s%d' >%snew.fdisk",
717 a->os_root, cmd_name(a, "ECHO"),
720 command_add(cmds, "%s%s 'p %d %d %lu %lu' >>%snew.fdisk",
721 a->os_root, cmd_name(a, "ECHO"),
722 slice_get_number(storage_get_selected_slice(a->s)),
724 slice_get_start(storage_get_selected_slice(a->s)),
725 slice_get_size(storage_get_selected_slice(a->s)),
727 if (slice_get_flags(storage_get_selected_slice(a->s)) & 0x80) {
728 command_add(cmds, "%s%s 'a %d' >>%snew.fdisk",
729 a->os_root, cmd_name(a, "ECHO"),
730 slice_get_number(storage_get_selected_slice(a->s)),
734 command_add(cmds, "%s%s %snew.fdisk",
735 a->os_root, cmd_name(a, "CAT"), a->tmp);
736 temp_file_add(a, "new.fdisk");
739 * Execute the fdisk script.
741 cmd = command_add(cmds, "%s%s -v -f %snew.fdisk %s",
742 a->os_root, cmd_name(a, "FDISK"), a->tmp,
743 disk_get_device_name(storage_get_selected_disk(a->s)));
744 if (slice_get_size(storage_get_selected_slice(a->s)) == 0xFFFFFFFFU)
745 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
748 * If there is an old 'virgin' disklabel hanging around
749 * in the temp dir, get rid of it. This won't happen
750 * from a real CD, but might happen with '-o' installs.
752 command_add(cmds, "%s%s -f %sinstall.disklabel.%s",
753 a->os_root, cmd_name(a, "RM"),
755 slice_get_device_name(storage_get_selected_slice(a->s)));
757 result = commands_execute(a, cmds);