From b35b567df377082e3ae84499884d5a9d2f0f3edd Mon Sep 17 00:00:00 2001
From: David Maciejak <david.maciejak@gmail.com>
Date: Sat, 22 Mar 2014 19:53:07 +0800
Subject: [PATCH] Cleaned releasing application

 When an application is created with WMInitializeApplication,
 it's never destroyed properly.
 The patch is adding some functions to free the
 memory and taking as example 'wmsetbg'. Moreover, in wmsetbg.c I also
 corrected 2 compiler warnings and a possible buffer overflow.

---
 WINGs/WINGs/WINGs.h       |  3 ++-
 WINGs/notification.c      | 12 +++++++++++
 WINGs/wapplication.c      | 11 ++++++++++
 WPrefs.app/TexturePanel.c |  1 +
 util/wmsetbg.c            | 54 ++++++++++++++++++++++++++++-------------------
 5 files changed, 58 insertions(+), 23 deletions(-)

diff --git a/WINGs/WINGs/WINGs.h b/WINGs/WINGs/WINGs.h
index aa95844..6597504 100644
--- a/WINGs/WINGs/WINGs.h
+++ b/WINGs/WINGs/WINGs.h
@@ -642,9 +642,10 @@ WMRect wmkrect(int x, int y, unsigned int width, unsigned int height);
 /* ---[ WINGs/wapplication.c ]-------------------------------------------- */
 
 
-
 void WMInitializeApplication(const char *applicationName, int *argc, char **argv);
 
+void WMReleaseApplication();
+
 void WMSetResourcePath(const char *path);
 
 /* don't free the returned string */
diff --git a/WINGs/notification.c b/WINGs/notification.c
index ada942f..ebb05ec 100644
--- a/WINGs/notification.c
+++ b/WINGs/notification.c
@@ -94,6 +94,18 @@ void W_InitNotificationCenter(void)
 	notificationCenter->observerTable = WMCreateHashTable(WMIntHashCallbacks);
 }
 
+void WMReleaseNotificationCenter()
+{
+	if (notificationCenter->nameTable)
+		WMFreeHashTable(notificationCenter->nameTable);
+	if (notificationCenter->objectTable)
+		WMFreeHashTable(notificationCenter->objectTable);
+	if (notificationCenter->observerTable)
+		WMFreeHashTable(notificationCenter->observerTable);
+	if (notificationCenter)
+		wfree(notificationCenter);
+}
+
 void
 WMAddNotificationObserver(WMNotificationObserverAction * observerAction,
 			  void *observer, const char *name, void *object)
diff --git a/WINGs/wapplication.c b/WINGs/wapplication.c
index a0aec2e..84ede06 100644
--- a/WINGs/wapplication.c
+++ b/WINGs/wapplication.c
@@ -48,6 +48,17 @@ void WMInitializeApplication(const char *applicationName, int *argc, char **argv
 	W_InitNotificationCenter();
 }
 
+void WMReleaseApplication() {
+	int i =0;
+	if (WMApplication.applicationName)
+		wfree(WMApplication.applicationName);
+	for (i = 0; i < WMApplication.argc; i++)
+		wfree(WMApplication.argv[i]);
+	if (WMApplication.argv)
+		wfree(WMApplication.argv);
+	WMReleaseNotificationCenter();
+}
+
 void WMSetResourcePath(const char *path)
 {
 	if (WMApplication.resourcePath)
diff --git a/WPrefs.app/TexturePanel.c b/WPrefs.app/TexturePanel.c
index 9f2b86a..530c124 100644
--- a/WPrefs.app/TexturePanel.c
+++ b/WPrefs.app/TexturePanel.c
@@ -1527,6 +1527,7 @@ int main(int argc, char **argv)
 	ShowTexturePanel(panel);
 
 	WMScreenMainLoop(scr);
+	WMReleaseApplication();
 	return 0;
 }
 #endif
diff --git a/util/wmsetbg.c b/util/wmsetbg.c
index 644c85d..d85eb43 100644
--- a/util/wmsetbg.c
+++ b/util/wmsetbg.c
@@ -100,6 +100,12 @@ typedef struct BackgroundTexture {
 	int height;
 } BackgroundTexture;
 
+static void quit(int rcode)
+{
+	WMReleaseApplication();
+	exit(rcode);
+}
+
 static void initXinerama(void)
 {
 	xineInfo.screens = NULL;
@@ -903,7 +909,7 @@ static noreturn void helperLoop(RContext * rc)
 			errcount--;
 			if (errcount == 0) {
 				wfatal("quitting");
-				exit(1);
+				quit(1);
 			}
 			continue;
 		}
@@ -917,7 +923,7 @@ static noreturn void helperLoop(RContext * rc)
 			errcount--;
 			if (errcount == 0) {
 				wfatal("quitting");
-				exit(1);
+				quit(1);
 			}
 			continue;
 		}
@@ -973,7 +979,7 @@ static noreturn void helperLoop(RContext * rc)
 #ifdef DEBUG
 			printf("exit command\n");
 #endif
-			exit(0);
+			quit(0);
 
 		default:
 			wwarning("unknown message received");
@@ -987,9 +993,11 @@ static void updateDomain(const char *domain, const char *key, const char *textur
 	char *program = "wdwrite";
 
 	/* here is a mem leak */
-	system(wstrconcat("wdwrite ",
+	int result = system(wstrconcat("wdwrite ",
 			  wstrconcat(domain, smooth ? " SmoothWorkspaceBack YES" : " SmoothWorkspaceBack NO")));
 
+	if (result == -1)
+		werror("error executing system command");
 	execlp(program, program, domain, key, texture, NULL);
 	wwarning("warning could not run \"%s\"", program);
 }
@@ -1228,7 +1236,7 @@ int main(int argc, char **argv)
 			i++;
 			if (i >= argc) {
 				wfatal("too few arguments for %s", argv[i - 1]);
-				exit(1);
+				quit(1);
 			}
 			display = argv[i];
 		} else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--scale") == 0) {
@@ -1260,61 +1268,61 @@ int main(int argc, char **argv)
 			i++;
 			if (i >= argc) {
 				wfatal("too few arguments for %s", argv[i - 1]);
-				exit(1);
+				quit(1);
 			}
 			domain = wstrdup(argv[i]);
 		} else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--colors") == 0) {
 			i++;
 			if (i >= argc) {
 				wfatal("too few arguments for %s", argv[i - 1]);
-				exit(1);
+				quit(1);
 			}
 			if (sscanf(argv[i], "%i", &cpc) != 1) {
 				wfatal("bad value for colors per channel: \"%s\"", argv[i]);
-				exit(1);
+				quit(1);
 			}
 		} else if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--back-color") == 0) {
 			i++;
 			if (i >= argc) {
 				wfatal("too few arguments for %s", argv[i - 1]);
-				exit(1);
+				quit(1);
 			}
 			back_color = argv[i];
 		} else if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--parse") == 0) {
 			i++;
 			if (i >= argc) {
 				wfatal("too few arguments for %s", argv[i - 1]);
-				exit(1);
+				quit(1);
 			}
 			texture = argv[i];
 		} else if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--workspace") == 0) {
 			i++;
 			if (i >= argc) {
 				wfatal("too few arguments for %s", argv[i - 1]);
-				exit(1);
+				quit(1);
 			}
 			if (sscanf(argv[i], "%i", &workspace) != 1) {
 				wfatal("bad value for workspace number: \"%s\"", argv[i]);
-				exit(1);
+				quit(1);
 			}
 		} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
 			printf("%s (Window Maker %s)\n", __progname, VERSION);
-			exit(0);
+			quit(0);
 		} else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
 			print_help();
-			exit(0);
+			quit(0);
 		} else if (argv[i][0] != '-') {
 			image_name = argv[i];
 		} else {
 			printf("%s: invalid argument '%s'\n", __progname, argv[i]);
 			printf("Try '%s --help' for more information\n", __progname);
-			exit(1);
+			quit(1);
 		}
 	}
 	if (!image_name && !texture && !helperMode) {
 		printf("%s: you must specify a image file name or a texture\n", __progname);
 		printf("Try '%s --help' for more information\n", __progname);
-		exit(1);
+		quit(1);
 	}
 
 	PixmapPath = getPixmapPath(domain);
@@ -1334,7 +1342,7 @@ int main(int argc, char **argv)
 	dpy = XOpenDisplay(display);
 	if (!dpy) {
 		wfatal("could not open display");
-		exit(1);
+		quit(1);
 	}
 #if 0
 	XSynchronize(dpy, 1);
@@ -1367,12 +1375,14 @@ int main(int argc, char **argv)
 
 	if (!rc) {
 		wfatal("could not initialize wrlib: %s", RMessageForError(RErrorCode));
-		exit(1);
+		quit(1);
 	}
 
 	if (helperMode) {
 		/* lower priority, so that it wont use all the CPU */
-		nice(15);
+		int result = nice(15);
+		if (result == -1)
+			werror("error could not nice process");
 
 		helperLoop(rc);
 	} else {
@@ -1381,8 +1391,7 @@ int main(int argc, char **argv)
 
 		if (!texture) {
 			char *image_path = getFullPixmapPath(image_name);
-
-			sprintf(buffer, "(%s, \"%s\", %s)", style, image_path, back_color);
+			snprintf(buffer, sizeof(buffer), "(%s, \"%s\", %s)", style, image_path, back_color);
 			wfree(image_path);
 			texture = (char *)buffer;
 		}
@@ -1393,7 +1402,7 @@ int main(int argc, char **argv)
 
 		tex = parseTexture(rc, texture);
 		if (!tex)
-			exit(1);
+			quit(1);
 
 		if (workspace < 0)
 			changeTexture(tex);
@@ -1403,5 +1412,6 @@ int main(int argc, char **argv)
 		}
 	}
 
+	WMReleaseApplication();
 	return 0;
 }
-- 
1.8.3.2

