1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains source for the ZGetVariable, ZSetVariable, and ZUnsetVariable
3  * functions.
4  *
5  *	Created by:	Robert French
6  *
7  *	Copyright (c) 1987 by the Massachusetts Institute of Technology.
8  *	For copying and distribution information, see the file
9  *	"mit-copyright.h".
10  */
11 
12 #include "libpurple/internal.h"
13 #include "internal.h"
14 #include "util.h"
15 
16 #include <ctype.h>
17 #ifndef WIN32
18 #include <pwd.h>
19 #endif
20 
21 static char *get_localvarfile __P((void));
22 static char *get_varval __P((char *fn, char *val));
23 static int varline __P((char *bfr, char *var));
24 
ZGetVariable(var)25 char *ZGetVariable(var)
26     char *var;
27 {
28 	char *varfile, *ret;
29 
30 	if ((varfile = get_localvarfile()) == NULL)
31 		return ((char *)0);
32 
33 	ret = get_varval(varfile, var);
34 	g_free(varfile);
35 	if (ret != ZERR_NONE)
36 		return ret;
37 
38 #ifdef WIN32
39 	varfile = g_strdup("C:\\zephyr\\zephyr.var");
40 #else
41 	varfile = g_strdup_printf("%s/zephyr.vars", CONFDIR);
42 #endif
43 	ret = get_varval(varfile, var);
44 	g_free(varfile);
45 
46 	return ret;
47 }
48 
ZSetVariable(var,value)49 Code_t ZSetVariable(var, value)
50     char *var;
51     char *value;
52 {
53     int written;
54     FILE *fpin, *fpout;
55     char *varfile, *varfilebackup, varbfr[512];
56 
57     written = 0;
58 
59     if ((varfile = get_localvarfile()) == NULL)
60 	return (ZERR_INTERNAL);
61 
62     varfilebackup = g_strconcat(varfile, ".backup", NULL);
63 
64     if (!(fpout = fopen(varfilebackup, "w"))) {
65 	g_free(varfile);
66 	g_free(varfilebackup);
67 	return (errno);
68     }
69     if ((fpin = fopen(varfile, "r")) != NULL) {
70 	while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
71 	    if (varbfr[strlen(varbfr)-1] < ' ')
72 		varbfr[strlen(varbfr)-1] = '\0';
73 	    if (varline(varbfr, var)) {
74 		fprintf(fpout, "%s = %s\n", var, value);
75 		written = 1;
76 	    }
77 	    else
78 		fprintf(fpout, "%s\n", varbfr);
79 	}
80 	(void) fclose(fpin);		/* don't care about errs on input */
81     }
82     if (!written)
83 	fprintf(fpout, "%s = %s\n", var, value);
84     if (fclose(fpout) == EOF) {
85     	g_free(varfilebackup);
86     	g_free(varfile);
87 	return(EIO);		/* can't rely on errno */
88     }
89     if (rename(varfilebackup, varfile)) {
90 	g_free(varfilebackup);
91 	g_free(varfile);
92 	return (errno);
93     }
94     g_free(varfilebackup);
95     g_free(varfile);
96     return (ZERR_NONE);
97 }
98 
ZUnsetVariable(var)99 Code_t ZUnsetVariable(var)
100     char *var;
101 {
102     FILE *fpin, *fpout;
103     char *varfile, *varfilebackup, varbfr[512];
104 
105     if ((varfile = get_localvarfile()) == NULL)
106 	return (ZERR_INTERNAL);
107 
108     varfilebackup = g_strconcat(varfile, ".backup", NULL);
109 
110     if (!(fpout = fopen(varfilebackup, "w"))) {
111 	g_free(varfile);
112 	g_free(varfilebackup);
113 	return (errno);
114     }
115     if ((fpin = fopen(varfile, "r")) != NULL) {
116 	while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
117 	    if (varbfr[strlen(varbfr)-1] < ' ')
118 		varbfr[strlen(varbfr)-1] = '\0';
119 	    if (!varline(varbfr, var))
120 		fprintf(fpout, "%s\n", varbfr);
121 	}
122 	(void) fclose(fpin);		/* don't care about read close errs */
123     }
124     if (fclose(fpout) == EOF) {
125 	g_free(varfilebackup);
126 	g_free(varfile);
127 	return(EIO);		/* errno isn't reliable */
128     }
129     if (rename(varfilebackup, varfile)) {
130 	g_free(varfilebackup);
131 	g_free(varfile);
132 	return (errno);
133     }
134     g_free(varfilebackup);
135     g_free(varfile);
136     return (ZERR_NONE);
137 }
138 
get_localvarfile(void)139 static char *get_localvarfile(void)
140 {
141     const char *base;
142 #ifndef WIN32
143     struct passwd *pwd;
144     base = purple_home_dir();
145 #else
146     base = getenv("HOME");
147     if (!base)
148         base = getenv("HOMEPATH");
149     if (!base)
150         base = "C:\\";
151 #endif
152     if (!base) {
153 #ifndef WIN32
154 	if (!(pwd = getpwuid((int) getuid()))) {
155 	    fprintf(stderr, "Zephyr internal failure: Can't find your entry in /etc/passwd\n");
156 	    return NULL;
157 	}
158 	base = pwd->pw_dir;
159 #endif
160     }
161 
162     return g_strconcat(base, "/.zephyr.vars", NULL);
163 }
164 
get_varval(fn,var)165 static char *get_varval(fn, var)
166     char *fn;
167     char *var;
168 {
169     FILE *fp;
170     static char varbfr[512];
171     int i;
172 
173     fp = fopen(fn, "r");
174     if (!fp)
175 	return ((char *)0);
176 
177     while (fgets(varbfr, sizeof varbfr, fp) != (char *) 0) {
178 	if (varbfr[strlen(varbfr)-1] < ' ')
179 	    varbfr[strlen(varbfr)-1] = '\0';
180 	if (!(i = varline(varbfr, var)))
181 	    continue;
182 	(void) fclose(fp);		/* open read-only, don't care */
183 	return (varbfr+i);
184     }
185     (void) fclose(fp);			/* open read-only, don't care */
186     return ((char *)0);
187 }
188 
189 /* If the variable in the line bfr[] is the same as var, return index to
190    the variable value, else return 0. */
varline(bfr,var)191 static int varline(bfr, var)
192     char *bfr;
193     char *var;
194 {
195     register char *cp;
196 
197 
198     if (!bfr[0] || bfr[0] == '#')	/* comment or null line */
199 	return (0);
200 
201     cp = bfr;
202     while (*cp && !isspace(*cp) && (*cp != '='))
203 	cp++;
204 
205 #ifndef WIN32
206 #define max(a,b) ((a > b) ? (a) : (b))
207 #endif
208 
209     if (g_ascii_strncasecmp(bfr, var, max(strlen(var), (gsize)(cp - bfr))))
210 	return(0);			/* var is not the var in
211 					   bfr ==> no match */
212 
213     cp = strchr(bfr, '=');
214     if (!cp)
215 	return(0);
216     cp++;
217     while (*cp && isspace(*cp))		/* space up to variable value */
218 	cp++;
219 
220     return (cp - bfr);			/* return index */
221 }
222