1 /*
2    The Evil Finder
3    Copyright (C) 2002 by Michal Zalewski <lcamtuf@coredump.cx>
4 */
5 
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <ctype.h>
12 #include <sys/time.h>
13 #include <signal.h>
14 
15 #define MAXOPT 1024
16 #define MAXBUF 1024
17 #define MINNEST 3
18 #define MAXNEST 5
19 
20 #define MAXRES 1
21 
22 struct Trec {
23   int num;
24   char* desc;
25 };
26 
27 
28 
29 struct proof {
30   int nest;
31   char* prolog;
32   int usednum[MAXNEST+2];
33   int utop;
34   char how[MAXBUF];
35   int val;
36 };
37 
38 
39 struct Trec options[MAXOPT];
40 struct Trec final[MAXOPT];
41 
42 char* rprolog[MAXRES];
43 char* results[MAXRES];
44 int restop;
45 
46 
47 int opttop, fintop;
48 
49 #define fatal(x) exit(printf("<p><font color=red><b>FATAL: <i>%s</i></b></font>",x)?1:1)
50 
51 
backwardize(int z)52  int backwardize(int z) {
53   // Laaame.
54   char buf[128],b2[128];
55   int i,q;
56   if (z<0) return -31337000;
57   sprintf(buf,"%d",z);
58   q=strlen(buf);
59   for (i=0;i<q;i++) b2[q-i-1]=buf[i];
60   b2[q]=0;
61   if (!strcmp(b2,buf)) return -31337000;
62   return atoi(b2);
63 }
64 
backstring(int z)65  char* backstring(int z) {
66   // Laaame.
67   char buf[128];
68   static char b2[128];
69   int i,q;
70   if (z<0) return "<error>";
71   sprintf(buf,"%d",z);
72   q=strlen(buf);
73   for (i=0;i<q;i++) b2[q-i-1]=buf[i];
74   b2[q]=0;
75   if (!strcmp(b2,buf)) return "<error>";
76   return b2;
77 }
78 
79 
tooctal(int z)80  int tooctal(int z) {
81   // Laaame.
82   char buf[128];
83   if (z<0) return -31337000;
84   sprintf(buf,"%o",z);
85   if (atoi(buf) == z) return -31337000;
86   return atoi(buf);
87 }
88 
89 
90 int rf=-1;
91 
get_random(void)92  unsigned int get_random(void) {
93   int val;
94   if (rf<0) {
95     rf=open("/dev/urandom",O_RDONLY);
96     if (rf<0) { perror("/dev/urandom"); exit(1); }
97   }
98   read(rf,&val,4);
99   return val;
100 }
101 
102 
trace_proof(struct proof * p)103  void trace_proof(struct proof* p) {
104   int i,a;
105   char order[12]={0,1,2,3,4,5,6,7,8,9,10,11};
106 
107 
108   // Whoops. Bail out.
109   if (restop >= MAXRES) return;
110 
111   // Check for "proven' conditions.
112   if (p->nest>=MINNEST && p->val>0)
113 
114   for (i=0;i<fintop;i++) {
115 
116     // Straight
117     if (p->val == final[i].num) {
118       char buf[MAXBUF*2];
119       strcpy(buf,p->how);
120       sprintf(&buf[strlen(buf)],"The number %d is %s.\n<p>\n<b>This clearly proves how evil the subject is. QED.\n",final[i].num,final[i].desc);
121       rprolog[restop]=p->prolog;
122       results[restop++]=strdup(buf);
123 //      printf("PROOF %d: %s\n",restop,buf);
124       return;
125     }
126 
127     // In reverse
128     if (p->val == backwardize(final[i].num)) {
129       char buf[MAXBUF*2];
130       strcpy(buf,p->how);
131       sprintf(&buf[strlen(buf)],"This number, read from right to left, is %d, or %s.\n<p>\n<b>No further questions. QED.\n",final[i].num,final[i].desc);
132       rprolog[restop]=p->prolog;
133       results[restop++]=strdup(buf);
134 //      printf("PROOF %d: %s\n",restop,buf);
135       return;
136     }
137 
138     // The result in octal is...
139     if (tooctal(p->val) == final[i].num) {
140       char buf[MAXBUF*2];
141       strcpy(buf,p->how);
142       sprintf(&buf[strlen(buf)],"This, written in octal, is %d, %s.\n<p>\n<b>It speaks for itself. QED.\n",final[i].num,final[i].desc);
143       rprolog[restop]=p->prolog;
144       results[restop++]=strdup(buf);
145 //      printf("PROOF %d: %s\n",restop,buf);
146       return;
147     }
148 
149     // The result is ..., which in octal...
150     if (p->val == tooctal(final[i].num)) {
151       char buf[MAXBUF*2];
152       strcpy(buf,p->how);
153       sprintf(&buf[strlen(buf)],"This number, read as octal, gives %d - %s.\n<p>\n<b>This is truly evil. QED.\n",final[i].num,final[i].desc);
154       rprolog[restop]=p->prolog;
155       results[restop++]=strdup(buf);
156 //      printf("PROOF %d: %s\n",restop,buf);
157       return;
158     }
159 
160     // The result in octal is ... backwards
161     if (tooctal(p->val) == backwardize(final[i].num) && tooctal(p->val)>0) {
162       char buf[MAXBUF*2];
163       strcpy(buf,p->how);
164       sprintf(&buf[strlen(buf)],"This, written in octal, is %d. This, read backwards, gives %d, %s.\n<p>\n<b>No doubt about its evilness. QED.\n",tooctal(p->val),final[i].num,final[i].desc);
165       rprolog[restop]=p->prolog;
166       results[restop++]=strdup(buf);
167 //      printf("PROOF %d: %s\n",restop,buf);
168       return;
169     }
170 
171     // The result is ..., which in octal is ... backwards
172     if (backwardize(p->val) == tooctal(final[i].num) && backwardize(p->val)>0) {
173       char buf[MAXBUF*2];
174       strcpy(buf,p->how);
175       sprintf(&buf[strlen(buf)],"This, when read backwards, gives %s. This is %d in octal, %s...\n<p>\n<b>Evil, QED.\n",backstring(p->val),final[i].num,final[i].desc);
176       rprolog[restop]=p->prolog;
177       results[restop++]=strdup(buf);
178 //      printf("PROOF %d: %s\n",restop,buf);
179       return;
180     }
181 
182     // The result backwards in octal is ...
183     if (tooctal(backwardize(p->val)) == final[i].num) {
184       char buf[MAXBUF*2];
185       strcpy(buf,p->how);
186       sprintf(&buf[strlen(buf)],"This number, when read backwards, gives %s. This, written in octal, gives %d - %s.\n<p>\n<b>Enough said - QED.\n",backstring(p->val),final[i].num,final[i].desc);
187       rprolog[restop]=p->prolog;
188       results[restop++]=strdup(buf);
189 //      printf("PROOF %d: %s\n",restop,buf);
190       return;
191     }
192 
193     // The result in octal is ... backwards
194     if (p->val == tooctal(backwardize(final[i].num))) {
195       char buf[MAXBUF*2];
196       strcpy(buf,p->how);
197       sprintf(&buf[strlen(buf)],"Write %d backwards. Translate it to octal - this will give you %d. Thus, %d stands for %d, %s.\n<p>\n<b>You get the picture. QED.\n",final[i].num,p->val,p->val,final[i].num,final[i].desc);
198       rprolog[restop]=p->prolog;
199       results[restop++]=strdup(buf);
200 //      printf("PROOF %d: %s\n",restop,buf);
201       return;
202     }
203 
204   }
205 
206   // Nest level exceeded. Abandon this branch.
207   if (p->nest>=MAXNEST) return;
208 
209   // Now, let's try all possibilities:
210 
211   // Shuffle check order
212   for (i=0;i<12;i++) {
213     char tmp;
214     int z=get_random() % 12;
215     tmp=order[i];
216     order[i]=order[z];
217     order[z]=tmp;
218   }
219 
220   for (a=0;a<12;a++)
221     switch(order[a]) {
222 
223       case 0:
224       // Straight addition
225       for (i=0;i<opttop;i++) {
226         struct proof* n;
227         int t;
228         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip1;
229         n=malloc(sizeof(struct proof));
230         memcpy(n,p,sizeof(struct proof));
231         n->val=p->val+options[i].num;
232         n->usednum[n->utop++]=options[i].num;
233         n->nest++;
234         sprintf(&n->how[strlen(n->how)],"Add %d, %s - the result is %d.\n<p>\n",
235                                       options[i].num,options[i].desc,n->val);
236         trace_proof(n);
237         free(n);
238     skip1:
239 	break;
240       }
241       break;
242 
243 
244       case 1:
245       // Right reverse addition
246       for (i=0;i<opttop;i++) {
247         struct proof* n;
248         int t;
249         if (backwardize(options[i].num)<0) continue;
250         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip2;
251         n=malloc(sizeof(struct proof));
252         memcpy(n,p,sizeof(struct proof));
253         n->val=p->val+backwardize(options[i].num);
254         n->usednum[n->utop++]=options[i].num;
255         n->nest++;
256         sprintf(&n->how[strlen(n->how)],"Add %s to it - this is %s, written backwards - you will get %d.\n<p>\n",
257                                       backstring(options[i].num),options[i].desc,n->val);
258         trace_proof(n);
259         free(n);
260     skip2:
261 	break;
262       }
263       break;
264 
265 
266       case 2:
267       // Left reverse addition
268       for (i=0;i<opttop;i++) {
269         struct proof* n;
270         int t;
271         if (backwardize(p->val)<0) continue;
272         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip3;
273         n=malloc(sizeof(struct proof));
274         memcpy(n,p,sizeof(struct proof));
275         n->usednum[n->utop++]=options[i].num;
276         n->val=backwardize(p->val)+options[i].num;
277         n->nest++;
278         sprintf(&n->how[strlen(n->how)],"Turn the number backwards, and add %d - %s. The number is now %d.\n<p>\n",
279                                       options[i].num,options[i].desc,n->val);
280         trace_proof(n);
281         free(n);
282     skip3:
283 	break;
284       }
285       break;
286 
287       case 3:
288       // Straight subtraction
289       for (i=0;i<opttop;i++) {
290         struct proof* n;
291         int t;
292         if (p->val-options[i].num<100) continue;
293         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip4;
294         n=malloc(sizeof(struct proof));
295         memcpy(n,p,sizeof(struct proof));
296         n->val=p->val-options[i].num;
297         n->usednum[n->utop++]=options[i].num;
298         n->nest++;
299         sprintf(&n->how[strlen(n->how)],"Subtract %d, %s. The result will be %d.\n<p>\n",
300                                       options[i].num,options[i].desc,n->val);
301         trace_proof(n);
302         free(n);
303     skip4:
304 	break;
305       }
306       break;
307 
308       case 4:
309       // Right reverse subtraction
310       for (i=0;i<opttop;i++) {
311         struct proof* n;
312         int t;
313         if (p->val-backwardize(options[i].num)<100) continue;
314         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip5;
315         n=malloc(sizeof(struct proof));
316         memcpy(n,p,sizeof(struct proof));
317         n->val=p->val-backwardize(options[i].num);
318         n->usednum[n->utop++]=options[i].num;
319         n->nest++;
320         sprintf(&n->how[strlen(n->how)],"Subtract %s from the number - this is %s, written backwards. It gives %d.\n<p>\n",
321                                       backstring(options[i].num),options[i].desc,n->val);
322         trace_proof(n);
323         free(n);
324     skip5:
325 	break;
326       }
327       break;
328 
329       case 5:
330       // Left reverse subtraction
331       for (i=0;i<opttop;i++) {
332         struct proof* n;
333         int t;
334         if (backwardize(p->val)-options[i].num<100) continue;
335         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip6;
336         n=malloc(sizeof(struct proof));
337         memcpy(n,p,sizeof(struct proof));
338         n->val=backwardize(p->val)-options[i].num;
339         n->usednum[n->utop++]=options[i].num;
340         n->nest++;
341         sprintf(&n->how[strlen(n->how)],"Turn the number backwards, subtract %d - %s. The number is now %d.\n<p>\n",
342                                       options[i].num,options[i].desc,n->val);
343         trace_proof(n);
344         free(n);
345     skip6:
346 	break;
347       }
348       break;
349 
350       case 6:
351       // Straight multiplication
352       for (i=0;i<opttop;i++) {
353         struct proof* n;
354         int t;
355         if (p->val*options[i].num>30000) continue;
356         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip7;
357         if ( options[i].num == 1) continue;
358         n=malloc(sizeof(struct proof));
359         memcpy(n,p,sizeof(struct proof));
360         n->val=p->val*options[i].num;
361         n->usednum[n->utop++]=options[i].num;
362         n->nest++;
363         sprintf(&n->how[strlen(n->how)],"Multiply it by %d, %s - the number is now %d.\n<p>\n",
364                                       options[i].num,options[i].desc,n->val);
365         trace_proof(n);
366         free(n);
367     skip7:
368 	break;
369       }
370       break;
371 
372       case 7:
373       // Right reverse multiplication
374       for (i=0;i<opttop;i++) {
375         struct proof* n;
376         int t;
377         if (backwardize(options[i].num)<0) continue;
378         if (p->val*backwardize(options[i].num)>30000) continue;
379         if ( options[i].num == 1) continue;
380         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip8;
381         n=malloc(sizeof(struct proof));
382         memcpy(n,p,sizeof(struct proof));
383         n->val=p->val*backwardize(options[i].num);
384         n->usednum[n->utop++]=options[i].num;
385         n->nest++;
386         sprintf(&n->how[strlen(n->how)],"Multiply the number by %s - this is %s, from right to left. It gives %d.\n<p>\n",
387                                       backstring(options[i].num),options[i].desc,n->val);
388         trace_proof(n);
389         free(n);
390     skip8:
391 	break;
392       }
393       break;
394 
395       case 8:
396       // Left reverse multiplication
397       for (i=0;i<opttop;i++) {
398         struct proof* n;
399         int t;
400         if (backwardize(p->val)<0) continue;
401         if (backwardize(p->val)*options[i].num>30000) continue;
402         if ( options[i].num == 1) continue;
403         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip9;
404         n=malloc(sizeof(struct proof));
405         memcpy(n,p,sizeof(struct proof));
406         n->val=backwardize(p->val)*options[i].num;
407         n->usednum[n->utop++]=options[i].num;
408         n->nest++;
409         sprintf(&n->how[strlen(n->how)],"Turn the number backwards, multiply by %d - %s. The number is now %d.\n<p>\n",
410                                       options[i].num,options[i].desc,n->val);
411         trace_proof(n);
412         free(n);
413     skip9:
414 	break;
415       }
416       break;
417 
418       case 9:
419       // Straight division
420       for (i=0;i<opttop;i++) {
421         struct proof* n;
422         int t;
423         if (p->val % options[i].num) continue;
424         if (p->val / options[i].num < 100) continue;
425         if ( options[i].num == 1) continue;
426         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip10;
427         n=malloc(sizeof(struct proof));
428         memcpy(n,p,sizeof(struct proof));
429         n->val=p->val/options[i].num;
430         n->usednum[n->utop++]=options[i].num;
431         n->nest++;
432         sprintf(&n->how[strlen(n->how)],"Divide by %d, %s - the result is %d.\n<p>\n",
433                                       options[i].num,options[i].desc,n->val);
434         trace_proof(n);
435         free(n);
436     skip10:
437 	break;
438       }
439       break;
440 
441       case 10:
442       // Right reverse division
443       for (i=0;i<opttop;i++) {
444         struct proof* n;
445         int t;
446         if (p->val % backwardize(options[i].num)) continue;
447         if (p->val / backwardize(options[i].num) < 100) continue;
448         if ( options[i].num == 1) continue;
449         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip11;
450         n=malloc(sizeof(struct proof));
451         memcpy(n,p,sizeof(struct proof));
452         n->val=p->val/backwardize(options[i].num);
453         n->usednum[n->utop++]=options[i].num;
454         n->nest++;
455         sprintf(&n->how[strlen(n->how)],"Divide the number by %s - this is %s, backwards. It gives %d.\n<p>\n",
456                                       backstring(options[i].num),options[i].desc,n->val);
457         trace_proof(n);
458         free(n);
459     skip11:
460 	break;
461       }
462       break;
463 
464       case 11:
465       // Left reverse division
466       for (i=0;i<opttop;i++) {
467         struct proof* n;
468         int t;
469         if (backwardize(p->val) % options[i].num) continue;
470         if (backwardize(p->val) / options[i].num < 100) continue;
471         if ( options[i].num == 1) continue;
472         for (t=0;t<p->utop;t++) if (options[i].num==p->usednum[t]) goto skip12;
473         n=malloc(sizeof(struct proof));
474         memcpy(n,p,sizeof(struct proof));
475         n->val=backwardize(p->val)/options[i].num;
476         n->usednum[n->utop++]=options[i].num;
477         n->nest++;
478         sprintf(&n->how[strlen(n->how)],"Turn the number backwards, divide by %d - %s. The number is now %d.\n<p>\n",
479                                       options[i].num,options[i].desc,n->val);
480         trace_proof(n);
481         free(n);
482     skip12:
483 	break;
484       }
485       break;
486 
487       default: fatal("Whoops.\n");
488     }
489 
490   // Ok. All set.
491 
492 }
493 
494 
mypow(int what,int cnt)495 int mypow(int what,int cnt) {
496   int i,res=1;
497   for (i=0;i<cnt;i++) res*=what;
498   return res;
499 }
500 
501 
simplify(int what)502 int simplify(int what) {
503   while (what > 9) what = (what / 10) + (what % 10);
504   return what;
505 }
506 
507 
508 int stopped;
509 int retrynum;
510 
interrupter(int x)511 void interrupter(int x) {
512   restop=MAXRES+1;
513   // printf("...restart.\n");
514   stopped=1;
515   retrynum++;
516 }
517 
518 
519 
520 int asum[10],nsum[10];
521 
main(void)522 int main(void) {
523   int z,i,ch=0;
524   FILE* f;
525   unsigned char ibuf[1024],tmp[256];
526 
527 
528   // We assume we're not in /tmp... how convinient!
529   sprintf(tmp,"/tmp/.tmp-%d-%u",getpid(),(int)time(0));
530   sprintf(ibuf,"/usr/local/libexec/ef-shuffle </usr/local/share/evilfinder/evilnumbers.dat >%s",tmp);
531   system(ibuf);
532 
533   f=fopen(tmp,"r");
534   if (!f) fatal("cannot open tmp file\n");
535   unlink(tmp);
536 
537   while(fgets(ibuf,sizeof(ibuf),f)) {
538     int num;char* d;
539     if (ibuf[0]=='*') num=atoi(&ibuf[1]); else num=atoi(ibuf);
540     d=ibuf;
541     while (*d && *d!=' ' && *d!='\t') d++;
542     if (!*d) fatal("malformed config file\n");
543     while (*d==' ' || *d=='\t') d++;
544     if (!strlen(d)) fatal("empty description in config file?\n");
545     if (strchr(d,'\n')) *strchr(d,'\n')=0;
546     if (ibuf[0]=='*') {
547       final[fintop].num=num;
548       final[fintop].desc=strdup(d);
549       fintop++;
550     } else {
551       options[opttop].num=num;
552       options[opttop].desc=strdup(d);
553       opttop++;
554     }
555   }
556 
557   if (!opttop) fatal("no entries in the config file.\n");
558   if (!fintop) fatal("no exit conditions in the config file.\n");
559 
560   fclose(f);
561 
562   // printf("Loaded %d config entries, %d of which are exit conditions.\n",opttop,fintop);
563 
564   { char* x;
565     x=getenv("QUERY_STRING_UNESCAPED");
566     if (!x) fatal("no input provided.\n");
567     if (strlen(x)>100) fatal("suspiciously long input.\n");
568     if (!strchr(x,'=')) fatal("malformed query string.\n");
569     x=strchr(x,'=')+1;
570     strcpy(ibuf,x);
571   }
572 
573   if (strlen(ibuf)<4) fatal("input too short.\n");
574   for (i=0;i<strlen(ibuf);i++) if (isalpha(ibuf[i])) ch++;
575   if (ch<4) fatal("not enough characters (letters).\n");
576   if (strlen(ibuf)>40) fatal("too many characters.\n");
577   if (strchr(ibuf,'<')) fatal("go cross-script yourself.\n");
578 
579   z=0;
580 
581   for (i=0;i<ch;i++) {
582     int cur=i/(ch/4);
583     while (!isalpha(ibuf[z])) z++;
584     if (cur>4) cur=4;
585     asum[cur]+=simplify(toupper(ibuf[z]));
586     nsum[cur]+=simplify(toupper(ibuf[z])-'A'+1);
587     z++;
588   }
589 
590   for (i=0;i<10;i++) { asum[i]=simplify(asum[i]);
591                        nsum[i]=simplify(nsum[i]); }
592 
593   // printf("asum = %d%d%d%d%d nsum = %d%d%d%d%d (chars = %d)\n",
594     //      asum[0],asum[1],asum[2],asum[3],asum[4],
595     //      nsum[0],nsum[1],nsum[2],nsum[3],nsum[4],ch);
596 
597 retry:
598 
599   stopped=0;
600   restop=0;
601   signal(SIGALRM,interrupter);
602   alarm(5+retrynum);
603 
604   if (get_random() % 2)
605 
606   { struct proof p;
607     int pcur=-1;
608     char t[10000];
609     bzero(t,sizeof(t));
610     bzero(&p,sizeof(p));
611     z=0;
612     for (i=0;i<ch;i++) {
613       while (!isalpha(ibuf[z])) z++;
614       t[strlen(t)]=' ';
615       t[strlen(t)]=' ';
616       t[strlen(t)]=' ';
617       t[strlen(t)]=toupper(ibuf[z]);
618       z++;
619     }
620     strcat(t,"\n");
621     z=0;
622     for (i=0;i<ch;i++) {
623       while (!isalpha(ibuf[z])) z++;
624       sprintf(&t[strlen(t)],"  %2d",toupper(ibuf[z])-'A'+1);
625       z++;
626     }
627     strcat(t,"     - as numbers\n");
628 
629     z=0;
630     for (i=0;i<ch;i++) {
631       while (!isalpha(ibuf[z])) z++;
632       sprintf(&t[strlen(t)],"   %d",simplify(toupper(ibuf[z])-'A'+1));
633       z++;
634     }
635     strcat(t,"     - digits added\n ");
636 
637     for (i=0;i<ch;i++) {
638       int cur=i/(ch/4);
639       if (cur>4) cur=4;
640       if (pcur!=cur) {
641         if (pcur != -1) strcat(t,"/");
642         strcat(t," \\_");
643       } else strcat(t,"____");
644       pcur=cur;
645     }
646 
647     strcat(t,"/\n");
648 
649     for (i=0;i<ch;i++) {
650       int cur=i/(ch/4);
651       if (cur>4) cur=4;
652       if (pcur!=cur) sprintf(&t[strlen(t)],"   %d",nsum[cur]);
653       else strcat(t,"    ");
654       pcur=cur;
655     }
656 
657     strcat(t,"     - digits added\n\n");
658 
659     if (!nsum[4])
660       p.val=nsum[0]*1000+nsum[1]*100+nsum[2]*10+nsum[3];
661     else
662       p.val=nsum[0]*10000+nsum[1]*1000+nsum[2]*100+nsum[3]*10+nsum[4];
663 
664     sprintf(&t[strlen(t)],"Thus, \"%s\" is %d.\n\n",ibuf,p.val);
665 
666     p.prolog=strdup(t);
667     p.usednum[0]=p.val;p.utop=1;
668 
669     trace_proof(&p);
670 
671   }
672 
673   else
674 
675   { struct proof p;
676     int pcur=-1;
677     char t[10000];
678     bzero(&p,sizeof(p));
679     bzero(t,sizeof(t));
680     z=0;
681     for (i=0;i<ch;i++) {
682       while (!isalpha(ibuf[z])) z++;
683       t[strlen(t)]=' ';
684       t[strlen(t)]=' ';
685       t[strlen(t)]=' ';
686       t[strlen(t)]=toupper(ibuf[z]);
687       z++;
688     }
689     strcat(t,"\n");
690     z=0;
691     for (i=0;i<ch;i++) {
692       while (!isalpha(ibuf[z])) z++;
693       sprintf(&t[strlen(t)],"  %2d",toupper(ibuf[z]));
694       z++;
695     }
696     strcat(t,"     - as ASCII values\n");
697 
698     z=0;
699     for (i=0;i<ch;i++) {
700       while (!isalpha(ibuf[z])) z++;
701       sprintf(&t[strlen(t)],"   %d",simplify(toupper(ibuf[z])));
702       z++;
703     }
704     strcat(t,"     - digits added\n ");
705 
706     for (i=0;i<ch;i++) {
707       int cur=i/(ch/4);
708       if (cur>4) cur=4;
709       if (pcur!=cur) {
710         if (pcur != -1) strcat(t,"/");
711         strcat(t," \\_");
712       } else strcat(t,"____");
713       pcur=cur;
714     }
715 
716     strcat(t,"/\n");
717 
718     for (i=0;i<ch;i++) {
719       int cur=i/(ch/4);
720       if (cur>4) cur=4;
721       if (pcur!=cur) sprintf(&t[strlen(t)],"   %d",asum[cur]);
722       else strcat(t,"    ");
723       pcur=cur;
724     }
725 
726     strcat(t,"     - digits added\n\n");
727 
728     if (!asum[4])
729       p.val=asum[0]*1000+asum[1]*100+asum[2]*10+asum[3];
730     else
731       p.val=asum[0]*10000+asum[1]*1000+asum[2]*100+asum[3]*10+asum[4];
732 
733     sprintf(&t[strlen(t)],"Thus, \"%s\" is %d.\n\n",ibuf,p.val);
734 
735     p.prolog=strdup(t);
736     p.usednum[0]=p.val;p.utop=1;
737 
738     trace_proof(&p);
739 
740   }
741 
742   alarm(0);
743 
744   if (stopped) {
745     if (retrynum<5) goto retry;
746     fatal("System timeout.\n");
747   }
748 
749 
750   if (!restop) fatal("There is no way to prove the evilness of this!\n");
751 
752   // Get random result
753 
754   z=get_random() % restop;
755   printf("<b>**** THE PROOF THAT <i>%s</i> IS EVIL ****</b>\n<p>\n<pre>%s</pre>\n\n<p>%s\n",ibuf,rprolog[z],results[z]);
756 
757   return 0;
758 }
759