Browse code

- 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 authored on 08/02/2008 05:37:44
Showing 3 changed files
... ...
@@ -108,6 +108,7 @@
108 108
 #ifdef HAVE_SYS_SOCKIO_H
109 109
 #include <sys/sockio.h>
110 110
 #endif
111
+#include <libgen.h>
111 112
 
112 113
 #include "config.h"
113 114
 #include "dprint.h"
... ...
@@ -893,6 +894,53 @@ error_port:
893 893
 }
894 894
 
895 895
 
896
+/** Update \c cfg_file variable to contain full pathname. The function updates
897
+ * the value of \c cfg_file global variable to contain full absolute pathname
898
+ * to the main configuration file of SER. The function uses CFG_FILE macro to
899
+ * determine the default path to the configuration file if the user did not
900
+ * specify one using the command line option. If \c cfg_file contains an
901
+ * absolute pathname then it is used unmodified, if it contains a relative
902
+ * pathanme than the value returned by \c getcwd function will be added at the
903
+ * beginning. This function must be run before SER changes its current working
904
+ * directory to / (in daemon mode).
905
+ * @return Zero on success, negative number
906
+ * on error.
907
+ */
908
+int fix_cfg_file(void)
909
+{
910
+	char* res = NULL;
911
+	size_t max_len, cwd_len, cfg_len;
912
+	
913
+	if (cfg_file == NULL) cfg_file = CFG_FILE;
914
+	if (cfg_file[0] == '/') return 0;
915
+	
916
+	/* cfg_file contains a relative pathname, get the current
917
+	 * working directory and add it at the beginning
918
+	 */
919
+	cfg_len = strlen(cfg_file);
920
+	
921
+	max_len = pathmax();
922
+	if ((res = malloc(max_len)) == NULL) goto error;
923
+	
924
+	if (getcwd(res, max_len) == NULL) goto error;
925
+	cwd_len = strlen(res);
926
+	
927
+	/* Make sure that the buffer is big enough */
928
+	if (cwd_len + 1 + cfg_len >= max_len) goto error;
929
+	
930
+	res[cwd_len] = '/';
931
+	memcpy(res + cwd_len + 1, cfg_file, cfg_len);
932
+	
933
+	res[cwd_len + 1 + cfg_len] = '\0'; /* Add terminating zero */
934
+	cfg_file = res;
935
+	return 0;
936
+	
937
+ error:
938
+	fprintf(stderr, "ERROR: Unable to fix cfg_file to contain full pathname\n");
939
+	if (res) free(res);
940
+	return -1;
941
+}
942
+
896 943
 
897 944
 /* main loop */
898 945
 int main_loop()
... ...
@@ -1350,8 +1398,9 @@ int main(int argc, char** argv)
1350 1350
 
1351 1351
 	if (init_routes()<0) goto error;
1352 1352
 	if (init_nonsip_hooks()<0) goto error;
1353
-	/* fill missing arguments with the default values*/
1354
-	if (cfg_file==0) cfg_file=CFG_FILE;
1353
+
1354
+	/* Fix the value of cfg_file variable.*/
1355
+	if (fix_cfg_file() < 0) goto error;
1355 1356
 
1356 1357
 	/* load config file or die */
1357 1358
 	cfg_stream=fopen (cfg_file, "r");
... ...
@@ -28,7 +28,7 @@
28 28
  *
29 29
  */
30 30
 
31
-
31
+#define _GNU_SOURCE 1 /* strndup in get_abs_pathname */
32 32
 #include <string.h>
33 33
 #include <sys/types.h>
34 34
 #include <pwd.h>
... ...
@@ -40,6 +40,7 @@
40 40
 
41 41
 #include "ut.h"
42 42
 #include "mem/mem.h"
43
+#include "globals.h"
43 44
 
44 45
 
45 46
 /* converts a username into uid:gid,
... ...
@@ -204,4 +205,57 @@ unsigned int get_sys_version(int* major, int* minor, int* minor2)
204 204
 }
205 205
 
206 206
 
207
-
207
+char* get_abs_pathname(str* base, str* file)
208
+{
209
+	str ser_cfg;
210
+	char* buf, *dir, *res;
211
+	int len;
212
+  	
213
+	if (base == NULL) {
214
+		ser_cfg.s = cfg_file;
215
+		ser_cfg.len = strlen(cfg_file);
216
+		base = &ser_cfg;
217
+	}
218
+	
219
+	if (!base->s || base->len <= 0 || base->s[0] != '/') {
220
+		BUG("get_abs_pathname: Base file must be absolute pathname: "
221
+			"'%.*s'\n", STR_FMT(base));
222
+		return NULL;
223
+	}
224
+	
225
+	if (!file || !file->s || file->len <= 0) {
226
+		BUG("get_abs_pathname: Invalid 'file' parameter\n");
227
+		return NULL;
228
+	}
229
+	
230
+	if (file->s[0] == '/') {
231
+		/* This is an absolute pathname, make a zero terminated
232
+		 * copy and use it as it is */
233
+		if ((res = strndup(file->s, file->len)) == NULL) {
234
+			ERR("get_abs_pathname: No memory left (strndup failed)\n");
235
+		}
236
+	} else {
237
+		/* This is not an absolute pathname, make it relative
238
+		 * to the location of the base file
239
+		 */
240
+		/* Make a copy, function dirname may modify the string */
241
+		if ((buf = strndup(base->s, base->len)) == NULL) {
242
+			ERR("get_abs_pathname: No memory left (strdup failed)\n");
243
+			return NULL;
244
+		}
245
+		dir = dirname(buf);
246
+		
247
+		len = strlen(dir);
248
+		if ((res = malloc(len + 1 + file->len + 1)) == NULL) {
249
+			ERR("get_abs_pathname: No memory left (malloc failed)\n");
250
+			free(buf);
251
+			return NULL;
252
+		}
253
+		memcpy(res, dir, len);
254
+		res[len] = '/';
255
+		memcpy(res + len + 1, file->s, file->len);
256
+		res[len + 1 + file->len] = '\0';
257
+		free(buf);
258
+	}
259
+	return res;
260
+}
... ...
@@ -580,4 +580,20 @@ char* as_asciiz(str* s);
580 580
  * if the parameters are not null they are set to the coresp. part */
581 581
 unsigned int get_sys_version(int* major, int* minor, int* minor2);
582 582
 
583
+/** Converts relative pathnames to absolute pathnames. This function returns
584
+ * the full pathname of a file in parameter. If the file pathname does not
585
+ * start with / then it will be converted into an absolute pathname. The
586
+ * function gets the absolute directory pathname from \c base and appends \c
587
+ * file to it. The first parameter can be NULL, in this case the function will
588
+ * use the location of the main SER configuration file as reference.
589
+ * @param base filename to be used as reference when \c file is relative. It
590
+ *             must be absolute. The location of the SER configuration file
591
+ *             will be used as reference if you set the value of this
592
+ *             parameter to NULL.
593
+ * @param file A pathname to be converted to absolute.
594
+ * @return A string containing absolute pathname, the string must be freed
595
+ * with free. NULL on error.
596
+ */
597
+char* get_abs_pathname(str* base, str* file);
598
+
583 599
 #endif