1 #define _GNU_SOURCE
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <assert.h>
6 #include <stdint.h>
7 #include <ctype.h>
8
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <unistd.h>
12
13 #include "songinfo.h"
14 #include "uadeutils.h"
15 #include "ossupport.h"
16 #include "amifilemagic.h"
17 #include "support.h"
18
19
asciiline(char * dst,unsigned char * buf)20 static void asciiline(char *dst, unsigned char *buf)
21 {
22 int i, c;
23 for (i = 0; i < 16; i++) {
24 c = buf[i];
25 if (isgraph(c) || c == ' ') {
26 dst[i] = c;
27 } else {
28 dst[i] = '.';
29 }
30 }
31 dst[i] = 0;
32 }
33
hexdump(char * info,size_t maxlen,char * filename,size_t toread)34 static int hexdump(char *info, size_t maxlen, char *filename, size_t toread)
35 {
36 FILE *f;
37 size_t rb, ret;
38 uint8_t *buf;
39
40 assert(maxlen >= 8192);
41
42 f = fopen(filename, "rb");
43 if (f == NULL)
44 return 0;
45
46 buf = malloc(toread);
47 if (buf == NULL)
48 return 0;
49
50 rb = 0;
51 while (rb < toread) {
52 ret = fread(&buf[rb], 1, toread - rb, f);
53 if (ret == 0)
54 break;
55 rb += ret;
56 }
57
58 if (rb > 0) {
59 size_t roff = 0;
60 size_t woff = 0;
61
62 while (roff < rb) {
63 int iret;
64
65 if (woff >= maxlen)
66 break;
67
68 if (woff + 32 >= maxlen) {
69 strcpy(&info[woff], "\nbuffer overflow...\n");
70 woff += strlen(&info[woff]);
71 break;
72 }
73
74 iret = snprintf(&info[woff], maxlen - woff, "%.3zx: ",
75 roff);
76 assert(iret > 0);
77 woff += iret;
78
79 if (woff >= maxlen)
80 break;
81
82 if (roff + 16 > rb) {
83 iret = snprintf(&info[woff], maxlen - woff,
84 "Aligned line ");
85 assert(iret > 0);
86 woff += iret;
87
88 } else {
89 char dbuf[17];
90 asciiline(dbuf, &buf[roff]);
91 iret = snprintf(&info[woff], maxlen - woff,
92 "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x |%s|",
93 buf[roff + 0], buf[roff + 1],
94 buf[roff + 2], buf[roff + 3],
95 buf[roff + 4], buf[roff + 5],
96 buf[roff + 6], buf[roff + 7],
97 buf[roff + 8], buf[roff + 9],
98 buf[roff + 10], buf[roff + 11],
99 buf[roff + 12], buf[roff + 13],
100 buf[roff + 14], buf[roff + 15],
101 dbuf);
102 assert(iret > 0);
103 woff += iret;
104 }
105
106 if (woff >= maxlen)
107 break;
108
109 iret = snprintf(&info[woff], maxlen - woff, "\n");
110 woff += iret;
111
112 roff += 16;
113 }
114
115 if (woff >= maxlen)
116 woff = maxlen - 1;
117 info[woff] = 0;
118 }
119
120 fclose(f);
121 free(buf);
122 return rb == 0;
123 }
124
find_tag(uint8_t * buf,size_t startoffset,size_t buflen,uint8_t * tag,size_t taglen)125 static size_t find_tag(uint8_t * buf, size_t startoffset, size_t buflen,
126 uint8_t * tag, size_t taglen)
127 {
128 uint8_t *treasure;
129
130 if (startoffset >= buflen)
131 return -1;
132
133 treasure = memmem(buf + startoffset, buflen - startoffset, tag, taglen);
134 if (treasure == NULL)
135 return -1;
136
137 return (size_t) (treasure - buf);
138 }
139
string_checker(unsigned char * str,size_t off,size_t maxoff)140 static int string_checker(unsigned char *str, size_t off, size_t maxoff)
141 {
142 assert(maxoff > 0);
143 while (off < maxoff) {
144 if (*str == 0)
145 return 1;
146 off++;
147 str++;
148 }
149 return 0;
150 }
151
152 /* Wanted Team's loadseg modules */
process_WTWT_mod(char * credits,size_t credits_len,unsigned char * buf,size_t len,char * lo,char * hi,int rel)153 static void process_WTWT_mod(char *credits, size_t credits_len,
154 unsigned char *buf, size_t len, char *lo,
155 char *hi, int rel)
156 {
157 int offset, txt_offset, chunk;
158 char tmpstr[256];
159
160 /* check for Magic ID */
161 offset = find_tag((uint8_t *) buf, 0, len, (uint8_t *) lo, 4);
162 if (offset == -1)
163 return;
164
165 offset =
166 find_tag((uint8_t *) buf, offset + 4, offset + 8, (uint8_t *) hi,
167 4);
168 if (offset == -1)
169 return;
170
171 chunk = offset - 8; /* here's where our first chunk should be */
172 offset = offset + rel; /* offset to our info pointers */
173
174 if (chunk < len && offset < len) {
175 txt_offset = read_be_u32(buf + offset) + chunk;
176 if (txt_offset < len && txt_offset != chunk) {
177 if (!string_checker(buf, txt_offset, len))
178 return;
179 snprintf(tmpstr, sizeof tmpstr, "\nMODULENAME:\n %s\n",
180 buf + txt_offset);
181 strlcat(credits, tmpstr, credits_len);
182
183 }
184 txt_offset = read_be_u32(buf + offset + 4) + chunk;
185 if (txt_offset < len && txt_offset != chunk) {
186 if (!string_checker(buf, txt_offset, len))
187 return;
188 snprintf(tmpstr, sizeof tmpstr, "\nAUTHORNAME:\n %s\n",
189 buf + txt_offset);
190 strlcat(credits, tmpstr, credits_len);
191 }
192
193 txt_offset = read_be_u32(buf + offset + 8) + chunk;
194 if (txt_offset < len && txt_offset != chunk) {
195 if (!string_checker(buf, txt_offset, len))
196 return;
197 snprintf(tmpstr, sizeof tmpstr, "\nSPECIALINFO:\n %s",
198 buf + txt_offset);
199 strlcat(credits, tmpstr, credits_len);
200 }
201 }
202 }
203
204 /* Get the info out of the AHX module data*/
process_ahx_mod(char * credits,size_t credits_len,unsigned char * buf,size_t len)205 static void process_ahx_mod(char *credits, size_t credits_len,
206 unsigned char *buf, size_t len)
207 {
208 int i;
209 size_t offset;
210 char tmpstr[256];
211
212 if (len < 13)
213 return;
214
215 offset = read_be_u16(buf + 4);
216
217 if (offset >= len)
218 return;
219
220 if (!string_checker(buf, offset, len))
221 return;
222
223 snprintf(tmpstr, sizeof tmpstr, "\nSong title: %s\n", buf + offset);
224 strlcat(credits, tmpstr, credits_len);
225
226 for (i = 0; i < buf[12]; i++) {
227 if (!string_checker(buf, offset, len))
228 break;
229 offset = offset + 1 + strlen((char *)buf + offset);
230 if (offset < len) {
231 snprintf(tmpstr, 256, "\n %s", buf + offset);
232 strlcat(credits, tmpstr, credits_len);
233 }
234 }
235 }
236
237 /* Get the info out of the protracker module data*/
process_ptk_mod(char * credits,size_t credits_len,int inst,uint8_t * buf,size_t len)238 static void process_ptk_mod(char *credits, size_t credits_len, int inst,
239 uint8_t * buf, size_t len)
240 {
241 int i;
242 char tmpstr[256];
243
244 if (!string_checker(buf, 0, len))
245 return;
246
247 snprintf(tmpstr, 35, "\nSong title: %s", buf);
248 strlcat(credits, tmpstr, credits_len);
249
250 if (inst == 31) {
251 if (len >= 0x43c) {
252 snprintf(tmpstr, sizeof tmpstr,
253 "\nmax positions: %d\n", buf[0x3b6]);
254 strlcat(credits, tmpstr, credits_len);
255 }
256 } else {
257 if (len >= 0x1da) {
258 snprintf(tmpstr, sizeof tmpstr,
259 "\nmax positions: %d\n", buf[0x1d6]);
260 strlcat(credits, tmpstr, credits_len);
261 }
262 }
263
264 snprintf(tmpstr, sizeof tmpstr, "\nINST - NAME SIZE VOL FINE LSTART LSIZE\n");
265 strlcat(credits, tmpstr, credits_len);
266 if (len >= (0x14 + inst * 0x1e)) {
267 for (i = 0; i < inst; i++) {
268 if (!string_checker(buf, 0x14 + i * 0x1e, len))
269 break;
270 snprintf(tmpstr, sizeof tmpstr, "[%2d] - ", i + 1);
271 strlcat(credits, tmpstr, credits_len);
272 snprintf(tmpstr, 23, "%-23s", buf + 0x14 + (i * 0x1e));
273 strlcat(credits, tmpstr, credits_len);
274 snprintf(tmpstr, sizeof tmpstr,
275 " %6d %2d %2d %6d %6d\n",
276 read_be_u16(buf + 42 + i * 0x1e) * 2,
277 buf[45 + i * 0x1e], buf[44 + i * 0x1e],
278 read_be_u16(buf + 46 + i * 0x1e) * 2,
279 read_be_u16(buf + 48 + i * 0x1e) * 2);
280 strlcat(credits, tmpstr, credits_len);
281 }
282 }
283 }
284
285 /* Get the info out of the digibooster module data*/
process_digi_mod(char * credits,size_t credits_len,uint8_t * buf,size_t len)286 static void process_digi_mod(char *credits, size_t credits_len,
287 uint8_t * buf, size_t len)
288 {
289 int i;
290 char tmpstr[256];
291
292 if (len < (642 + 0x30 * 0x1e))
293 return;
294
295 if (!string_checker(buf, 610, len))
296 return;
297
298 snprintf(tmpstr, 0x2f, "\nSong title: %s \n", buf + 610);
299 strlcat(credits, tmpstr, credits_len);
300
301 snprintf(tmpstr, sizeof tmpstr, "max positions: %d\n", buf[47]);
302 strlcat(credits, tmpstr, credits_len);
303
304 snprintf(tmpstr, sizeof tmpstr, "\nINST - NAME SIZE VOL FINE LSTART LSIZE\n");
305 strlcat(credits, tmpstr, credits_len);
306 if (len >= (642 + 0x1f * 0x1e)) {
307 for (i = 0; i < 0x1f; i++) {
308 if (!string_checker(buf, 642 + i * 0x1e, len))
309 break;
310 snprintf(tmpstr, sizeof tmpstr, "[%2d] - ", i + 1);
311 strlcat(credits, tmpstr, credits_len);
312 snprintf(tmpstr, 30, "%-30s", buf + 642 + (i * 0x1e));
313 strlcat(credits, tmpstr, credits_len);
314 snprintf(tmpstr, sizeof tmpstr,
315 " %11d %2d %3d %11d %11d\n",
316 read_be_u32(buf + 176 + i * 4), buf[548 + i],
317 buf[579 + i], read_be_u32(buf + 300 + i * 4),
318 read_be_u32(buf + 424 + i * 4));
319 strlcat(credits, tmpstr, credits_len);
320 }
321 }
322 }
323
324 /* Get the info out of custom song. FIX ME, clean this function. */
process_custom(char * credits,size_t credits_len,unsigned char * buf,size_t len)325 static void process_custom(char *credits, size_t credits_len,
326 unsigned char *buf, size_t len)
327 {
328 char tmpstr[1024];
329 unsigned char *hunk;
330 unsigned char *tag_table;
331 int hunk_size;
332 int table_size;
333
334 int i;
335 int offset;
336 unsigned int x, y;
337 unsigned char startpattern[4] = { 0x70, 0xff, 0x4e, 0x75 };
338
339 if (len < 4)
340 return;
341
342 if (read_be_u32(buf) != 0x000003f3)
343 return;
344
345 i = find_tag(buf, 0, len, startpattern, sizeof startpattern);
346 if (i == -1 || (i + 12) >= len)
347 return;
348
349 if (strncmp((char *)buf + i + 4, "DELIRIUM", 8) != 0 &&
350 strncmp((char *)buf + i + 4, "EPPLAYER", 8) != 0) {
351 return;
352 }
353
354 /* Hunk found */
355 hunk = buf + i;
356 hunk_size = len - i;
357
358 if (16 + i + 5 >= hunk_size)
359 return;
360
361 /* Check if $VER is available */
362 if (!memcmp(&hunk[16], "$VER:", 5)) {
363 offset = 16 + 5;
364 while (offset < hunk_size) {
365 if (memcmp(&hunk[offset], " ", 1))
366 break;
367 offset++;
368 }
369 if (offset >= hunk_size)
370 return;
371
372 if ((offset + strlen((char *)hunk + offset) + 1) >
373 ((size_t) hunk_size))
374 return;
375
376 snprintf(tmpstr, sizeof tmpstr, "\nVERSION:\n%s\n\n",
377 hunk + offset);
378 strlcat(credits, tmpstr, credits_len);
379 }
380
381 offset = read_be_u32(hunk + 12);
382 if (offset < 0) {
383 return;
384 }
385
386 tag_table = hunk + offset;
387
388 if (tag_table >= &buf[len])
389 return;
390
391 table_size = ((int)(&buf[len] - tag_table)) / 8;
392
393 if (table_size <= 0)
394 return;
395
396 /* check all tags in this loop */
397 for (i = 0; i < table_size; i += 2) {
398 x = read_be_u32(tag_table + 4 * i);
399 y = read_be_u32(tag_table + 4 * (i + 1));
400
401 if (!x)
402 break;
403
404 switch (x) {
405 case 0x8000445a:
406 if (y >= ((unsigned int)hunk_size))
407 return;
408 if ((y + strlen((char *)hunk + y) + 1) >
409 ((size_t) hunk_size))
410 return;
411 snprintf(tmpstr, sizeof tmpstr, "\nCREDITS:\n%s\n\n",
412 hunk + y);
413 strlcat(credits, tmpstr, credits_len);
414 break;
415 default:
416 break;
417 }
418 }
419 }
420
421 /*
422 * Get the info out of the Deltamusic 2 module data
423 */
process_dm2_mod(char * credits,size_t credits_len,unsigned char * buf,size_t len)424 static void process_dm2_mod(char *credits, size_t credits_len,
425 unsigned char *buf, size_t len)
426 {
427 char tmpstr[256];
428 if (!string_checker(buf, 0x148, len))
429 return;
430 snprintf(tmpstr, sizeof tmpstr, "\nRemarks:\n%s", buf + 0x148);
431 strlcat(credits, tmpstr, credits_len);
432 }
433
process_module(char * credits,size_t credits_len,char * filename)434 static int process_module(char *credits, size_t credits_len, char *filename)
435 {
436 FILE *modfile;
437 struct stat st;
438 size_t modfilelen;
439 unsigned char *buf;
440 char pre[11];
441 char tmpstr[256];
442 size_t rb;
443
444 if (!(modfile = fopen(filename, "rb")))
445 return 0;
446
447 if (fstat(fileno(modfile), &st))
448 return 0;
449
450 modfilelen = st.st_size;
451
452 if ((buf = malloc(modfilelen)) == NULL) {
453 fprintf(stderr, "uade: can't allocate mem in process_module()");
454 fclose(modfile);
455 return 0;
456 }
457
458 rb = 0;
459 while (rb < modfilelen) {
460 size_t ret = fread(&buf[rb], 1, modfilelen - rb, modfile);
461 if (ret == 0)
462 break;
463 rb += ret;
464 }
465
466 fclose(modfile);
467
468 if (rb < modfilelen) {
469 fprintf(stderr, "uade: song info could not read %s fully\n",
470 filename);
471 free(buf);
472 return 0;
473 }
474
475 snprintf(tmpstr, sizeof tmpstr, "UADE2 MODINFO:\n\nFile name: %s\nFile length: %zd bytes\n", filename, modfilelen);
476 strlcpy(credits, tmpstr, credits_len);
477
478 /* Get filetype in pre */
479 uade_filemagic(buf, modfilelen, pre, modfilelen, filename, 0);
480
481 snprintf(tmpstr, sizeof tmpstr, "File prefix: %s.*\n", pre);
482 strlcat(credits, tmpstr, credits_len);
483
484 if (strcasecmp(pre, "CUST") == 0) {
485 /* CUST */
486 process_custom(credits, credits_len, buf, modfilelen);
487
488 } else if (strcasecmp(pre, "DM2") == 0) {
489 /* DM2 */
490 process_dm2_mod(credits, credits_len, buf, modfilelen);
491
492 } else if (strcasecmp(pre, "DIGI") == 0) {
493 /* DIGIBooster */
494 process_digi_mod(credits, credits_len, buf, modfilelen);
495
496 } else if ((strcasecmp(pre, "AHX") == 0) ||
497 (strcasecmp(pre, "THX") == 0)) {
498 /* AHX */
499 process_ahx_mod(credits, credits_len, buf, modfilelen);
500
501 } else if ((strcasecmp(pre, "MOD15") == 0) ||
502 (strcasecmp(pre, "MOD15_UST") == 0) ||
503 (strcasecmp(pre, "MOD15_MST") == 0) ||
504 (strcasecmp(pre, "MOD15_ST-IV") == 0)) {
505 /*MOD15 */
506 process_ptk_mod(credits, credits_len, 15, buf, modfilelen);
507
508 } else if ((strcasecmp(pre, "MOD") == 0) ||
509 (strcasecmp(pre, "MOD_DOC") == 0) ||
510 (strcasecmp(pre, "MOD_NTK") == 0) ||
511 (strcasecmp(pre, "MOD_NTK1") == 0) ||
512 (strcasecmp(pre, "MOD_NTK2") == 0) ||
513 (strcasecmp(pre, "MOD_FLT4") == 0) ||
514 (strcasecmp(pre, "MOD_FLT8") == 0) ||
515 (strcasecmp(pre, "MOD_ADSC4") == 0) ||
516 (strcasecmp(pre, "MOD_ADSC8") == 0) ||
517 (strcasecmp(pre, "MOD_COMP") == 0) ||
518 (strcasecmp(pre, "MOD_NTKAMP") == 0) ||
519 (strcasecmp(pre, "PPK") == 0) ||
520 (strcasecmp(pre, "MOD_PC") == 0) ||
521 (strcasecmp(pre, "ICE") == 0) ||
522 (strcasecmp(pre, "ADSC") == 0)) {
523 /*MOD*/
524 process_ptk_mod(credits, credits_len, 31, buf, modfilelen);
525 } else if (strcasecmp(pre, "DL") == 0) {
526 process_WTWT_mod(credits, credits_len, buf, modfilelen, "UNCL",
527 "EART", 0x28);
528 } else if (strcasecmp(pre, "BSS") == 0) {
529 process_WTWT_mod(credits, credits_len, buf, modfilelen, "BEAT",
530 "HOVE", 0x1c);
531 } else if (strcasecmp(pre, "GRAY") == 0) {
532 process_WTWT_mod(credits, credits_len, buf, modfilelen, "FRED",
533 "GRAY", 0x10);
534 } else if (strcasecmp(pre, "JMF") == 0) {
535 process_WTWT_mod(credits, credits_len, buf, modfilelen, "J.FL",
536 "OGEL", 0x14);
537 } else if (strcasecmp(pre, "SPL") == 0) {
538 process_WTWT_mod(credits, credits_len, buf, modfilelen, "!SOP",
539 "ROL!", 0x10);
540 } else if (strcasecmp(pre, "HD") == 0) {
541 process_WTWT_mod(credits, credits_len, buf, modfilelen, "H.DA",
542 "VIES", 24);
543 } else if (strcasecmp(pre, "RIFF") == 0) {
544 process_WTWT_mod(credits, credits_len, buf, modfilelen, "RIFF",
545 "RAFF", 0x14);
546 } else if (strcasecmp(pre, "FP") == 0) {
547 process_WTWT_mod(credits, credits_len, buf, modfilelen, "F.PL",
548 "AYER", 0x8);
549 } else if (strcasecmp(pre, "CORE") == 0) {
550 process_WTWT_mod(credits, credits_len, buf, modfilelen, "S.PH",
551 "IPPS", 0x20);
552 } else if (strcasecmp(pre, "BDS") == 0) {
553 process_WTWT_mod(credits, credits_len, buf, modfilelen, "DAGL",
554 "ISH!", 0x14);
555 }
556
557 free(buf);
558
559 return 0;
560 }
561
uade_generate_song_title(char * title,size_t dstlen,struct uade_state * state)562 int uade_generate_song_title(char *title, size_t dstlen,
563 struct uade_state *state)
564 {
565 size_t srcoffs;
566 size_t dstoffs;
567 size_t srclen;
568 char *format;
569 char *bname;
570 char p[64];
571 char *default_format = "%F %X [%P]";
572 struct uade_song *us = state->song;
573 struct uade_config *uc = &state->config;
574
575 /* %A min subsong
576 %B cur subsong
577 %C max subsong
578 %F file base name (us->module_filename)
579 %P player name
580 %T title
581 %X print subsong info if more than one subsong exist
582 */
583
584 format = uc->song_title;
585
586 if (format == NULL)
587 format = default_format;
588
589 if (strcmp("default", format) == 0)
590 format = default_format;
591
592 if ((srclen = strlen(format)) == 0) {
593 fprintf(stderr, "Warning: empty song_title format string.\n");
594 return 1;
595 }
596
597 if (dstlen == 0)
598 return 1;
599
600 if (strlen(us->module_filename) == 0)
601 return 1;
602
603 bname = xbasename(us->module_filename);
604
605 p[0] = 0;
606 if (us->formatname[0] == 0) {
607 if (us->playername[0] == 0) {
608 strlcpy(p, "Custom", sizeof p);
609 } else {
610 strlcpy(p, us->playername, sizeof p);
611 }
612 } else {
613 if (strncmp(us->formatname, "type: ", 6) == 0) {
614 strlcpy(p, us->formatname + 6, sizeof p);
615 } else {
616 strlcpy(p, us->formatname, sizeof p);
617 }
618 }
619
620 srcoffs = dstoffs = 0;
621
622 title[0] = 0;
623
624 while (dstoffs < dstlen) {
625 char c;
626 if (srcoffs >= srclen)
627 break;
628
629 if ((c = format[srcoffs]) == 0)
630 break;
631
632 if (c != '%') {
633 title[dstoffs++] = format[srcoffs++];
634 } else {
635 size_t inc;
636 char *dat = NULL;
637 char tmp[32];
638
639 if ((srcoffs + 1) >= srclen) {
640 fprintf(stderr, "Error: no identifier given in song title format: %s\n", format);
641 title[dstoffs] = 0;
642 return 1;
643 }
644
645 c = format[srcoffs + 1];
646
647 switch (c) {
648 case 'A':
649 snprintf(tmp, sizeof tmp, "%d",
650 us->min_subsong);
651 dat = tmp;
652 break;
653 case 'B':
654 snprintf(tmp, sizeof tmp, "%d",
655 us->cur_subsong);
656 dat = tmp;
657 break;
658 case 'C':
659 snprintf(tmp, sizeof tmp, "%d",
660 us->max_subsong);
661 dat = tmp;
662 break;
663 case 'F':
664 dat = bname;
665 break;
666 case 'P':
667 dat = p;
668 break;
669 case 'T':
670 dat = us->modulename;
671 if (strcmp("<no songtitle>", dat) == 0)
672 dat[0] = 0;
673 if (dat[0] == 0)
674 dat = bname;
675 break;
676 case 'X':
677 if (us->min_subsong == us->max_subsong) {
678 tmp[0] = 0;
679 } else {
680 snprintf(tmp, sizeof tmp, "(%d/%d)",
681 us->cur_subsong,
682 us->max_subsong);
683 }
684 dat = tmp;
685 break;
686 default:
687 fprintf(stderr,
688 "Unknown identifier %%%c in song_title format: %s\n",
689 c, format);
690 title[dstoffs] = 0;
691 return 1;
692 }
693 inc = strlcpy(&title[dstoffs], dat, dstlen - dstoffs);
694 srcoffs += 2;
695 dstoffs += inc;
696 }
697 }
698
699 if (dstoffs < dstlen)
700 title[dstoffs] = 0;
701 else
702 title[dstlen - 1] = 0;
703
704 return 0;
705 }
706
707 /* Returns zero on success, non-zero otherwise. */
uade_song_info(char * info,size_t maxlen,char * filename,enum song_info_type type)708 int uade_song_info(char *info, size_t maxlen, char *filename,
709 enum song_info_type type)
710 {
711 switch (type) {
712 case UADE_MODULE_INFO:
713 return process_module(info, maxlen, filename);
714 case UADE_HEX_DUMP_INFO:
715 return hexdump(info, maxlen, filename, 2048);
716 default:
717 fprintf(stderr, "Illegal info requested.\n");
718 exit(-1);
719 }
720 return 0;
721 }
722