Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F26445940
dumpsexp.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
18 KB
Subscribers
None
dumpsexp.c
View Options
/* dumpsexp.c - Dump S-expressions.
* Copyright (C) 2007, 2010 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include
<config.h>
#include
<stdio.h>
#include
<string.h>
#include
<stdlib.h>
#include
<assert.h>
#include
<stdarg.h>
#include
<errno.h>
/* For a native WindowsCE binary we need to include gpg-error.h to
provide a replacement for strerror. */
#ifdef __MINGW32CE__
# include <gpg-error.h>
#endif
#define PGM "dumpsexp"
#define MYVERSION_LINE PGM " (Libgcrypt) " VERSION
#define BUGREPORT_LINE "\nReport bugs to <bug-libgcrypt@gnupg.org>.\n"
static
int
verbose
;
/* Verbose mode. */
static
int
decimal
;
/* Print addresses in decimal. */
static
int
assume_hex
;
/* Assume input is hexencoded. */
static
int
advanced
;
/* Advanced format output. */
static
void
print_version
(
int
with_help
)
{
fputs
(
MYVERSION_LINE
"
\n
"
"Copyright (C) 2010 Free Software Foundation, Inc.
\n
"
"License GPLv3+: GNU GPL version 3 or later "
"<http://gnu.org/licenses/gpl.html>
\n
"
"This is free software: you are free to change and redistribute it.
\n
"
"There is NO WARRANTY, to the extent permitted by law.
\n
"
,
stdout
);
if
(
with_help
)
fputs
(
"
\n
"
"Usage: "
PGM
" [OPTIONS] [file]
\n
"
"Debug tool for S-expressions
\n
"
"
\n
"
" --decimal Print offsets using decimal notation
\n
"
" --assume-hex Assume input is a hex dump
\n
"
" --advanced Print file in advanced format
\n
"
" --verbose Show what we are doing
\n
"
" --version Print version of the program and exit
\n
"
" --help Display this help and exit
\n
"
BUGREPORT_LINE
,
stdout
);
exit
(
0
);
}
static
int
print_usage
(
void
)
{
fputs
(
"usage: "
PGM
" [OPTIONS] NBYTES
\n
"
,
stderr
);
fputs
(
" (use --help to display options)
\n
"
,
stderr
);
exit
(
1
);
}
#define space_p(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t')
#define digit_p(a) ((a) >= '0' && (a) <= '9')
#define octdigit_p(a) ((a) >= '0' && (a) <= '7')
#define alpha_p(a) ( ((a) >= 'A' && (a) <= 'Z') \
|| ((a) >= 'a' && (a) <= 'z'))
#define hexdigit_p(a) (digit_p (a) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'a' && (a) <= 'f'))
#define xtoi_1(a) ((a) <= '9'? ((a)- '0'): \
(a) <= 'F'? ((a)-'A'+10):((a)-'a'+10))
/* Return true if P points to a byte containing a whitespace according
to the S-expressions definition. */
static
inline
int
whitespace_p
(
int
c
)
{
switch
(
c
)
{
case
' '
:
case
'\t'
:
case
'\v'
:
case
'\f'
:
case
'\r'
:
case
'\n'
:
return
1
;
default
:
return
0
;
}
}
static
void
logit
(
const
char
*
format
,
...)
{
va_list
arg_ptr
;
va_start
(
arg_ptr
,
format
)
;
fputs
(
PGM
": "
,
stderr
);
vfprintf
(
stderr
,
format
,
arg_ptr
);
putc
(
'\n'
,
stderr
);
va_end
(
arg_ptr
);
}
/* The raw data buffer and its current length */
static
unsigned
char
databuffer
[
16
];
static
int
databufferlen
;
/* The number of bytes in databuffer which should be skipped at a flush. */
static
int
skipdatabufferlen
;
/* The number of raw bytes printed on the last line. */
static
int
nbytesprinted
;
/* The file offset of the current data buffer . */
static
unsigned
long
databufferoffset
;
static
int
my_getc
(
FILE
*
fp
)
{
int
c1
,
c2
;
if
(
!
assume_hex
)
return
getc
(
fp
);
while
(
(
c1
=
getc
(
fp
))
!=
EOF
&&
space_p
(
c1
)
)
;
if
(
c1
==
EOF
)
return
EOF
;
if
(
!
hexdigit_p
(
c1
))
{
logit
(
"non hex-digit encountered
\n
"
);
return
EOF
;
}
while
(
(
c2
=
getc
(
fp
))
!=
EOF
&&
space_p
(
c2
)
)
;
if
(
c2
==
EOF
)
{
logit
(
"error reading second hex nibble
\n
"
);
return
EOF
;
}
if
(
!
hexdigit_p
(
c2
))
{
logit
(
"second hex nibble is not a hex-digit
\n
"
);
return
EOF
;
}
return
xtoi_1
(
c1
)
*
16
+
xtoi_1
(
c2
);
}
/* Flush the raw data buffer. */
static
void
flushdatabuffer
(
void
)
{
int
i
;
if
(
!
databufferlen
)
return
;
nbytesprinted
=
0
;
if
(
decimal
)
printf
(
"%08lu "
,
databufferoffset
);
else
printf
(
"%08lx "
,
databufferoffset
);
for
(
i
=
0
;
i
<
databufferlen
;
i
++
)
{
if
(
i
==
8
)
putchar
(
' '
);
if
(
i
<
skipdatabufferlen
)
fputs
(
" "
,
stdout
);
else
{
printf
(
" %02x"
,
databuffer
[
i
]);
databufferoffset
++
;
}
nbytesprinted
++
;
}
for
(;
i
<
sizeof
(
databuffer
);
i
++
)
{
if
(
i
==
8
)
putchar
(
' '
);
fputs
(
" "
,
stdout
);
}
fputs
(
" |"
,
stdout
);
for
(
i
=
0
;
i
<
databufferlen
;
i
++
)
{
if
(
i
<
skipdatabufferlen
)
putchar
(
' '
);
else
if
(
databuffer
[
i
]
>=
' '
&&
databuffer
[
i
]
<=
'~'
&&
databuffer
[
i
]
!=
'|'
)
putchar
(
databuffer
[
i
]);
else
putchar
(
'.'
);
}
putchar
(
'|'
);
putchar
(
'\n'
);
databufferlen
=
0
;
skipdatabufferlen
=
0
;
}
/* Add C to the raw data buffer and flush as needed. */
static
void
addrawdata
(
int
c
)
{
if
(
databufferlen
>=
sizeof
databuffer
)
flushdatabuffer
();
databuffer
[
databufferlen
++
]
=
c
;
}
static
void
printcursor
(
int
both
)
{
int
i
;
flushdatabuffer
();
printf
(
"%8s "
,
""
);
for
(
i
=
0
;
i
<
sizeof
(
databuffer
);
i
++
)
{
if
(
i
==
8
)
putchar
(
' '
);
if
(
i
+
1
==
nbytesprinted
)
{
fputs
(
" ^ "
,
stdout
);
if
(
!
both
)
break
;
}
else
fputs
(
" "
,
stdout
);
}
if
(
both
)
{
fputs
(
" "
,
stdout
);
for
(
i
=
0
;
i
<
nbytesprinted
-1
;
i
++
)
putchar
(
' '
);
putchar
(
'^'
);
}
databufferlen
=
skipdatabufferlen
=
nbytesprinted
;
}
static
void
printerr
(
const
char
*
text
)
{
printcursor
(
1
);
printf
(
"
\n
Error: %s
\n
"
,
text
);
}
static
void
printctl
(
const
char
*
text
)
{
if
(
verbose
&&
!
advanced
)
{
printcursor
(
0
);
printf
(
"%s
\n
"
,
text
);
}
}
static
void
printchr
(
int
c
)
{
putchar
(
c
);
}
/* static void */
/* printhex (int c) */
/* { */
/* printf ("\\x%02x", c); */
/* } */
#if 0
/****************
* Print SEXP to buffer using the MODE. Returns the length of the
* SEXP in buffer or 0 if the buffer is too short (We have at least an
* empty list consisting of 2 bytes). If a buffer of NULL is provided,
* the required length is returned.
*/
size_t
gcry_sexp_sprint (const gcry_sexp_t list,
void *buffer, size_t maxlength )
{
static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
const unsigned char *s;
char *d;
DATALEN n;
char numbuf[20];
int i, indent = 0;
s = list? list->d : empty;
d = buffer;
while ( *s != ST_STOP )
{
switch ( *s )
{
case ST_OPEN:
s++;
if (indent)
putchar ('\n');
for (i=0; i < indent; i++)
putchar (' ');
putchar ('(');
indent++;
break;
case ST_CLOSE:
s++;
putchar (')');
indent--;
if (*s != ST_OPEN && *s != ST_STOP)
{
putchar ('\n');
for (i=0; i < indent; i++)
putchar (' ');
}
break;
case ST_DATA:
s++;
memcpy (&n, s, sizeof n);
s += sizeof n;
{
int type;
size_t nn;
switch ( (type=suitable_encoding (s, n)))
{
case 1: nn = convert_to_string (s, n, NULL); break;
case 2: nn = convert_to_token (s, n, NULL); break;
default: nn = convert_to_hex (s, n, NULL); break;
}
switch (type)
{
case 1: convert_to_string (s, n, d); break;
case 2: convert_to_token (s, n, d); break;
default: convert_to_hex (s, n, d); break;
}
d += nn;
if (s[n] != ST_CLOSE)
putchar (' ');
}
else
{
snprintf (numbuf, sizeof numbuf, "%u:", (unsigned int)n );
d = stpcpy (d, numbuf);
memcpy (d, s, n);
d += n;
}
s += n;
break;
default:
BUG ();
}
}
putchar ('\n');
return len;
}
#endif
/* Prepare for saving a chunk of data. */
static
void
init_data
(
void
)
{
}
/* Push C on the current data chunk. */
static
void
push_data
(
int
c
)
{
(
void
)
c
;
}
/* Flush and thus print the current data chunk. */
static
void
flush_data
(
void
)
{
}
/* Returns 0 on success. */
static
int
parse_and_print
(
FILE
*
fp
)
{
static
const
char
tokenchars
[]
=
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789-./_:*+="
;
int
c
;
int
level
=
0
;
int
tokenc
=
0
;
int
hexcount
=
0
;
int
disphint
=
0
;
unsigned
long
datalen
=
0
;
char
quote_buf
[
10
];
int
quote_idx
=
0
;
enum
{
INIT_STATE
=
0
,
IN_NUMBER
,
PRE_DATA
,
IN_DATA
,
IN_STRING
,
IN_ESCAPE
,
IN_OCT_ESC
,
IN_HEX_ESC
,
CR_ESC
,
LF_ESC
,
IN_HEXFMT
,
IN_BASE64
}
state
=
INIT_STATE
;
while
((
c
=
my_getc
(
fp
))
!=
EOF
)
{
addrawdata
(
c
);
switch
(
state
)
{
case
INIT_STATE
:
if
(
tokenc
)
{
if
(
strchr
(
tokenchars
,
c
))
{
printchr
(
c
);
continue
;
}
tokenc
=
0
;
}
parse_init_state
:
if
(
c
==
'('
)
{
if
(
disphint
)
{
printerr
(
"unmatched display hint"
);
disphint
=
0
;
}
printctl
(
"open"
);
level
++
;
}
else
if
(
c
==
')'
)
{
if
(
disphint
)
{
printerr
(
"unmatched display hint"
);
disphint
=
0
;
}
printctl
(
"close"
);
level
--
;
}
else
if
(
c
==
'\"'
)
{
state
=
IN_STRING
;
printctl
(
"beginstring"
);
init_data
();
}
else
if
(
c
==
'#'
)
{
state
=
IN_HEXFMT
;
hexcount
=
0
;
printctl
(
"beginhex"
);
init_data
();
}
else
if
(
c
==
'|'
)
{
state
=
IN_BASE64
;
printctl
(
"beginbase64"
);
init_data
();
}
else
if
(
c
==
'['
)
{
if
(
disphint
)
printerr
(
"nested display hint"
);
disphint
=
c
;
}
else
if
(
c
==
']'
)
{
if
(
!
disphint
)
printerr
(
"no open display hint"
);
disphint
=
0
;
}
else
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
if
(
c
==
'0'
)
printerr
(
"zero prefixed length"
);
state
=
IN_NUMBER
;
datalen
=
(
c
-
'0'
);
}
else
if
(
strchr
(
tokenchars
,
c
))
{
printchr
(
c
);
tokenc
=
c
;
}
else
if
(
whitespace_p
(
c
))
;
else
if
(
c
==
'{'
)
{
printerr
(
"rescanning is not supported"
);
}
else
if
(
c
==
'&'
||
c
==
'\\'
)
{
printerr
(
"reserved punctuation detected"
);
}
else
{
printerr
(
"bad character detected"
);
}
break
;
case
IN_NUMBER
:
if
(
digit_p
(
c
))
{
unsigned
long
tmp
=
datalen
*
10
+
(
c
-
'0'
);
if
(
tmp
<
datalen
)
{
printerr
(
"overflow in data length"
);
state
=
INIT_STATE
;
datalen
=
0
;
}
else
datalen
=
tmp
;
}
else
if
(
c
==
':'
)
{
if
(
!
datalen
)
{
printerr
(
"no data length"
);
state
=
INIT_STATE
;
}
else
state
=
PRE_DATA
;
}
else
if
(
c
==
'\"'
||
c
==
'#'
||
c
==
'|'
)
{
/* We ignore the optional length and divert to the init
state parser code. */
goto
parse_init_state
;
}
else
printerr
(
"invalid length specification"
);
break
;
case
PRE_DATA
:
state
=
IN_DATA
;
printctl
(
"begindata"
);
init_data
();
/* fall through */
case
IN_DATA
:
if
(
datalen
)
{
push_data
(
c
);
datalen
--
;
}
if
(
!
datalen
)
{
state
=
INIT_STATE
;
printctl
(
"enddata"
);
flush_data
();
}
break
;
case
IN_STRING
:
if
(
c
==
'\"'
)
{
printctl
(
"endstring"
);
flush_data
();
state
=
INIT_STATE
;
}
else
if
(
c
==
'\\'
)
state
=
IN_ESCAPE
;
else
push_data
(
c
);
break
;
case
IN_ESCAPE
:
switch
(
c
)
{
case
'b'
:
push_data
(
'\b'
);
state
=
IN_STRING
;
break
;
case
't'
:
push_data
(
'\t'
);
state
=
IN_STRING
;
break
;
case
'v'
:
push_data
(
'\v'
);
state
=
IN_STRING
;
break
;
case
'n'
:
push_data
(
'\n'
);
state
=
IN_STRING
;
break
;
case
'f'
:
push_data
(
'\f'
);
state
=
IN_STRING
;
break
;
case
'r'
:
push_data
(
'\r'
);
state
=
IN_STRING
;
break
;
case
'"'
:
push_data
(
'"'
);
state
=
IN_STRING
;
break
;
case
'\''
:
push_data
(
'\''
);
state
=
IN_STRING
;
break
;
case
'\\'
:
push_data
(
'\\'
);
state
=
IN_STRING
;
break
;
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
state
=
IN_OCT_ESC
;
quote_idx
=
0
;
quote_buf
[
quote_idx
++
]
=
c
;
break
;
case
'x'
:
state
=
IN_HEX_ESC
;
quote_idx
=
0
;
break
;
case
'\r'
:
state
=
CR_ESC
;
break
;
case
'\n'
:
state
=
LF_ESC
;
break
;
default
:
printerr
(
"invalid escape sequence"
);
state
=
IN_STRING
;
break
;
}
break
;
case
IN_OCT_ESC
:
if
(
quote_idx
<
3
&&
strchr
(
"01234567"
,
c
))
{
quote_buf
[
quote_idx
++
]
=
c
;
if
(
quote_idx
==
3
)
{
push_data
((
unsigned
int
)
quote_buf
[
0
]
*
8
*
8
+
(
unsigned
int
)
quote_buf
[
1
]
*
8
+
(
unsigned
int
)
quote_buf
[
2
]);
state
=
IN_STRING
;
}
}
else
state
=
IN_STRING
;
break
;
case
IN_HEX_ESC
:
if
(
quote_idx
<
2
&&
strchr
(
"0123456789abcdefABCDEF"
,
c
))
{
quote_buf
[
quote_idx
++
]
=
c
;
if
(
quote_idx
==
2
)
{
push_data
(
xtoi_1
(
quote_buf
[
0
])
*
16
+
xtoi_1
(
quote_buf
[
1
]));
state
=
IN_STRING
;
}
}
else
state
=
IN_STRING
;
break
;
case
CR_ESC
:
state
=
IN_STRING
;
break
;
case
LF_ESC
:
state
=
IN_STRING
;
break
;
case
IN_HEXFMT
:
if
(
hexdigit_p
(
c
))
{
push_data
(
c
);
hexcount
++
;
}
else
if
(
c
==
'#'
)
{
if
((
hexcount
&
1
))
printerr
(
"odd number of hex digits"
);
printctl
(
"endhex"
);
flush_data
();
state
=
INIT_STATE
;
}
else
if
(
!
whitespace_p
(
c
))
printerr
(
"bad hex character"
);
break
;
case
IN_BASE64
:
if
(
c
==
'|'
)
{
printctl
(
"endbase64"
);
flush_data
();
state
=
INIT_STATE
;
}
else
push_data
(
c
);
break
;
default
:
logit
(
"invalid state %d detected"
,
state
);
exit
(
1
);
}
}
flushdatabuffer
();
if
(
ferror
(
fp
))
{
logit
(
"error reading input: %s
\n
"
,
strerror
(
errno
));
return
-1
;
}
return
0
;
}
int
main
(
int
argc
,
char
**
argv
)
{
int
rc
;
if
(
argc
)
{
argc
--
;
argv
++
;
}
while
(
argc
&&
**
argv
==
'-'
&&
(
*
argv
)[
1
]
==
'-'
)
{
if
(
!
(
*
argv
)[
2
])
{
argc
--
;
argv
++
;
break
;
}
else
if
(
!
strcmp
(
*
argv
,
"--version"
))
print_version
(
0
);
else
if
(
!
strcmp
(
*
argv
,
"--help"
))
print_version
(
1
);
else
if
(
!
strcmp
(
*
argv
,
"--verbose"
))
{
argc
--
;
argv
++
;
verbose
=
1
;
}
else
if
(
!
strcmp
(
*
argv
,
"--decimal"
))
{
argc
--
;
argv
++
;
decimal
=
1
;
}
else
if
(
!
strcmp
(
*
argv
,
"--assume-hex"
))
{
argc
--
;
argv
++
;
assume_hex
=
1
;
}
else
if
(
!
strcmp
(
*
argv
,
"--advanced"
))
{
argc
--
;
argv
++
;
advanced
=
1
;
}
else
print_usage
();
}
if
(
!
argc
)
{
rc
=
parse_and_print
(
stdin
);
}
else
{
rc
=
0
;
for
(;
argc
;
argv
++
,
argc
--
)
{
FILE
*
fp
=
fopen
(
*
argv
,
"rb"
);
if
(
!
fp
)
{
logit
(
"can't open `%s': %s
\n
"
,
*
argv
,
strerror
(
errno
));
rc
=
1
;
}
else
{
if
(
parse_and_print
(
fp
))
rc
=
1
;
fclose
(
fp
);
}
}
}
return
!!
rc
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Jul 17, 12:10 AM (6 h, 58 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
df/43/bbd36329cf1515063d246f7e50b9
Attached To
rC libgcrypt
Event Timeline
Log In to Comment