qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] ui/cocoa.m: Add configuration file support
@ 2015-09-06 20:39 Programmingkid
  2015-09-06 20:41 ` Peter Maydell
  0 siblings, 1 reply; 2+ messages in thread
From: Programmingkid @ 2015-09-06 20:39 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel qemu-devel

[-- Attachment #1: Type: text/plain, Size: 9068 bytes --]

Having to type out all the arguments to QEMU isn't fun. That is why we need an
easier way to setup QEMU. With a configuration file system, we just make this
file once, and allow QEMU to do the work for us. This configuration file system
is similar to how a shell like Bash works. 

A configuration file is just a text file with QEMU's arguments in it.
Configuration files can have comments in them making them easy to document. The
comment character is '#'. Everything including this character is ignored up to
the next newline character. 

With this patch, QEMU could be placed in the dock and launched with a single click.
This is way faster, easier, and more user-friendly than the current system. 
Using a terminal to launch QEMU still works just the way it always has for those
who wish to continue using it.

When QEMU is launched and no arguments are given to it, it will look for a
default configuration file in the same folder that QEMU is kept. If this file is
found, it is then loaded. If it isn't found, a file open dialog box is displayed
asking the user to select a configuration file to load. Being able to select a
configuration file gives the user options for how he may want QEMU to run. There
could be a configuration file for a Linux guest. Another one for a Mac OS X
guest. Another for a debug configuration for a Mac OS 9 guest. The possibilites
are endless.

Signed-off-by: John Arbuckle <programmingkidx@gmail.com>

---
This code in this patch is pretty portable. I would not be surprised if someone
implemented this patch in Linux. 

 ui/cocoa.m |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 136 insertions(+), 24 deletions(-)

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 334e6f6..3fcfd57 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -69,6 +69,8 @@ char **gArgv;
 bool stretch_video;
 NSTextField *pauseLabel;
 NSArray * supportedImageFileTypes;
+bool configFileLoaded = false;
+char *programPath; /* Used by loadConfigFile() */
 
 // keymap conversion
 int keymap[] =
@@ -264,6 +266,124 @@ static void handleAnyDeviceErrors(Error * err)
 }
 
 /*
+ * Loads QEMU's config file.
+ * Output is set using gArgv and gArgc variables.
+ */
+static void loadConfigFile(char *filePath)
+{
+    const int maxWordSize = 1024;
+    const int maxNumberOfWords = 1000;
+    char argvReplacement[maxNumberOfWords][maxWordSize];
+    const char commentCharacter = '#';
+    char c;
+    int index, word;
+    FILE *configFile;
+    bool lookingForOtherDoubleQuote;
+    bool lookingForOtherSingleQuote;
+
+    COCOA_DEBUG("loadConfigFile(): opening file %s\n", filePath);
+    configFile = fopen(filePath, "r");
+    if (!configFile) {
+        printf("Error: Failed to open file %s!\n", filePath);
+        printf("Reason: %s\n", strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    lookingForOtherDoubleQuote = false;
+    lookingForOtherSingleQuote = false;
+    index = 0;
+    word = 0;
+
+    /* Read every character in the config file */
+    while ((c = fgetc(configFile)) != EOF) {
+
+        if (c == commentCharacter) {
+            while(fgetc(configFile) != '\n') { /* Skip to end of line */ }
+            continue; /* Skip comment lines */
+        }
+
+        if (c == '"') {
+            lookingForOtherDoubleQuote = !lookingForOtherDoubleQuote;
+            continue;
+        }
+
+        if(c == '\'') {
+            lookingForOtherSingleQuote = !lookingForOtherSingleQuote;
+            continue;
+        }
+
+        if((c == '\n' || c == ' ') && !lookingForOtherDoubleQuote &&
+                                                !lookingForOtherSingleQuote) {
+            argvReplacement[word][index] = '\0';
+            index = 0;
+            if(strlen(argvReplacement[word]) > 0) {  /* If not empty line */
+                word++;
+            }
+            if (word >= maxNumberOfWords) {
+                printf("Error: word limit in config file reached!\n");
+                exit(EXIT_FAILURE);
+            }
+            continue;
+        }
+
+        argvReplacement[word][index] = c;
+        index++;
+        if(index >= maxWordSize) {
+            printf("Error: max word size reached in config file!\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    /* Initialize global variables */
+    gArgc = word+1; /* Add one for the application's path */
+    gArgv = (char **) g_malloc(sizeof(char*) * gArgc);
+
+    /* Add program's name to global variable */
+    gArgv[0] = programPath;
+
+    /* Copy data from temporary buffer to global variable */
+    for(index = 1; index < gArgc; index++) {
+        gArgv[index] = g_strdup_printf("%s", argvReplacement[index-1]);
+    }
+    configFileLoaded = true;
+    fclose(configFile);
+
+#ifdef DEBUG
+    printf("Printing out every argument being used:\n");
+    for (index = 0; index < gArgc; index++) {
+        printf("argv[%d] = %s\n", index, gArgv[index]);
+    }
+#endif
+}
+
+/* Finds and loads the default configuration file */
+static void loadDefaultConfigFile(char *programPath)
+{
+    int index;
+
+    /* Obtain the program's file path only */
+    index = strlen(programPath) - 1;
+    while(programPath[index] != '/' && index > 0) {
+        index--;
+    }
+    char *pathOnlyString; /* file path minus file name */
+    pathOnlyString = g_strndup(programPath, index+1); /* +1 for the '/' */
+
+    char *defaultConfigFilePath;
+    const char *fileName = "QEMU_config.txt";
+    defaultConfigFilePath = g_strdup_printf("%s%s", pathOnlyString, fileName);
+    FILE *configFile;
+    configFile = fopen(defaultConfigFilePath, "r");
+    if (configFile) { /* See if the file is there */
+        fclose(configFile);
+        loadConfigFile(defaultConfigFilePath);
+        printf("Using default configuration file\n");
+    }
+    g_free(defaultConfigFilePath);
+    g_free(pathOnlyString);
+}
+
+/*
  ------------------------------------------------------
     QemuCocoaView
  ------------------------------------------------------
@@ -898,12 +1018,12 @@ QemuCocoaView *cocoaView;
 
     // Display an open dialog box if no arguments were passed or
     // if qemu was launched from the finder ( the Finder passes "-psn" )
-    if( gArgc <= 1 || strncmp ((char *)gArgv[1], "-psn", 4) == 0) {
+    // and no default configuration file was loaded.
+    if (configFileLoaded == false && gArgc <= 1) {
         NSOpenPanel *op = [[NSOpenPanel alloc] init];
-        [op setPrompt:@"Boot image"];
-        [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
+        [op setPrompt:@"Load Config File"];
+        [op setMessage:@"Select the configuration file you want to load"];
 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
-        [op setAllowedFileTypes:supportedImageFileTypes];
         [op beginSheetModalForWindow:normalWindow
             completionHandler:^(NSInteger returnCode)
             { [self openPanelDidEnd:op
@@ -955,20 +1075,10 @@ QemuCocoaView *cocoaView;
     if (returnCode == NSFileHandlingPanelCancelButton) {
         exit(0);
     } else if (returnCode == NSFileHandlingPanelOKButton) {
-        char *img = (char*)[ [ [ sheet URL ] path ] cStringUsingEncoding:NSASCIIStringEncoding];
-
-        char **argv = g_new(char *, 4);
-
+        char *file = (char*)[ [ [ sheet URL ] path ] cStringUsingEncoding:NSASCIIStringEncoding];
         [sheet close];
-
-        argv[0] = g_strdup(gArgv[0]);
-        argv[1] = g_strdup("-hda");
-        argv[2] = g_strdup(img);
-        argv[3] = NULL;
-
-        // printf("Using argc %d argv %s -hda %s\n", 3, gArgv[0], img);
-
-        [self startEmulationWithArgc:3 argv:(char**)argv];
+        loadConfigFile(file);
+        [self startEmulationWithArgc:gArgc argv:gArgv];
     }
 }
 
@@ -1127,16 +1237,20 @@ QemuCocoaView *cocoaView;
 
 @end
 
-
 int main (int argc, const char * argv[]) {
-
+    NSAutoreleasePool * pool = [NSAutoreleasePool new];
+    programPath = g_strdup_printf("%s", argv[0]);
     gArgc = argc;
     gArgv = (char **)argv;
-    int i;
 
+    if(argc == 1) {  /* If only the program's name was given */
+        loadDefaultConfigFile(programPath);
+    }
+
+    int i;
     /* In case we don't need to display a window, let's not do that */
-    for (i = 1; i < argc; i++) {
-        const char *opt = argv[i];
+    for (i = 1; i < gArgc; i++) {
+        const char *opt = gArgv[i];
 
         if (opt[0] == '-') {
             /* Treat --foo the same as -foo.  */
@@ -1154,8 +1268,6 @@ int main (int argc, const char * argv[]) {
         }
     }
 
-    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
-
     // Pull this console process up to being a fully-fledged graphical
     // app with a menubar and Dock icon
     ProcessSerialNumber psn = { 0, kCurrentProcess };
-- 
1.7.5.4


[-- Attachment #2: Type: text/html, Size: 46551 bytes --]

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [PATCH] ui/cocoa.m: Add configuration file support
  2015-09-06 20:39 [Qemu-devel] [PATCH] ui/cocoa.m: Add configuration file support Programmingkid
@ 2015-09-06 20:41 ` Peter Maydell
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Maydell @ 2015-09-06 20:41 UTC (permalink / raw)
  To: Programmingkid; +Cc: qemu-devel qemu-devel

On 6 September 2015 at 21:39, Programmingkid <programmingkidx@gmail.com> wrote:
> Having to type out all the arguments to QEMU isn't fun. That is why we need
> an
> easier way to setup QEMU. With a configuration file system, we just make
> this
> file once, and allow QEMU to do the work for us. This configuration file
> system
> is similar to how a shell like Bash works.

This should definitely not be in the Cocoa UI frontend code.
And we already have '-readconfig', so we should improve any
deficiencies it has, not just add a completely separate config
file system.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-09-06 20:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-06 20:39 [Qemu-devel] [PATCH] ui/cocoa.m: Add configuration file support Programmingkid
2015-09-06 20:41 ` Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).