Added execv() and system().
authorMichael Brown <mcb30@etherboot.org>
Fri, 8 Dec 2006 01:23:11 +0000 (01:23 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 8 Dec 2006 01:23:11 +0000 (01:23 +0000)
src/core/exec.c [new file with mode: 0644]
src/include/gpxe/command.h [new file with mode: 0644]
src/include/stdlib.h
src/include/unistd.h [new file with mode: 0644]

diff --git a/src/core/exec.c b/src/core/exec.c
new file mode 100644 (file)
index 0000000..a0f0b52
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <assert.h>
+#include <vsprintf.h>
+#include <gpxe/tables.h>
+#include <gpxe/command.h>
+
+/** @file
+ *
+ * Command execution
+ *
+ */
+
+static struct command commands[0] __table_start ( commands );
+static struct command commands_end[0] __table_end ( commands );
+
+/**
+ * Execute command
+ *
+ * @v command          Command name
+ * @v argv             Argument list
+ * @ret rc             Command exit status
+ *
+ * Execute the named command.  Unlike a traditional POSIX execv(),
+ * this function returns the exit status of the command.
+ */
+int execv ( const char *command, char * const argv[] ) {
+       struct command *cmd;
+       int argc = 0;
+
+       assert ( argv[0] != NULL );
+
+       /* Count number of arguments */
+       do {
+               argc++;
+       } while ( argv[argc] != NULL );
+
+       /* Reset getopt() library ready for use by the command.  This
+        * is an artefact of the POSIX getopt() API within the context
+        * of Etherboot; see the documentation for reset_getopt() for
+        * details.
+        */
+       reset_getopt();
+
+       /* Hand off to command implementation */
+       for ( cmd = commands ; cmd < commands_end ; cmd++ ) {
+               if ( strcmp ( command, cmd->name ) == 0 )
+                       return cmd->exec ( argc, ( char ** ) argv );
+       }
+
+       printf ( "%s: command not found\n", command );
+       return -ENOEXEC;
+}
+
+/**
+ * Split command line into argv array
+ *
+ * @v args             Command line
+ * @v argv             Argument array to populate, or NULL
+ * @ret argc           Argument count
+ *
+ * Splits the command line into whitespace-delimited arguments.  If @c
+ * argv is non-NULL, any whitespace in the command line will be
+ * replaced with NULs.
+ */
+static int split_args ( char *args, char * argv[] ) {
+       int argc = 0;
+
+       while ( 1 ) {
+               /* Skip over any whitespace / convert to NUL */
+               while ( *args == ' ' ) {
+                       if ( argv )
+                               *args = '\0';
+                       args++;
+               }
+               /* Check for end of line */
+               if ( ! *args )
+                       break;
+               /* We have found the start of the next argument */
+               if ( argv )
+                       argv[argc] = args;
+               argc++;
+               /* Skip to start of next whitespace, if any */
+               while ( *args && ( *args != ' ' ) ) {
+                       args++;
+               }
+       }
+       return argc;
+}
+
+/**
+ * Execute command line
+ *
+ * @v command          Command line
+ * @ret rc             Command exit status
+ *
+ * Execute the named command and arguments.
+ */
+int system ( const char *command ) {
+       char *args = strdup ( command );
+       int argc;
+       
+       if ( ! args )
+               return -ENOMEM;
+
+       /* Count arguments */
+       argc = split_args ( args, NULL );
+
+       /* Create argv array and execute command */
+       {
+               char * argv[argc + 1];
+               
+               split_args ( args, argv );
+               argv[argc] = NULL;
+               return execv ( argv[0], argv );
+       }
+}
diff --git a/src/include/gpxe/command.h b/src/include/gpxe/command.h
new file mode 100644 (file)
index 0000000..95f6c5e
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _GPXE_COMMAND_H
+#define _GPXE_COMMAND_H
+
+#include <gpxe/tables.h>
+
+/** A command-line command */
+struct command {
+       /** Name of the command */
+       const char *name;
+       /**
+        * Function implementing the command
+        *
+        * @v argc              Argument count
+        * @v argv              Argument list
+        * @ret rc              Return status code
+        */
+       int ( * exec ) ( int argc, char **argv );
+};
+
+#define __command __table ( commands, 01 )
+
+#endif /* _GPXE_COMMAND_H */
index a7dd1d8..d71ee1a 100644 (file)
@@ -5,6 +5,7 @@ extern unsigned long strtoul ( const char *p, char **endp, int base );
 extern void * realloc ( void *old_ptr, size_t new_size );
 extern void * malloc ( size_t size );
 extern void free ( void *ptr );
+extern int system ( const char *command );
 
 /**
  * Allocate cleared memory
diff --git a/src/include/unistd.h b/src/include/unistd.h
new file mode 100644 (file)
index 0000000..9dd51dc
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+#include <stddef.h>
+#include <stdarg.h>
+
+extern int execv ( const char *command, char * const argv[] );
+
+/**
+ * Execute command
+ *
+ * @v command          Command name
+ * @v arg ...          Argument list (starting with argv[0])
+ * @ret rc             Command exit status
+ *
+ * This is a front end to execv().
+ */
+#define execl( command, arg, ... ) ( {                                 \
+               char * const argv[] = { (arg), ## __VA_ARGS__, NULL };  \
+               int rc = execv ( (command), argv );                     \
+               rc;                                                     \
+       } )
+
+#endif /* _UNISTD_H */