<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  
  <title></title>
</head>
<body text="#000000" bgcolor="#ffffff">
<tt>Michael Brown wrote:</tt>
<blockquote type="cite" cite="mid:201003051630.24203.mbrown@fensystems.co.uk">
  
  
  <title>Re: [gPXE-devel] Minor Scripting Improvements</title>
<!-- Converted from text/plain format -->
  <p><tt><font size="2">Looking at the patch itself...<br>
  <br>
Could this be rearranged to avoid goto?  We generally use goto only for<br>
structured error clean-up.<br>
  </font></tt></p>
</blockquote>
<tt><br>
Ok.<br>
<br>
</tt>
<blockquote type="cite" cite="mid:201003051630.24203.mbrown@fensystems.co.uk">
  <p><tt><font size="2">Also, using -ENOTSUP as a magic value meaning
"loop" seems kind of icky. <br>
There's a similarity between "exit" and "loopif" here; both commands
need to<br>
set temporary state that affects the "move to next line of script"
logic. <br>
Maybe have "loopif" set a flag as well; still fairly icky but at least
it's<br>
icky in the same way that "exit" currently is.</font></tt></p>
</blockquote>
<tt><br>
How about abuse of the same state variable?  Something like this
80-byte cost attachment...  I'm not too sure why it costs so much.<br>
<br>
If the user types in 'loopif' manually at the CLI, they'd get an
unexpected 'exit', however.  'loopif' is really only useful for scripts.<br>
<br>
Thanks again.<br>
<br>
- Shao Miller<br>
-----<br>
<br>
diff --git a/src/hci/shell.c b/src/hci/shell.c<br>
index 5bedbdc..825dac3 100644<br>
--- a/src/hci/shell.c<br>
+++ b/src/hci/shell.c<br>
@@ -35,13 +35,13 @@ FILE_LICENCE ( GPL2_OR_LATER );<br>
 static const char shell_prompt[] = "gPXE&gt; ";<br>
 <br>
 /** Flag set in order to exit shell */<br>
-static int exit_flag = 0;<br>
+int shell_exit_flag = 0;<br>
 <br>
 /** "exit" command body */<br>
 static int exit_exec ( int argc, char **argv __unused ) {<br>
 <br>
     if ( argc == 1 ) {<br>
-        exit_flag = 1;<br>
+        shell_exit_flag = 1;<br>
     } else {<br>
         printf ( "Usage: exit\n"<br>
              "Exits the command shell\n" );<br>
@@ -91,8 +91,8 @@ struct command help_command __command = {<br>
 void shell ( void ) {<br>
     char *line;<br>
 <br>
-    exit_flag = 0;<br>
-    while ( ! exit_flag ) {<br>
+    shell_exit_flag = 0;<br>
+    while ( ! shell_exit_flag ) {<br>
         line = readline ( shell_prompt );<br>
         if ( line ) {<br>
             system ( line );<br>
diff --git a/src/image/script.c b/src/image/script.c<br>
index 0835ecb..bc29116 100644<br>
--- a/src/image/script.c<br>
+++ b/src/image/script.c<br>
@@ -29,7 +29,9 @@ FILE_LICENCE ( GPL2_OR_LATER );<br>
 #include &lt;stdlib.h&gt;<br>
 #include &lt;ctype.h&gt;<br>
 #include &lt;errno.h&gt;<br>
+#include &lt;gpxe/command.h&gt;<br>
 #include &lt;gpxe/image.h&gt;<br>
+#include &lt;gpxe/shell.h&gt;<br>
 <br>
 struct image_type script_image_type __image_type ( PROBE_NORMAL );<br>
 <br>
@@ -51,7 +53,9 @@ static int script_exec ( struct image *image ) {<br>
     unregister_image ( image );<br>
 <br>
     while ( offset &lt; image-&gt;len ) {<br>
-    <br>
+        /* Reset the loop/exit flag */<br>
+        shell_exit_flag = 0;<br>
+<br>
         /* Find length of next line, excluding any terminating '\n' */<br>
         eol = memchr_user ( image-&gt;data, offset, '\n',<br>
                     ( image-&gt;len - offset ) );<br>
@@ -72,9 +76,19 @@ static int script_exec ( struct image *image ) {<br>
                 goto done;<br>
             }<br>
         }<br>
-        <br>
-        /* Move to next line */<br>
-        offset += ( len + 1 );<br>
+<br>
+        switch ( shell_exit_flag ) {<br>
+            case 1:<br>
+                /* "exit" command should exit this script */<br>
+                goto done;<br>
+            case 2:<br>
+                /* "loopif" command told us to loop */<br>
+                offset = 0;<br>
+                break;<br>
+            default:<br>
+                /* Move to next line */<br>
+                offset += ( len + 1 );<br>
+        }<br>
     }<br>
 <br>
     rc = 0;<br>
@@ -124,3 +138,16 @@ struct image_type script_image_type __image_type (
PROBE_NORMAL ) = {<br>
     .load = script_load,<br>
     .exec = script_exec,<br>
 };<br>
+<br>
+/** "loopif" command body */<br>
+static int loopif_exec ( int argc, char **argv ) {<br>
+    if ( argc &gt; 1 &amp;&amp; strtoul ( argv[1], NULL, 0 ) )<br>
+        shell_exit_flag = 2;<br>
+    return 0;<br>
+}<br>
+<br>
+/** "loopif" command definition */<br>
+struct command loopif_command __command = {<br>
+    .name = "loopif",<br>
+    .exec = loopif_exec,<br>
+};<br>
diff --git a/src/include/gpxe/shell.h b/src/include/gpxe/shell.h<br>
index a65a344..148ea83 100644<br>
--- a/src/include/gpxe/shell.h<br>
+++ b/src/include/gpxe/shell.h<br>
@@ -9,6 +9,7 @@<br>
 <br>
 FILE_LICENCE ( GPL2_OR_LATER );<br>
 <br>
+extern int shell_exit_flag;<br>
 extern void shell ( void );<br>
 <br>
 #endif /* _GPXE_SHELL_H */<br>
<br>
</tt>
</body>
</html>