diff --git a/src/arch/i386/include/librm.h b/src/arch/i386/include/librm.h index 32dceed6..31b50979 100644 --- a/src/arch/i386/include/librm.h +++ b/src/arch/i386/include/librm.h @@ -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 * diff --git a/src/image/script.c b/src/image/script.c index a24bc09a..749131d6 100644 --- a/src/image/script.c +++ b/src/image/script.c @@ -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;