1 /*
2  * Everything that im not directly responsible for i put in here.  Almost
3  * all of this stuff is either borrowed from somewhere else (for those poor
4  * saps that dont have something you need), or i wrote (and put into the
5  * public domain) in order to make epic compile on some of the more painful
6  * systems.  None of this is part of EPIC-proper, so dont feel that youre
7  * going to hurt my feelings if you re-use this.
8  */
9 
10 #include "defs.h"
11 #include "ircaux.h"
12 #include "irc_std.h"
13 #define MAIN_SOURCE
14 #include "modval.h"
15 
16 
17 /* --- start of tparm.c --- */
18 #ifndef HAVE_TPARM
19 /*
20  * tparm.c
21  *
22  * By Ross Ridge
23  * Public Domain
24  * 92/02/01 07:30:36
25  *
26  */
27 #include <ctype.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31 
32 #ifndef MAX_PUSHED
33 #define MAX_PUSHED	32
34 #endif
35 
36 #define ARG	1
37 #define NUM	2
38 
39 #define INTEGER	1
40 #define STRING	2
41 
42 #define MAX_LINE 640
43 
44 typedef void* anyptr;
45 
46 typedef struct stack_str {
47 	int	type;
48 	int	argnum;
49 	int	value;
50 } stack;
51 
52 static stack S[MAX_PUSHED];
53 static stack vars['z'-'a'+1];
54 static int pos = 0;
55 
56 static struct arg_str {
57 	int type;
58 	int	integer;
59 	char	*string;
60 } arg_list[10];
61 
62 static int argcnt;
63 
64 static va_list tparm_args;
65 
pusharg(int arg)66 static int pusharg(int arg)
67 {
68 	if (pos == MAX_PUSHED)
69 		return 1;
70 	S[pos].type = ARG;
71 	S[pos++].argnum = arg;
72 	return 0;
73 }
74 
pushnum(int num)75 static int pushnum(int num)
76 {
77 	if (pos == MAX_PUSHED)
78 		return 1;
79 	S[pos].type = NUM;
80 	S[pos++].value = num;
81 	return 0;
82 }
83 
84 /* VARARGS2 */
getarg(int argnum,int type,anyptr p)85 static int getarg(int argnum, int type, anyptr p)
86 {
87 	while (argcnt < argnum) {
88 		arg_list[argcnt].type = INTEGER;
89 		arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
90 	}
91 	if (argcnt > argnum) {
92 		if (arg_list[argnum].type != type)
93 			return 1;
94 		else if (type == STRING)
95 			*(char **)p = arg_list[argnum].string;
96 		else
97 			*(int *)p = arg_list[argnum].integer;
98 	} else {
99 		arg_list[argcnt].type = type;
100 		if (type == STRING)
101 			*(char **)p = arg_list[argcnt++].string
102 				= (char *) va_arg(tparm_args, char *);
103 		else
104 			*(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
105 	}
106 	return 0;
107 }
108 
109 
popstring(char ** str)110 static int popstring(char **str)
111 {
112 	if (pos-- == 0)
113 		return 1;
114 	if (S[pos].type != ARG)
115 		return 1;
116 	return(getarg(S[pos].argnum, STRING, (anyptr) str));
117 }
118 
popnum(int * num)119 static int popnum(int *num)
120 {
121 	if (pos-- == 0)
122 		return 1;
123 	switch (S[pos].type) {
124 	case ARG:
125 		return (getarg(S[pos].argnum, INTEGER, (anyptr) num));
126 	case NUM:
127 		*num = S[pos].value;
128 		return 0;
129 	}
130 	return 1;
131 }
132 
cvtchar(const char * sp,char * c)133 static int cvtchar(const char *sp, char *c)
134 {
135 	switch(*sp) {
136 	case '\\':
137 		switch(*++sp) {
138 		case '\'':
139 		case '$':
140 		case '\\':
141 		case '%':
142 			*c = *sp;
143 			return 2;
144 		case '\0':
145 			*c = '\\';
146 			return 1;
147 		case '0':
148 			if (sp[1] == '0' && sp[2] == '0') {
149 				*c = '\0';
150 				return 4;
151 			}
152 			*c = '\200'; /* '\0' ???? */
153 			return 2;
154 		default:
155 			*c = *sp;
156 			return 2;
157 		}
158 	default:
159 		*c = *sp;
160 		return 1;
161 	}
162 }
163 
164 static int termcap;
165 
166 /* sigh... this has got to be the ugliest code I've ever written.
167    Trying to handle everything has its cost, I guess.
168 
169    It actually isn't to hard to figure out if a given % code is supposed
170    to be interpeted with its termcap or terminfo meaning since almost
171    all terminfo codes are invalid unless something has been pushed on
172    the stack and termcap strings will never push things on the stack
173    (%p isn't used by termcap). So where we have a choice we make the
174    decision by wether or not somthing has been pushed on the stack.
175    The static variable termcap keeps track of this; it starts out set
176    to 1 and is incremented as each argument processed by a termcap % code,
177    however if something is pushed on the stack it's set to 0 and the
178    rest of the % codes are interpeted as terminfo % codes. Another way
179    of putting it is that if termcap equals one we haven't decided either
180    way yet, if it equals zero we're looking for terminfo codes, and if
181    its greater than 1 we're looking for termcap codes.
182 
183    Terminfo % codes:
184 
185 	%%	output a '%'
186 	%[[:][-+# ][width][.precision]][doxXs]
187 		output pop according to the printf format
188 	%c	output pop as a char
189 	%'c'	push character constant c.
190 	%{n}	push decimal constant n.
191 	%p[1-9] push paramter [1-9]
192 	%g[a-z] push variable [a-z]
193 	%P[a-z] put pop in variable [a-z]
194 	%l	push the length of pop (a string)
195 	%+	add pop to pop and push the result
196 	%-	subtract pop from pop and push the result
197 	%*	multiply pop and pop and push the result
198 	%&	bitwise and pop and pop and push the result
199 	%|	bitwise or pop and pop and push the result
200 	%^	bitwise xor pop and pop and push the result
201 	%~	push the bitwise not of pop
202 	%=	compare if pop and pop are equal and push the result
203 	%>	compare if pop is less than pop and push the result
204 	%<	compare if pop is greater than pop and push the result
205 	%A	logical and pop and pop and push the result
206 	%O	logical or pop and pop and push the result
207 	%!	push the logical not of pop
208 	%? condition %t if_true [%e if_false] %;
209 		if condtion evaulates as true then evaluate if_true,
210 		else evaluate if_false. elseif's can be done:
211 %? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
212 	%i	add one to parameters 1 and 2. (ANSI)
213 
214   Termcap Codes:
215 
216 	%%	output a %
217 	%.	output parameter as a character
218 	%d	kutput parameter as a decimal number
219 	%2	output parameter in printf format %02d
220 	%3	output parameter in printf format %03d
221 	%+x	add the character x to parameter and output it as a character
222 (UW)	%-x	subtract parameter FROM the character x and output it as a char
223 (UW)	%ax	add the character x to parameter
224 (GNU)	%a[+*-/=][cp]x
225 		GNU arithmetic.
226 (UW)	%sx	subtract parameter FROM the character x
227 	%>xy	if parameter > character x then add character y to parameter
228 	%B	convert to BCD (parameter = (parameter/10)*16 + parameter%16)
229 	%D	Delta Data encode (parameter = parameter - 2*(paramter%16))
230 	%i	increment the first two parameters by one
231 	%n	xor the first two parameters by 0140
232 (GNU)	%m	xor the first two parameters by 0177
233 	%r	swap the first two parameters
234 (GNU)	%b	backup to previous parameter
235 (GNU)	%f	skip this parameter
236 
237   Note the two definitions of %a, the GNU defintion is used if the characters
238   after the 'a' are valid, otherwise the UW definition is used.
239 
240   (GNU) used by GNU Emacs termcap libraries
241   (UW) used by the University of Waterloo (MFCF) termcap libraries
242 
243 */
244 
tparm(const char * str,...)245 char *tparm(const char *str, ...) {
246 	static char OOPS[] = "OOPS";
247 	static char buf[MAX_LINE];
248 	register const char *sp;
249 	register char *dp;
250 	register char *fmt;
251 	char conv_char;
252 	char scan_for;
253 	int scan_depth = 0, if_depth;
254 	static int i, j;
255 	static char *s, c;
256 	char fmt_buf[MAX_LINE];
257 	char sbuf[MAX_LINE];
258 	if (!str)
259 		return NULL;
260 	va_start(tparm_args, str);
261 
262 	sp = str;
263 	dp = buf;
264 	scan_for = 0;
265 	if_depth = 0;
266 	argcnt = 0;
267 	pos = 0;
268 	termcap = 1;
269 	while(*sp != '\0') {
270 		switch(*sp) {
271 		case '\\':
272 			if (scan_for) {
273 				if (*++sp != '\0')
274 					sp++;
275 				break;
276 			}
277 			*dp++ = *sp++;
278 			if (*sp != '\0')
279 				*dp++ = *sp++;
280 			break;
281 		case '%':
282 			sp++;
283 			if (scan_for) {
284 				if (*sp == scan_for && if_depth == scan_depth) {
285 					if (scan_for == ';')
286 						if_depth--;
287 					scan_for = 0;
288 				} else if (*sp == '?')
289 					if_depth++;
290 				else if (*sp == ';') {
291 					if (if_depth == 0)
292 						return OOPS;
293 					else
294 						if_depth--;
295 				}
296 				sp++;
297 				break;
298 			}
299 			fmt = NULL;
300 			switch(*sp) {
301 			case '%':
302 				*dp++ = *sp++;
303 				break;
304 			case '+':
305 				if (!termcap) {
306 					if (popnum(&j) || popnum(&i))
307 						return OOPS;
308 					i += j;
309 					if (pushnum(i))
310 						return OOPS;
311 					sp++;
312 					break;
313 				}
314 				;/* FALLTHROUGH */
315 			case 'C':
316 				if (*sp == 'C') {
317 					if (getarg(termcap - 1, INTEGER, &i))
318 						return OOPS;
319 					if (i >= 96) {
320 						i /= 96;
321 						if (i == '$')
322 							*dp++ = '\\';
323 						*dp++ = i;
324 					}
325 				}
326 				fmt = "%c";
327 				/* FALLTHROUGH */
328 			case 'a':
329 				if (!termcap)
330 					return OOPS;
331 				if (getarg(termcap - 1, INTEGER, (anyptr) &i))
332 					return OOPS;
333 				if (*++sp == '\0')
334 					return OOPS;
335 				if ((sp[1] == 'p' || sp[1] == 'c')
336 			            && sp[2] != '\0' && fmt == NULL) {
337 					/* GNU aritmitic parameter, what they
338 					   realy need is terminfo.	      */
339 					int val, lc;
340 					if (sp[1] == 'p'
341 					    && getarg(termcap - 1 + sp[2] - '@',
342 						      INTEGER, (anyptr) &val))
343 						return OOPS;
344 					if (sp[1] == 'c') {
345 						lc = cvtchar(sp + 2, &c) + 2;
346 					/* Mask out 8th bit so \200 can be
347 					   used for \0 as per GNU doc's    */
348 						val = c & 0177;
349 					} else
350 						lc = 2;
351 					switch(sp[0]) {
352 					case '=':
353 						break;
354 					case '+':
355 						val = i + val;
356 						break;
357 					case '-':
358 						val = i - val;
359 						break;
360 					case '*':
361 						val = i * val;
362 						break;
363 					case '/':
364 						val = i / val;
365 						break;
366 					default:
367 					/* Not really GNU's %a after all... */
368 						lc = cvtchar(sp, &c);
369 						val = c + i;
370 						break;
371 					}
372 					arg_list[termcap - 1].integer = val;
373 					sp += lc;
374 					break;
375 				}
376 				sp += cvtchar(sp, &c);
377 				arg_list[termcap - 1].integer = c + i;
378 				if (fmt == NULL)
379 					break;
380 				sp--;
381 				/* FALLTHROUGH */
382 			case '-':
383 				if (!termcap) {
384 					if (popnum(&j) || popnum(&i))
385 						return OOPS;
386 					i -= j;
387 					if (pushnum(i))
388 						return OOPS;
389 					sp++;
390 					break;
391 				}
392 				fmt = "%c";
393 				/* FALLTHROUGH */
394 			case 's':
395 				if (termcap && (fmt == NULL || *sp == '-')) {
396 					if (getarg(termcap - 1, INTEGER, &i))
397 						return OOPS;
398 					if (*++sp == '\0')
399 						return OOPS;
400 					sp += cvtchar(sp, &c);
401 					arg_list[termcap - 1].integer = c - i;
402 					if (fmt == NULL)
403 						break;
404 					sp--;
405 				}
406 				if (!termcap)
407 					return OOPS;
408 				;/* FALLTHROUGH */
409 			case '.':
410 				if (termcap && fmt == NULL)
411 					fmt = "%c";
412 				;/* FALLTHROUGH */
413 			case 'd':
414 				if (termcap && fmt == NULL)
415 					fmt = "%d";
416 				;/* FALLTHROUGH */
417 			case '2':
418 				if (termcap && fmt == NULL)
419 					fmt = "%02d";
420 				;/* FALLTHROUGH */
421 			case '3':
422 				if (termcap && fmt == NULL)
423 					fmt = "%03d";
424 				;/* FALLTHROUGH */
425 			case ':': case ' ': case '#': case 'u':
426 			case 'x': case 'X': case 'o': case 'c':
427 			case '0': case '1': case '4': case '5':
428 			case '6': case '7': case '8': case '9':
429 				if (fmt == NULL) {
430 					if (termcap)
431 						return OOPS;
432 					if (*sp == ':')
433 						sp++;
434 					fmt = fmt_buf;
435 					*fmt++ = '%';
436 					while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') {
437 						if (*sp == '\0')
438 							return OOPS;
439 						*fmt++ = *sp++;
440 					}
441 					*fmt++ = *sp;
442 					*fmt = '\0';
443 					fmt = fmt_buf;
444 				}
445 				conv_char = fmt[strlen(fmt) - 1];
446 				if (conv_char == 's') {
447 					if (popstring(&s))
448 						return OOPS;
449 					sprintf(sbuf, fmt, s);
450 				} else {
451 					if (termcap) {
452 						if (getarg(termcap++ - 1,
453 							   INTEGER, &i))
454 							return OOPS;
455 					} else
456 						if (popnum(&i))
457 							return OOPS;
458 					if (i == 0 && conv_char == 'c')
459 						*sbuf = 0;
460 					else
461 						sprintf(sbuf, fmt, i);
462 				}
463 				sp++;
464 				fmt = sbuf;
465 				while(*fmt != '\0') {
466 					if (*fmt == '$')
467 						*dp++ = '\\';
468 					*dp++ = *fmt++;
469 				}
470 				break;
471 			case 'r':
472 				if (!termcap || getarg(1, INTEGER, &i))
473 					return OOPS;
474 				arg_list[1].integer = arg_list[0].integer;
475 				arg_list[0].integer = i;
476 				sp++;
477 				break;
478 			case 'i':
479 				if (getarg(1, INTEGER, &i)
480 				    || arg_list[0].type != INTEGER)
481 					return OOPS;
482 				arg_list[1].integer++;
483 				arg_list[0].integer++;
484 				sp++;
485 				break;
486 			case 'n':
487 				if (!termcap || getarg(1, INTEGER, &i))
488 					return OOPS;
489 				arg_list[0].integer ^= 0140;
490 				arg_list[1].integer ^= 0140;
491 				sp++;
492 				break;
493 			case '>':
494 				if (!termcap) {
495 					if (popnum(&j) || popnum(&i))
496 						return OOPS;
497 					i = (i > j);
498 					if (pushnum(i))
499 						return OOPS;
500 					sp++;
501 					break;
502 				}
503 				if (getarg(termcap-1, INTEGER, &i))
504 					return OOPS;
505 				sp += cvtchar(sp, &c);
506 				if (i > c) {
507 					sp += cvtchar(sp, &c);
508 					arg_list[termcap-1].integer += c;
509 				} else
510 					sp += cvtchar(sp, &c);
511 				sp++;
512 				break;
513 			case 'B':
514 				if (!termcap || getarg(termcap-1, INTEGER, &i))
515 					return OOPS;
516 				arg_list[termcap-1].integer = 16*(i/10)+i%10;
517 				sp++;
518 				break;
519 			case 'D':
520 				if (!termcap || getarg(termcap-1, INTEGER, &i))
521 					return OOPS;
522 				arg_list[termcap-1].integer = i - 2 * (i % 16);
523 				sp++;
524 				break;
525 			case 'p':
526 				if (termcap > 1)
527 					return OOPS;
528 				if (*++sp == '\0')
529 					return OOPS;
530 				if (*sp == '0')
531 					i = 9;
532 				else
533 					i = *sp - '1';
534 				if (i < 0 || i > 9)
535 					return OOPS;
536 				if (pusharg(i))
537 					return OOPS;
538 				termcap = 0;
539 				sp++;
540 				break;
541 			case 'P':
542 				if (termcap || *++sp == '\0')
543 					return OOPS;
544 				i = *sp++ - 'a';
545 				if (i < 0 || i > 25)
546 					return OOPS;
547 				if (pos-- == 0)
548 					return OOPS;
549 				switch(vars[i].type = S[pos].type) {
550 				case ARG:
551 					vars[i].argnum = S[pos].argnum;
552 					break;
553 				case NUM:
554 					vars[i].value = S[pos].value;
555 					break;
556 				}
557 				break;
558 			case 'g':
559 				if (termcap || *++sp == '\0')
560 					return OOPS;
561 				i = *sp++ - 'a';
562 				if (i < 0 || i > 25)
563 					return OOPS;
564 				switch(vars[i].type) {
565 				case ARG:
566 					if (pusharg(vars[i].argnum))
567 						return OOPS;
568 					break;
569 				case NUM:
570 					if (pushnum(vars[i].value))
571 						return OOPS;
572 					break;
573 				}
574 				break;
575 			case '\'':
576 				if (termcap > 1)
577 					return OOPS;
578 				if (*++sp == '\0')
579 					return OOPS;
580 				sp += cvtchar(sp, &c);
581 				if (pushnum(c) || *sp++ != '\'')
582 					return OOPS;
583 				termcap = 0;
584 				break;
585 			case '{':
586 				if (termcap > 1)
587 					return OOPS;
588 				i = 0;
589 				sp++;
590 				while(isdigit((unsigned char)*sp))
591 					i = 10 * i + *sp++ - '0';
592 				if (*sp++ != '}' || pushnum(i))
593 					return OOPS;
594 				termcap = 0;
595 				break;
596 			case 'l':
597 				if (termcap || popstring(&s))
598 					return OOPS;
599 				i = strlen(s);
600 				if (pushnum(i))
601 					return OOPS;
602 				sp++;
603 				break;
604 			case '*':
605 				if (termcap || popnum(&j) || popnum(&i))
606 					return OOPS;
607 				i *= j;
608 				if (pushnum(i))
609 					return OOPS;
610 				sp++;
611 				break;
612 			case '/':
613 				if (termcap || popnum(&j) || popnum(&i))
614 					return OOPS;
615 				i /= j;
616 				if (pushnum(i))
617 					return OOPS;
618 				sp++;
619 				break;
620 			case 'm':
621 				if (termcap) {
622 					if (getarg(1, INTEGER, &i))
623 						return OOPS;
624 					arg_list[0].integer ^= 0177;
625 					arg_list[1].integer ^= 0177;
626 					sp++;
627 					break;
628 				}
629 				if (popnum(&j) || popnum(&i))
630 					return OOPS;
631 				i %= j;
632 				if (pushnum(i))
633 					return OOPS;
634 				sp++;
635 				break;
636 			case '&':
637 				if (popnum(&j) || popnum(&i))
638 					return OOPS;
639 				i &= j;
640 				if (pushnum(i))
641 					return OOPS;
642 				sp++;
643 				break;
644 			case '|':
645 				if (popnum(&j) || popnum(&i))
646 					return OOPS;
647 				i |= j;
648 				if (pushnum(i))
649 					return OOPS;
650 				sp++;
651 				break;
652 			case '^':
653 				if (popnum(&j) || popnum(&i))
654 					return OOPS;
655 				i ^= j;
656 				if (pushnum(i))
657 					return OOPS;
658 				sp++;
659 				break;
660 			case '=':
661 				if (popnum(&j) || popnum(&i))
662 					return OOPS;
663 				i = (i == j);
664 				if (pushnum(i))
665 					return OOPS;
666 				sp++;
667 				break;
668 			case '<':
669 				if (popnum(&j) || popnum(&i))
670 					return OOPS;
671 				i = (i < j);
672 				if (pushnum(i))
673 					return OOPS;
674 				sp++;
675 				break;
676 			case 'A':
677 				if (popnum(&j) || popnum(&i))
678 					return OOPS;
679 				i = (i && j);
680 				if (pushnum(i))
681 					return OOPS;
682 				sp++;
683 				break;
684 			case 'O':
685 				if (popnum(&j) || popnum(&i))
686 					return OOPS;
687 				i = (i || j);
688 				if (pushnum(i))
689 					return OOPS;
690 				sp++;
691 				break;
692 			case '!':
693 				if (popnum(&i))
694 					return OOPS;
695 				i = !i;
696 				if (pushnum(i))
697 					return OOPS;
698 				sp++;
699 				break;
700 			case '~':
701 				if (popnum(&i))
702 					return OOPS;
703 				i = ~i;
704 				if (pushnum(i))
705 					return OOPS;
706 				sp++;
707 				break;
708 			case '?':
709 				if (termcap > 1)
710 					return OOPS;
711 				termcap = 0;
712 				if_depth++;
713 				sp++;
714 				break;
715 			case 't':
716 				if (popnum(&i) || if_depth == 0)
717 					return OOPS;
718 				if (!i) {
719 					scan_for = 'e';
720 					scan_depth = if_depth;
721 				}
722 				sp++;
723 				break;
724 			case 'e':
725 				if (if_depth == 0)
726 					return OOPS;
727 				scan_for = ';';
728 				scan_depth = if_depth;
729 				sp++;
730 				break;
731 			case ';':
732 				if (if_depth-- == 0)
733 					return OOPS;
734 				sp++;
735 				break;
736 			case 'b':
737 				if (--termcap < 1)
738 					return OOPS;
739 				sp++;
740 				break;
741 			case 'f':
742 				if (!termcap++)
743 					return OOPS;
744 				sp++;
745 				break;
746 			}
747 			break;
748 		default:
749 			if (scan_for)
750 				sp++;
751 			else
752 				*dp++ = *sp++;
753 			break;
754 		}
755 	}
756 	va_end(tparm_args);
757 	*dp = '\0';
758 	return buf;
759 }
760 #endif
761 /* --- end of tparm.c --- */
762 
763 /* --- start of strtoul.c --- */
764 #ifndef HAVE_STRTOUL
765 /*
766  * Copyright (c) 1990 Regents of the University of California.
767  * All rights reserved.
768  *
769  * Redistribution and use in source and binary forms, with or without
770  * modification, are permitted provided that the following conditions
771  * are met:
772  * 1. Redistributions of source code must retain the above copyright
773  *    notice, this list of conditions and the following disclaimer.
774  * 2. Redistributions in binary form must reproduce the above copyright
775  *    notice, this list of conditions and the following disclaimer in the
776  *    documentation and/or other materials provided with the distribution.
777  * 3. All advertising materials mentioning features or use of this software
778  *    must display the following acknowledgement:
779  *	This product includes software developed by the University of
780  *	California, Berkeley and its contributors.
781  * 4. Neither the name of the University nor the names of its contributors
782  *    may be used to endorse or promote products derived from this software
783  *    without specific prior written permission.
784  *
785  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
786  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
787  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
788  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
789  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
790  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
791  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
792  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
793  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
794  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
795  * SUCH DAMAGE.
796  */
797 
798 /*
799  * Convert a string to an unsigned long integer.
800  *
801  * Ignores `locale' stuff.  Assumes that the upper and lower case
802  * alphabets and digits are each contiguous.
803  */
strtoul(const char * nptr,char ** endptr,int base)804 unsigned long strtoul (const char *nptr, char **endptr, int base)
805 {
806 	const char *s;
807 	unsigned long acc, cutoff;
808 	int c;
809 	int neg, any, cutlim;
810 
811 	s = nptr;
812 	do
813 		c = *s++;
814 	while (isspace(c));
815 
816 	if (c == '-')
817 	{
818 		neg = 1;
819 		c = *s++;
820 	}
821 	else
822 	{
823 		neg = 0;
824 		if (c == '+')
825 			c = *s++;
826 	}
827 
828 	if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X'))
829 	{
830 		c = s[1];
831 		s += 2;
832 		base = 16;
833 	}
834 
835 	if (base == 0)
836 		base = c == '0' ? 8 : 10;
837 
838 #ifndef ULONG_MAX
839 #define ULONG_MAX (unsigned long) -1
840 #endif
841 
842 	cutoff = ULONG_MAX / (unsigned long)base;
843 	cutlim = ULONG_MAX % (unsigned long)base;
844 
845 	for (acc = 0, any = 0;; c = *s++)
846 	{
847 		if (isdigit(c))
848 			c -= '0';
849 		else if (isalpha(c))
850 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
851 		else
852 			break;
853 
854 		if (c >= base)
855 			break;
856 
857 		if (any < 0)
858 			continue;
859 
860 		if (acc > cutoff || acc == cutoff && c > cutlim)
861 		{
862 			any = -1;
863 			acc = ULONG_MAX;
864 			errno = ERANGE;
865 		}
866 		else
867 		{
868 			any = 1;
869 			acc *= (unsigned long)base;
870 			acc += c;
871 		}
872 	}
873 	if (neg && any > 0)
874 		acc = -acc;
875 	if (endptr != 0)
876 		*endptr = (char *) (any ? s - 1 : nptr);
877 	return (acc);
878 }
879 #endif /* DO NOT HAVE STRTOUL */
880 /* --- end of strtoul.c --- */
881 
882 /* --- start of scandir.c --- */
883 #ifndef HAVE_SCANDIR
884 /*
885  * Scandir.c -- A painful file for painful operating systems
886  *
887  * Technically, scandir is not a "standard" function.  It belongs to
888  * 4.2BSD derived systems, and most everone that has any repsect for their
889  * customers implements it sanely.  Which probably explains why its broken
890  * on Solaris 2.
891  *
892  * I removed the 4BSD scandir function because it required intimite knowledge
893  * of what was inside the DIR type, which sort of defeats the point.  What I
894  * left was this extremely generic scandir function that only depends on
895  * opendir(), readdir(), and closedir(), and perhaps the DIRSIZ macro.
896  * The only member of struct dirent we peer into is d_name.
897  *
898  * Public domain
899  */
900 
901 
902 #define RESIZEDIR(x, y, z) x = realloc((void *)(x), sizeof(y) * (z))
903 
904 /* Initial guess at directory size. */
905 #define INITIAL_SIZE	30
906 
907 typedef struct dirent DIRENT;
908 
909 /*
910  * If the system doesnt have a way to tell us how big a directory entry
911  * is, then we make a wild guess.  This shouldnt ever be SMALLER than
912  * the actual size, and if its larger, so what?  This will probably not
913  * be a size thats divisible by 4, so the memcpy() may not be super
914  * efficient.  But so what?  Any system that cant provide a decent scandir
915  * im not worried about efficiency.
916  */
917 /* The SCO hack is at the advice of FireClown, thanks! =) */
918 #if defined(_SCO_DS)
919 # undef DIRSIZ
920 #endif
921 
922 #ifndef DIRSIZ
923 #  define DIRSIZ(d) (sizeof(DIRENT) + strlen(d->d_name) + 1)
924 #endif
925 
926 
927 /*
928  * Scan the directory dirname calling select to make a list of selected
929  * directory entries then sort using qsort and compare routine dcomp. Returns
930  * the number of entries and a pointer to a list of pointers to struct direct
931  * (through namelist). Returns -1 if there were any errors.
932  */
scandir(const char * name,DIRENT *** list,int (* selector)(DIRENT *),int (* sorter)(const void *,const void *))933 int	scandir (const char *name,
934 		 DIRENT ***list,
935 		 int 	(*selector) (DIRENT *),
936 		 int 	(*sorter) (const void *, const void *))
937 {
938 		DIRENT	**names;
939 	static	DIRENT	*e;
940     		DIR	*dp;
941     		int	i;
942     		int	size = INITIAL_SIZE;
943 
944 	if (!(names = (DIRENT **)malloc(size * sizeof(DIRENT *))))
945 		return -1;
946 
947 	if (access(name, R_OK | X_OK))
948 		return -1;
949 
950 	if (!(dp = opendir(name)))
951 		return -1;
952 
953 	/* Read entries in the directory. */
954 	for (i = 0; (e = readdir(dp));)
955 	{
956 		if (!selector || (*selector)(e))
957 		{
958 			if (i + 1 >= size)
959 			{
960 				size <<= 1;
961 				RESIZEDIR(names, DIRENT *, size);
962 				if (!names)
963 				{
964 					closedir(dp);
965 					return (-1);
966 				}
967 			}
968 			names[i] = (DIRENT *)malloc(DIRSIZ(e));
969 			if (names[i] == NULL)
970 			{
971 				int j;
972 				for (j = 0; j < i; j++)
973 					free(names[j]);
974 				free(names);
975 				closedir(dp);
976 				return -1;
977 			}
978 			memcpy(names[i], e, DIRSIZ(e));
979 			i++;
980 		}
981 	}
982 
983 	/*
984 	 * Truncate the "names" array down to its actual size (why?)
985 	 */
986 	RESIZEDIR(names, DIRENT *, i + 2);
987 	names[i + 1] = 0;
988 	*list = names;
989 	closedir(dp);
990 
991 	/*
992 	 * Sort if neccesary...
993 	 */
994 	if (i && sorter)
995 		qsort(names, i, sizeof(DIRENT *), sorter);
996 
997 	return i;
998 }
999 #endif
1000 /* --- end of scandir.c --- */
1001 
1002 /* --- start of env.c --- */
1003 #ifndef HAVE_SETENV
1004 /*
1005  * Copyright (c) 1987, 1988, 1993
1006  *	The Regents of the University of California.  All rights reserved.
1007  * See above for the neccesary list of conditions on use.
1008  */
1009 
1010 #include <stdlib.h>
1011 #include <stddef.h>
1012 #include <string.h>
1013 
1014 int   bsd_setenv(const char *name, const char *value, int rewrite);
1015 
1016 /*
1017  * __findenv --
1018  *	Returns pointer to value associated with name, if any, else NULL.
1019  *	Sets offset to be the offset of the name/value combination in the
1020  *	environmental array, for use by setenv(3) and unsetenv(3).
1021  *	Explicitly removes '=' in argument name.
1022  *
1023  *	This routine *should* be a static; don't use it.
1024  */
__findenv(const char * name,int * offset)1025 __inline__ static char *__findenv(const char *name, int *offset)
1026 {
1027 	extern char **environ;
1028 	register int len, i;
1029 	register const char *np;
1030 	register char **p, *cp;
1031 
1032 	if (name == NULL || environ == NULL)
1033 		return (NULL);
1034 	for (np = name; *np && *np != '='; ++np)
1035 		continue;
1036 	len = np - name;
1037 	for (p = environ; (cp = *p) != NULL; ++p) {
1038 		for (np = name, i = len; i && *cp; i--)
1039 			if (*cp++ != *np++)
1040 				break;
1041 		if (i == 0 && *cp++ == '=') {
1042 			*offset = p - environ;
1043 			return (cp);
1044 		}
1045 	}
1046 	return (NULL);
1047 }
1048 
1049 /*
1050  * getenv --
1051  *	Returns ptr to value associated with name, if any, else NULL.
1052  */
bsd_getenv(const char * name)1053 char *bsd_getenv(const char *name)
1054 {
1055 	int offset;
1056 
1057 	return (__findenv(name, &offset));
1058 }
1059 
1060 /*
1061  * setenv --
1062  *	Set the value of the environmental variable "name" to be
1063  *	"value".  If rewrite is set, replace any current value.
1064  */
bsd_setenv(const char * name,const char * value,int rewrite)1065 int bsd_setenv(const char *name, const char *value, int rewrite)
1066 {
1067 	extern char **environ;
1068 	static int alloced;			/* if allocated space before */
1069 	register char *c;
1070 	int l_value, offset;
1071 
1072 	if (*value == '=')			/* no `=' in value */
1073 		++value;
1074 	l_value = strlen(value);
1075 	if ((c = __findenv(name, &offset))) {	/* find if already exists */
1076 		if (!rewrite)
1077 			return (0);
1078 		if (strlen(c) >= l_value) {	/* old larger; copy over */
1079 			while ( (*c++ = *value++) );
1080 			return (0);
1081 		}
1082 	} else {					/* create new slot */
1083 		register int cnt;
1084 		register char **p;
1085 
1086 		for (p = environ, cnt = 0; *p; ++p, ++cnt);
1087 		if (alloced) {			/* just increase size */
1088 			environ = (char **)realloc((char *)environ,
1089 			    (size_t)(sizeof(char *) * (cnt + 2)));
1090 			if (!environ)
1091 				return (-1);
1092 		}
1093 		else {				/* get new space */
1094 			alloced = 1;		/* copy old entries into it */
1095 			p = malloc((size_t)(sizeof(char *) * (cnt + 2)));
1096 			if (!p)
1097 				return (-1);
1098 			memcpy(p, environ, cnt * sizeof(char *));
1099 			environ = p;
1100 		}
1101 		environ[cnt + 1] = NULL;
1102 		offset = cnt;
1103 	}
1104 	for (c = (char *)name; *c && *c != '='; ++c);	/* no `=' in name */
1105 	if (!(environ[offset] =			/* name + `=' + value */
1106 	    malloc((size_t)((int)(c - name) + l_value + 2))))
1107 		return (-1);
1108 	for (c = environ[offset]; (*c = *name++) && *c != '='; ++c);
1109 	for (*c++ = '='; (*c++ = *value++); );
1110 	return (0);
1111 }
1112 
bsd_putenv(const char * str)1113 int bsd_putenv(const char *str)
1114 {
1115 	char *p, *equal;
1116 	int rval;
1117 
1118 	if ((p = strdup(str)) == NULL)
1119 		return (-1);
1120 	if ((equal = strchr(p, '=')) == NULL) {
1121 		free(p);
1122 		return (-1);
1123 	}
1124 	*equal = '\0';
1125 	rval = bsd_setenv(p, equal + 1, 1);
1126 	free(p);
1127 	return (rval);
1128 }
1129 
1130 /*
1131  * unsetenv(name) --
1132  *	Delete environmental variable "name".
1133  */
bsd_unsetenv(const char * name)1134 void bsd_unsetenv(const char *name)
1135 {
1136 	extern char **environ;
1137 	register char **p;
1138 	int offset;
1139 
1140 	while (__findenv(name, &offset))	/* if set multiple times */
1141 		for (p = &environ[offset];; ++p)
1142 			if (!(*p = *(p + 1)))
1143 				break;
1144 }
1145 #endif
1146 /* --- end of env.c --- */
1147 
1148 /* --- start of inet_aton.c --- */
1149 #if !defined(HAVE_INET_ATON)
1150 /*
1151  * Copyright (c) 1983, 1990, 1993
1152  *    The Regents of the University of California.  All rights reserved.
1153  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
1154  * See above for the neccesary list of conditions on use.
1155  */
1156 
1157 /*
1158  * Check whether "cp" is a valid ascii representation
1159  * of an Internet address and convert to a binary address.
1160  * Returns 1 if the address is valid, 0 if not.
1161  * This replaces inet_addr, the return value from which
1162  * cannot distinguish between failure and a local broadcast address.
1163  */
inet_aton(const char * cp,struct in_addr * addr)1164 int inet_aton(const char *cp, struct in_addr *addr)
1165 {
1166 	unsigned long	val;
1167 	int		base, n;
1168 	char		c;
1169 	unsigned	parts[4];
1170 	unsigned	*pp = parts;
1171 
1172 	c = *cp;
1173 	for (;;) {
1174 		/*
1175 		 * Collect number up to ``.''.
1176 		 * Values are specified as for C:
1177 		 * 0x=hex, 0=octal, isdigit=decimal.
1178 		 */
1179 		if (!isdigit((unsigned char)c))
1180 			return (0);
1181 		val = 0; base = 10;
1182 		if (c == '0') {
1183 			c = *++cp;
1184 			if (c == 'x' || c == 'X')
1185 				base = 16, c = *++cp;
1186 			else
1187 				base = 8;
1188 		}
1189 		for (;;) {
1190 			if (isascii((unsigned char)c) && isdigit((unsigned char)c)) {
1191 				val = (val * base) + (c - '0');
1192 				c = *++cp;
1193 			} else if (base == 16 && isascii((unsigned char)c) && isxdigit((unsigned char)c)) {
1194 				val = (val << 4) |
1195 					(c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
1196 				c = *++cp;
1197 			} else
1198 				break;
1199 		}
1200 		if (c == '.') {
1201 			/*
1202 			 * Internet format:
1203 			 *	a.b.c.d
1204 			 *	a.b.c	(with c treated as 16 bits)
1205 			 *	a.b	(with b treated as 24 bits)
1206 			 */
1207 			if (pp >= parts + 3)
1208 				return (0);
1209 			*pp++ = val;
1210 			c = *++cp;
1211 		} else
1212 			break;
1213 	}
1214 	/*
1215 	 * Check for trailing characters.
1216 	 */
1217 	if (c != '\0' && (!isascii((unsigned char)c) || !isspace((unsigned char)c)))
1218 		return (0);
1219 	/*
1220 	 * Concoct the address according to
1221 	 * the number of parts specified.
1222 	 */
1223 	n = pp - parts + 1;
1224 	switch (n) {
1225 
1226 	case 0:
1227 		return (0);		/* initial nondigit */
1228 
1229 	case 1:				/* a -- 32 bits */
1230 		break;
1231 
1232 	case 2:				/* a.b -- 8.24 bits */
1233 		if (val > 0xffffff)
1234 			return (0);
1235 		val |= parts[0] << 24;
1236 		break;
1237 
1238 	case 3:				/* a.b.c -- 8.8.16 bits */
1239 		if (val > 0xffff)
1240 			return (0);
1241 		val |= (parts[0] << 24) | (parts[1] << 16);
1242 		break;
1243 
1244 	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
1245 		if (val > 0xff)
1246 			return (0);
1247 		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
1248 		break;
1249 	}
1250 	if (addr)
1251 		addr->s_addr = htonl(val);
1252 	return (1);
1253 }
1254 #endif
1255 /* --- end of inet_aton.c --- */
1256 
1257 /* --- start of misc stuff --- */
1258 #if 0
1259 int vsnprintf (char *str, size_t size, const char *format, va_list ap)
1260 {
1261 	int ret = vsprintf(str, format, ap);
1262 
1263 	/* If the string ended up overflowing, just give up. */
1264 	if (ret == (int)str && strlen(str) > size)
1265 		ircpanic("Buffer overflow in vsnprintf");
1266 	if (ret != (int)str && ret > size)
1267 		ircpanic("Buffer overflow in vsnprintf");
1268 
1269 	return ret;
1270 }
1271 #endif
1272 
1273 #if 0
1274 int snprintf (char *str, size_t size, const char *format, ...)
1275 {
1276 	int ret;
1277 	va_list args;
1278 
1279 	va_start(args, format);
1280 	ret = vsnprintf(str, size, format, args);
1281 	va_end(args);
1282 	return ret;
1283 }
1284 #endif
1285 
1286 /*
1287 
1288   Author: Tomi Salo <ttsalo@ssh.fi>
1289 
1290   Copyright (C) 1996 SSH Communications Security Oy, Espoo, Finland
1291   See COPYING for distribution conditions.
1292 
1293   Implementation of functions snprintf() and vsnprintf()
1294 
1295   */
1296 
1297 /*
1298  * $Id: compat.c 462 2013-11-13 11:43:57Z keaston $
1299  * $Log: compat.c,v $
1300  * Revision 1.1.1.1  2003/04/11 01:09:07  dan
1301  * inital import into backup cvs server
1302  *
1303  *
1304  * Revision 1.3  2002/10/24 11:00:42  nuke
1305  * Added hebrew patches.  Fixed problems with isalpha() etc.  Cleaned up some
1306  * #ifdefs and other general code cleanups.
1307  *
1308  * Revision 1.2  2001/05/07 08:44:56  nuke
1309  * All exported functions are now called through the global table internally.
1310  *
1311  * Revision 1.1  2001/03/05 19:39:37  nuke
1312  * Added BitchX to the archive... slightly post 1.0c18
1313  *
1314  * Revision 1.3  2000/10/29 04:55:52  cvs
1315  * Attemped fixes for Close from window list hanging PMBX.  Fix for
1316  * input line being updated incorrectly.
1317  *
1318  * Revision 1.2  2000/06/09 10:08:39  nuke
1319  * Various fixes and code cleanup in exec.c  Fixed a crash in detach_shared
1320  * when a menu didn't exist. Added virtual host support on OS/2.
1321  *
1322  * Revision 1.1.1.1  2000/05/10 06:52:03  edwards
1323  * BitchX Source
1324  *
1325  *
1326  * 1999/05/28 00:59:04 rlm
1327  *      Adapted code to fit frequency, fixed ambiguous else
1328  *
1329  * Revision 1.3  1999/02/23 08:30:59  tri
1330  * 	Downgraded includes to ssh1 style.
1331  *
1332  * Revision 1.2  1999/02/23 07:06:17  tri
1333  *      Fixed compilation errors.
1334  *
1335  * Revision 1.1  1999/02/21 19:52:37  ylo
1336  *      Intermediate commit of ssh1.2.27 stuff.
1337  *      Main change is sprintf -> snprintf; however, there are also
1338  *      many other changes.
1339  *
1340  * Revision 1.23  1998/11/05 21:14:05  ylo
1341  *      Changed to ignore return value from sprintf (it returns char *
1342  *      on some systems, e.g. SunOS 4.1.x).
1343  *
1344  * Revision 1.22  1998/10/28 05:19:06  ylo
1345  *      Changed to compile in the kernel environment if KERNEL is defined.
1346  *
1347  * Revision 1.21  1998/10/06 11:32:34  sjl
1348  *      Fixed previous.
1349  *
1350  * Revision 1.20  1998/10/05 10:16:01  sjl
1351  *      Added (char) cast to format_str_ptr, as suggested by someone
1352  *      who compiled with IRIX (or Ultrix).
1353  *
1354  * Revision 1.19  1998/06/03 00:45:30  ylo
1355  *      Fixed initialization of prefix and flags.
1356  *
1357  * Revision 1.18  1998/03/28  13:18:57  ylo
1358  *      Changed snprintf to return the length of the resulting string
1359  *      (not len+1) when the string fits in the buffer.
1360  *
1361  * Revision 1.17  1998/01/28 10:14:31  ylo
1362  *      Major changes in util library.  Several files were renamed,
1363  *      and many very commonly used functions and types were renamed
1364  *      (mostly to add ssh prefix).  The event loop and timeout
1365  *      interface was changed, and split to portable and
1366  *      machine-dependent parts.  Thousands of calls to
1367  *      renamed/modified functions were changed accordingly.
1368  *
1369  * Revision 1.16  1997/12/28 02:22:25  ylo
1370  *      Removed unused variable tmp.
1371  *
1372  * Revision 1.15  1997/09/18 06:07:41  kivinen
1373  *      Added check that if we print NULL pointer print (null) just
1374  *      like normal printf will do.
1375  *
1376  * Revision 1.14  1997/06/04 21:54:51  ylo
1377  *      Added include snprintf.h.
1378  *      Removed obsolete xmalloc/xfree pair.
1379  *
1380  * Revision 1.13  1996/11/03 19:41:29  ttsalo
1381  *       Kludged & fixed snprintf
1382  *
1383  * Revision 1.12  1996/11/03 18:47:56  ttsalo
1384  *       Changed buffering in snprintf_convert_float
1385  *
1386  * Revision 1.11  1996/11/03 17:46:24  ttsalo
1387  *       Removed references to bsd's float conversion
1388  *
1389  * Revision 1.10  1996/11/03 17:44:18  ttsalo
1390  *       Re-implemented float conversion, uses system's sprintf
1391  *
1392  * Revision 1.9  1996/08/21 15:32:47  kivinen
1393  *      Removed xmalloc.h and fatal.h includes, as they are now in
1394  *      includes.h.
1395  *
1396  * Revision 1.8  1996/08/09 14:44:03  ttsalo
1397  *      Fixed a problem in non-null-terminated string formatting
1398  *
1399  * Revision 1.7  1996/08/09 13:41:59  ttsalo
1400  *        Don't pad left-justified numbers with zeros
1401  *
1402  * Revision 1.6  1996/08/09 12:11:10  ttsalo
1403  *      More fine-tuning of float-printing
1404  *
1405  * Revision 1.5  1996/08/09 11:37:20  ttsalo
1406  *      Ansi C - conforming snprintf and vsnprintf.
1407  *
1408  * Revision 1.4  1996/08/07 10:12:50  ttsalo
1409  *      Fixed the banner again
1410  *
1411  * Revision 1.3  1996/08/07 10:08:24  ttsalo
1412  *      Fixed the banner
1413  *
1414  * Revision 1.2  1996/08/07 09:52:07  ttsalo
1415  *      Removed diagnostic printf:s
1416  *
1417  * Revision 1.1  1996/08/06 19:00:40  ttsalo
1418  *      Implementation of snprintf and vsnprintf. Everything except
1419  *      floating point conversions ready.
1420  *
1421  * $EndLog$
1422  */
1423 
1424 #ifndef HAVE_VSNPRINTF
1425 
1426 #undef isdigit
1427 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
1428 
1429 #define MINUS_FLAG 0x1
1430 #define PLUS_FLAG 0x2
1431 #define SPACE_FLAG 0x4
1432 #define HASH_FLAG 0x8
1433 #define CONV_TO_SHORT 0x10
1434 #define IS_LONG_INT 0x20
1435 #define IS_LONG_DOUBLE 0x40
1436 #define X_UPCASE 0x80
1437 #define IS_NEGATIVE 0x100
1438 #define UNSIGNED_DEC 0x200
1439 #define ZERO_PADDING 0x400
1440 
1441 #undef sprintf
1442 
1443 /* Extract a formatting directive from str. Str must point to a '%'.
1444    Returns number of characters used or zero if extraction failed. */
1445 
1446 static int
snprintf_get_directive(const char * str,int * flags,int * width,int * precision,char * format_char,va_list * ap)1447 snprintf_get_directive(const char *str, int *flags, int *width,
1448                        int *precision, char *format_char, va_list *ap)
1449 {
1450   int length, value;
1451   const char *orig_str = str;
1452 
1453   *flags = 0;
1454   *width = 0;
1455   *precision = 0;
1456   *format_char = (char)0;
1457 
1458   if (*str == '%')
1459     {
1460       /* Get the flags */
1461       str++;
1462       while (*str == '-' || *str == '+' || *str == ' '
1463              || *str == '#' || *str == '0')
1464         {
1465           switch (*str)
1466             {
1467             case '-':
1468               *flags |= MINUS_FLAG;
1469               break;
1470             case '+':
1471               *flags |= PLUS_FLAG;
1472               break;
1473             case ' ':
1474               *flags |= SPACE_FLAG;
1475               break;
1476             case '#':
1477               *flags |= HASH_FLAG;
1478               break;
1479             case '0':
1480               *flags |= ZERO_PADDING;
1481               break;
1482             }
1483           str++;
1484         }
1485 
1486       /* Don't pad left-justified numbers withs zeros */
1487       if ((*flags & MINUS_FLAG) && (*flags & ZERO_PADDING))
1488         *flags &= ~ZERO_PADDING;
1489 
1490       /* Is width field present? */
1491       if (isdigit(*str))
1492         {
1493           for (value = 0; *str && isdigit(*str); str++)
1494             value = 10 * value + *str - '0';
1495           *width = value;
1496         }
1497       else
1498         if (*str == '*')
1499           {
1500             *width = va_arg(*ap, int);
1501             str++;
1502           }
1503 
1504       /* Is the precision field present? */
1505       if (*str == '.')
1506         {
1507           str++;
1508           if (isdigit(*str))
1509             {
1510               for (value = 0; *str && isdigit(*str); str++)
1511                 value = 10 * value + *str - '0';
1512               *precision = value;
1513             }
1514           else
1515             if (*str == '*')
1516               {
1517                 *precision = va_arg(*ap, int);
1518                 str++;
1519               }
1520             else
1521               *precision = 0;
1522         }
1523 
1524       /* Get the optional type character */
1525       if (*str == 'h')
1526         {
1527           *flags |= CONV_TO_SHORT;
1528           str++;
1529         }
1530       else
1531         {
1532           if (*str == 'l')
1533             {
1534               *flags |= IS_LONG_INT;
1535               str++;
1536             }
1537           else
1538             {
1539               if (*str == 'L')
1540                 {
1541                   *flags |= IS_LONG_DOUBLE;
1542                   str++;
1543                 }
1544             }
1545         }
1546 
1547       /* Get and check the formatting character */
1548 
1549       *format_char = *str;
1550       str++;
1551       length = str - orig_str;
1552 
1553       switch (*format_char)
1554         {
1555         case 'i': case 'd': case 'o': case 'u': case 'x': case 'X':
1556         case 'f': case 'e': case 'E': case 'g': case 'G':
1557         case 'c': case 's': case 'p': case 'n':
1558           if (*format_char == 'X')
1559             *flags |= X_UPCASE;
1560           if (*format_char == 'o')
1561             *flags |= UNSIGNED_DEC;
1562           return length;
1563 
1564         default:
1565           return 0;
1566         }
1567     }
1568   else
1569     {
1570       return 0;
1571     }
1572 }
1573 
1574 /* Convert a integer from unsigned long int representation
1575    to string representation. This will insert prefixes if needed
1576    (leading zero for octal and 0x or 0X for hexadecimal) and
1577    will write at most buf_size characters to buffer.
1578    tmp_buf is used because we want to get correctly truncated
1579    results.
1580    */
1581 
1582 static int
snprintf_convert_ulong(char * buffer,size_t buf_size,int base,char * digits,unsigned long int ulong_val,int flags,int width,int precision)1583 snprintf_convert_ulong(char *buffer, size_t buf_size, int base, char *digits,
1584                        unsigned long int ulong_val, int flags, int width,
1585                        int precision)
1586 {
1587   int tmp_buf_len = 100 + width, len;
1588   char *tmp_buf, *tmp_buf_ptr, prefix[2];
1589   tmp_buf = alloca(tmp_buf_len+1);
1590 
1591   prefix[0] = '\0';
1592   prefix[1] = '\0';
1593 
1594   /* Make tmp_buf_ptr point just past the last char of buffer */
1595   tmp_buf_ptr = tmp_buf + tmp_buf_len;
1596 
1597   /* Main conversion loop */
1598   do
1599     {
1600       *--tmp_buf_ptr = digits[ulong_val % base];
1601       ulong_val /= base;
1602       precision--;
1603     }
1604   while ((ulong_val != 0 || precision > 0) && tmp_buf_ptr > tmp_buf);
1605 
1606   /* Get the prefix */
1607   if (!(flags & IS_NEGATIVE))
1608     {
1609       if (base == 16 && (flags & HASH_FLAG))
1610 	{
1611           if (flags && X_UPCASE)
1612             {
1613               prefix[0] = 'x';
1614               prefix[1] = '0';
1615             }
1616           else
1617             {
1618               prefix[0] = 'X';
1619               prefix[1] = '0';
1620             }
1621           }
1622       if (base == 8 && (flags & HASH_FLAG))
1623           prefix[0] = '0';
1624 
1625       if (base == 10 && !(flags & UNSIGNED_DEC) && (flags & PLUS_FLAG))
1626           prefix[0] = '+';
1627       else
1628         if (base == 10 && !(flags & UNSIGNED_DEC) && (flags & SPACE_FLAG))
1629           prefix[0] = ' ';
1630     }
1631   else
1632       prefix[0] = '-';
1633 
1634   if (prefix[0] != '\0' && tmp_buf_ptr > tmp_buf)
1635     {
1636       *--tmp_buf_ptr = prefix[0];
1637       if (prefix[1] != '\0' && tmp_buf_ptr > tmp_buf)
1638         *--tmp_buf_ptr = prefix[1];
1639     }
1640 
1641   len = (tmp_buf + tmp_buf_len) - tmp_buf_ptr;
1642 
1643   if (len <= buf_size)
1644     {
1645       if (len < width)
1646         {
1647           if (width > (tmp_buf_ptr - tmp_buf))
1648             width = (tmp_buf_ptr - tmp_buf);
1649           if (flags & MINUS_FLAG)
1650             {
1651               memcpy(buffer, tmp_buf_ptr, len);
1652               memset(buffer + len, (flags & ZERO_PADDING)?'0':' ',
1653                      width - len);
1654               len = width;
1655             }
1656           else
1657             {
1658               memset(buffer, (flags & ZERO_PADDING)?'0':' ',
1659                      width - len);
1660               memcpy(buffer + width - len, tmp_buf_ptr, len);
1661               len = width;
1662             }
1663         }
1664       else
1665         {
1666           memcpy(buffer, tmp_buf_ptr, len);
1667         }
1668       return len;
1669     }
1670   else
1671     {
1672       memcpy(buffer, tmp_buf_ptr, buf_size);
1673       return buf_size;
1674     }
1675 }
1676 
1677 #ifndef KERNEL
1678 
1679 static int
snprintf_convert_float(char * buffer,size_t buf_size,double dbl_val,int flags,int width,int precision,char format_char)1680 snprintf_convert_float(char *buffer, size_t buf_size,
1681                        double dbl_val, int flags, int width,
1682                        int precision, char format_char)
1683 {
1684   char print_buf[160], print_buf_len = 0;
1685   char format_str[80], *format_str_ptr;
1686 
1687   format_str_ptr = format_str;
1688 
1689   if (width > 155) width = 155;
1690   if (precision <= 0)
1691     precision = 6;
1692   if (precision > 120)
1693     precision = 120;
1694 
1695   /* Construct the formatting string and let system's sprintf
1696      do the real work. */
1697 
1698   *format_str_ptr++ = '%';
1699 
1700   if (flags & MINUS_FLAG)
1701     *format_str_ptr++ = '-';
1702   if (flags & PLUS_FLAG)
1703     *format_str_ptr++ = '+';
1704   if (flags & SPACE_FLAG)
1705     *format_str_ptr++ = ' ';
1706   if (flags & ZERO_PADDING)
1707     *format_str_ptr++ = '0';
1708   if (flags & HASH_FLAG)
1709     *format_str_ptr++ = '#';
1710 
1711   sprintf(format_str_ptr, "%d.%d", width, precision);
1712   format_str_ptr += strlen(format_str_ptr);
1713 
1714   if (flags & IS_LONG_DOUBLE)
1715     *format_str_ptr++ = 'L';
1716   *format_str_ptr++ = format_char;
1717   *format_str_ptr++ = '\0';
1718 
1719   sprintf(print_buf, format_str, dbl_val);
1720   print_buf_len = strlen(print_buf);
1721 
1722   if (print_buf_len > buf_size)
1723     print_buf_len = buf_size;
1724   strncpy(buffer, print_buf, print_buf_len);
1725   return print_buf_len;
1726 }
1727 
1728 #endif /* KERNEL */
1729 #endif /* HAVE_VSNPRINTF */
1730 
1731 #ifndef HAVE_SNPRINTF
snprintf(char * str,size_t size,const char * format,...)1732 extern int snprintf(char *str, size_t size, const char *format, ...)
1733 {
1734   int ret;
1735   va_list ap;
1736   va_start(ap, format);
1737   ret = vsnprintf(str, size, format, ap);
1738   va_end(ap);
1739 
1740   return ret;
1741 }
1742 #endif
1743 
1744 #ifndef HAVE_VSNPRINTF
1745 
vsnprintf(char * str,size_t size,const char * format,va_list ap)1746 extern int vsnprintf(char *str, size_t size, const char *format, va_list ap)
1747 {
1748   int status, left = (int)size - 1;
1749   const char *format_ptr = format;
1750   int flags, width, precision, i;
1751   char format_char, *orig_str = str;
1752   int *int_ptr;
1753   long int long_val;
1754   unsigned long int ulong_val;
1755   char *str_val;
1756 #ifndef KERNEL
1757   double dbl_val;
1758 #endif /* KERNEL */
1759 
1760   flags = 0;
1761   while (format_ptr < format + strlen(format))
1762     {
1763       if (*format_ptr == '%')
1764         {
1765           if (format_ptr[1] == '%' && left > 0)
1766             {
1767               *str++ = '%';
1768               left--;
1769               format_ptr += 2;
1770             }
1771           else
1772             {
1773               if (left <= 0)
1774                 {
1775                   *str = '\0';
1776                   return size;
1777                 }
1778               else
1779                 {
1780                   status = snprintf_get_directive(format_ptr, &flags, &width,
1781                                                   &precision, &format_char,
1782                                                   &ap);
1783                   if (status == 0)
1784                     {
1785                       *str = '\0';
1786                       return 0;
1787                     }
1788                   else
1789                     {
1790                       format_ptr += status;
1791                       /* Print a formatted argument */
1792                       switch (format_char)
1793                         {
1794                         case 'i': case 'd':
1795                           /* Convert to unsigned long int before
1796                              actual conversion to string */
1797                           if (flags & IS_LONG_INT)
1798                             long_val = va_arg(ap, long int);
1799                           else
1800                             long_val = (long int) va_arg(ap, int);
1801 
1802                           if (long_val < 0)
1803                             {
1804                               ulong_val = (unsigned long int) -long_val;
1805                               flags |= IS_NEGATIVE;
1806                             }
1807                           else
1808                             {
1809                               ulong_val = (unsigned long int) long_val;
1810                             }
1811                           status = snprintf_convert_ulong(str, left, 10,
1812                                                           "0123456789",
1813                                                           ulong_val, flags,
1814                                                           width, precision);
1815                           str += status;
1816                           left -= status;
1817                           break;
1818 
1819                         case 'x':
1820                           if (flags & IS_LONG_INT)
1821                             ulong_val = va_arg(ap, unsigned long int);
1822                           else
1823                             ulong_val =
1824                               (unsigned long int) va_arg(ap, unsigned int);
1825 
1826                           status = snprintf_convert_ulong(str, left, 16,
1827                                                           "0123456789abcdef",
1828                                                           ulong_val, flags,
1829                                                           width, precision);
1830                           str += status;
1831                           left -= status;
1832                           break;
1833 
1834                         case 'X':
1835                           if (flags & IS_LONG_INT)
1836                             ulong_val = va_arg(ap, unsigned long int);
1837                           else
1838                             ulong_val =
1839                               (unsigned long int) va_arg(ap, unsigned int);
1840 
1841                           status = snprintf_convert_ulong(str, left, 16,
1842                                                           "0123456789ABCDEF",
1843                                                           ulong_val, flags,
1844                                                           width, precision);
1845                           str += status;
1846                           left -= status;
1847                           break;
1848 
1849                         case 'o':
1850                           if (flags & IS_LONG_INT)
1851                             ulong_val = va_arg(ap, unsigned long int);
1852                           else
1853                             ulong_val =
1854                               (unsigned long int) va_arg(ap, unsigned int);
1855 
1856                           status = snprintf_convert_ulong(str, left, 8,
1857                                                           "01234567",
1858                                                           ulong_val, flags,
1859                                                           width, precision);
1860                           str += status;
1861                           left -= status;
1862                           break;
1863 
1864                         case 'u':
1865                           if (flags & IS_LONG_INT)
1866                             ulong_val = va_arg(ap, unsigned long int);
1867                           else
1868                             ulong_val =
1869                               (unsigned long int) va_arg(ap, unsigned int);
1870 
1871                           status = snprintf_convert_ulong(str, left, 10,
1872                                                           "0123456789",
1873                                                           ulong_val, flags,
1874                                                           width, precision);
1875                           str += status;
1876                           left -= status;
1877                           break;
1878 
1879                         case 'p':
1880                           break;
1881 
1882                         case 'c':
1883                           if (flags & IS_LONG_INT)
1884                             ulong_val = va_arg(ap, unsigned long int);
1885                           else
1886                             ulong_val =
1887                               (unsigned long int) va_arg(ap, unsigned int);
1888                           *str++ = (unsigned char)ulong_val;
1889                           left--;
1890                           break;
1891 
1892                         case 's':
1893                           str_val = va_arg(ap, char *);
1894 
1895                           if (str_val == NULL)
1896                             str_val = "(null)";
1897 
1898                           if (precision == 0)
1899                             precision = strlen(str_val);
1900                           else
1901                             {
1902                               if (memchr(str_val, 0, precision) != NULL)
1903                                 precision = strlen(str_val);
1904                             }
1905                           if (precision > left)
1906                             precision = left;
1907 
1908                           if (width > left)
1909                             width = left;
1910                           if (width < precision)
1911                             width = precision;
1912                           i = width - precision;
1913 
1914                           if (flags & MINUS_FLAG)
1915                             {
1916                               strncpy(str, str_val, precision);
1917                               memset(str + precision,
1918                                      (flags & ZERO_PADDING)?'0':' ', i);
1919                             }
1920                           else
1921                             {
1922                               memset(str, (flags & ZERO_PADDING)?'0':' ', i);
1923                               strncpy(str + i, str_val, precision);
1924                             }
1925                           str += width;
1926                           left -= width;
1927                           break;
1928 
1929                         case 'n':
1930                           int_ptr = va_arg(ap, int *);
1931                           *int_ptr = str - orig_str;
1932                           break;
1933 
1934 #ifndef KERNEL
1935                         case 'f': case 'e': case 'E': case 'g': case 'G':
1936                           if (flags & IS_LONG_DOUBLE)
1937                             dbl_val = (double) va_arg(ap, long double);
1938                           else
1939                             dbl_val = va_arg(ap, double);
1940                           status =
1941                             snprintf_convert_float(str, left, dbl_val, flags,
1942                                                    width, precision,
1943                                                    format_char);
1944                           str += status;
1945                           left -= status;
1946                           break;
1947 #endif /* KERNEL */
1948 
1949                         default:
1950                           break;
1951                         }
1952                     }
1953                 }
1954             }
1955         }
1956       else
1957         {
1958           if (left > 0)
1959             {
1960               *str++ = *format_ptr++;
1961               left--;
1962             }
1963           else
1964             {
1965               *str = '\0';
1966               return size;
1967             }
1968         }
1969     }
1970   *str = '\0';
1971   return size - left - 1;
1972 }
1973 #endif
1974 
1975 /**************************************************************************/
1976 /* ---------------------- strlcpy, strlcat ----------------------------- */
1977 /*
1978  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1979  * All rights reserved.
1980  * Licensed under the 3-clase BSD license
1981  */
1982 
1983 #ifndef HAVE_STRLCPY
1984 /*
1985  * Copy src to string dst of size siz.  At most siz-1 characters
1986  * will be copied.  Always NUL terminates (unless siz == 0).
1987  * Returns strlen(src); if retval >= siz, truncation occurred.
1988  */
strlcpy(char * dst,const char * src,size_t siz)1989 size_t strlcpy (char *dst, const char *src, size_t siz)
1990 {
1991         char *d = dst;
1992         const char *s = src;
1993         size_t n = siz;
1994 
1995         /* Copy as many bytes as will fit */
1996         if (n != 0 && --n != 0) {
1997                 do {
1998                         if ((*d++ = *s++) == 0)
1999                                 break;
2000                 } while (--n != 0);
2001         }
2002 
2003         /* Not enough room in dst, add NUL and traverse rest of src */
2004         if (n == 0) {
2005                 if (siz != 0)
2006                         *d = '\0';              /* NUL-terminate dst */
2007                 while (*s++)
2008                         ;
2009         }
2010 
2011         return(s - src - 1);    /* count does not include NUL */
2012 }
2013 #endif
2014 
2015 #ifndef HAVE_STRLCAT
2016 /*
2017  * Appends src to string dst of size siz (unlike strncat, siz is the
2018  * full size of dst, not space left).  At most siz-1 characters
2019  * will be copied.  Always NUL terminates (unless siz == 0).
2020  * Returns strlen(src); if retval >= siz, truncation occurred.
2021  */
strlcat(char * dst,const char * src,size_t siz)2022 size_t strlcat(char *dst, const char *src, size_t siz)
2023 {
2024         char *d = dst;
2025         const char *s = src;
2026         size_t n = siz;
2027         size_t dlen;
2028 
2029         /* Find the end of dst and adjust bytes left but don't go past end */
2030         while (*d != '\0' && n-- != 0)
2031                 d++;
2032         dlen = d - dst;
2033         n = siz - dlen;
2034 
2035         if (n == 0)
2036                 return(dlen + strlen(s));
2037         while (*s != '\0') {
2038                 if (n != 1) {
2039                         *d++ = *s;
2040                         n--;
2041                 }
2042                 s++;
2043         }
2044         *d = '\0';
2045 
2046         return(dlen + (s - src));       /* count does not include NUL */
2047 }
2048 #endif
2049 
2050 
2051 #ifndef HAVE_SETSID
setsid(void)2052 int	setsid	(void)
2053 {
2054 #ifdef __EMX__
2055 	return 0;
2056 #else
2057 	return setpgrp(getpid(), getpid());
2058 #endif
2059 }
2060 #endif
2061 
2062 #ifndef HAVE_MEMMOVE
2063 /*  $Revision: 462 $
2064 **
2065 **  This file has been modified to get it to compile more easily
2066 **  on pre-4.4BSD systems.  Rich $alz, June 1991.
2067 */
2068 
2069 /*
2070  * sizeof(word) MUST BE A POWER OF TWO
2071  * SO THAT wmask BELOW IS ALL ONES
2072  */
2073 typedef	int word;		/* "word" used for optimal copy speed */
2074 
2075 #define	wsize	sizeof(word)
2076 #define	wmask	(wsize - 1)
2077 
2078 /*
2079  * Copy a block of memory, handling overlap.
2080  * This is the routine that actually implements
2081  * (the portable versions of) bcopy, memcpy, and memmove.
2082  */
memmove(char * dst0,const char * src0,register size_t length)2083 void * memmove(char *dst0, const char *src0, register size_t length)
2084 {
2085 	register char *dst = dst0;
2086 	register const char *src = src0;
2087 	register size_t t;
2088 
2089 	if (length == 0 || dst == src)		/* nothing to do */
2090 		goto retval;
2091 
2092 	/*
2093 	 * Macros: loop-t-times; and loop-t-times, t>0
2094 	 */
2095 #define	TLOOP(s) if (t) TLOOP1(s)
2096 #define	TLOOP1(s) do { s; } while (--t)
2097 
2098 	if ((unsigned long)dst < (unsigned long)src) {
2099 		/*
2100 		 * Copy forward.
2101 		 */
2102 		t = (int)src;	/* only need low bits */
2103 		if ((t | (int)dst) & wmask) {
2104 			/*
2105 			 * Try to align operands.  This cannot be done
2106 			 * unless the low bits match.
2107 			 */
2108 			if ((t ^ (int)dst) & wmask || length < wsize)
2109 				t = length;
2110 			else
2111 				t = wsize - (t & wmask);
2112 			length -= t;
2113 			TLOOP1(*dst++ = *src++);
2114 		}
2115 		/*
2116 		 * Copy whole words, then mop up any trailing bytes.
2117 		 */
2118 		t = length / wsize;
2119 		TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
2120 		t = length & wmask;
2121 		TLOOP(*dst++ = *src++);
2122 	} else {
2123 		/*
2124 		 * Copy backwards.  Otherwise essentially the same.
2125 		 * Alignment works as before, except that it takes
2126 		 * (t&wmask) bytes to align, not wsize-(t&wmask).
2127 		 */
2128 		src += length;
2129 		dst += length;
2130 		t = (int)src;
2131 		if ((t | (int)dst) & wmask) {
2132 			if ((t ^ (int)dst) & wmask || length <= wsize)
2133 				t = length;
2134 			else
2135 				t &= wmask;
2136 			length -= t;
2137 			TLOOP1(*--dst = *--src);
2138 		}
2139 		t = length / wsize;
2140 		TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
2141 		t = length & wmask;
2142 		TLOOP(*--dst = *--src);
2143 	}
2144 retval:
2145 	return(dst0);
2146 }
2147 #endif
2148 
2149 #ifdef CLOAKED
2150 
2151 char **Argv = NULL;             /* pointer to argument vector */
2152 char *LastArgv = NULL;          /* end of argv */
2153 
2154 /**  SETPROCTITLE -- set process title for ps
2155 **
2156 **	Parameters:
2157 **		fmt -- a printf style format string.
2158 **		a, b, c -- possible parameters to fmt.
2159 **
2160 **	Returns:
2161 **		none.
2162 **
2163 **	Side Effects:
2164 **		Clobbers argv of our main procedure so ps(1) will
2165 **		display the title.
2166 */
2167 
2168 #define SPT_NONE	0	/* don't use it at all */
2169 #define SPT_REUSEARGV	1	/* cover argv with title information */
2170 #define SPT_BUILTIN	2	/* use libc builtin */
2171 #define SPT_PSTAT	3	/* use pstat(PSTAT_SETCMD, ...) */
2172 #define SPT_PSSTRINGS	4	/* use PS_STRINGS->... */
2173 #define SPT_SYSMIPS	5	/* use sysmips() supported by NEWS-OS 6 */
2174 #define SPT_SCO		6	/* write kernel u. area */
2175 #define SPT_CHANGEARGV	7	/* write our own strings into argv[] */
2176 #define SPACELEFT(buf, ptr)  (sizeof buf - ((ptr) - buf))
2177 
2178 #ifndef SPT_TYPE
2179 # define SPT_TYPE	SPT_REUSEARGV
2180 #endif
2181 
2182 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
2183 
2184 # if SPT_TYPE == SPT_PSTAT
2185 #  include <sys/pstat.h>
2186 # endif
2187 # if SPT_TYPE == SPT_PSSTRINGS
2188 #  include <machine/vmparam.h>
2189 #  include <sys/exec.h>
2190 #  ifndef PS_STRINGS	/* hmmmm....  apparently not available after all */
2191 #   undef SPT_TYPE
2192 #   define SPT_TYPE	SPT_REUSEARGV
2193 #  else
2194 #   ifndef NKPDE			/* FreeBSD 2.0 */
2195 #    define NKPDE 63
2196 typedef unsigned int	*pt_entry_t;
2197 #   endif
2198 #  endif
2199 # endif
2200 
2201 # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
2202 #  define SETPROC_STATIC	static
2203 # else
2204 #  define SETPROC_STATIC
2205 # endif
2206 
2207 # if SPT_TYPE == SPT_SYSMIPS
2208 #  include <sys/sysmips.h>
2209 #  include <sys/sysnews.h>
2210 # endif
2211 
2212 # if SPT_TYPE == SPT_SCO
2213 #  include <sys/immu.h>
2214 #  include <sys/dir.h>
2215 #  include <sys/user.h>
2216 #  include <sys/fs/s5param.h>
2217 #  if PSARGSZ > MAXLINE
2218 #   define SPT_BUFSIZE	PSARGSZ
2219 #  endif
2220 # endif
2221 
2222 # ifndef SPT_PADCHAR
2223 #  define SPT_PADCHAR	' '
2224 # endif
2225 
2226 # ifndef SPT_BUFSIZE
2227 #  define SPT_BUFSIZE	140
2228 # endif
2229 
2230 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
2231 extern char **Argv;
2232 extern char *LastArgv;
2233 
2234 /*
2235 **  Pointers for setproctitle.
2236 **	This allows "ps" listings to give more useful information.
2237 */
initsetproctitle(int argc,char ** argv,char ** envp)2238 void initsetproctitle(int argc, char **argv, char **envp)
2239 {
2240 	register int i, envpsize = 0;
2241 	extern char **environ;
2242 
2243 	/*
2244 	**  Move the environment so setproctitle can use the space at
2245 	**  the top of memory.
2246 	*/
2247 
2248 	for (i = 0; envp[i] != NULL; i++)
2249 		envpsize += strlen(envp[i]) + 1;
2250 	environ = (char **) malloc(sizeof (char *) * (i + 1));
2251 	for (i = 0; envp[i] != NULL; i++)
2252 		environ[i] = strdup(envp[i]);
2253 	environ[i] = NULL;
2254 
2255 	/*
2256 	**  Save start and extent of argv for setproctitle.
2257 	*/
2258 
2259 	Argv = argv;
2260 
2261 	/*
2262 	**  Find the last environment variable within sendmail's
2263 	**  process memory area.
2264 	*/
2265 	while (i > 0 && (envp[i - 1] < argv[0] ||
2266 			 envp[i - 1] > (argv[argc - 1] +
2267 					strlen(argv[argc - 1]) + 1 + envpsize)))
2268 		i--;
2269 
2270 	if (i > 0)
2271 		LastArgv = envp[i - 1] + strlen(envp[i - 1]);
2272 	else
2273 		LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
2274 }
2275 
setproctitle(const char * fmt,...)2276 void setproctitle(const char *fmt, ...)
2277 {
2278 #if defined(CLOAKED)
2279 /* this was removed from wu-ftpd which removed it from sendmail */
2280 	register char *p;
2281 	register int i;
2282 	SETPROC_STATIC char buf[SPT_BUFSIZE];
2283 #if SPT_TYPE == SPT_PSTAT
2284 	union pstun pst;
2285 #endif
2286 #if SPT_TYPE == SPT_SCO
2287 	off_t seek_off;
2288 	static int kmem = -1;
2289 	static int kmempid = -1;
2290 	struct user u;
2291 #endif
2292 	va_list args;
2293 
2294 	p = buf;
2295 
2296 	*p = 0;
2297 	p += strlen(p);
2298 
2299 	/* print the argument string */
2300 	va_start(args, fmt);
2301 	(void) vsnprintf(p, SPACELEFT(buf, p), fmt, args);
2302 	va_end(args);
2303 
2304 	i = strlen(buf);
2305 
2306 #if SPT_TYPE == SPT_PSTAT
2307 	pst.pst_command = buf;
2308 	pstat(PSTAT_SETCMD, pst, i, 0, 0);
2309 #endif
2310 #if SPT_TYPE == SPT_PSSTRINGS
2311 	PS_STRINGS->ps_nargvstr = 1;
2312 	PS_STRINGS->ps_argvstr = buf;
2313 #endif
2314 #if SPT_TYPE == SPT_SYSMIPS
2315 	sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
2316 #endif
2317 #if SPT_TYPE == SPT_SCO
2318 	if (kmem < 0 || kmempid != getpid())
2319 	{
2320 		if (kmem >= 0)
2321 			close(kmem);
2322 		kmem = open(_PATH_KMEM, O_RDWR, 0);
2323 		if (kmem < 0)
2324 			return;
2325 		(void) fcntl(kmem, F_SETFD, 1);
2326 		kmempid = getpid();
2327 	}
2328 	buf[PSARGSZ - 1] = '\0';
2329 	seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
2330 	if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
2331 		(void) write(kmem, buf, PSARGSZ);
2332 #endif
2333 #if SPT_TYPE == SPT_REUSEARGV
2334 	if (i > LastArgv - Argv[0] - 2)
2335 	{
2336 		i = LastArgv - Argv[0] - 2;
2337 		buf[i] = '\0';
2338 	}
2339 	(void) strcpy(Argv[0], buf);
2340 	p = &Argv[0][i];
2341 	while (p < LastArgv)
2342 		*p++ = SPT_PADCHAR;
2343 	Argv[1] = NULL;
2344 #endif
2345 #if SPT_TYPE == SPT_CHANGEARGV
2346 	Argv[0] = buf;
2347 	Argv[1] = 0;
2348 #endif
2349 #endif /* SPT_TYPE != SPT_NONE */
2350 }
2351 #endif /* CLOAKED */
2352 
2353 /* --- end of misc stuff --- */
2354 
2355 #ifdef __EMX__
2356 #include <sys/utsname.h>
uname(struct utsname * buf)2357 int uname(struct utsname *buf)
2358 {
2359 	ULONG aulBuffer[4];
2360 	APIRET rc;
2361 	if (!buf) return EFAULT;
2362 	rc = DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_MS_COUNT,(void *)aulBuffer, 4*sizeof(ULONG));
2363 	strcpy(buf->sysname,"OS/2");
2364 	strcpy(buf->release, "1.x");
2365 	if (aulBuffer[0] == 20)
2366 	{
2367 		int i = (unsigned int)aulBuffer[1];
2368 		strcpy(buf->release, ltoa(i));
2369 		if (i > 20)
2370 		{
2371 			strcpy(buf->sysname,"Warp");
2372 			sprintf(buf->release, "%d.%d", (int)i/10, i-(((int)i/10)*10));
2373 		}
2374 		else if (i == 10)
2375 			strcpy(buf->release, "2.1");
2376 		else if (i == 0)
2377 			strcpy(buf->release, "2.0");
2378 		strcpy(buf->machine, "i386");
2379 		if(getenv("HOSTNAME") != NULL)
2380 			strcpy(buf->nodename, getenv("HOSTNAME"));
2381 		else
2382 			strcpy(buf->nodename, "unknown");
2383 	}
2384 	return 0;
2385 }
2386 #endif
2387 
2388 
2389 #ifdef WINNT
tputs(const unsigned char * str,int nlines,int (* outfun)(int))2390 int tputs(const unsigned char *str, int nlines, int (*outfun)(int))
2391 {
2392 register unsigned int count = 0;
2393   /* Safety check. */
2394 	if (str)
2395 	{
2396 		/* Now output the capability string. */
2397 		while (*str)
2398 			(*outfun) (*str++), count++;
2399 	}
2400 	return count;
2401 }
2402 #endif
2403