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