[script] Remove arbitrary limit on script line lengths
authorMichael Brown <mcb30@etherboot.org>
Tue, 17 Jun 2008 23:43:58 +0000 (00:43 +0100)
committerMichael Brown <mcb30@etherboot.org>
Tue, 17 Jun 2008 23:43:58 +0000 (00:43 +0100)
src/arch/i386/include/librm.h
src/image/script.c

index 32dceed..31b5097 100644 (file)
@@ -210,6 +210,23 @@ strlen_user ( userptr_t buffer, off_t offset ) {
        return strlen ( ( void * ) buffer + offset );
 }
 
+/**
+ * Find character in user buffer
+ *
+ * @v buffer           User buffer
+ * @v offset           Starting offset within buffer
+ * @v c                        Character to search for
+ * @v len              Length of user buffer
+ * @ret offset         Offset of character, or <0 if not found
+ */
+static inline __attribute__ (( always_inline )) off_t
+memchr_user ( userptr_t buffer, off_t offset, int c, size_t len ) {
+       void *found;
+
+       found = memchr ( ( ( void * ) buffer + offset ), c, len );
+       return ( found ? ( found - ( void * ) buffer ) : -1 );
+}
+
 /**
  * Convert virtual address to user buffer
  *
index a24bc09..749131d 100644 (file)
@@ -37,11 +37,9 @@ struct image_type script_image_type __image_type ( PROBE_NORMAL );
  * @ret rc             Return status code
  */
 static int script_exec ( struct image *image ) {
-       char cmdbuf[256];
        size_t offset = 0;
-       size_t remaining;
+       off_t eol;
        size_t len;
-       char *eol;
        int rc;
 
        /* Temporarily de-register image, so that a "boot" command
@@ -53,36 +51,29 @@ static int script_exec ( struct image *image ) {
 
        while ( offset < image->len ) {
        
-               /* Read up to cmdbuf bytes from script into buffer */
-               remaining = ( image->len - offset );
-               len = sizeof ( cmdbuf );
-               if ( len > remaining )
-                       len = remaining;
-               memset ( cmdbuf, 0, sizeof ( cmdbuf ) );
-               copy_from_user ( cmdbuf, image->data, offset, len );
+               /* Find length of next line, excluding any terminating '\n' */
+               eol = memchr_user ( image->data, offset, '\n',
+                                   ( image->len - offset ) );
+               if ( eol < 0 )
+                       eol = image->len;
+               len = ( eol - offset );
 
-               /* Find end of line */
-               eol = memchr ( cmdbuf, '\n', sizeof ( cmdbuf ) );
-               if ( ! eol )
-                       eol = memchr ( cmdbuf, '\0', sizeof ( cmdbuf ) );
-               if ( ! eol ) {
-                       DBG ( "Script line too long (max %zd bytes)\n",
-                             sizeof ( cmdbuf ) );
-                       rc = -ENOEXEC;
-                       goto done;
-               }
+               /* Copy line, terminate with NUL, and execute command */
+               {
+                       char cmdbuf[ len + 1 ];
 
-               /* Mark end of line and execute command */
-               *eol = '\0';
-               DBG ( "$ %s\n", cmdbuf );
-               if ( ( rc = system ( cmdbuf ) ) != 0 ) {
-                       DBG ( "Command \"%s\" failed: %s\n",
-                             cmdbuf, strerror ( rc ) );
-                       goto done;
+                       copy_from_user ( cmdbuf, image->data, offset, len );
+                       cmdbuf[len] = '\0';
+                       DBG ( "$ %s\n", cmdbuf );
+                       if ( ( rc = system ( cmdbuf ) ) != 0 ) {
+                               DBG ( "Command \"%s\" failed: %s\n",
+                                     cmdbuf, strerror ( rc ) );
+                               goto done;
+                       }
                }
                
                /* Move to next line */
-               offset += ( ( eol - cmdbuf ) + 1 );
+               offset += ( len + 1 );
        }
 
        rc = 0;