xref: /original-bsd/usr.sbin/sendmail/src/util.c (revision 8208c1e2)
1 # include <stdio.h>
2 # include <sys/types.h>
3 # include <sys/stat.h>
4 # include <sysexits.h>
5 # include "useful.h"
6 # include <ctype.h>
7 
8 SCCSID(@(#)util.c	3.14		03/20/82);
9 
10 /*
11 **  STRIPQUOTES -- Strip quotes & quote bits from a string.
12 **
13 **	Runs through a string and strips off unquoted quote
14 **	characters and quote bits.  This is done in place.
15 **
16 **	Parameters:
17 **		s -- the string to strip.
18 **		qf -- if set, remove actual `` " '' characters
19 **			as well as the quote bits.
20 **
21 **	Returns:
22 **		none.
23 **
24 **	Side Effects:
25 **		none.
26 **
27 **	Called By:
28 **		deliver
29 */
30 
31 stripquotes(s, qf)
32 	char *s;
33 	bool qf;
34 {
35 	register char *p;
36 	register char *q;
37 	register char c;
38 
39 	if (s == NULL)
40 		return;
41 
42 	for (p = q = s; (c = *p++) != '\0'; )
43 	{
44 		if (c != '"' || !qf)
45 			*q++ = c & 0177;
46 	}
47 	*q = '\0';
48 }
49 /*
50 **  CAPITALIZE -- return a copy of a string, properly capitalized.
51 **
52 **	Parameters:
53 **		s -- the string to capitalize.
54 **
55 **	Returns:
56 **		a pointer to a properly capitalized string.
57 **
58 **	Side Effects:
59 **		none.
60 */
61 
62 char *
63 capitalize(s)
64 	register char *s;
65 {
66 	static char buf[50];
67 	register char *p;
68 
69 	p = buf;
70 
71 	for (;;)
72 	{
73 		while (!isalpha(*s) && *s != '\0')
74 			*p++ = *s++;
75 		if (*s == '\0')
76 			break;
77 		*p++ = toupper(*s++);
78 		while (isalpha(*s))
79 			*p++ = *s++;
80 	}
81 
82 	*p = '\0';
83 	return (buf);
84 }
85 /*
86 **  XALLOC -- Allocate memory and bitch wildly on failure.
87 **
88 **	THIS IS A CLUDGE.  This should be made to give a proper
89 **	error -- but after all, what can we do?
90 **
91 **	Parameters:
92 **		sz -- size of area to allocate.
93 **
94 **	Returns:
95 **		pointer to data region.
96 **
97 **	Side Effects:
98 **		Memory is allocated.
99 */
100 
101 char *
102 xalloc(sz)
103 	register unsigned int sz;
104 {
105 	register char *p;
106 
107 	p = malloc(sz);
108 	if (p == NULL)
109 	{
110 		syserr("Out of memory!!");
111 		exit(EX_UNAVAILABLE);
112 	}
113 	return (p);
114 }
115 /*
116 **  NEWSTR -- make copy of string.
117 **
118 **	Space is allocated for it using xalloc.
119 **
120 **	Parameters:
121 **		string to copy.
122 **
123 **	Returns:
124 **		pointer to new string.
125 **
126 **	Side Effects:
127 **		none.
128 */
129 
130 char *
131 newstr(s)
132 	register char *s;
133 {
134 	register char *p;
135 
136 	p = xalloc((unsigned) (strlen(s) + 1));
137 	strcpy(p, s);
138 	return (p);
139 }
140 /*
141 **  COPYPLIST -- copy list of pointers.
142 **
143 **	This routine is the equivalent of newstr for lists of
144 **	pointers.
145 **
146 **	Parameters:
147 **		list -- list of pointers to copy.
148 **			Must be NULL terminated.
149 **		copycont -- if TRUE, copy the contents of the vector
150 **			(which must be a string) also.
151 **
152 **	Returns:
153 **		a copy of 'list'.
154 **
155 **	Side Effects:
156 **		none.
157 */
158 
159 char **
160 copyplist(list, copycont)
161 	char **list;
162 	bool copycont;
163 {
164 	register char **vp;
165 	register char **newvp;
166 
167 	for (vp = list; *vp != NULL; vp++)
168 		continue;
169 
170 	vp++;
171 
172 	newvp = (char **) xalloc((unsigned) (vp - list) * sizeof *vp);
173 	bmove((char *) list, (char *) newvp, (vp - list) * sizeof *vp);
174 
175 	if (copycont)
176 	{
177 		for (vp = newvp; *vp != NULL; vp++)
178 			*vp = newstr(*vp);
179 	}
180 
181 	return (newvp);
182 }
183 /*
184 **  PRINTAV -- print argument vector.
185 **
186 **	Parameters:
187 **		av -- argument vector.
188 **
189 **	Returns:
190 **		none.
191 **
192 **	Side Effects:
193 **		prints av.
194 */
195 
196 # ifdef DEBUG
197 printav(av)
198 	register char **av;
199 {
200 	while (*av != NULL)
201 	{
202 		printf("\t%08x=", *av);
203 		xputs(*av++);
204 		putchar('\n');
205 	}
206 }
207 # endif DEBUG
208 /*
209 **  LOWER -- turn letter into lower case.
210 **
211 **	Parameters:
212 **		c -- character to turn into lower case.
213 **
214 **	Returns:
215 **		c, in lower case.
216 **
217 **	Side Effects:
218 **		none.
219 */
220 
221 char
222 lower(c)
223 	register char c;
224 {
225 	if (isascii(c) && isupper(c))
226 		c = c - 'A' + 'a';
227 	return (c);
228 }
229 /*
230 **  XPUTS -- put string doing control escapes.
231 **
232 **	Parameters:
233 **		s -- string to put.
234 **
235 **	Returns:
236 **		none.
237 **
238 **	Side Effects:
239 **		output to stdout
240 */
241 
242 # ifdef DEBUG
243 xputs(s)
244 	register char *s;
245 {
246 	register char c;
247 
248 	while ((c = *s++) != '\0')
249 	{
250 		if (!isascii(c))
251 		{
252 			putchar('\\');
253 			c &= 0177;
254 		}
255 		if (iscntrl(c))
256 		{
257 			putchar('^');
258 			c |= 0100;
259 		}
260 		putchar(c);
261 	}
262 	(void) fflush(stdout);
263 }
264 # endif DEBUG
265 /*
266 **  MAKELOWER -- Translate a line into lower case
267 **
268 **	Parameters:
269 **		p -- the string to translate.  If NULL, return is
270 **			immediate.
271 **
272 **	Returns:
273 **		none.
274 **
275 **	Side Effects:
276 **		String pointed to by p is translated to lower case.
277 **
278 **	Called By:
279 **		parse
280 */
281 
282 makelower(p)
283 	register char *p;
284 {
285 	register char c;
286 
287 	if (p == NULL)
288 		return;
289 	for (; (c = *p) != '\0'; p++)
290 		if (isascii(c) && isupper(c))
291 			*p = c - 'A' + 'a';
292 }
293 /*
294 **  SAMEWORD -- return TRUE if the words are the same
295 **
296 **	Ignores case.
297 **
298 **	Parameters:
299 **		a, b -- the words to compare.
300 **
301 **	Returns:
302 **		TRUE if a & b match exactly (modulo case)
303 **		FALSE otherwise.
304 **
305 **	Side Effects:
306 **		none.
307 */
308 
309 bool
310 sameword(a, b)
311 	register char *a, *b;
312 {
313 	while (lower(*a) == lower(*b))
314 	{
315 		if (*a == '\0')
316 			return (TRUE);
317 		a++;
318 		b++;
319 	}
320 	return (FALSE);
321 }
322 /*
323 **  CLEAR -- clear a block of memory
324 **
325 **	Parameters:
326 **		p -- location to clear.
327 **		l -- number of bytes to clear.
328 **
329 **	Returns:
330 **		none.
331 **
332 **	Side Effects:
333 **		none.
334 */
335 
336 clear(p, l)
337 	register char *p;
338 	register int l;
339 {
340 	while (l-- > 0)
341 		*p++ = 0;
342 }
343 /*
344 **  BUILDFNAME -- build full name from gecos style entry.
345 **
346 **	This routine interprets the strange entry that would appear
347 **	in the GECOS field of the password file.
348 **
349 **	Parameters:
350 **		p -- name to build.
351 **		login -- the login name of this user (for &).
352 **		buf -- place to put the result.
353 **
354 **	Returns:
355 **		none.
356 **
357 **	Side Effects:
358 **		none.
359 */
360 
361 buildfname(p, login, buf)
362 	register char *p;
363 	char *login;
364 	char *buf;
365 {
366 	register char *bp = buf;
367 
368 	if (*p == '*')
369 		p++;
370 	while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
371 	{
372 		if (*p == '&')
373 		{
374 			(void) strcpy(bp, login);
375 			*bp = toupper(*bp);
376 			while (*bp != '\0')
377 				bp++;
378 			p++;
379 		}
380 		else
381 			*bp++ = *p++;
382 	}
383 	*bp = '\0';
384 }
385 /*
386 **  SAFEFILE -- return true if a file exists and is safe for a user.
387 **
388 **	Parameters:
389 **		fn -- filename to check.
390 **		uid -- uid to compare against.
391 **		mode -- mode bits that must match.
392 **
393 **	Returns:
394 **		TRUE if fn exists, is owned by uid, and matches mode.
395 **		FALSE otherwise.
396 **
397 **	Side Effects:
398 **		none.
399 */
400 
401 bool
402 safefile(fn, uid, mode)
403 	char *fn;
404 	int uid;
405 	int mode;
406 {
407 	struct stat stbuf;
408 
409 	if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
410 	    (stbuf.st_mode & mode) == mode)
411 		return (TRUE);
412 	return (FALSE);
413 }
414 /*
415 **  FIXCRLF -- fix <CR><LF> in line.
416 **
417 **	Looks for the <CR><LF> combination and turns it into the
418 **	UNIX canonical <NL> character.  It only takes one line,
419 **	i.e., it is assumed that the first <NL> found is the end
420 **	of the line.
421 **
422 **	Parameters:
423 **		line -- the line to fix.
424 **		stripnl -- if true, strip the newline also.
425 **
426 **	Returns:
427 **		none.
428 **
429 **	Side Effects:
430 **		line is changed in place.
431 */
432 
433 fixcrlf(line, stripnl)
434 	char *line;
435 	bool stripnl;
436 {
437 	register char *p;
438 
439 	p = index(line, '\n');
440 	if (p == NULL)
441 		return;
442 	if (p[-1] == '\r')
443 		p--;
444 	if (!stripnl)
445 		*p++ = '\n';
446 	*p = '\0';
447 }
448 /*
449 **  SYSLOG -- fake entry to fool lint
450 */
451 
452 # ifdef LOG
453 # ifdef lint
454 
455 /*VARARGS2*/
456 syslog(pri, fmt, args)
457 	int pri;
458 	char *fmt;
459 {
460 	pri = *fmt;
461 	args = pri;
462 	pri = args;
463 }
464 
465 # endif lint
466 # endif LOG
467