Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/source/compat.c
1069 views
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
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
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 */
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
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
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
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
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
*/
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
*/
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
#if 1
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
*/
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
*/
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
*/
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
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
*/
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
*/
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 <[email protected]>
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 3 2008-02-25 09:49:14Z 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
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
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
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
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
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 <[email protected]>
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
*/
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
*/
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
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: 3 $
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
*/
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 proctitlestr[140];
2152
char **Argv = NULL; /* pointer to argument vector */
2153
char *LastArgv = NULL; /* end of argv */
2154
2155
/** SETPROCTITLE -- set process title for ps
2156
**
2157
** Parameters:
2158
** fmt -- a printf style format string.
2159
** a, b, c -- possible parameters to fmt.
2160
**
2161
** Returns:
2162
** none.
2163
**
2164
** Side Effects:
2165
** Clobbers argv of our main procedure so ps(1) will
2166
** display the title.
2167
*/
2168
2169
#define SPT_NONE 0 /* don't use it at all */
2170
#define SPT_REUSEARGV 1 /* cover argv with title information */
2171
#define SPT_BUILTIN 2 /* use libc builtin */
2172
#define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
2173
#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
2174
#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
2175
#define SPT_SCO 6 /* write kernel u. area */
2176
#define SPT_CHANGEARGV 7 /* write our own strings into argv[] */
2177
#define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf))
2178
2179
#ifndef SPT_TYPE
2180
# define SPT_TYPE SPT_REUSEARGV
2181
#endif
2182
2183
#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
2184
2185
# if SPT_TYPE == SPT_PSTAT
2186
# include <sys/pstat.h>
2187
# endif
2188
# if SPT_TYPE == SPT_PSSTRINGS
2189
# include <machine/vmparam.h>
2190
# include <sys/exec.h>
2191
# ifndef PS_STRINGS /* hmmmm.... apparently not available after all */
2192
# undef SPT_TYPE
2193
# define SPT_TYPE SPT_REUSEARGV
2194
# else
2195
# ifndef NKPDE /* FreeBSD 2.0 */
2196
# define NKPDE 63
2197
typedef unsigned int *pt_entry_t;
2198
# endif
2199
# endif
2200
# endif
2201
2202
# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
2203
# define SETPROC_STATIC static
2204
# else
2205
# define SETPROC_STATIC
2206
# endif
2207
2208
# if SPT_TYPE == SPT_SYSMIPS
2209
# include <sys/sysmips.h>
2210
# include <sys/sysnews.h>
2211
# endif
2212
2213
# if SPT_TYPE == SPT_SCO
2214
# include <sys/immu.h>
2215
# include <sys/dir.h>
2216
# include <sys/user.h>
2217
# include <sys/fs/s5param.h>
2218
# if PSARGSZ > MAXLINE
2219
# define SPT_BUFSIZE PSARGSZ
2220
# endif
2221
# endif
2222
2223
# ifndef SPT_PADCHAR
2224
# define SPT_PADCHAR ' '
2225
# endif
2226
2227
# ifndef SPT_BUFSIZE
2228
# define SPT_BUFSIZE 140
2229
# endif
2230
2231
#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
2232
extern char **Argv;
2233
extern char *LastArgv;
2234
2235
/*
2236
** Pointers for setproctitle.
2237
** This allows "ps" listings to give more useful information.
2238
*/
2239
void initsetproctitle(int argc, char **argv, char **envp)
2240
{
2241
register int i, envpsize = 0;
2242
extern char **environ;
2243
2244
/*
2245
** Move the environment so setproctitle can use the space at
2246
** the top of memory.
2247
*/
2248
2249
for (i = 0; envp[i] != NULL; i++)
2250
envpsize += strlen(envp[i]) + 1;
2251
environ = (char **) malloc(sizeof (char *) * (i + 1));
2252
for (i = 0; envp[i] != NULL; i++)
2253
environ[i] = strdup(envp[i]);
2254
environ[i] = NULL;
2255
2256
/*
2257
** Save start and extent of argv for setproctitle.
2258
*/
2259
2260
Argv = argv;
2261
2262
/*
2263
** Find the last environment variable within sendmail's
2264
** process memory area.
2265
*/
2266
while (i > 0 && (envp[i - 1] < argv[0] ||
2267
envp[i - 1] > (argv[argc - 1] +
2268
strlen(argv[argc - 1]) + 1 + envpsize)))
2269
i--;
2270
2271
if (i > 0)
2272
LastArgv = envp[i - 1] + strlen(envp[i - 1]);
2273
else
2274
LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
2275
}
2276
2277
void setproctitle(const char *fmt, ...)
2278
{
2279
#if defined(CLOAKED)
2280
/* this was removed from wu-ftpd which removed it from sendmail */
2281
register char *p;
2282
register int i;
2283
SETPROC_STATIC char buf[SPT_BUFSIZE];
2284
#if SPT_TYPE == SPT_PSTAT
2285
union pstun pst;
2286
#endif
2287
#if SPT_TYPE == SPT_SCO
2288
off_t seek_off;
2289
static int kmem = -1;
2290
static int kmempid = -1;
2291
struct user u;
2292
#endif
2293
va_list args;
2294
2295
p = buf;
2296
2297
*p = 0;
2298
p += strlen(p);
2299
2300
/* print the argument string */
2301
va_start(args, fmt);
2302
(void) vsnprintf(p, SPACELEFT(buf, p), fmt, args);
2303
va_end(args);
2304
2305
i = strlen(buf);
2306
2307
#if SPT_TYPE == SPT_PSTAT
2308
pst.pst_command = buf;
2309
pstat(PSTAT_SETCMD, pst, i, 0, 0);
2310
#endif
2311
#if SPT_TYPE == SPT_PSSTRINGS
2312
PS_STRINGS->ps_nargvstr = 1;
2313
PS_STRINGS->ps_argvstr = buf;
2314
#endif
2315
#if SPT_TYPE == SPT_SYSMIPS
2316
sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
2317
#endif
2318
#if SPT_TYPE == SPT_SCO
2319
if (kmem < 0 || kmempid != getpid())
2320
{
2321
if (kmem >= 0)
2322
close(kmem);
2323
kmem = open(_PATH_KMEM, O_RDWR, 0);
2324
if (kmem < 0)
2325
return;
2326
(void) fcntl(kmem, F_SETFD, 1);
2327
kmempid = getpid();
2328
}
2329
buf[PSARGSZ - 1] = '\0';
2330
seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
2331
if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
2332
(void) write(kmem, buf, PSARGSZ);
2333
#endif
2334
#if SPT_TYPE == SPT_REUSEARGV
2335
if (i > LastArgv - Argv[0] - 2)
2336
{
2337
i = LastArgv - Argv[0] - 2;
2338
buf[i] = '\0';
2339
}
2340
(void) strcpy(Argv[0], buf);
2341
p = &Argv[0][i];
2342
while (p < LastArgv)
2343
*p++ = SPT_PADCHAR;
2344
Argv[1] = NULL;
2345
#endif
2346
#if SPT_TYPE == SPT_CHANGEARGV
2347
Argv[0] = buf;
2348
Argv[1] = 0;
2349
#endif
2350
#endif /* SPT_TYPE != SPT_NONE */
2351
}
2352
#endif /* CLOAKED */
2353
2354
/* --- end of misc stuff --- */
2355
2356
#ifdef __EMX__
2357
#include <sys/utsname.h>
2358
int uname(struct utsname *buf)
2359
{
2360
ULONG aulBuffer[4];
2361
APIRET rc;
2362
if (!buf) return EFAULT;
2363
rc = DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_MS_COUNT,(void *)aulBuffer, 4*sizeof(ULONG));
2364
strcpy(buf->sysname,"OS/2");
2365
strcpy(buf->release, "1.x");
2366
if (aulBuffer[0] == 20)
2367
{
2368
int i = (unsigned int)aulBuffer[1];
2369
strcpy(buf->release, ltoa(i));
2370
if (i > 20)
2371
{
2372
strcpy(buf->sysname,"Warp");
2373
sprintf(buf->release, "%d.%d", (int)i/10, i-(((int)i/10)*10));
2374
}
2375
else if (i == 10)
2376
strcpy(buf->release, "2.1");
2377
else if (i == 0)
2378
strcpy(buf->release, "2.0");
2379
strcpy(buf->machine, "i386");
2380
if(getenv("HOSTNAME") != NULL)
2381
strcpy(buf->nodename, getenv("HOSTNAME"));
2382
else
2383
strcpy(buf->nodename, "unknown");
2384
}
2385
return 0;
2386
}
2387
#endif
2388
2389
2390
#ifdef WINNT
2391
int tputs(const unsigned char *str, int nlines, int (*outfun)(int))
2392
{
2393
register unsigned int count = 0;
2394
/* Safety check. */
2395
if (str)
2396
{
2397
/* Now output the capability string. */
2398
while (*str)
2399
(*outfun) (*str++), count++;
2400
}
2401
return count;
2402
}
2403
#endif
2404
2405
/* ----------------------- start of base64 stuff ---------------------------*/
2406
/*
2407
* Copyright (c) 1995-2001 Kungliga Tekniska H�gskolan
2408
* (Royal Institute of Technology, Stockholm, Sweden).
2409
* All rights reserved.
2410
*
2411
* This is licensed under the 3-clause BSD license, which is found above.
2412
*/
2413
2414
static char base64_chars[] =
2415
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2416
2417
/*
2418
* Return a malloced, base64 string representation of the first 'size' bytes
2419
* starting at 'data'. Returns strlen(*str).
2420
*/
2421
int my_base64_encode (const void *data, int size, char **str)
2422
{
2423
char *s, *p;
2424
int i;
2425
unsigned c;
2426
const unsigned char *q;
2427
2428
// XXX
2429
// p = s = (char *)new_malloc(size * 4 / 3 + 4);
2430
p = s = (char *)malloc(size * 4 / 3 + 4);
2431
if (p == NULL)
2432
return -1;
2433
q = (const unsigned char *) data;
2434
i = 0;
2435
for (i = 0; i < size;) {
2436
c = (unsigned)(unsigned char)q[i++];
2437
c *= 256;
2438
if (i < size)
2439
c += (unsigned)(unsigned char)q[i];
2440
i++;
2441
c *= 256;
2442
if (i < size)
2443
c += (unsigned)(unsigned char)q[i];
2444
i++;
2445
p[0] = base64_chars[(c & 0x00fc0000) >> 18];
2446
p[1] = base64_chars[(c & 0x0003f000) >> 12];
2447
p[2] = base64_chars[(c & 0x00000fc0) >> 6];
2448
p[3] = base64_chars[(c & 0x0000003f) >> 0];
2449
if (i > size)
2450
p[3] = '=';
2451
if (i > size + 1)
2452
p[2] = '=';
2453
p += 4;
2454
}
2455
*p = 0;
2456
*str = s;
2457
return strlen(s);
2458
}
2459
2460