changeset 496:6fc71114d145

Extract function to determine executable directory from load_config so it can be used elsewhere
author Mike Pavone <pavone@retrodev.com>
date Mon, 28 Oct 2013 21:48:46 -0700
parents 39cad98d2789
children 0820a71b80f3
files blastem.c config.c config.h util.c util.h
diffstat 5 files changed, 96 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Mon Oct 28 19:37:30 2013 -0700
+++ b/blastem.c	Mon Oct 28 21:48:46 2013 -0700
@@ -11,6 +11,7 @@
 #include "render.h"
 #include "blastem.h"
 #include "gst.h"
+#include "util.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -1762,7 +1763,8 @@
 		fputs("Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n", stderr);
 		return 1;
 	}
-	config = load_config(argv[0]);
+	set_exe_str(argv[0]);
+	config = load_config();
 	detect_region();
 	int width = -1;
 	int height = -1;
--- a/config.c	Mon Oct 28 19:37:30 2013 -0700
+++ b/config.c	Mon Oct 28 21:48:46 2013 -0700
@@ -9,10 +9,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
 #define MAX_NEST 30 //way more than I'll ever need
 
 tern_node * parse_config(char * config_data)
@@ -102,32 +98,9 @@
 	return ret;
 }
 
-char * readlink_alloc(char * path)
+tern_node * load_config()
 {
-	char * linktext = NULL;
-	ssize_t linksize = 512;
-	ssize_t cursize = 0;
-	do {
-		if (linksize > cursize) {
-			cursize = linksize;
-			if (linktext) {
-				free(linktext);
-			}
-		}
-		linktext = malloc(cursize);
-		linksize = readlink(path, linktext, cursize-1);
-		if (linksize == -1) {
-			perror("readlink");
-			free(linktext);
-			linktext = NULL;
-		}
-	} while (linksize > cursize);
-	return linktext;
-}
-
-tern_node * load_config(char * expath)
-{
-	char * linktext;
+	char * exe_dir;
 	char * home = getenv("HOME");
 	if (!home) {
 		goto load_in_app_dir;
@@ -139,33 +112,18 @@
 	}
 	free(path);
 load_in_app_dir:
-
-	linktext = readlink_alloc("/proc/self/exe");
-	if (!linktext) {
-		goto link_prob;
-	}
-	char * cur;
-	int linksize = strlen(linktext);
-	for(cur = linktext + linksize - 1; cur != linktext; cur--)
-	{
-		if (*cur == '/') {
-			*cur = 0;
-			break;
-		}
+	exe_dir = get_exe_dir();
+	if (!exe_dir) {
+		goto no_config;
 	}
-	if (cur == linktext) {
-		goto link_prob;
-	}
-	path = alloc_concat(linktext, "/default.cfg");
+	path = alloc_concat(exe_dir, "/default.cfg");
 	ret = parse_config_file(path);
+	free(path);
 success:
-	return ret;
-link_prob:
-	if (linktext) {
-		free(linktext);
+	if (ret) {
+		return ret;
 	}
-no_proc:
-	//TODO: Fall back to using expath if /proc is not available
+no_config:
 	fputs("Failed to find a config file in ~/.config/blastem/blastem.cfg or in the blastem executable directory\n", stderr);
 	exit(1);
 }
--- a/config.h	Mon Oct 28 19:37:30 2013 -0700
+++ b/config.h	Mon Oct 28 21:48:46 2013 -0700
@@ -1,13 +1,13 @@
 /*
  Copyright 2013 Michael Pavone
- This file is part of BlastEm. 
+ This file is part of BlastEm.
  BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 */
 #ifndef CONFIG_H_
 #define CONFIG_H_
 #include "tern.h"
 
-tern_node * load_config(char * expath);
+tern_node * load_config();
 
 #endif //CONFIG_H_
 
--- a/util.c	Mon Oct 28 19:37:30 2013 -0700
+++ b/util.c	Mon Oct 28 21:48:46 2013 -0700
@@ -3,6 +3,10 @@
 #include <stdio.h>
 #include <ctype.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 char * alloc_concat(char * first, char * second)
 {
 	int flen = strlen(first);
@@ -63,3 +67,73 @@
 	*text = 0;
 	return text+1;
 }
+
+static char * exe_str;
+
+void set_exe_str(char * str)
+{
+	exe_str = str;
+}
+
+char * readlink_alloc(char * path)
+{
+	char * linktext = NULL;
+	ssize_t linksize = 512;
+	ssize_t cursize = 0;
+	do {
+		if (linksize > cursize) {
+			cursize = linksize;
+			if (linktext) {
+				free(linktext);
+			}
+		}
+		linktext = malloc(cursize);
+		linksize = readlink(path, linktext, cursize-1);
+		if (linksize == -1) {
+			perror("readlink");
+			free(linktext);
+			linktext = NULL;
+		}
+	} while (linksize > cursize);
+	return linktext;
+}
+
+char * get_exe_dir()
+{
+	static char * exe_dir;
+	if (!exe_dir) {
+		char * linktext = readlink_alloc("/proc/self/exe");
+		if (!linktext) {
+			goto fallback;
+		}
+		char * cur;
+		int linksize = strlen(linktext);
+		for(cur = linktext + linksize - 1; cur != linktext; cur--)
+		{
+			if (*cur == '/') {
+				*cur = 0;
+				break;
+			}
+		}
+		if (cur == linktext) {
+			free(linktext);
+fallback:
+			if (!exe_str) {
+				fputs("/proc/self/exe is not available and set_exe_str was not called!", stderr);
+			}
+			int pathsize = strlen(exe_str);
+			for(cur = exe_str + pathsize - 1; cur != exe_str; cur--)
+			{
+				if (*cur == '/') {
+					exe_dir = malloc(cur-exe_str+1);
+					memcpy(exe_dir, exe_str, cur-exe_str);
+					exe_dir[cur-exe_str] = 0;
+					break;
+				}
+			}
+		} else {
+			exe_dir = linktext;
+		}
+	}
+	return exe_dir;
+}
--- a/util.h	Mon Oct 28 19:37:30 2013 -0700
+++ b/util.h	Mon Oct 28 21:48:46 2013 -0700
@@ -13,6 +13,13 @@
 long file_size(FILE * f);
 //Strips whitespace and non-printable characters from the beginning and end of a string
 char * strip_ws(char * text);
+//Inserts a null after the first word, returns a pointer to the second word
 char * split_keyval(char * text);
+//Should be called by main with the value of argv[0] for use by get_exe_dir
+void set_exe_str(char * str);
+//Returns the directory the executable is in
+char * get_exe_dir();
+//Returns the contents of a symlink in a newly allocated string
+char * readlink_alloc(char * path);
 
 #endif //UTIL_H_