685 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			685 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id: indep.c,v 1.18 2001/12/14 17:10:54 ukai Exp $ */
 | |
| #include "fm.h"
 | |
| #include <stdio.h>
 | |
| #include <pwd.h>
 | |
| #include <sys/param.h>
 | |
| #include <sys/types.h>
 | |
| #include <stdlib.h>
 | |
| #include "indep.h"
 | |
| #include "Str.h"
 | |
| #include "gc.h"
 | |
| #include "myctype.h"
 | |
| #include "entity.h"
 | |
| 
 | |
| char *
 | |
| allocStr(const char *s, int len)
 | |
| {
 | |
|     char *ptr;
 | |
| 
 | |
|     if (s == NULL)
 | |
| 	return NULL;
 | |
|     if (len < 0)
 | |
| 	len = strlen(s);
 | |
|     ptr = NewAtom_N(char, len + 1);
 | |
|     if (ptr == NULL) {
 | |
| 	fprintf(stderr, "fm: Can't allocate string. Give me more memory!\n");
 | |
| 	exit(-1);
 | |
|     }
 | |
|     bcopy(s, ptr, len);
 | |
|     ptr[len] = '\0';
 | |
|     return ptr;
 | |
| }
 | |
| 
 | |
| int
 | |
| strCmp(const void *s1, const void *s2)
 | |
| {
 | |
|     return strcmp(*(const char **)s1, *(const char **)s2);
 | |
| }
 | |
| 
 | |
| char *
 | |
| currentdir()
 | |
| {
 | |
|     char *path;
 | |
| #ifdef HAVE_GETCWD
 | |
| #ifdef MAXPATHLEN
 | |
|     path = NewAtom_N(char, MAXPATHLEN);
 | |
|     getcwd(path, MAXPATHLEN);
 | |
| #else
 | |
|     path = getcwd(NULL, 0);
 | |
| #endif
 | |
| #else				/* not HAVE_GETCWD */
 | |
| #ifdef HAVE_GETWD
 | |
|     path = NewAtom_N(char, 1024);
 | |
|     getwd(path);
 | |
| #else				/* not HAVE_GETWD */
 | |
|     FILE *f;
 | |
|     char *p;
 | |
|     path = NewAtom_N(char, 1024);
 | |
|     f = popen("pwd", "r");
 | |
|     fgets(path, 1024, f);
 | |
|     pclose(f);
 | |
|     for (p = path; *p; p++)
 | |
| 	if (*p == '\n') {
 | |
| 	    *p = '\0';
 | |
| 	    break;
 | |
| 	}
 | |
| #endif				/* not HAVE_GETWD */
 | |
| #endif				/* not HAVE_GETCWD */
 | |
|     return path;
 | |
| }
 | |
| 
 | |
| char *
 | |
| cleanupName(char *name)
 | |
| {
 | |
|     char *buf, *p, *q;
 | |
| 
 | |
|     buf = allocStr(name, -1);
 | |
|     p = buf;
 | |
|     q = name;
 | |
|     while (*q != '\0') {
 | |
| 	if (strncmp(p, "/../", 4) == 0) {	/* foo/bar/../FOO */
 | |
| 	    if (p - 2 == buf && strncmp(p - 2, "..", 2) == 0) {
 | |
| 		/* ../../       */
 | |
| 		p += 3;
 | |
| 		q += 3;
 | |
| 	    }
 | |
| 	    else if (p - 3 >= buf && strncmp(p - 3, "/..", 3) == 0) {
 | |
| 		/* ../../../    */
 | |
| 		p += 3;
 | |
| 		q += 3;
 | |
| 	    }
 | |
| 	    else {
 | |
| 		while (p != buf && *--p != '/') ;	/* ->foo/FOO */
 | |
| 		*p = '\0';
 | |
| 		q += 3;
 | |
| 		strcat(buf, q);
 | |
| 	    }
 | |
| 	}
 | |
| 	else if (strcmp(p, "/..") == 0) {	/* foo/bar/..   */
 | |
| 	    if (p - 2 == buf && strncmp(p - 2, "..", 2) == 0) {
 | |
| 		/* ../..        */
 | |
| 	    }
 | |
| 	    else if (p - 3 >= buf && strncmp(p - 3, "/..", 3) == 0) {
 | |
| 		/* ../../..     */
 | |
| 	    }
 | |
| 	    else {
 | |
| 		while (p != buf && *--p != '/') ;	/* ->foo/ */
 | |
| 		*++p = '\0';
 | |
| 	    }
 | |
| 	    break;
 | |
| 	}
 | |
| 	else if (strncmp(p, "/./", 3) == 0) {	/* foo/./bar */
 | |
| 	    *p = '\0';		/* -> foo/bar           */
 | |
| 	    q += 2;
 | |
| 	    strcat(buf, q);
 | |
| 	}
 | |
| 	else if (strcmp(p, "/.") == 0) {	/* foo/. */
 | |
| 	    *++p = '\0';	/* -> foo/              */
 | |
| 	    break;
 | |
| 	}
 | |
| 	else if (strncmp(p, "//", 2) == 0) {	/* foo//bar */
 | |
| 	    /* -> foo/bar           */
 | |
| 	    *p = '\0';
 | |
| 	    q++;
 | |
| 	    strcat(buf, q);
 | |
| 	}
 | |
| 	else {
 | |
| 	    p++;
 | |
| 	    q++;
 | |
| 	}
 | |
|     }
 | |
|     return buf;
 | |
| }
 | |
| 
 | |
| char *
 | |
| expandPath(char *name)
 | |
| {
 | |
|     Str userName = NULL;
 | |
|     char *p;
 | |
|     struct passwd *passent, *getpwnam(const char *);
 | |
|     Str extpath = Strnew();
 | |
| 
 | |
|     if (name == NULL)
 | |
| 	return NULL;
 | |
|     p = name;
 | |
|     if (*p == '~') {
 | |
| 	p++;
 | |
| 	if (IS_ALPHA(*p)) {
 | |
| 	    userName = Strnew();
 | |
| 	    while (IS_ALNUM(*p) || *p == '_' || *p == '-')
 | |
| 		Strcat_char(userName, *(p++));
 | |
| 	    passent = getpwnam(userName->ptr);
 | |
| 	    if (passent == NULL) {
 | |
| 		p = name;
 | |
| 		goto rest;
 | |
| 	    }
 | |
| 	    Strcat_charp(extpath, passent->pw_dir);
 | |
| 	}
 | |
| 	else {
 | |
| 	    Strcat_charp(extpath, getenv("HOME"));
 | |
| 	}
 | |
| 	if (Strcmp_charp(extpath, "/") == 0 && *p == '/')
 | |
| 	    p++;
 | |
|     }
 | |
|   rest:
 | |
|     Strcat_charp(extpath, p);
 | |
|     return extpath->ptr;
 | |
| }
 | |
| 
 | |
| #ifndef HAVE_STRCASESTR
 | |
| /* string search using the simplest algorithm */
 | |
| char *
 | |
| strcasestr(const char *s1, const char *s2)
 | |
| {
 | |
|     int len1, len2;
 | |
|     if (s2 == NULL)
 | |
| 	return (char *)s1;
 | |
|     if (*s2 == '\0')
 | |
| 	return (char *)s1;
 | |
|     len1 = strlen(s1);
 | |
|     len2 = strlen(s2);
 | |
|     while (*s1 && len1 >= len2) {
 | |
| 	if (strncasecmp(s1, s2, len2) == 0)
 | |
| 	    return (char *)s1;
 | |
| 	s1++;
 | |
| 	len1--;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static int
 | |
| strcasematch(char *s1, char *s2)
 | |
| {
 | |
|     int x;
 | |
|     while (*s1) {
 | |
| 	if (*s2 == '\0')
 | |
| 	    return 1;
 | |
| 	x = tolower(*s1) - tolower(*s2);
 | |
| 	if (x != 0)
 | |
| 	    break;
 | |
| 	s1++;
 | |
| 	s2++;
 | |
|     }
 | |
|     return (*s2 == '\0');
 | |
| }
 | |
| 
 | |
| /* search multiple strings */
 | |
| int
 | |
| strcasemstr(char *str, char *srch[], char **ret_ptr)
 | |
| {
 | |
|     int i;
 | |
|     while (*str) {
 | |
| 	for (i = 0; srch[i]; i++) {
 | |
| 	    if (strcasematch(str, srch[i])) {
 | |
| 		if (ret_ptr)
 | |
| 		    *ret_ptr = str;
 | |
| 		return i;
 | |
| 	    }
 | |
| 	}
 | |
| 	str++;
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| char *
 | |
| remove_space(char *str)
 | |
| {
 | |
|     char *p, *q;
 | |
| 
 | |
|     for (p = str; *p && IS_SPACE(*p); p++) ;
 | |
|     for (q = p; *q; q++) ;
 | |
|     for (; q > p && IS_SPACE(*(q - 1)); q--) ;
 | |
|     if (*q != '\0')
 | |
| 	return Strnew_charp_n(p, q - p)->ptr;
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| int
 | |
| non_null(char *s)
 | |
| {
 | |
|     if (s == NULL)
 | |
| 	return FALSE;
 | |
|     while (*s) {
 | |
| 	if (!IS_SPACE(*s))
 | |
| 	    return TRUE;
 | |
| 	s++;
 | |
|     }
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| void
 | |
| cleanup_line(Str s, int mode)
 | |
| {
 | |
|     if (s->length >= 2 &&
 | |
| 	s->ptr[s->length - 2] == '\r' && s->ptr[s->length - 1] == '\n') {
 | |
| 	Strshrink(s, 2);
 | |
| 	Strcat_char(s, '\n');
 | |
|     }
 | |
|     else if (Strlastchar(s) == '\r')
 | |
| 	s->ptr[s->length - 1] = '\n';
 | |
|     else if (Strlastchar(s) != '\n')
 | |
| 	Strcat_char(s, '\n');
 | |
|     if (mode != PAGER_MODE) {
 | |
| 	int i;
 | |
| 	for (i = 0; i < s->length; i++) {
 | |
| 	    if (s->ptr[i] == '\0')
 | |
| 		s->ptr[i] = ' ';
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| int
 | |
| getescapechar(char **str)
 | |
| {
 | |
|     int dummy = -1;
 | |
|     char *p = *str, *q;
 | |
|     int strict_entity = TRUE;
 | |
| 
 | |
|     if (*p == '&')
 | |
| 	p++;
 | |
|     if (*p == '#') {
 | |
| 	p++;
 | |
| 	if (*p == 'x' || *p == 'X') {
 | |
| 	    p++;
 | |
| 	    if (!IS_XDIGIT(*p)) {
 | |
| 		*str = p;
 | |
| 		return -1;
 | |
| 	    }
 | |
| 	    for (dummy = GET_MYCDIGIT(*p), p++; IS_XDIGIT(*p); p++)
 | |
| 		dummy = dummy * 0x10 + GET_MYCDIGIT(*p);
 | |
| 	    if (*p == ';')
 | |
| 		p++;
 | |
| 	    *str = p;
 | |
| 	    return dummy;
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (!IS_DIGIT(*p)) {
 | |
| 		*str = p;
 | |
| 		return -1;
 | |
| 	    }
 | |
| 	    for (dummy = GET_MYCDIGIT(*p), p++; IS_DIGIT(*p); p++)
 | |
| 		dummy = dummy * 10 + GET_MYCDIGIT(*p);
 | |
| 	    if (*p == ';')
 | |
| 		p++;
 | |
| 	    *str = p;
 | |
| 	    return dummy;
 | |
| 	}
 | |
|     }
 | |
|     if (!IS_ALPHA(*p)) {
 | |
| 	*str = p;
 | |
| 	return -1;
 | |
|     }
 | |
|     q = p;
 | |
|     for (p++; IS_ALNUM(*p); p++) ;
 | |
|     q = allocStr(q, p - q);
 | |
|     if (strcasestr("lt gt amp quot nbsp", q) && *p != '=') {
 | |
| 	/* a character entity MUST be terminated with ";". However,
 | |
| 	 * there's MANY web pages which uses < , > or something
 | |
| 	 * like them as <, >, etc. Therefore, we treat the most
 | |
| 	 * popular character entities (including &#xxxx;) without
 | |
| 	 * the last ";" as character entities. If the trailing character
 | |
| 	 * is "=", it must be a part of query in an URL. So <=, >=, etc.
 | |
| 	 * are not regarded as character entities.
 | |
| 	 */
 | |
| 	strict_entity = FALSE;
 | |
|     }
 | |
|     if (*p == ';')
 | |
| 	p++;
 | |
|     else if (strict_entity) {
 | |
| 	*str = p;
 | |
| 	return -1;
 | |
|     }
 | |
|     *str = p;
 | |
|     return getHash_si(&entity, q, -1);
 | |
| }
 | |
| 
 | |
| char *
 | |
| getescapecmd(char **s)
 | |
| {
 | |
|     char *save = *s;
 | |
|     Str tmp;
 | |
|     int ch = getescapechar(s);
 | |
| 
 | |
|     if (ch >= 0)
 | |
| 	return conv_entity(ch);
 | |
| 
 | |
|     if (*save != '&')
 | |
| 	tmp = Strnew_charp("&");
 | |
|     else
 | |
| 	tmp = Strnew();
 | |
|     Strcat_charp_n(tmp, save, *s - save);
 | |
|     return tmp->ptr;
 | |
| }
 | |
| 
 | |
| char *
 | |
| html_quote_char(char c)
 | |
| {
 | |
|     switch (c) {
 | |
|     case '&':
 | |
| 	return "&";
 | |
|     case '<':
 | |
| 	return "<";
 | |
|     case '>':
 | |
| 	return ">";
 | |
|     case '"':
 | |
| 	return """;
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| char *
 | |
| html_quote(char *str)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p, *q;
 | |
| 
 | |
|     for (p = str; *p; p++) {
 | |
| 	q = html_quote_char(*p);
 | |
| 	if (q) {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(str, (int)(p - str));
 | |
| 	    Strcat_charp(tmp, q);
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (tmp)
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	}
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp->ptr;
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| char *
 | |
| html_unquote(char *str)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p, *q;
 | |
| 
 | |
|     for (p = str; *p;) {
 | |
| 	if (*p == '&') {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(str, (int)(p - str));
 | |
| 	    q = getescapecmd(&p);
 | |
| 	    Strcat_charp(tmp, q);
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (tmp)
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	    p++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if (tmp)
 | |
| 	return tmp->ptr;
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| static char xdigit[0x10] = "0123456789ABCDEF";
 | |
| 
 | |
| #define url_unquote_char(pstr) \
 | |
|   (IS_XDIGIT((*(pstr))[1]) ? \
 | |
|     (IS_XDIGIT((*(pstr))[2]) ? \
 | |
|     (*(pstr) += 3, (GET_MYCDIGIT((*(pstr))[-2]) << 4) | GET_MYCDIGIT((*(pstr))[-1])) : \
 | |
|     (*(pstr) += 2, GET_MYCDIGIT((*(pstr))[-1]))) : \
 | |
|    -1)
 | |
| 
 | |
| char *
 | |
| url_quote(char *str)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p;
 | |
| 
 | |
|     for (p = str; *p; p++) {
 | |
| 	if (IS_CNTRL(*p) || *p == ' ' || !IS_ASCII(*p)) {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(str, (int)(p - str));
 | |
| 	    Strcat_char(tmp, '%');
 | |
| 	    Strcat_char(tmp, xdigit[((unsigned char)*p >> 4) & 0xF]);
 | |
| 	    Strcat_char(tmp, xdigit[(unsigned char)*p & 0xF]);
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (tmp)
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	}
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp->ptr;
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| char *
 | |
| url_unquote(char *str)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p, *q;
 | |
|     int c;
 | |
| 
 | |
|     for (p = str; *p;) {
 | |
| 	if (*p == '%') {
 | |
| 	    q = p;
 | |
| 	    c = url_unquote_char(&q);
 | |
| 	    if (c >= 0 && (IS_CNTRL(c) || c == ' ' || !IS_ASCII(c))) {
 | |
| 		if (tmp == NULL)
 | |
| 		    tmp = Strnew_charp_n(str, (int)(p - str));
 | |
| 		if (c != '\0' && c != '\n' && c != '\r')
 | |
| 		    Strcat_char(tmp, (char)c);
 | |
| 		p = q;
 | |
| 		continue;
 | |
| 	    }
 | |
| 	}
 | |
| 	if (tmp)
 | |
| 	    Strcat_char(tmp, *p);
 | |
| 	p++;
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp->ptr;
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| char *
 | |
| file_quote(char *str)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p;
 | |
|     char buf[4];
 | |
| 
 | |
|     for (p = str; *p; p++) {
 | |
| 	if (IS_CNTRL(*p) || *p == ' ' || !IS_ASCII(*p) || *p == '+' ||
 | |
| 	    *p == ':' || *p == '#' || *p == '?' || *p == '&' || *p == '%') {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(str, (int)(p - str));
 | |
| 	    sprintf(buf, "%%%02X", (unsigned char)*p);
 | |
| 	    Strcat_charp(tmp, buf);
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (tmp)
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	}
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp->ptr;
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| char *
 | |
| file_unquote(char *str)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p, *q;
 | |
|     int c;
 | |
| 
 | |
|     for (p = str; *p;) {
 | |
| 	if (*p == '%') {
 | |
| 	    q = p;
 | |
| 	    c = url_unquote_char(&q);
 | |
| 	    if (c >= 0) {
 | |
| 		if (tmp == NULL)
 | |
| 		    tmp = Strnew_charp_n(str, (int)(p - str));
 | |
| 		if (c != '\0' && c != '\n' && c != '\r')
 | |
| 		    Strcat_char(tmp, (char)c);
 | |
| 		p = q;
 | |
| 		continue;
 | |
| 	    }
 | |
| 	}
 | |
| 	if (tmp)
 | |
| 	    Strcat_char(tmp, *p);
 | |
| 	p++;
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp->ptr;
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| /* rfc1808 safe */
 | |
| static int
 | |
| is_url_safe(char c)
 | |
| {
 | |
|     switch (c) {
 | |
| 	/* safe */
 | |
|     case '$':
 | |
|     case '-':
 | |
|     case '_':
 | |
|     case '.':
 | |
| 	return 1;
 | |
|     default:
 | |
| 	return IS_ALNUM(c);
 | |
|     }
 | |
| }
 | |
| 
 | |
| Str
 | |
| Str_form_quote(Str x)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p = x->ptr, *ep = x->ptr + x->length;
 | |
|     char buf[4];
 | |
| 
 | |
|     for (; p < ep; p++) {
 | |
| 	if (*p == ' ') {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | |
| 	    Strcat_char(tmp, '+');
 | |
| 	}
 | |
| 	else if (!is_url_safe(*p)) {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | |
| 	    sprintf(buf, "%%%02X", (unsigned char)*p);
 | |
| 	    Strcat_charp(tmp, buf);
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (tmp)
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	}
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp;
 | |
|     return x;
 | |
| }
 | |
| 
 | |
| Str
 | |
| Str_form_unquote(Str x)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p = x->ptr, *ep = x->ptr + x->length, *q;
 | |
|     int c;
 | |
| 
 | |
|     for (; p < ep;) {
 | |
| 	if (*p == '+') {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | |
| 	    Strcat_char(tmp, ' ');
 | |
| 	    p++;
 | |
| 	    continue;
 | |
| 	}
 | |
| 	else if (*p == '%') {
 | |
| 	    q = p;
 | |
| 	    c = url_unquote_char(&q);
 | |
| 	    if (c >= 0) {
 | |
| 		if (tmp == NULL)
 | |
| 		    tmp = Strnew_charp_n(x->ptr, (int)(p - x->ptr));
 | |
| 		Strcat_char(tmp, (char)c);
 | |
| 		p = q;
 | |
| 		continue;
 | |
| 	    }
 | |
| 	}
 | |
| 	if (tmp)
 | |
| 	    Strcat_char(tmp, *p);
 | |
| 	p++;
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp;
 | |
|     return x;
 | |
| }
 | |
| 
 | |
| static int
 | |
| is_shell_safe(char c)
 | |
| {
 | |
|     switch (c) {
 | |
| 	/* safe */
 | |
|     case '/':
 | |
|     case '.':
 | |
|     case '_':
 | |
|     case ':':
 | |
| 	return 1;
 | |
|     default:
 | |
| 	return IS_ALNUM(c) || (c & 0x80);
 | |
|     }
 | |
| }
 | |
| 
 | |
| char *
 | |
| shell_quote(char *str)
 | |
| {
 | |
|     Str tmp = NULL;
 | |
|     char *p;
 | |
| 
 | |
|     for (p = str; *p; p++) {
 | |
| 	if (!is_shell_safe(*p)) {
 | |
| 	    if (tmp == NULL)
 | |
| 		tmp = Strnew_charp_n(str, (int)(p - str));
 | |
| 	    Strcat_char(tmp, '\\');
 | |
| 	    Strcat_char(tmp, *p);
 | |
| 	}
 | |
| 	else {
 | |
| 	    if (tmp)
 | |
| 		Strcat_char(tmp, *p);
 | |
| 	}
 | |
|     }
 | |
|     if (tmp)
 | |
| 	return tmp->ptr;
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| static char *
 | |
| w3m_dir(const char *name, char *dft)
 | |
| {
 | |
| #ifdef USE_PATH_ENVVAR
 | |
|     char *value = getenv(name);
 | |
|     return value ? value : dft;
 | |
| #else
 | |
|     return dft;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| char *
 | |
| w3m_lib_dir()
 | |
| {
 | |
|     return w3m_dir("W3M_LIB_DIR", LIB_DIR);
 | |
| }
 | |
| 
 | |
| char *
 | |
| w3m_etc_dir()
 | |
| {
 | |
|     return w3m_dir("W3M_ETC_DIR", ETC_DIR);
 | |
| }
 | |
| 
 | |
| char *
 | |
| w3m_help_dir()
 | |
| {
 | |
|     return w3m_dir("W3M_HELP_DIR", HELP_DIR);
 | |
| }
 | |
| /* Local Variables:    */
 | |
| /* c-basic-offset: 4   */
 | |
| /* tab-width: 8        */
 | |
| /* End:                */
 |