/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* Copyright (c) 1987, 1988 Microsoft Corporation */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <inttypes.h>
#include <libintl.h>
/*
* Types
*/
/*
* Opcodes
*/
#define EQ 0
/* %ld, %s, %lo mask: with bit 6 on, used to locate */
/* print formats */
/*
* Misc
*/
/*
* Structure of magic file entry
*/
struct entry {
union {
char *str;
} e_value;
const char *e_str;
};
/* Non-localized string giving name of command. Defined in file.c */
extern const char *File;
/*
* 2nd magic table, includes default tests and magic entries
* to be applied after default position-sensitive tests
*/
static char *
{
char *newstr;
char *s;
long val;
int base;
return (NULL);
}
s = newstr;
while (*p != '\0') {
if (*p != '\\') {
*s++ = *p++;
continue;
}
p++;
if (*p == '\0')
break;
if (isdigit(*p)) {
if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) {
/* hex */
base = 16;
} else {
base = 8;
}
errno = 0;
"table invalid string value\n"), File,
file);
return (NULL);
}
*s++ = (char)val;
} else {
/* escape the character */
switch (*p) {
case 'n':
*s = '\n';
break;
case 'r':
*s = '\r';
break;
case 'a':
*s = '\a';
break;
case 'b':
*s = '\b';
break;
case 'f':
*s = '\f';
break;
case 't':
*s = '\t';
break;
case 'v':
*s = '\v';
break;
default:
*s = *p;
break;
}
p++;
s++;
}
}
*s = '\0';
return (newstr);
}
/*
* f_mkmtab - fills mtab array of magic table entries with
* values from the file magfile.
* May be called more than once if multiple magic
* files were specified.
* Stores entries sequentially in one of two magic
* tables: mtab1, if first = 1; mtab2 otherwise.
*
* If -c option is specified, cflg is non-zero, and
* f_mkmtab() reports on errors in the magic file.
*
* Two magic tables may need to be created. The first
* one (mtab1) contains magic entries to be checked before
* the programmatic default position-sensitive tests in
* def_position_tests().
* The second one (mtab2) should start with the default
* the programmatic default position-sensitive tests in
* def_position_tests(). The parameter "first" would
* be 1 for the former set of tables, 0 for the latter
* set of magic tables.
* No mtab2 should be created if file will not be
* applying default tests; in that case, all magic table
* entries should be in mtab1.
*
* f_mkmtab returns 0 on success, -1 on error. The calling
* program is not expected to proceed after f_mkmtab()
* returns an error.
*/
int
{
int lcnt = 0;
if (first) {
} else {
}
/* mtab may have been allocated on a previous f_mkmtab call */
return (-1);
}
}
errno = 0;
return (-1);
}
char *p = buf;
char *p2;
char *p3;
char opc;
/*
* ensure we have one extra entry allocated
* to mark end of the table, after the while loop
*/
return (-1);
} else {
}
}
lcnt++;
if (*p == '\n' || *p == '#')
continue;
/* LEVEL */
if (*p == '>') {
p++;
}
/* OFFSET */
if (cflg)
"error, no tab after %s on line %d\n"),
continue;
}
while (*p2 == '\t')
p2++;
/* TYPE */
p = p2;
if (cflg)
"error, no tab after %s on line %d\n"),
continue;
}
*p3++ = '\0';
0); /* returns 0 or ULLONG_MAX on error */
} else {
}
switch (*p) {
case 'd':
if (*(p+1) == NULL) {
/* d */
switch (*(p+1)) {
case 'C':
case '1':
/* dC, d1 */
break;
case 'S':
case '2':
/* dS, d2 */
break;
case 'I':
case 'L':
case '4':
/* dI, dL, d4 */
break;
case '8':
/* d8 */
break;
default:
break;
}
}
break;
case 'l':
if (*(p+1) == 'l') { /* llong */
} else { /* long */
}
break;
case 's':
if (*(p+1) == 'h') {
/* short */
} else {
/* s or string */
}
break;
case 'u':
if (*(p+1) == NULL) {
/* u */
switch (*(p+1)) {
case 'C':
case '1':
/* uC, u1 */
break;
case 'S':
case '2':
/* uS, u2 */
break;
case 'I':
case 'L':
case '4':
/* uI, uL, u4 */
break;
case '8':
/* u8 */
break;
default:
break;
}
} else { /* u?* */
switch (*(p+1)) {
case 'b': /* ubyte */
break;
case 's': /* ushort */
break;
case 'l':
if (*(p+2) == 'l') {
/* ullong */
} else {
/* ulong */
}
break;
default:
/* default, same as "u" */
break;
}
}
break;
default:
/* retain (undocumented) default type */
break;
}
}
while (*p2 == '\t')
p2++;
/* OP-VALUE */
p = p2;
if (cflg)
"error, no tab after %s on line %d\n"),
continue;
}
opc = *p++;
switch (opc) {
case '=':
break;
case '>':
break;
case '<':
break;
case 'x':
break;
case '&':
break;
case '^':
break;
default: /* EQ (i.e. 0) is default */
p--; /* since global ep->e_opcode=0 */
}
}
(char **)NULL, 0);
return (-1);
}
}
/* STRING */
return (-1);
} else {
*p = '\0';
}
ep++;
} /* end while (fgets) */
if (first) {
} else {
}
return (-1);
}
return (0);
}
/*
* Check for Magic Table entries in the file.
*
* Since there may be two sets of magic tables, first = 1
* for the first magic table (mtab1) and 0 for the second magic
* table (mtab2).
*/
int
{
int result;
char *p;
int lev1 = 0;
if (first) {
} else {
}
return (0); /* no magic file tests in this table */
}
if (lev1) { /* valid magic file entries */
break;
continue;
}
continue;
case STR:
{
continue;
if (lev1) {
(void) putchar(' ');
}
else
lev1 = 1;
continue;
/*
* We've matched the string and printed the message;
* no STR processing occurs beyond this point.
*/
}
case BYTE:
case UBYTE:
break;
case SHORT:
case USHORT:
break;
case LONG:
case ULONG:
break;
case LLONG:
case ULLONG:
break;
}
}
/*
* Compare the values according to the size and sign
* of the type. For =, &, and ^ operators, the sign
* does not have any effect, so these are always compared
* unsigned. Only for < and > operators is the
* sign significant.
* If the file value was masked, the compare should
* be unsigned.
*/
case EQ:
case BYTE:
case UBYTE:
continue;
break;
case SHORT:
case USHORT:
continue;
break;
case LONG:
case ULONG:
continue;
break;
case LLONG:
case ULLONG:
continue;
break;
default:
continue;
}
break;
case GT:
case BYTE:
continue;
break;
}
/*FALLTHROUGH*/
case UBYTE:
continue;
break;
case SHORT:
continue;
break;
}
/*FALLTHROUGH*/
case USHORT:
continue;
break;
case LONG:
continue;
break;
}
/*FALLTHROUGH*/
case ULONG:
continue;
break;
case LLONG:
continue;
break;
}
/*FALLTHROUGH*/
case ULLONG:
continue;
break;
default:
continue;
}
break;
case LT:
case BYTE:
continue;
break;
}
/*FALLTHROUGH*/
case UBYTE:
continue;
break;
case SHORT:
continue;
break;
}
/*FALLTHROUGH*/
case USHORT:
continue;
break;
case LONG:
continue;
break;
}
/*FALLTHROUGH*/
case ULONG:
continue;
break;
case LLONG:
continue;
break;
}
/*FALLTHROUGH*/
case ULLONG:
continue;
break;
default:
continue;
}
break;
case AND:
case BYTE:
case UBYTE:
break;
continue;
case SHORT:
case USHORT:
break;
continue;
case LONG:
case ULONG:
break;
continue;
case LLONG:
case ULLONG:
break;
continue;
default:
continue;
}
break;
case NSET:
case BYTE:
case UBYTE:
break;
continue;
case SHORT:
case USHORT:
break;
continue;
case LONG:
case ULONG:
break;
continue;
case LLONG:
case ULLONG:
break;
continue;
default:
continue;
}
break;
case ANY: /* matches anything */
break;
default: /* shouldn't occur; ignore it */
continue;
}
if (lev1)
(void) putchar(' ');
case LLONG:
#ifdef XPG4
break;
}
#endif /* XPG4 */
/*FALLTHROUGH*/
case ULLONG:
break;
case LONG:
#ifdef XPG4
break;
}
#endif /* XPG4 */
/*FALLTHROUGH*/
case ULONG:
break;
case SHORT:
#ifdef XPG4
break;
}
#endif /* XPG4 */
/*FALLTHROUGH*/
case USHORT:
break;
case BYTE:
#ifdef XPG4
break;
}
#endif /* XPG4 */
/*FALLTHROUGH*/
case UBYTE:
break;
case STR:
/*
* Note: Currently can't get type
* STR here because we already
* did a 'continue' out of the
* loop earlier for case STR
*/
break;
}
} else
lev1 = 1;
}
return (result);
}
static void
{
char c;
while ((c = *s++) != '\0')
if (c >= 040 && c < 0176) {
(void) putchar(c);
width--;
} else {
(void) putchar('\\');
switch (c) {
case '\n':
(void) putchar('n');
width -= 2;
break;
case '\r':
(void) putchar('r');
width -= 2;
break;
case '\a':
(void) putchar('a');
width -= 2;
break;
case '\b':
(void) putchar('b');
width -= 2;
break;
case '\t':
(void) putchar('t');
width -= 2;
break;
case '\f':
(void) putchar('f');
width -= 2;
break;
case '\v':
(void) putchar('v');
width -= 2;
break;
default:
width -= 4;
break;
}
}
while (width >= 0) {
(void) putchar(' ');
width--;
};
}
static char *
{
char *s;
case BYTE:
s = "byte";
break;
case SHORT:
s = "short";
break;
case LONG:
s = "long";
break;
case LLONG:
s = "llong";
break;
case UBYTE:
s = "ubyte";
break;
case USHORT:
s = "ushort";
break;
case ULONG:
s = "ulong";
break;
case ULLONG:
s = "ullong";
break;
case STR:
return ("string");
default:
/* more of an emergency measure .. */
return (buf);
}
return (buf);
} else
return (s);
}
static char
{
char c;
case EQ:
case STRC:
c = '=';
break;
case GT:
c = '>';
break;
case LT:
c = '<';
break;
case ANY:
c = 'x';
break;
case AND:
c = '&';
break;
case NSET:
c = '^';
break;
default:
c = '?';
break;
}
return (c);
}
/*
* f_prtmtab - Prints out a header, then entries from both magic
* tables, mtab1 and mtab2, if any exist.
*/
void
f_prtmtab(void)
{
int count;
(void) printf("%-7s %-7s %-10s %-7s %-11s %s\n",
"level", "off", "type", "opcode", "value", "string");
continue;
}
(void) printf("%-7d %-7ld %-10s %-7c ",
} else { /* numeric */
}
(void) printf("\tsubst");
(void) printf("\n");
}
}
}
{
if (first) {
} else {
}
return (0);
}
case STR:
break;
case BYTE:
case UBYTE:
break;
case SHORT:
case USHORT:
break;
case LONG:
case ULONG:
break;
case LLONG:
case ULLONG:
break;
}
}
}
return (max);
}