1 /* util2.c
2  */
3 /* This software is copyrighted as detailed in the LICENSE file. */
4 
5 
6 #include "EXTERN.h"
7 #include "common.h"
8 #include "list.h"
9 #include "hash.h"
10 #include "ngdata.h"
11 #include "nntpclient.h"
12 #include "datasrc.h"
13 #include "nntp.h"
14 #include "nntpauth.h"
15 #include "util.h"
16 #include "util3.h"
17 #include "INTERN.h"
18 #include "util2.h"
19 
20 #ifdef TILDENAME
21 static char* tildename = NULL;
22 static char* tildedir = NULL;
23 #endif
24 
25 /* copy a string to a safe spot */
26 
27 char*
savestr(str)28 savestr(str)
29 char* str;
30 {
31     register char* newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
32 
33     strcpy(newaddr,str);
34     return newaddr;
35 }
36 
37 /* safe version of string copy */
38 
39 char*
safecpy(to,from,len)40 safecpy(to,from,len)
41 char* to;
42 register char* from;
43 register int len;
44 {
45     register char* dest = to;
46 
47     if (from) {
48 	while (--len && *from)
49 	    *dest++ = *from++;
50     }
51     *dest = '\0';
52 
53     return to;
54 }
55 
56 /* copy a string up to some (non-backslashed) delimiter, if any */
57 
58 char*
cpytill(to,from,delim)59 cpytill(to,from,delim)
60 register char* to;
61 register char* from;
62 register int delim;
63 {
64     while (*from) {
65 	if (*from == '\\' && from[1] == delim)
66 	    from++;
67 	else if (*from == delim)
68 	    break;
69 	*to++ = *from++;
70     }
71     *to = '\0';
72     return from;
73 }
74 
75 /* expand filename via %, ~, and $ interpretation */
76 /* returns pointer to static area */
77 /* Note that there is a 1-deep cache of ~name interpretation */
78 
79 char*
filexp(s)80 filexp(s)
81 register char* s;
82 {
83     static char filename[CBUFLEN];
84     char scrbuf[CBUFLEN];
85     register char* d;
86 
87 #ifdef DEBUG
88     if (debug & DEB_FILEXP)
89 	printf("< %s\n",s) FLUSH;
90 #endif
91     /* interpret any % escapes */
92     dointerp(filename,sizeof filename,s,(char*)NULL,(char*)NULL);
93 #ifdef DEBUG
94     if (debug & DEB_FILEXP)
95 	printf("%% %s\n",filename) FLUSH;
96 #endif
97     s = filename;
98     if (*s == '~') {	/* does destination start with ~? */
99 	if (!*(++s) || *s == '/') {
100 	    sprintf(scrbuf,"%s%s",homedir,s);
101 				/* swap $HOME for it */
102 #ifdef DEBUG
103 	    if (debug & DEB_FILEXP)
104 		printf("~ %s\n",scrbuf) FLUSH;
105 #endif
106 	    strcpy(filename,scrbuf);
107 	}
108 	else if (*s == '~' && (!s[1] || s[1] == '/')) {
109 	    d = getenv("TRNPREFIX");
110 	    if (!d)
111 		d = INSTALLPREFIX;
112 	    sprintf(scrbuf,"%s%s",d,s+1);
113 #ifdef DEBUG
114 	    if (debug & DEB_FILEXP)
115 		printf("~~ %s\n",scrbuf) FLUSH;
116 #endif
117 	}
118 	else {
119 #ifdef TILDENAME
120 	    for (d = scrbuf; isalnum(*s); s++, d++) *d = *s;
121 	    *d = '\0';
122 	    if (tildedir && strEQ(tildename,scrbuf)) {
123 		strcpy(scrbuf,tildedir);
124 		strcat(scrbuf, s);
125 		strcpy(filename, scrbuf);
126 #ifdef DEBUG
127 		if (debug & DEB_FILEXP)
128 		    printf("r %s %s\n",tildename,tildedir) FLUSH;
129 #endif
130 	    }
131 	    else {
132 		if (tildename)
133 		    free(tildename);
134 		if (tildedir)
135 		    free(tildedir);
136 		tildedir = NULL;
137 		tildename = savestr(scrbuf);
138 #ifdef HAS_GETPWENT	/* getpwnam() is not the paragon of efficiency */
139 		{
140 		    struct passwd* pwd = getpwnam(tildename);
141 		    if (pwd == NULL) {
142 			printf("%s is an unknown user. Using default.\n",tildename) FLUSH;
143 			return NULL;
144 		    }
145 		    sprintf(scrbuf,"%s%s",pwd->pw_dir,s);
146 		    tildedir = savestr(pwd->pw_dir);
147 		    strcpy(filename,scrbuf);
148 		    endpwent();
149 		}
150 #else			/* this will run faster, and is less D space */
151 		{	/* just be sure LOGDIRFIELD is correct */
152 		    FILE* pfp = fopen(filexp(PASSFILE),"r");
153 		    char tmpbuf[512];
154 		    int i;
155 
156 		    if (pfp) {
157 			while (fgets(tmpbuf,512,pfp) != NULL) {
158 			    d = cpytill(scrbuf,tmpbuf,':');
159 #ifdef DEBUG
160 			    if (debug & DEB_FILEXP)
161 				printf("p %s\n",tmpbuf) FLUSH;
162 #endif
163 			    if (strEQ(scrbuf,tildename)) {
164 				for (i=LOGDIRFIELD-2; i; i--) {
165 				    if (d)
166 					d = index(d+1,':');
167 				}
168 				if (d) {
169 				    cpytill(scrbuf,d+1,':');
170 				    tildedir = savestr(scrbuf);
171 				    strcat(scrbuf,s);
172 				    strcpy(filename,scrbuf);
173 				}
174 				break;
175 			    }
176 			}
177 			fclose(pfp);
178 		    }
179 		    if (!tildedir) {
180 			printf("%s is an unknown user. Using default.\n",tildename) FLUSH;
181 			return NULL;
182 		    }
183 		}
184 #endif
185 	    }
186 #else /* !TILDENAME */
187 #ifdef VERBOSE
188 	    IF(verbose)
189 		fputs("~loginname not implemented.\n",stdout) FLUSH;
190 	    ELSE
191 #endif
192 #ifdef TERSE
193 		fputs("~login not impl.\n",stdout) FLUSH;
194 #endif
195 #endif
196 	}
197     }
198     else if (*s == '$') {	/* starts with some env variable? */
199 	d = scrbuf;
200 	*d++ = '%';
201 	if (s[1] == '{')
202 	    strcpy(d,s+2);
203 	else {
204 	    *d++ = '{';
205 	    for (s++; isalnum(*s); s++) *d++ = *s;
206 				/* skip over token */
207 	    *d++ = '}';
208 	    strcpy(d,s);
209 	}
210 #ifdef DEBUG
211 	if (debug & DEB_FILEXP)
212 	    printf("$ %s\n",scrbuf) FLUSH;
213 #endif
214 	/* this might do some extra '%'s, but that's how the Mercedes Benz */
215 	dointerp(filename,sizeof filename,scrbuf,(char*)NULL,(char*)NULL);
216     }
217 #ifdef DEBUG
218     if (debug & DEB_FILEXP)
219 	printf("> %s\n",filename) FLUSH;
220 #endif
221     return filename;
222 }
223 
224 /* return ptr to little string in big string, NULL if not found */
225 
226 char*
instr(big,little,case_matters)227 instr(big, little, case_matters)
228 char* big;
229 char* little;
230 bool_int case_matters;
231 {
232     register char* t;
233     register char* s;
234     register char* x;
235 
236     for (t = big; *t; t++) {
237 	for (x=t,s=little; *s; x++,s++) {
238 	    if (!*x)
239 		return NULL;
240 	    if (case_matters == TRUE) {
241 		if (*s != *x)
242 		    break;
243 	    } else {
244 		register char c,d;
245 		if (isupper(*s))
246 		    c = tolower(*s);
247 		else
248 		    c = *s;
249 		if (isupper(*x))
250 		    d = tolower(*x);
251 		else
252 		    d = *x;
253 		if ( c != d )
254 		    break;
255 	   }
256 	}
257 	if (!*s)
258 	    return t;
259     }
260     return NULL;
261 }
262 
263 #ifndef HAS_STRCASECMP
264 static Uchar casemap[256] = {
265     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
266     0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
267     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
268     0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
269     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
270     0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
271     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
272     0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
273     0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
274     0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
275     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
276     0x78,0x79,0x7A,0x7B,0x5C,0x5D,0x5E,0x5F,
277     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
278     0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
279     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
280     0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
281     0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
282     0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
283     0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
284     0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
285     0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
286     0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
287     0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
288     0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
289     0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
290     0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
291     0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
292     0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
293     0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
294     0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
295     0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
296     0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
297 };
298 #endif
299 
300 #ifndef HAS_STRCASECMP
301 int
trn_casecmp(s1,s2)302 trn_casecmp(s1, s2)
303 register char* s1;
304 register char* s2;
305 {
306     do {
307 	if (casemap[(Uchar)*s1++] != casemap[(Uchar)*s2])
308 	    return casemap[(Uchar)s1[-1]] - casemap[(Uchar)*s2];
309     } while (*s2++ != '\0');
310     return 0;
311 }
312 #endif
313 
314 #ifndef HAS_STRCASECMP
315 int
trn_ncasecmp(s1,s2,len)316 trn_ncasecmp(s1, s2, len)
317 register char* s1;
318 register char* s2;
319 register int len;
320 {
321     while (len--) {
322 	if (casemap[(Uchar)*s1++] != casemap[(Uchar)*s2])
323 	    return casemap[(Uchar)s1[-1]] - casemap[(Uchar)*s2];
324 	if (*s2++ == '\0')
325 	    break;
326     }
327     return 0;
328 }
329 #endif
330 
331 #ifdef SUPPORT_NNTP
332 char*
read_auth_file(file,pass_ptr)333 read_auth_file(file, pass_ptr)
334 char* file;
335 char** pass_ptr;
336 {
337     FILE* fp;
338     char* strptr[2];
339     char buf[1024];
340     strptr[0] = strptr[1] = NULL;
341     if ((fp = fopen(file,"r")) != NULL) {
342 	int i;
343 	for (i = 0; i < 2; i++) {
344 	    if (fgets(buf, sizeof buf, fp) != NULL) {
345 		char* cp = buf + strlen(buf) - 1;
346 		if (*cp == '\n')
347 		    *cp = '\0';
348 		strptr[i] = savestr(buf);
349 	    }
350 	}
351 	fclose(fp);
352     }
353     *pass_ptr = strptr[1];
354     return strptr[0];
355 }
356 #endif
357 
358 #ifdef MSDOS
359 int
ChDir(path)360 ChDir(path)
361 char* path;
362 {
363     if (isalpha(*path) && path[1] == ':') {
364 	setdisk(path[0]&0x1f);
365 	path += 2;
366     }
367 #undef chdir
368     return chdir(path);
369 }
370 #endif
371 
372 #ifdef MSDOS
373 int
getuid()374 getuid()
375 {
376     return 2;
377 }
378 #endif
379