Browse Source

- Make sure that the global cfg_file variable always contains
full absolute pathname.
- Added get_abs_pathname function that can be used to convert
relative pathnames to absolutes with using the location of
cfg_file (or another file) as reference.

Jan Janak 17 years ago
parent
commit
b2471cfce2
3 changed files with 123 additions and 4 deletions
  1. 51 2
      main.c
  2. 56 2
      ut.c
  3. 16 0
      ut.h

+ 51 - 2
main.c

@@ -108,6 +108,7 @@
 #ifdef HAVE_SYS_SOCKIO_H
 #ifdef HAVE_SYS_SOCKIO_H
 #include <sys/sockio.h>
 #include <sys/sockio.h>
 #endif
 #endif
+#include <libgen.h>
 
 
 #include "config.h"
 #include "config.h"
 #include "dprint.h"
 #include "dprint.h"
@@ -893,6 +894,53 @@ error_port:
 }
 }
 
 
 
 
+/** Update \c cfg_file variable to contain full pathname. The function updates
+ * the value of \c cfg_file global variable to contain full absolute pathname
+ * to the main configuration file of SER. The function uses CFG_FILE macro to
+ * determine the default path to the configuration file if the user did not
+ * specify one using the command line option. If \c cfg_file contains an
+ * absolute pathname then it is used unmodified, if it contains a relative
+ * pathanme than the value returned by \c getcwd function will be added at the
+ * beginning. This function must be run before SER changes its current working
+ * directory to / (in daemon mode).
+ * @return Zero on success, negative number
+ * on error.
+ */
+int fix_cfg_file(void)
+{
+	char* res = NULL;
+	size_t max_len, cwd_len, cfg_len;
+	
+	if (cfg_file == NULL) cfg_file = CFG_FILE;
+	if (cfg_file[0] == '/') return 0;
+	
+	/* cfg_file contains a relative pathname, get the current
+	 * working directory and add it at the beginning
+	 */
+	cfg_len = strlen(cfg_file);
+	
+	max_len = pathmax();
+	if ((res = malloc(max_len)) == NULL) goto error;
+	
+	if (getcwd(res, max_len) == NULL) goto error;
+	cwd_len = strlen(res);
+	
+	/* Make sure that the buffer is big enough */
+	if (cwd_len + 1 + cfg_len >= max_len) goto error;
+	
+	res[cwd_len] = '/';
+	memcpy(res + cwd_len + 1, cfg_file, cfg_len);
+	
+	res[cwd_len + 1 + cfg_len] = '\0'; /* Add terminating zero */
+	cfg_file = res;
+	return 0;
+	
+ error:
+	fprintf(stderr, "ERROR: Unable to fix cfg_file to contain full pathname\n");
+	if (res) free(res);
+	return -1;
+}
+
 
 
 /* main loop */
 /* main loop */
 int main_loop()
 int main_loop()
@@ -1350,8 +1398,9 @@ int main(int argc, char** argv)
 
 
 	if (init_routes()<0) goto error;
 	if (init_routes()<0) goto error;
 	if (init_nonsip_hooks()<0) goto error;
 	if (init_nonsip_hooks()<0) goto error;
-	/* fill missing arguments with the default values*/
-	if (cfg_file==0) cfg_file=CFG_FILE;
+
+	/* Fix the value of cfg_file variable.*/
+	if (fix_cfg_file() < 0) goto error;
 
 
 	/* load config file or die */
 	/* load config file or die */
 	cfg_stream=fopen (cfg_file, "r");
 	cfg_stream=fopen (cfg_file, "r");

+ 56 - 2
ut.c

@@ -28,7 +28,7 @@
  *
  *
  */
  */
 
 
-
+#define _GNU_SOURCE 1 /* strndup in get_abs_pathname */
 #include <string.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/types.h>
 #include <pwd.h>
 #include <pwd.h>
@@ -40,6 +40,7 @@
 
 
 #include "ut.h"
 #include "ut.h"
 #include "mem/mem.h"
 #include "mem/mem.h"
+#include "globals.h"
 
 
 
 
 /* converts a username into uid:gid,
 /* converts a username into uid:gid,
@@ -204,4 +205,57 @@ unsigned int get_sys_version(int* major, int* minor, int* minor2)
 }
 }
 
 
 
 
-
+char* get_abs_pathname(str* base, str* file)
+{
+	str ser_cfg;
+	char* buf, *dir, *res;
+	int len;
+  	
+	if (base == NULL) {
+		ser_cfg.s = cfg_file;
+		ser_cfg.len = strlen(cfg_file);
+		base = &ser_cfg;
+	}
+	
+	if (!base->s || base->len <= 0 || base->s[0] != '/') {
+		BUG("get_abs_pathname: Base file must be absolute pathname: "
+			"'%.*s'\n", STR_FMT(base));
+		return NULL;
+	}
+	
+	if (!file || !file->s || file->len <= 0) {
+		BUG("get_abs_pathname: Invalid 'file' parameter\n");
+		return NULL;
+	}
+	
+	if (file->s[0] == '/') {
+		/* This is an absolute pathname, make a zero terminated
+		 * copy and use it as it is */
+		if ((res = strndup(file->s, file->len)) == NULL) {
+			ERR("get_abs_pathname: No memory left (strndup failed)\n");
+		}
+	} else {
+		/* This is not an absolute pathname, make it relative
+		 * to the location of the base file
+		 */
+		/* Make a copy, function dirname may modify the string */
+		if ((buf = strndup(base->s, base->len)) == NULL) {
+			ERR("get_abs_pathname: No memory left (strdup failed)\n");
+			return NULL;
+		}
+		dir = dirname(buf);
+		
+		len = strlen(dir);
+		if ((res = malloc(len + 1 + file->len + 1)) == NULL) {
+			ERR("get_abs_pathname: No memory left (malloc failed)\n");
+			free(buf);
+			return NULL;
+		}
+		memcpy(res, dir, len);
+		res[len] = '/';
+		memcpy(res + len + 1, file->s, file->len);
+		res[len + 1 + file->len] = '\0';
+		free(buf);
+	}
+	return res;
+}

+ 16 - 0
ut.h

@@ -580,4 +580,20 @@ char* as_asciiz(str* s);
  * if the parameters are not null they are set to the coresp. part */
  * if the parameters are not null they are set to the coresp. part */
 unsigned int get_sys_version(int* major, int* minor, int* minor2);
 unsigned int get_sys_version(int* major, int* minor, int* minor2);
 
 
+/** Converts relative pathnames to absolute pathnames. This function returns
+ * the full pathname of a file in parameter. If the file pathname does not
+ * start with / then it will be converted into an absolute pathname. The
+ * function gets the absolute directory pathname from \c base and appends \c
+ * file to it. The first parameter can be NULL, in this case the function will
+ * use the location of the main SER configuration file as reference.
+ * @param base filename to be used as reference when \c file is relative. It
+ *             must be absolute. The location of the SER configuration file
+ *             will be used as reference if you set the value of this
+ *             parameter to NULL.
+ * @param file A pathname to be converted to absolute.
+ * @return A string containing absolute pathname, the string must be freed
+ * with free. NULL on error.
+ */
+char* get_abs_pathname(str* base, str* file);
+
 #endif
 #endif