1 /*
2 * Ascii magic -- file types that we know based on keywords
3 * that can appear anywhere in the file.
4 *
5 * Copyright (c) Ian F. Darwin, 1987.
6 * Written by Ian F. Darwin.
7 *
8 * This software is not subject to any license of the American Telephone
9 * and Telegraph Company or of the Regents of the University of California.
10 *
11 * Permission is granted to anyone to use this software for any purpose on
12 * any computer system, and to alter it and redistribute it freely, subject
13 * to the following restrictions:
14 *
15 * 1. The author is not responsible for the consequences of use of this
16 * software, no matter how awful, even if they arise from flaws in it.
17 *
18 * 2. The origin of this software must not be misrepresented, either by
19 * explicit claim or by omission. Since few users ever read sources,
20 * credits must appear in the documentation.
21 *
22 * 3. Altered versions must be plainly marked as such, and must not be
23 * misrepresented as being the original software. Since few users
24 * ever read sources, credits must appear in the documentation.
25 *
26 * 4. This notice may not be removed or altered.
27 */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include "file.h"
35 #include "names.h"
36
37 #ifndef lint
38 static char *moduleid =
39 "@(#)$Id: ascmagic.c,v 1.14 93/03/24 17:34:34 ian Exp $";
40 #endif /* lint */
41
42 /* an optimisation over plain strcmp() */
43 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
44
45 int
ascmagic(buf,nbytes)46 ascmagic(buf, nbytes)
47 unsigned char *buf;
48 int nbytes; /* size actually read */
49 {
50 int i, isblock, has_escapes = 0;
51 unsigned char *s;
52 char nbuf[HOWMANY+1]; /* one extra for terminating '\0' */
53 char *token;
54 register struct names *p;
55
56 /* these are easy, do them first */
57
58 /*
59 * for troff, look for . + letter + letter or .\";
60 * this must be done to disambiguate tar archives' ./file
61 * and other trash from real troff input.
62 */
63 if (*buf == '.') {
64 unsigned char *tp = buf + 1;
65
66 while (isascii(*tp) && isspace(*tp))
67 ++tp; /* skip leading whitespace */
68 if ((isascii(*tp) && (isalnum(*tp) || *tp=='\\') &&
69 isascii(*(tp+1)) && (isalnum(*(tp+1)) || *tp=='"'))) {
70 ckfputs("troff or preprocessor input text", stdout);
71 return 1;
72 }
73 }
74 if ((*buf == 'c' || *buf == 'C') &&
75 isascii(*(buf + 1)) && isspace(*(buf + 1))) {
76 ckfputs("fortran program text", stdout);
77 return 1;
78 }
79
80 /* look for tokens from names.h - this is expensive! */
81 /* make a copy of the buffer here because strtok() will destroy it */
82 s = (unsigned char*) memcpy(nbuf, buf, HOWMANY);
83 has_escapes = (memchr(s, '\033', HOWMANY) != NULL);
84 while ((token = strtok((char*)s, " \t\n\r\f")) != NULL) {
85 s = NULL; /* make strtok() keep on tokin' */
86 for (p = names; p < names + NNAMES; p++) {
87 if (STREQ(p->name, token)) {
88 ckfputs(types[p->type], stdout);
89 if (has_escapes)
90 ckfputs(" (with escape sequences)",
91 stdout);
92 return 1;
93 }
94 }
95 }
96
97 switch (is_tar(buf)) {
98 case 1:
99 ckfputs("tar archive", stdout);
100 return 1;
101 case 2:
102 ckfputs("POSIX tar archive", stdout);
103 return 1;
104 }
105
106 if (i = is_compress(buf, &isblock)) {
107 if (zflag) {
108 unsigned char *newbuf;
109 int newsize;
110
111 if (newsize = uncompress(buf, &newbuf, nbytes)) {
112 tryit(newbuf, newsize);
113 free(newbuf);
114 }
115 printf(" (%scompressed data - %d bits)",
116 isblock ? "block " : "", i);
117 }
118 else printf("%scompressed data - %d bits",
119 isblock ? "block " : "", i);
120 return 1;
121 }
122
123 for (i = 0; i < nbytes; i++) {
124 if (!isascii(*(buf+i)))
125 return 0; /* not all ascii */
126 }
127
128 /* all else fails, but it is ascii... */
129 ckfputs("ascii text", stdout);
130 if (has_escapes) {
131 ckfputs(" (with escape sequences)", stdout);
132 }
133 return 1;
134 }
135
136
137