1 /*
2  * This file is part of DGD, https://github.com/dworkin/dgd
3  * Copyright (C) 1993-2010 Dworkin B.V.
4  * Copyright (C) 2010-2012 DGD Authors (see the commit log for details)
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 # ifndef FUNCDEF
21 # define INCLUDE_CTYPE
22 # include "kfun.h"
23 # include "parse.h"
24 # include "asn.h"
25 # endif
26 
27 # ifdef FUNCDEF
28 FUNCDEF("encrypt", kf_encrypt, pt_encrypt, 0)
29 # else
30 extern string *P_encrypt_des_key (frame*, string*);
31 extern string *P_encrypt_des (frame*, string*, string*);
32 
33 char pt_encrypt[] = { C_TYPECHECKED | C_STATIC, 2, 1, 0, 9, T_MIXED, T_STRING,
34 		      T_STRING, T_STRING };
35 
36 /*
37  * NAME:	kfun->enc_key()
38  * DESCRIPTION:	prepare a key for encryption
39  */
40 void kf_enc_key(frame *f, int nargs, value *val)
41 {
42     string *str;
43 
44     if (nargs != 1) {
45 	error("Too many arguments for kfun encrypt");
46     }
47     str = P_encrypt_des_key(f, f->sp->u.string);
48     PUT_STRVAL_NOREF(val, str);
49 }
50 
51 /*
52  * NAME:	kfun->enc()
53  * DESCRIPTION:	encrypt
54  */
55 void kf_enc(frame *f, int nargs, value *val)
56 {
57     string *str;
58 
59     if (nargs != 2) {
60 	error("Too few arguments for kfun encrypt");
61     }
62     str = P_encrypt_des(f, f->sp[1].u.string, f->sp->u.string);
63     PUT_STRVAL_NOREF(val, str);
64 }
65 # endif
66 
67 
68 # ifdef FUNCDEF
69 FUNCDEF("decrypt", kf_decrypt, pt_decrypt, 0)
70 # else
71 extern string *P_decrypt_des_key (frame*, string*);
72 
73 char pt_decrypt[] = { C_TYPECHECKED | C_STATIC, 2, 1, 0, 9, T_MIXED, T_STRING,
74 		      T_STRING, T_STRING };
75 
76 /*
77  * NAME:	kfun->dec_key()
78  * DESCRIPTION:	prepare a key for decryption
79  */
80 void kf_dec_key(frame *f, int nargs, value *val)
81 {
82     string *str;
83 
84     if (nargs != 1) {
85 	error("Too many arguments for kfun decrypt");
86     }
87     str = P_decrypt_des_key(f, f->sp->u.string);
88     PUT_STRVAL_NOREF(val, str);
89 }
90 
91 /*
92  * NAME:	kfun->dec()
93  * DESCRIPTION:	decrypt
94  */
95 void kf_dec(frame *f, int nargs, value *val)
96 {
97     string *str;
98 
99     if (nargs != 2) {
100 	error("Too few arguments for kfun decrypt");
101     }
102     /* Given the proper key, DES is its own inverse */
103     str = P_encrypt_des(f, f->sp[1].u.string, f->sp->u.string);
104     PUT_STRVAL_NOREF(val, str);
105 }
106 # endif
107 
108 
109 # ifdef FUNCDEF
110 FUNCDEF("ctime", kf_ctime, pt_ctime, 0)
111 # else
112 char pt_ctime[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_STRING, T_INT };
113 
114 /*
115  * NAME:	kfun->ctime()
116  * DESCRIPTION:	convert a time value to a string
117  */
118 int kf_ctime(frame *f)
119 {
120     char buf[26];
121 
122     i_add_ticks(f, 5);
123     P_ctime(buf, f->sp->u.number);
124     PUT_STRVAL(f->sp, str_new(buf, 24L));
125 
126     return 0;
127 }
128 # endif
129 
130 
131 # ifdef FUNCDEF
132 FUNCDEF("explode", kf_explode, pt_explode, 0)
133 # else
134 char pt_explode[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8,
135 		      T_STRING | (1 << REFSHIFT), T_STRING, T_STRING };
136 
137 /*
138  * NAME:	kfun->explode()
139  * DESCRIPTION:	explode a string
140  */
141 int kf_explode(frame *f)
142 {
143     unsigned int len, slen, size;
144     char *p, *s;
145     value *v;
146     array *a;
147 
148     p = f->sp[1].u.string->text;
149     len = f->sp[1].u.string->len;
150     s = f->sp->u.string->text;
151     slen = f->sp->u.string->len;
152 
153     if (len == 0) {
154 	/*
155 	 * exploding "" always gives an empty array
156 	 */
157 	a = arr_new(f->data, 0L);
158     } else if (slen == 0) {
159 	/*
160 	 * the sepatator is ""; split string into single characters
161 	 */
162 	a = arr_new(f->data, (long) len);
163 	for (v = a->elts; len > 0; v++, --len) {
164 	    PUT_STRVAL(v, str_new(p, 1L));
165 	    p++;
166 	}
167     } else {
168 	/*
169 	 * split up the string with the separator
170 	 */
171 	size = 1;
172 	if (len >= slen && memcmp(p, s, slen) == 0) {
173 	    /* skip leading separator */
174 	    p += slen;
175 	    len -= slen;
176 	}
177 	while (len > slen) {
178 	    if (memcmp(p, s, slen) == 0) {
179 		/* separator found */
180 		p += slen;
181 		len -= slen;
182 		size++;
183 	    } else {
184 		/* next char */
185 		p++;
186 		--len;
187 	    }
188 	}
189 
190 	a = arr_new(f->data, (long) size);
191 	v = a->elts;
192 
193 	p = f->sp[1].u.string->text;
194 	len = f->sp[1].u.string->len;
195 	size = 0;
196 	if (len > slen && memcmp(p, s, slen) == 0) {
197 	    /* skip leading separator */
198 	    p += slen;
199 	    len -= slen;
200 	}
201 	while (len > slen) {
202 	    if (memcmp(p, s, slen) == 0) {
203 		/* separator found */
204 		PUT_STRVAL(v, str_new(p - size, (long) size));
205 		v++;
206 		p += slen;
207 		len -= slen;
208 		size = 0;
209 	    } else {
210 		/* next char */
211 		p++;
212 		--len;
213 		size++;
214 	    }
215 	}
216 	if (len != slen || memcmp(p, s, slen) != 0) {
217 	    /* remainder isn't a sepatator */
218 	    size += len;
219 	    p += len;
220 	}
221 	/* final array element */
222 	PUT_STRVAL(v, str_new(p - size, (long) size));
223     }
224 
225     str_del((f->sp++)->u.string);
226     str_del(f->sp->u.string);
227     PUT_ARRVAL(f->sp, a);
228     i_add_ticks(f, (Int) 2 * a->size);
229 
230     return 0;
231 }
232 # endif
233 
234 
235 # ifdef FUNCDEF
236 FUNCDEF("implode", kf_implode, pt_implode, 0)
237 # else
238 char pt_implode[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING,
239 		      T_STRING | (1 << REFSHIFT), T_STRING };
240 
241 /*
242  * NAME:	kfun->implode()
243  * DESCRIPTION:	implode an array
244  */
245 int kf_implode(frame *f)
246 {
247     long len;
248     unsigned int i, slen;
249     char *p, *s;
250     value *v;
251     string *str;
252 
253     s = f->sp->u.string->text;
254     slen = f->sp->u.string->len;
255 
256     /* first, determine the size of the imploded string */
257     i = f->sp[1].u.array->size;
258     i_add_ticks(f, i);
259     if (i != 0) {
260 	len = (i - 1) * (long) slen;	/* size of all separators */
261 	for (v = d_get_elts(f->sp[1].u.array); i > 0; v++, --i) {
262 	    if (v->type != T_STRING) {
263 		/* not a (string *) */
264 		return 1;
265 	    }
266 	    len += v->u.string->len;
267 	}
268 	str = str_new((char *) NULL, len);
269 
270 	/* create the imploded string */
271 	p = str->text;
272 	for (i = f->sp[1].u.array->size, v -= i; i > 1; --i, v++) {
273 	    /* copy array part */
274 	    memcpy(p, v->u.string->text, v->u.string->len);
275 	    p += v->u.string->len;
276 	    /* copy separator */
277 	    memcpy(p, s, slen);
278 	    p += slen;
279 	}
280 	/* copy final array part */
281 	memcpy(p, v->u.string->text, v->u.string->len);
282     } else {
283 	/* zero size array gives zero size string */
284 	str = str_new((char *) NULL, 0L);
285     }
286 
287     str_del((f->sp++)->u.string);
288     arr_del(f->sp->u.array);
289     PUT_STRVAL(f->sp, str);
290     return 0;
291 }
292 # endif
293 
294 
295 # ifdef FUNCDEF
296 FUNCDEF("random", kf_random, pt_random, 0)
297 # else
298 char pt_random[] = { C_TYPECHECKED | C_STATIC, 1, 0, 0, 7, T_INT, T_INT };
299 
300 /*
301  * NAME:	kfun->random()
302  * DESCRIPTION:	return a random number
303  */
304 int kf_random(frame *f)
305 {
306     i_add_ticks(f, 1);
307     PUT_INT(f->sp, (f->sp->u.number > 0) ? P_random() % f->sp->u.number : 0);
308     return 0;
309 }
310 # endif
311 
312 
313 # ifdef FUNCDEF
314 FUNCDEF("sscanf", kf_sscanf, pt_sscanf, 0)
315 # else
316 char pt_sscanf[] = { C_STATIC | C_ELLIPSIS, 2, 1, 0, 9, T_INT, T_STRING,
317 		     T_STRING, T_LVALUE };
318 
319 /*
320  * NAME:	match
321  * DESCRIPTION:	match a string possibly including %%, up to the next %[sdfc] or
322  *		the end of the string
323  */
324 static bool match(char *f, char *s, unsigned int *flenp, unsigned int *slenp)
325 {
326     char *p;
327     unsigned int flen, slen;
328 
329     flen = *flenp;
330     slen = *slenp;
331 
332     while (flen > 0) {
333 	/* look for first % */
334 	p = (char *) memchr(f, '%', flen);
335 
336 	if (p == (char *) NULL) {
337 	    /* no remaining % */
338 	    if (memcmp(f, s, flen) == 0) {
339 		*slenp -= slen - flen;
340 		return TRUE;
341 	    } else {
342 		return FALSE;	/* no match */
343 	    }
344 	}
345 
346 	if (p[1] == '%') {
347 	    /* %% */
348 	    if (memcmp(f, s, ++p - f) == 0) {
349 		/* matched up to and including the first % */
350 		s += p - f;
351 		slen -= p - f;
352 		flen -= ++p - f;
353 		f = p;
354 	    } else {
355 		return FALSE;	/* no match */
356 	    }
357 	} else if (memcmp(f, s, p - f) == 0) {
358 	    /* matched up to the first % */
359 	    *flenp -= flen - (p - f);
360 	    *slenp -= slen - (p - f);
361 	    return TRUE;
362 	} else {
363 	    return FALSE;	/* no match */
364 	}
365     }
366 
367     *slenp -= slen;
368     return TRUE;
369 }
370 
371 /*
372  * NAME:	kfun->sscanf()
373  * DESCRIPTION:	scan a string
374  */
375 int kf_sscanf(frame *f, int nargs)
376 {
377     unsigned int flen, slen, size;
378     char *format, *x;
379     unsigned int fl, sl;
380     int matches;
381     char *s;
382     Int i;
383     xfloat flt;
384     bool skip;
385     value *top, *v;
386 
387     size = 0;
388     x = NULL;
389 
390     if (nargs < 2) {
391 	return -1;
392     }
393     nargs -= 2;
394     if (nargs > MAX_LOCALS) {
395 	return 4;
396     }
397     top = i_reverse(f, nargs);
398     if (top[1].type != T_STRING) {
399 	return 1;
400     }
401     s = top[1].u.string->text;
402     slen = top[1].u.string->len;
403     if (top[0].type != T_STRING) {
404 	return 2;
405     }
406     format = top[0].u.string->text;
407     flen = top[0].u.string->len;
408 
409     i_add_ticks(f, 8 * nargs);
410     matches = 0;
411 
412     while (flen > 0) {
413 	if (format[0] != '%' || format[1] == '%') {
414 	    /* match initial part */
415 	    fl = flen;
416 	    sl = slen;
417 	    if (!match(format, s, &fl, &sl) || fl == flen) {
418 		goto no_match;
419 	    }
420 	    format += fl;
421 	    flen -= fl;
422 	    s += sl;
423 	    slen -= sl;
424 	}
425 
426 	/* skip first % */
427 	format++;
428 	--flen;
429 
430 	/*
431 	 * check for %*
432 	 */
433 	if (*format == '*') {
434 	    /* no assignment */
435 	    format++;
436 	    --flen;
437 	    skip = TRUE;
438 	} else {
439 	    skip = FALSE;
440 	}
441 
442 	--flen;
443 	switch (*format++) {
444 	case 's':
445 	    /* %s */
446 	    if (format[0] == '%' && format[1] != '%') {
447 		switch ((format[1] == '*') ? format[2] : format[1]) {
448 		case 'd':
449 		    /*
450 		     * %s%d
451 		     */
452 		    size = slen;
453 		    x = s;
454 		    while (!isdigit(*x)) {
455 			if (slen == 0) {
456 			    goto no_match;
457 			}
458 			if (x[0] == '-' && isdigit(x[1])) {
459 			    break;
460 			}
461 			x++;
462 			--slen;
463 		    }
464 		    size -= slen;
465 		    break;
466 
467 		case 'f':
468 		    /*
469 		     * %s%f
470 		     */
471 		    size = slen;
472 		    x = s;
473 		    while (!isdigit(*x)) {
474 			if (slen == 0) {
475 			    goto no_match;
476 			}
477 			if ((x[0] == '-' || x[0] == '.') && isdigit(x[1])) {
478 			    break;
479 			}
480 			x++;
481 			--slen;
482 		    }
483 		    size -= slen;
484 		    break;
485 
486 		default:
487 		    error("Bad sscanf format string");
488 		}
489 	    } else {
490 		/*
491 		 * %s followed by non-%
492 		 */
493 		if (flen == 0) {
494 		    /* match whole string */
495 		    size = slen;
496 		    x = s + slen;
497 		    slen = 0;
498 		} else {
499 		    /* get # of chars to match after string */
500 		    for (x = format, size = 0; x - format != flen;
501 			 x++, size++) {
502 			x = (char *) memchr(x, '%', flen - (x - format));
503 			if (x == (char *) NULL) {
504 			    x = format + flen;
505 			    break;
506 			} else if (x[1] != '%') {
507 			    break;
508 			}
509 		    }
510 		    size = (x - format) - size;
511 
512 		    x = s;
513 		    for (;;) {
514 			sl = slen - (x - s);
515 			if (sl < size) {
516 			    goto no_match;
517 			}
518 			x = (char *) memchr(x, format[0], sl - size + 1);
519 			if (x == (char *) NULL) {
520 			    goto no_match;
521 			}
522 			fl = flen;
523 			if (match(format, x, &fl, &sl)) {
524 			    format += fl;
525 			    flen -= fl;
526 			    size = x - s;
527 			    x += sl;
528 			    slen -= size + sl;
529 			    break;
530 			}
531 			x++;
532 		    }
533 		}
534 	    }
535 
536 	    if (!skip) {
537 		if (nargs == 0) {
538 		    error("No lvalue for %%s");
539 		}
540 		--nargs;
541 		PUSH_STRVAL(f, str_new(s, (long) size));
542 		v = f->sp;
543 		i_store(f);
544 		v->u.string->ref--;
545 	    }
546 	    s = x;
547 	    break;
548 
549 	case 'd':
550 	    /* %d */
551 	    x = s;
552 	    while (slen != 0 && *x == ' ') {
553 		x++;
554 		--slen;
555 	    }
556 	    s = x;
557 	    i = strtoint(&s);
558 	    if (s == x) {
559 		goto no_match;
560 	    }
561 	    slen -= (s - x);
562 
563 	    if (!skip) {
564 		if (nargs == 0) {
565 		    error("No lvalue for %%d");
566 		}
567 		--nargs;
568 		PUSH_INTVAL(f, i);
569 		i_store(f);
570 	    }
571 	    break;
572 
573 	case 'f':
574 	    /* %f */
575 	    x = s;
576 	    while (slen != 0 && *x == ' ') {
577 		x++;
578 		--slen;
579 	    }
580 	    s = x;
581 	    if (!flt_atof(&s, &flt) || s == x) {
582 		goto no_match;
583 	    }
584 	    slen -= (s - x);
585 
586 	    if (!skip) {
587 		if (nargs == 0) {
588 		    error("No lvalue for %%f");
589 		}
590 		--nargs;
591 		PUSH_FLTVAL(f, flt);
592 		i_store(f);
593 	    }
594 	    break;
595 
596 	case 'c':
597 	    /* %c */
598 	    if (slen == 0) {
599 		goto no_match;
600 	    }
601 	    if (!skip) {
602 		if (nargs == 0) {
603 		    error("No lvalue for %%c");
604 		}
605 		--nargs;
606 		PUSH_INTVAL(f, UCHAR(*s));
607 		i_store(f);
608 	    }
609 	    s++;
610 	    --slen;
611 	    break;
612 
613 	default:
614 	    error("Bad sscanf format string");
615 	}
616 	matches++;
617     }
618 
619 no_match:
620     i_pop(f, top - f->sp + 2);
621     PUSH_INTVAL(f, matches);
622     return 0;
623 }
624 # endif
625 
626 
627 # ifdef FUNCDEF
628 FUNCDEF("parse_string", kf_parse_string, pt_parse_string, 0)
629 # else
630 char pt_parse_string[] = { C_TYPECHECKED | C_STATIC, 2, 1, 0, 9,
631 			   T_MIXED | (1 << REFSHIFT), T_STRING, T_STRING,
632 			   T_INT };
633 
634 /*
635  * NAME:	kfun->parse_string()
636  * DESCRIPTION:	parse a string
637  */
638 int kf_parse_string(frame *f, int nargs)
639 {
640     Int maxalt;
641     array *a;
642 
643     if (nargs > 2) {
644 	maxalt = (f->sp++)->u.number + 1;
645 	if (maxalt <= 0) {
646 	    return 3;
647 	}
648     } else {
649 	maxalt = 1;	/* default: just one valid parse tree */
650     }
651 
652     if (OBJR(f->oindex)->flags & O_SPECIAL) {
653 	error("parse_string() from special purpose object");
654     }
655 
656     a = ps_parse_string(f, f->sp[1].u.string, f->sp->u.string, maxalt);
657     str_del((f->sp++)->u.string);
658     str_del(f->sp->u.string);
659 
660     if (a != (array *) NULL) {
661 	/* return parse tree */
662 	PUT_ARRVAL(f->sp, a);
663     } else {
664 	/* parsing failed */
665 	*f->sp = nil_value;
666     }
667     return 0;
668 }
669 # endif
670 
671 
672 # ifdef FUNCDEF
673 FUNCDEF("hash_crc16", kf_hash_crc16, pt_hash_crc16, 0)
674 # else
675 char pt_hash_crc16[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
676 			 T_INT, T_STRING, T_STRING };
677 
678 /*
679  * NAME:	kfun->hash_crc16()
680  * DESCRIPTION:	Compute a 16 bit cyclic redundancy code for a string.
681  *		Based on "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS",
682  *		by Ross N. Williams.
683  *
684  *		    Name:	"CRC-16/CCITT"	(supposedly)
685  *		    Width:	16
686  *		    Poly:	1021		(X^16 + X^12 + X^5 + 1)
687  *		    Init:	FFFF
688  *		    RefIn:	False
689  *		    RefOut:	False
690  *		    XorOut:	0000
691  *		    Check:	29B1
692  */
693 int kf_hash_crc16(frame *f, int nargs)
694 {
695     static unsigned short crctab[] = {
696 	0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xa550, 0xc660, 0xe770,
697 	0x0881, 0x2991, 0x4aa1, 0x6bb1, 0x8cc1, 0xadd1, 0xcee1, 0xeff1,
698 	0x3112, 0x1002, 0x7332, 0x5222, 0xb552, 0x9442, 0xf772, 0xd662,
699 	0x3993, 0x1883, 0x7bb3, 0x5aa3, 0xbdd3, 0x9cc3, 0xfff3, 0xdee3,
700 	0x6224, 0x4334, 0x2004, 0x0114, 0xe664, 0xc774, 0xa444, 0x8554,
701 	0x6aa5, 0x4bb5, 0x2885, 0x0995, 0xeee5, 0xcff5, 0xacc5, 0x8dd5,
702 	0x5336, 0x7226, 0x1116, 0x3006, 0xd776, 0xf666, 0x9556, 0xb446,
703 	0x5bb7, 0x7aa7, 0x1997, 0x3887, 0xdff7, 0xfee7, 0x9dd7, 0xbcc7,
704 	0xc448, 0xe558, 0x8668, 0xa778, 0x4008, 0x6118, 0x0228, 0x2338,
705 	0xccc9, 0xedd9, 0x8ee9, 0xaff9, 0x4889, 0x6999, 0x0aa9, 0x2bb9,
706 	0xf55a, 0xd44a, 0xb77a, 0x966a, 0x711a, 0x500a, 0x333a, 0x122a,
707 	0xfddb, 0xdccb, 0xbffb, 0x9eeb, 0x799b, 0x588b, 0x3bbb, 0x1aab,
708 	0xa66c, 0x877c, 0xe44c, 0xc55c, 0x222c, 0x033c, 0x600c, 0x411c,
709 	0xaeed, 0x8ffd, 0xeccd, 0xcddd, 0x2aad, 0x0bbd, 0x688d, 0x499d,
710 	0x977e, 0xb66e, 0xd55e, 0xf44e, 0x133e, 0x322e, 0x511e, 0x700e,
711 	0x9fff, 0xbeef, 0xdddf, 0xfccf, 0x1bbf, 0x3aaf, 0x599f, 0x788f,
712 	0x8891, 0xa981, 0xcab1, 0xeba1, 0x0cd1, 0x2dc1, 0x4ef1, 0x6fe1,
713 	0x8010, 0xa100, 0xc230, 0xe320, 0x0450, 0x2540, 0x4670, 0x6760,
714 	0xb983, 0x9893, 0xfba3, 0xdab3, 0x3dc3, 0x1cd3, 0x7fe3, 0x5ef3,
715 	0xb102, 0x9012, 0xf322, 0xd232, 0x3542, 0x1452, 0x7762, 0x5672,
716 	0xeab5, 0xcba5, 0xa895, 0x8985, 0x6ef5, 0x4fe5, 0x2cd5, 0x0dc5,
717 	0xe234, 0xc324, 0xa014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544,
718 	0xdba7, 0xfab7, 0x9987, 0xb897, 0x5fe7, 0x7ef7, 0x1dc7, 0x3cd7,
719 	0xd326, 0xf236, 0x9106, 0xb016, 0x5766, 0x7676, 0x1546, 0x3456,
720 	0x4cd9, 0x6dc9, 0x0ef9, 0x2fe9, 0xc899, 0xe989, 0x8ab9, 0xaba9,
721 	0x4458, 0x6548, 0x0678, 0x2768, 0xc018, 0xe108, 0x8238, 0xa328,
722 	0x7dcb, 0x5cdb, 0x3feb, 0x1efb, 0xf98b, 0xd89b, 0xbbab, 0x9abb,
723 	0x754a, 0x545a, 0x376a, 0x167a, 0xf10a, 0xd01a, 0xb32a, 0x923a,
724 	0x2efd, 0x0fed, 0x6cdd, 0x4dcd, 0xaabd, 0x8bad, 0xe89d, 0xc98d,
725 	0x267c, 0x076c, 0x645c, 0x454c, 0xa23c, 0x832c, 0xe01c, 0xc10c,
726 	0x1fef, 0x3eff, 0x5dcf, 0x7cdf, 0x9baf, 0xbabf, 0xd98f, 0xf89f,
727 	0x176e, 0x367e, 0x554e, 0x745e, 0x932e, 0xb23e, 0xd10e, 0xf01e
728     };
729     unsigned short crc;
730     int i;
731     ssizet len;
732     char *p;
733     Int cost;
734 
735     cost = 0;
736     for (i = nargs; --i >= 0; ) {
737 	cost += f->sp[i].u.string->len;
738     }
739     cost = 3 * nargs + (cost >> 2);
740     if (!f->rlim->noticks && f->rlim->ticks <= cost) {
741 	f->rlim->ticks = 0;
742 	error("Out of ticks");
743     }
744     i_add_ticks(f, cost);
745 
746     crc = 0xffff;
747     for (i = nargs; --i >= 0; ) {
748 	p = f->sp[i].u.string->text;
749 	for (len = f->sp[i].u.string->len; len != 0; --len) {
750 	    crc = (crc >> 8) ^ crctab[UCHAR(crc ^ *p++)];
751 	}
752 	str_del(f->sp[i].u.string);
753     }
754     crc = (crc >> 8) + (crc << 8);
755 
756     f->sp += nargs - 1;
757     PUT_INTVAL(f->sp, crc);
758     return 0;
759 }
760 # endif
761 
762 
763 # ifdef FUNCDEF
764 FUNCDEF("hash_crc32", kf_hash_crc32, pt_hash_crc32, 0)
765 # else
766 char pt_hash_crc32[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
767 			 T_INT, T_STRING, T_STRING };
768 
769 /*
770  * NAME:	kfun->hash_crc32()
771  * DESCRIPTION:	Compute a 32 bit cyclic redundancy code for a string.
772  *		Based on "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS",
773  *		by Ross N. Williams.
774  *
775  *		    Name:	"CRC-32"	(as in libz)
776  *		    Width:	16
777  *		    Poly:	04C11DB7
778  *		    Init:	FFFFFFFF
779  *		    RefIn:	True
780  *		    RefOut:	True
781  *		    XorOut:	FFFFFFFF
782  *		    Check:	CBF43926
783  */
784 int kf_hash_crc32(frame *f, int nargs)
785 {
786     static Uint crctab[] = {
787 	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
788 	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
789 	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
790 	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
791 	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
792 	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
793 	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
794 	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
795 	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
796 	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
797 	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
798 	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
799 	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
800 	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
801 	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
802 	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
803 	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
804 	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
805 	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
806 	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
807 	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
808 	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
809 	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
810 	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
811 	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
812 	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
813 	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
814 	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
815 	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
816 	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
817 	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
818 	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
819 	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
820 	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
821 	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
822 	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
823 	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
824 	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
825 	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
826 	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
827 	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
828 	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
829 	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
830 	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
831 	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
832 	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
833 	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
834 	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
835 	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
836 	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
837 	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
838 	0x2d02ef8dL
839     };
840     Uint crc;
841     int i;
842     ssizet len;
843     char *p;
844     Int cost;
845 
846     cost = 0;
847     for (i = nargs; --i >= 0; ) {
848 	cost += f->sp[i].u.string->len;
849     }
850     cost = 3 * nargs + (cost >> 2);
851     if (!f->rlim->noticks && f->rlim->ticks <= cost) {
852 	f->rlim->ticks = 0;
853 	error("Out of ticks");
854     }
855     i_add_ticks(f, cost);
856 
857     crc = 0xffffffff;
858     for (i = nargs; --i >= 0; ) {
859 	p = f->sp[i].u.string->text;
860 	for (len = f->sp[i].u.string->len; len != 0; --len) {
861 	    crc = (crc >> 8) ^ crctab[UCHAR(crc ^ *p++)];
862 	}
863 	str_del(f->sp[i].u.string);
864     }
865     crc ^= 0xffffffffL;
866 
867     f->sp += nargs - 1;
868     PUT_INTVAL(f->sp, crc);
869     return 0;
870 }
871 # endif
872 
873 
874 # ifdef FUNCDEF
875 FUNCDEF("hash_string", kf_hash_string, pt_hash_string, 0)
876 # else
877 extern char *P_crypt (char*, char*);
878 
879 char pt_hash_string[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 2, 1, 0, 9,
880 			  T_STRING, T_STRING, T_STRING, T_STRING };
881 
882 /*
883  * NAME:	kfun->xcrypt()
884  * DESCRIPTION:	hash a string with Unix password crypt
885  */
886 void kf_xcrypt(frame *f, int nargs, value *val)
887 {
888     static char salts[] =
889 	    "0123456789./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
890     char s[3];
891     string *str;
892 
893     if (nargs > 2) {
894 	error("Too many arguments for kfun hash_string");
895     }
896     if (nargs == 2 && f->sp->u.string->len >= 2) {
897 	/* fixed salt */
898 	s[0] = f->sp->u.string->text[0];
899 	s[1] = f->sp->u.string->text[1];
900     } else {
901 	Uint n;
902 
903 	/* random salt */
904 	n = P_random();
905 	s[0] = salts[n & 63];
906 	s[1] = salts[(n >> 8) & 63];
907     }
908     s[2] = '\0';
909 
910     i_add_ticks(f, 900);
911     str = str_new(P_crypt(f->sp[nargs - 1].u.string->text, s), 13);
912     PUT_STRVAL_NOREF(val, str);
913 }
914 
915 # define ROTL(x, s)			(((x) << s) | ((x) >> (32 - s)))
916 # define R1(a, b, c, d, Mj, s, ti)	(a += (((c ^ d) & b) ^ d) + Mj + ti, \
917 					 a = b + ROTL(a, s))
918 # define R2(a, b, c, d, Mj, s, ti)	(a += (((b ^ c) & d) ^ c) + Mj + ti, \
919 					 a = b + ROTL(a, s))
920 # define R3(a, b, c, d, Mj, s, ti)	(a += (b ^ c ^ d) + Mj + ti,	     \
921 					 a = b + ROTL(a, s))
922 # define R4(a, b, c, d, Mj, s, ti)	(a += (c ^ (b | ~d)) + Mj + ti,	     \
923 					 a = b + ROTL(a, s))
924 
925 /*
926  * NAME:	hash->md5_start()
927  * DESCRIPTION:	MD5 message digest.  See "Applied Cryptography" by Bruce
928  *		Schneier, Second Edition, p. 436-441.
929  */
930 static Int hash_md5_start(frame *f, int nargs, Uint *digest)
931 {
932     Int cost;
933 
934     /*
935      * These constants must apparently be little-endianized, though AC2 does
936      * not explicitly say so.
937      */
938     digest[0] = 0x67452301L;
939     digest[1] = 0xefcdab89L;
940     digest[2] = 0x98badcfeL;
941     digest[3] = 0x10325476L;
942 
943     cost = 3 * nargs + 64;
944     while (--nargs >= 0) {
945 	cost += f->sp[nargs].u.string->len;
946     }
947     return cost;
948 }
949 
950 /*
951  * NAME:	hash->md5_block()
952  * DESCRIPTION:	add another 512 bit block to the message digest
953  */
954 static void hash_md5_block(Uint *ABCD, char *block)
955 {
956     Uint M[16];
957     int i, j;
958     Uint a, b, c, d;
959 
960     for (i = j = 0; i < 16; i++, j += 4) {
961 	M[i] = UCHAR(block[j + 0]) | (UCHAR(block[j + 1]) << 8) |
962 	       (UCHAR(block[j + 2]) << 16) | (UCHAR(block[j + 3]) << 24);
963 
964     }
965 
966     a = ABCD[0];
967     b = ABCD[1];
968     c = ABCD[2];
969     d = ABCD[3];
970 
971     R1(a, b, c, d, M[ 0],  7, 0xd76aa478L);
972     R1(d, a, b, c, M[ 1], 12, 0xe8c7b756L);
973     R1(c, d, a, b, M[ 2], 17, 0x242070dbL);
974     R1(b, c, d, a, M[ 3], 22, 0xc1bdceeeL);
975     R1(a, b, c, d, M[ 4],  7, 0xf57c0fafL);
976     R1(d, a, b, c, M[ 5], 12, 0x4787c62aL);
977     R1(c, d, a, b, M[ 6], 17, 0xa8304613L);
978     R1(b, c, d, a, M[ 7], 22, 0xfd469501L);
979     R1(a, b, c, d, M[ 8],  7, 0x698098d8L);
980     R1(d, a, b, c, M[ 9], 12, 0x8b44f7afL);
981     R1(c, d, a, b, M[10], 17, 0xffff5bb1L);
982     R1(b, c, d, a, M[11], 22, 0x895cd7beL);
983     R1(a, b, c, d, M[12],  7, 0x6b901122L);
984     R1(d, a, b, c, M[13], 12, 0xfd987193L);
985     R1(c, d, a, b, M[14], 17, 0xa679438eL);
986     R1(b, c, d, a, M[15], 22, 0x49b40821L);
987 
988     R2(a, b, c, d, M[ 1],  5, 0xf61e2562L);
989     R2(d, a, b, c, M[ 6],  9, 0xc040b340L);
990     R2(c, d, a, b, M[11], 14, 0x265e5a51L);
991     R2(b, c, d, a, M[ 0], 20, 0xe9b6c7aaL);
992     R2(a, b, c, d, M[ 5],  5, 0xd62f105dL);
993     R2(d, a, b, c, M[10],  9, 0x02441453L);
994     R2(c, d, a, b, M[15], 14, 0xd8a1e681L);
995     R2(b, c, d, a, M[ 4], 20, 0xe7d3fbc8L);
996     R2(a, b, c, d, M[ 9],  5, 0x21e1cde6L);
997     R2(d, a, b, c, M[14],  9, 0xc33707d6L);
998     R2(c, d, a, b, M[ 3], 14, 0xf4d50d87L);
999     R2(b, c, d, a, M[ 8], 20, 0x455a14edL);
1000     R2(a, b, c, d, M[13],  5, 0xa9e3e905L);
1001     R2(d, a, b, c, M[ 2],  9, 0xfcefa3f8L);
1002     R2(c, d, a, b, M[ 7], 14, 0x676f02d9L);
1003     R2(b, c, d, a, M[12], 20, 0x8d2a4c8aL);
1004 
1005     R3(a, b, c, d, M[ 5],  4, 0xfffa3942L);
1006     R3(d, a, b, c, M[ 8], 11, 0x8771f681L);
1007     R3(c, d, a, b, M[11], 16, 0x6d9d6122L);
1008     R3(b, c, d, a, M[14], 23, 0xfde5380cL);
1009     R3(a, b, c, d, M[ 1],  4, 0xa4beea44L);
1010     R3(d, a, b, c, M[ 4], 11, 0x4bdecfa9L);
1011     R3(c, d, a, b, M[ 7], 16, 0xf6bb4b60L);
1012     R3(b, c, d, a, M[10], 23, 0xbebfbc70L);
1013     R3(a, b, c, d, M[13],  4, 0x289b7ec6L);
1014     R3(d, a, b, c, M[ 0], 11, 0xeaa127faL);
1015     R3(c, d, a, b, M[ 3], 16, 0xd4ef3085L);
1016     R3(b, c, d, a, M[ 6], 23, 0x04881d05L);
1017     R3(a, b, c, d, M[ 9],  4, 0xd9d4d039L);
1018     R3(d, a, b, c, M[12], 11, 0xe6db99e5L);
1019     R3(c, d, a, b, M[15], 16, 0x1fa27cf8L);
1020     R3(b, c, d, a, M[ 2], 23, 0xc4ac5665L);
1021 
1022     R4(a, b, c, d, M[ 0],  6, 0xf4292244L);
1023     R4(d, a, b, c, M[ 7], 10, 0x432aff97L);
1024     R4(c, d, a, b, M[14], 15, 0xab9423a7L);
1025     R4(b, c, d, a, M[ 5], 21, 0xfc93a039L);
1026     R4(a, b, c, d, M[12],  6, 0x655b59c3L);
1027     R4(d, a, b, c, M[ 3], 10, 0x8f0ccc92L);
1028     R4(c, d, a, b, M[10], 15, 0xffeff47dL);
1029     R4(b, c, d, a, M[ 1], 21, 0x85845dd1L);
1030     R4(a, b, c, d, M[ 8],  6, 0x6fa87e4fL);
1031     R4(d, a, b, c, M[15], 10, 0xfe2ce6e0L);
1032     R4(c, d, a, b, M[ 6], 15, 0xa3014314L);
1033     R4(b, c, d, a, M[13], 21, 0x4e0811a1L);
1034     R4(a, b, c, d, M[ 4],  6, 0xf7537e82L);
1035     R4(d, a, b, c, M[11], 10, 0xbd3af235L);
1036     R4(c, d, a, b, M[ 2], 15, 0x2ad7d2bbL);
1037     R4(b, c, d, a, M[ 9], 21, 0xeb86d391L);
1038 
1039     ABCD[0] += a;
1040     ABCD[1] += b;
1041     ABCD[2] += c;
1042     ABCD[3] += d;
1043 }
1044 
1045 /*
1046  * NAME:	hash->md5_end()
1047  * DESCRIPTION:	finish up MD5 hash
1048  */
1049 static string *hash_md5_end(Uint *digest, char *buffer, unsigned int bufsz, Uint length)
1050 {
1051     int i;
1052 
1053     /* append padding and digest final block(s) */
1054     buffer[bufsz++] = 0x80;
1055     if (bufsz > 56) {
1056 	memset(buffer + bufsz, '\0', 64 - bufsz);
1057 	hash_md5_block(digest, buffer);
1058 	bufsz = 0;
1059     }
1060     memset(buffer + bufsz, '\0', 64 - bufsz);
1061     buffer[56] = length << 3;
1062     buffer[57] = length >> 5;
1063     buffer[58] = length >> 13;
1064     buffer[59] = length >> 21;
1065     buffer[60] = length >> 29;
1066     hash_md5_block(digest, buffer);
1067 
1068     for (bufsz = i = 0; i < 4; bufsz += 4, i++) {
1069 	buffer[bufsz + 0] = digest[i];
1070 	buffer[bufsz + 1] = digest[i] >> 8;
1071 	buffer[bufsz + 2] = digest[i] >> 16;
1072 	buffer[bufsz + 3] = digest[i] >> 24;
1073     }
1074     return str_new(buffer, 16L);
1075 }
1076 
1077 /*
1078  * NAME:	hash->sha1_start()
1079  * DESCRIPTION:	SHA-1 message digest.  See FIPS 180-2.
1080  */
1081 static Int hash_sha1_start(frame *f, int nargs, Uint *digest)
1082 {
1083     Int cost;
1084 
1085     digest[0] = 0x67452301L;
1086     digest[1] = 0xefcdab89L;
1087     digest[2] = 0x98badcfeL;
1088     digest[3] = 0x10325476L;
1089     digest[4] = 0xc3d2e1f0L;
1090 
1091     cost = 3 * nargs + 64;
1092     while (--nargs >= 0) {
1093 	cost += f->sp[nargs].u.string->len;
1094     }
1095     return cost;
1096 }
1097 
1098 /*
1099  * NAME:	hash->sha1_block()
1100  * DESCRIPTION:	add another 512 bit block to the message digest
1101  */
1102 static void hash_sha1_block(Uint *ABCDE, char *block)
1103 {
1104     Uint W[80];
1105     int i, j;
1106     Uint a, b, c, d, e, t;
1107 
1108     for (i = j = 0; i < 16; i++, j += 4) {
1109        W[i] = (UCHAR(block[j + 0]) << 24) | (UCHAR(block[j + 1]) << 16) |
1110 	      (UCHAR(block[j + 2]) << 8) | UCHAR(block[j + 3]);
1111 
1112     }
1113     while (i < 80) {
1114 	W[i] = ROTL(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
1115 	i++;
1116     }
1117 
1118     a = ABCDE[0];
1119     b = ABCDE[1];
1120     c = ABCDE[2];
1121     d = ABCDE[3];
1122     e = ABCDE[4];
1123 
1124     for (i = 0; i < 20; i++) {
1125 	t = ROTL(a, 5) + (((c ^ d) & b) ^ d) + e + W[i] + 0x5a827999L;
1126 	e = d;
1127 	d = c;
1128 	c = ROTL(b, 30);
1129 	b = a;
1130 	a = t;
1131     }
1132     while (i < 40) {
1133 	t = ROTL(a, 5) + (b ^ c ^ d) + e + W[i] + 0x6ed9eba1L;
1134 	e = d;
1135 	d = c;
1136 	c = ROTL(b, 30);
1137 	b = a;
1138 	a = t;
1139 	i++;
1140     }
1141     while (i < 60) {
1142 	t = ROTL(a, 5) + ((b & c) | ((b | c) & d)) + e + W[i] + 0x8f1bbcdcL;
1143 	e = d;
1144 	d = c;
1145 	c = ROTL(b, 30);
1146 	b = a;
1147 	a = t;
1148 	i++;
1149     }
1150     while (i < 80) {
1151 	t = ROTL(a, 5) + (b ^ c ^ d) + e + W[i] + 0xca62c1d6L;
1152 	e = d;
1153 	d = c;
1154 	c = ROTL(b, 30);
1155 	b = a;
1156 	a = t;
1157 	i++;
1158     }
1159 
1160     ABCDE[0] += a;
1161     ABCDE[1] += b;
1162     ABCDE[2] += c;
1163     ABCDE[3] += d;
1164     ABCDE[4] += e;
1165 }
1166 
1167 
1168 /*
1169  * NAME:	hash->sha1_end()
1170  * DESCRIPTION:	finish up SHA-1 hash
1171  */
1172 static string *hash_sha1_end(Uint *digest, char *buffer, unsigned int bufsz, Uint length)
1173 {
1174     int i;
1175 
1176     /* append padding and digest final block(s) */
1177     buffer[bufsz++] = 0x80;
1178     if (bufsz > 56) {
1179 	memset(buffer + bufsz, '\0', 64 - bufsz);
1180 	hash_sha1_block(digest, buffer);
1181 	bufsz = 0;
1182     }
1183     memset(buffer + bufsz, '\0', 64 - bufsz);
1184     buffer[59] = length >> 29;
1185     buffer[60] = length >> 21;
1186     buffer[61] = length >> 13;
1187     buffer[62] = length >> 5;
1188     buffer[63] = length << 3;
1189     hash_sha1_block(digest, buffer);
1190 
1191     for (bufsz = i = 0; i < 5; bufsz += 4, i++) {
1192 	buffer[bufsz + 0] = digest[i] >> 24;
1193 	buffer[bufsz + 1] = digest[i] >> 16;
1194 	buffer[bufsz + 2] = digest[i] >> 8;
1195 	buffer[bufsz + 3] = digest[i];
1196     }
1197     return str_new(buffer, 20L);
1198 }
1199 
1200 /*
1201  * NAME:	hash->blocks()
1202  * DESCRIPTION:	hash string blocks with a given function
1203  */
1204 static Uint hash_blocks(frame *f, int nargs, Uint *digest, char *buffer,
1205 	unsigned short *bufsize, unsigned int blocksz,
1206 	void (*hash_block) (Uint*, char*))
1207 {
1208     ssizet len;
1209     unsigned short bufsz;
1210     char *p;
1211     Uint length;
1212 
1213     length = 0;
1214     bufsz = 0;
1215     while (--nargs >= 0) {
1216 	len = f->sp[nargs].u.string->len;
1217 	if (len != 0) {
1218 	    length += len;
1219 	    p = f->sp[nargs].u.string->text;
1220 	    if (bufsz != 0) {
1221 		unsigned short size;
1222 
1223 		/* fill buffer and digest */
1224 		size = blocksz - bufsz;
1225 		if (size > len) {
1226 		    size = len;
1227 		}
1228 		memcpy(buffer + bufsz, p, size);
1229 		p += size;
1230 		len -= size;
1231 		bufsz += size;
1232 
1233 		if (bufsz == blocksz) {
1234 		    (*hash_block)(digest, buffer);
1235 		    bufsz = 0;
1236 		}
1237 	    }
1238 
1239 	    while (len >= blocksz) {
1240 		/* digest directly from string */
1241 		(*hash_block)(digest, p);
1242 		p += blocksz;
1243 		len -= blocksz;
1244 	    }
1245 
1246 	    if (len != 0) {
1247 		/* put remainder in buffer */
1248 		memcpy(buffer, p, bufsz = len);
1249 	    }
1250 	}
1251     }
1252 
1253     *bufsize = bufsz;
1254     return length;
1255 }
1256 
1257 /*
1258  * NAME:	kfun->md5()
1259  * DESCRIPTION:	compute MD5 hash
1260  */
1261 void kf_md5(frame *f, int nargs, value *val)
1262 {
1263     char buffer[64];
1264     Uint digest[5];
1265     Int cost;
1266     Uint length;
1267     unsigned short bufsz;
1268     string *str;
1269 
1270     cost = hash_md5_start(f, nargs, digest);
1271     if (!f->rlim->noticks && f->rlim->ticks <= cost) {
1272 	f->rlim->ticks = 0;
1273 	error("Out of ticks");
1274     }
1275     i_add_ticks(f, cost);
1276 
1277     length = hash_blocks(f, nargs, digest, buffer, &bufsz, 64, &hash_md5_block);
1278     str = hash_md5_end(digest, buffer, bufsz, length);
1279     PUT_STRVAL_NOREF(val, str);
1280 }
1281 
1282 /*
1283  * NAME:	kfun->sha1()
1284  * DESCRIPTION:	compute SHA1 hash
1285  */
1286 void kf_sha1(frame *f, int nargs, value *val)
1287 {
1288     char buffer[64];
1289     Uint digest[5];
1290     Int cost;
1291     Uint length;
1292     unsigned short bufsz;
1293     string *str;
1294 
1295     cost = hash_sha1_start(f, nargs, digest);
1296     if (!f->rlim->noticks && f->rlim->ticks <= cost) {
1297 	f->rlim->ticks = 0;
1298 	error("Out of ticks");
1299     }
1300     i_add_ticks(f, cost);
1301 
1302     length = hash_blocks(f, nargs, digest, buffer, &bufsz, 64,
1303 			 &hash_sha1_block);
1304     str = hash_sha1_end(digest, buffer, bufsz, length);
1305     PUT_STRVAL_NOREF(val, str);
1306 }
1307 # endif
1308 
1309 
1310 # ifdef FUNCDEF
1311 FUNCDEF("crypt", kf_crypt, pt_crypt, 0)
1312 # else
1313 char pt_crypt[] = { C_TYPECHECKED | C_STATIC, 1, 1, 0, 8, T_STRING, T_STRING,
1314 		    T_STRING };
1315 
1316 /*
1317  * NAME:	kfun->crypt()
1318  * DESCRIPTION:	hash_string("crypt", ...)
1319  */
1320 int kf_crypt(frame *f, int nargs)
1321 {
1322     value val;
1323 
1324     kf_xcrypt(f, nargs, &val);
1325     i_ref_value(&val);
1326     i_pop(f, nargs);
1327     *--f->sp = val;
1328     return 0;
1329 }
1330 # endif
1331 
1332 
1333 # ifdef FUNCDEF
1334 FUNCDEF("0.hash_md5", kf_hash_md5, pt_hash_md5, 0)
1335 # else
1336 char pt_hash_md5[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
1337 		       T_STRING, T_STRING, T_STRING };
1338 
1339 /*
1340  * NAME:	kfun->hash_md5()
1341  * DESCRIPTION:	hash_string("MD5", ...)
1342  */
1343 int kf_hash_md5(frame *f, int nargs)
1344 {
1345     char buffer[64];
1346     Uint digest[4];
1347     Int cost;
1348     Uint length;
1349     unsigned short bufsz;
1350 
1351     cost = hash_md5_start(f, nargs, digest);
1352     if (!f->rlim->noticks && f->rlim->ticks <= cost) {
1353 	f->rlim->ticks = 0;
1354 	error("Out of ticks");
1355     }
1356     i_add_ticks(f, cost);
1357 
1358     length = hash_blocks(f, nargs, digest, buffer, &bufsz, 64, &hash_md5_block);
1359 
1360     i_pop(f, nargs);
1361     PUSH_STRVAL(f, hash_md5_end(digest, buffer, bufsz, length));
1362     return 0;
1363 }
1364 # endif
1365 
1366 
1367 # ifdef FUNCDEF
1368 FUNCDEF("0.hash_sha1", kf_hash_sha1, pt_hash_sha1, 0)
1369 # else
1370 char pt_hash_sha1[] = { C_TYPECHECKED | C_STATIC | C_ELLIPSIS, 1, 1, 0, 8,
1371 			T_STRING, T_STRING, T_STRING };
1372 
1373 /*
1374  * NAME:	kfun->hash_sha1()
1375  * DESCRIPTION:	hash_string("SHA1", ...)
1376  */
1377 int kf_hash_sha1(frame *f, int nargs)
1378 {
1379     char buffer[64];
1380     Uint digest[5];
1381     Int cost;
1382     Uint length;
1383     unsigned short bufsz;
1384 
1385     cost = hash_sha1_start(f, nargs, digest);
1386     if (!f->rlim->noticks && f->rlim->ticks <= cost) {
1387 	f->rlim->ticks = 0;
1388 	error("Out of ticks");
1389     }
1390     i_add_ticks(f, cost);
1391 
1392     length = hash_blocks(f, nargs, digest, buffer, &bufsz, 64,
1393 			 &hash_sha1_block);
1394 
1395     i_pop(f, nargs);
1396     PUSH_STRVAL(f, hash_sha1_end(digest, buffer, bufsz, length));
1397     return 0;
1398 }
1399 # endif
1400 
1401 
1402 # ifdef FUNCDEF
1403 FUNCDEF("asn_add", kf_asn_add, pt_asn_add, 0)
1404 # else
1405 char pt_asn_add[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
1406 		      T_STRING, T_STRING };
1407 
1408 /*
1409  * NAME:	kfun->asn_add()
1410  * DESCRIPTION:	add two arbitrary precision numbers
1411  */
1412 int kf_asn_add(frame *f)
1413 {
1414     string *str;
1415 
1416     str = asn_add(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
1417     str_del((f->sp++)->u.string);
1418     str_del((f->sp++)->u.string);
1419     str_del(f->sp->u.string);
1420     PUT_STR(f->sp, str);
1421 
1422     return 0;
1423 }
1424 # endif
1425 
1426 
1427 # ifdef FUNCDEF
1428 FUNCDEF("asn_sub", kf_asn_sub, pt_asn_sub, 0)
1429 # else
1430 char pt_asn_sub[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
1431 		      T_STRING, T_STRING };
1432 
1433 /*
1434  * NAME:	kfun->asn_sub()
1435  * DESCRIPTION:	subtract arbitrary precision numbers
1436  */
1437 int kf_asn_sub(frame *f)
1438 {
1439     string *str;
1440 
1441     str = asn_sub(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
1442     str_del((f->sp++)->u.string);
1443     str_del((f->sp++)->u.string);
1444     str_del(f->sp->u.string);
1445     PUT_STR(f->sp, str);
1446 
1447     return 0;
1448 }
1449 # endif
1450 
1451 
1452 # ifdef FUNCDEF
1453 FUNCDEF("asn_cmp", kf_asn_cmp, pt_asn_cmp, 0)
1454 # else
1455 char pt_asn_cmp[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_INT, T_STRING,
1456 		      T_STRING };
1457 
1458 /*
1459  * NAME:	kfun->asn_cmp()
1460  * DESCRIPTION:	subtract arbitrary precision numbers
1461  */
1462 int kf_asn_cmp(frame *f)
1463 {
1464     int cmp;
1465 
1466     cmp = asn_cmp(f, f->sp[1].u.string, f->sp[0].u.string);
1467     str_del((f->sp++)->u.string);
1468     str_del(f->sp->u.string);
1469     PUT_INTVAL(f->sp, cmp);
1470 
1471     return 0;
1472 }
1473 # endif
1474 
1475 
1476 # ifdef FUNCDEF
1477 FUNCDEF("asn_mult", kf_asn_mult, pt_asn_mult, 0)
1478 # else
1479 char pt_asn_mult[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
1480 		       T_STRING, T_STRING };
1481 
1482 /*
1483  * NAME:	kfun->asn_mult()
1484  * DESCRIPTION:	multiply arbitrary precision numbers
1485  */
1486 int kf_asn_mult(frame *f)
1487 {
1488     string *str;
1489 
1490     str = asn_mult(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
1491     str_del((f->sp++)->u.string);
1492     str_del((f->sp++)->u.string);
1493     str_del(f->sp->u.string);
1494     PUT_STR(f->sp, str);
1495 
1496     return 0;
1497 }
1498 # endif
1499 
1500 
1501 # ifdef FUNCDEF
1502 FUNCDEF("asn_div", kf_asn_div, pt_asn_div, 0)
1503 # else
1504 char pt_asn_div[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
1505 		      T_STRING, T_STRING };
1506 
1507 /*
1508  * NAME:	kfun->asn_div()
1509  * DESCRIPTION:	divide arbitrary precision numbers
1510  */
1511 int kf_asn_div(frame *f)
1512 {
1513     string *str;
1514 
1515     str = asn_div(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
1516     str_del((f->sp++)->u.string);
1517     str_del((f->sp++)->u.string);
1518     str_del(f->sp->u.string);
1519     PUT_STR(f->sp, str);
1520 
1521     return 0;
1522 }
1523 # endif
1524 
1525 
1526 # ifdef FUNCDEF
1527 FUNCDEF("asn_mod", kf_asn_mod, pt_asn_mod, 0)
1528 # else
1529 char pt_asn_mod[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
1530 		      T_STRING };
1531 
1532 /*
1533  * NAME:	kfun->asn_mod()
1534  * DESCRIPTION:	modulus of arbitrary precision number
1535  */
1536 int kf_asn_mod(frame *f)
1537 {
1538     string *str;
1539 
1540     str = asn_mod(f, f->sp[1].u.string, f->sp[0].u.string);
1541     str_del((f->sp++)->u.string);
1542     str_del(f->sp->u.string);
1543     PUT_STR(f->sp, str);
1544 
1545     return 0;
1546 }
1547 # endif
1548 
1549 
1550 # ifdef FUNCDEF
1551 FUNCDEF("asn_pow", kf_asn_pow, pt_asn_pow, 0)
1552 # else
1553 char pt_asn_pow[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING, T_STRING,
1554 		      T_STRING, T_STRING };
1555 
1556 /*
1557  * NAME:	kfun->asn_pow()
1558  * DESCRIPTION:	power of an arbitrary precision number
1559  */
1560 int kf_asn_pow(frame *f)
1561 {
1562     string *str;
1563 
1564     str = asn_pow(f, f->sp[2].u.string, f->sp[1].u.string, f->sp[0].u.string);
1565     str_del((f->sp++)->u.string);
1566     str_del((f->sp++)->u.string);
1567     str_del(f->sp->u.string);
1568     PUT_STR(f->sp, str);
1569 
1570     return 0;
1571 }
1572 # endif
1573 
1574 
1575 # ifdef FUNCDEF
1576 FUNCDEF("asn_lshift", kf_asn_lshift, pt_asn_lshift, 0)
1577 # else
1578 char pt_asn_lshift[] = { C_TYPECHECKED | C_STATIC, 3, 0, 0, 9, T_STRING,
1579 			 T_STRING, T_INT, T_STRING };
1580 
1581 /*
1582  * NAME:	kfun->asn_lshift()
1583  * DESCRIPTION:	left shift an arbitrary precision number
1584  */
1585 int kf_asn_lshift(frame *f)
1586 {
1587     string *str;
1588 
1589     str = asn_lshift(f, f->sp[2].u.string, f->sp[1].u.number, f->sp->u.string);
1590     str_del(f->sp->u.string);
1591     f->sp += 2;
1592     str_del(f->sp->u.string);
1593     PUT_STR(f->sp, str);
1594 
1595     return 0;
1596 }
1597 # endif
1598 
1599 
1600 # ifdef FUNCDEF
1601 FUNCDEF("asn_rshift", kf_asn_rshift, pt_asn_rshift, 0)
1602 # else
1603 char pt_asn_rshift[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING,
1604 			 T_STRING, T_INT };
1605 
1606 /*
1607  * NAME:	kfun->asn_rshift()
1608  * DESCRIPTION:	right shift of arbitrary precision number
1609  */
1610 int kf_asn_rshift(frame *f)
1611 {
1612     string *str;
1613 
1614     str = asn_rshift(f, f->sp[1].u.string, f->sp->u.number);
1615     f->sp++;
1616     str_del(f->sp->u.string);
1617     PUT_STR(f->sp, str);
1618 
1619     return 0;
1620 }
1621 # endif
1622 
1623 
1624 # ifdef FUNCDEF
1625 FUNCDEF("asn_and", kf_asn_and, pt_asn_and, 0)
1626 # else
1627 char pt_asn_and[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
1628 		      T_STRING };
1629 
1630 /*
1631  * NAME:	kfun->asn_and()
1632  * DESCRIPTION:	logical and of arbitrary precision numbers
1633  */
1634 int kf_asn_and(frame *f)
1635 {
1636     string *str;
1637 
1638     str = asn_and(f, f->sp[1].u.string, f->sp->u.string);
1639     str_del((f->sp++)->u.string);
1640     str_del(f->sp->u.string);
1641     PUT_STR(f->sp, str);
1642 
1643     return 0;
1644 }
1645 # endif
1646 
1647 
1648 # ifdef FUNCDEF
1649 FUNCDEF("asn_or", kf_asn_or, pt_asn_or, 0)
1650 # else
1651 char pt_asn_or[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
1652 		     T_STRING };
1653 
1654 /*
1655  * NAME:	kfun->asn_or()
1656  * DESCRIPTION:	logical or of arbitrary precision numbers
1657  */
1658 int kf_asn_or(frame *f)
1659 {
1660     string *str;
1661 
1662     str = asn_or(f, f->sp[1].u.string, f->sp->u.string);
1663     str_del((f->sp++)->u.string);
1664     str_del(f->sp->u.string);
1665     PUT_STR(f->sp, str);
1666 
1667     return 0;
1668 }
1669 # endif
1670 
1671 
1672 # ifdef FUNCDEF
1673 FUNCDEF("asn_xor", kf_asn_xor, pt_asn_xor, 0)
1674 # else
1675 char pt_asn_xor[] = { C_TYPECHECKED | C_STATIC, 2, 0, 0, 8, T_STRING, T_STRING,
1676 		      T_STRING };
1677 
1678 /*
1679  * NAME:	kfun->asn_xor()
1680  * DESCRIPTION:	logical xor of arbitrary precision numbers
1681  */
1682 int kf_asn_xor(frame *f)
1683 {
1684     string *str;
1685 
1686     str = asn_xor(f, f->sp[1].u.string, f->sp->u.string);
1687     str_del((f->sp++)->u.string);
1688     str_del(f->sp->u.string);
1689     PUT_STR(f->sp, str);
1690 
1691     return 0;
1692 }
1693 # endif
1694