#include <stdio.h>
#include <string.h>
#include <time.h>
#define mystr "My own utility. Copyright (C) 2007-2010 hpgl, Russia"
#define allow595B
#define allowA95B
#define allow2A7B
#define fSVCTAG 0
#define fHDDSN 1
#define fHDDold 2
#define t595B 0
#define tD35B 1
#define tA95B 2
#define t2A7B 3
#ifdef allow595B
#define f595B
#endif
#ifdef allowA95B
#define f595B
#endif
#ifdef allow2A7B
#define f595B
#endif
char bSuffix[ ] = "595BD35BA95B2A7B" ;
char scancods[ ] = "\00 \033 1234567890-=\010 \011 qwertyuiop[]\015 \377 asdfghjkl;'`\377 \\ zxcvbnm,./" ;
char encscans[ ] = { 0x05 , 0x10 , 0x13 , 0x09 , 0x32 , 0x03 , 0x25 , 0x11 , 0x1F , 0x17 , 0x06 , 0x15 , \
0x30 , 0x19 , 0x26 , 0x22 , 0x0A , 0x02 , 0x2C , 0x2F , 0x16 , 0x14 , 0x07 , 0x18 , \
0x24 , 0x23 , 0x31 , 0x20 , 0x1E , 0x08 , 0x2D , 0x21 , 0x04 , 0x0B , 0x12 , 0x2E } ;
#ifdef allow2A7B
char chartabl2A7B[ 72 ] = "012345679abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0" ;
#endif
unsigned int MD5magic[ 64 ] = {
0xd76aa478 , 0xe8c7b756 , 0x242070db , 0xc1bdceee ,
0xf57c0faf , 0x4787c62a , 0xa8304613 , 0xfd469501 ,
0x698098d8 , 0x8b44f7af , 0xffff5bb1 , 0x895cd7be ,
0x6b901122 , 0xfd987193 , 0xa679438e , 0x49b40821 ,
0xf61e2562 , 0xc040b340 , 0x265e5a51 , 0xe9b6c7aa ,
0xd62f105d , 0x02441453 , 0xd8a1e681 , 0xe7d3fbc8 ,
0x21e1cde6 , 0xc33707d6 , 0xf4d50d87 , 0x455a14ed ,
0xa9e3e905 , 0xfcefa3f8 , 0x676f02d9 , 0x8d2a4c8a ,
0xfffa3942 , 0x8771f681 , 0x6d9d6122 , 0xfde5380c ,
0xa4beea44 , 0x4bdecfa9 , 0xf6bb4b60 , 0xbebfbc70 ,
0x289b7ec6 , 0xeaa127fa , 0xd4ef3085 , 0x4881d05 ,
0xd9d4d039 , 0xe6db99e5 , 0x1fa27cf8 , 0xc4ac5665 ,
0xf4292244 , 0x432aff97 , 0xab9423a7 , 0xfc93a039 ,
0x655b59c3 , 0x8f0ccc92 , 0xffeff47d , 0x85845dd1 ,
0x6fa87e4f , 0xfe2ce6e0 , 0xa3014314 , 0x4e0811a1 ,
0xf7537e82 , 0xbd3af235 , 0x2ad7d2bb , 0xeb86d391 } ;
unsigned char inData[ 23 ] , outData[ 16 ] ;
char buf1output[ 32 ] , buf1input[ 20 ] ;
char bug4;
void calcsuffix( char bfunc, char btype, char * outbuf) ;
void initData( void ) {
* ( int * ) ( & outData[ 0 ] ) = 0x67452301 ;
* ( int * ) ( & outData[ 4 ] ) = 0xEFCDAB89 ;
* ( int * ) ( & outData[ 8 ] ) = 0x98BADCFE ;
* ( int * ) ( & outData[ 12 ] ) = 0x10325476 ;
}
typedef int ( encfuncT1) ( int num1, int num2, int num3) ;
#ifdef f595B
int enc0F2( int num1, int num2, int num3) { return ( ( ( ~num3 ^ num2) & num1) ^ ~num3) ; }
int enc0F4( int num1, int num2, int num3) { return ( ( ~num2 ^ num1) ^ num3) ; }
int enc0F5( int num1, int num2, int num3) { return ( ( ~num1 | ~num3) ^ num2) ; }
#endif
int enc1F2( int num1, int num2, int num3) { return ( ( ( num3 ^ num2) & num1) ^ num3) ; }
int enc1F4( int num1, int num2, int num3) { return ( ( num2 ^ num1) ^ num3) ; }
int enc1F5( int num1, int num2, int num3) { return ( ( num1 | ~num3) ^ num2) ; }
int encF3 ( int num1, int num2, int num3) { return ( ( ( num1 ^ num2) & num3) ^ num2) ; }
typedef int ( encfuncT2) ( encfuncT1 func, int num1, int num2, int num3, int key) ;
int enc1F1 ( encfuncT1 func, int num1, int num2, int num3, int key)
{
return func( num1, num2, num3) + key;
}
#ifdef f595B
int enc0F1 ( encfuncT1 func, int num1, int num2, int num3, int key)
{
return func( num1, num2, num3) - key;
}
#endif
unsigned int rol( unsigned int t, int bitsrot)
{
return ( t >> ( 32 - bitsrot) ) | ( t << bitsrot) ;
}
void blockEncodeF( int * outdata, int * encblock, encfuncT2 func1,
encfuncT1 func2, encfuncT1 func3, encfuncT1 func4, encfuncT1 func5 )
{
char S[ 4 ] [ 4 ] = { { 7 , 12 , 17 , 22 } , { 5 , 9 , 14 , 20 } , { 4 , 11 , 16 , 23 } , { 6 , 10 , 15 , 21 } } ;
int A, B, C, D, t, i;
A= outdata[ 0 ] ;
B= outdata[ 1 ] ;
C= outdata[ 2 ] ;
D= outdata[ 3 ] ;
for ( i= 0 ; i< 64 ; i++ ) { t= MD5magic[ i] ; switch ( i>> 4 ) {
case 0 : t= A+ func1( func2, B, C, D, t+ encblock[ ( i) & 15 ] ) ; break ;
case 1 : t= A+ func1( func3, B, C, D, t+ encblock[ ( i* 5 + 1 ) & 15 ] ) ; break ;
case 2 : t= A+ func1( func4, B, C, D, t+ encblock[ ( i* 3 + 5 ) & 15 ] ) ; break ;
case 3 : t= A+ func1( func5, B, C, D, t+ encblock[ ( i* 7 ) & 15 ] ) ; break ;
}
A= D; D= C; C= B; B+= rol( t, S[ i>> 4 ] [ i& 3 ] ) ;
} ;
outdata[ 0 ] += A;
outdata[ 1 ] += B;
outdata[ 2 ] += C;
outdata[ 3 ] += D;
}
void blockEncode( char * outdata, int * encblock, char btype) {
if ( btype== tD35B)
blockEncodeF( ( int * ) outdata, encblock, enc1F1, enc1F2, encF3, enc1F4, enc1F5) ;
#ifdef f595B
else
blockEncodeF( ( int * ) outdata, encblock, enc0F1, enc0F2, encF3, enc0F4, enc0F5) ;
#endif
}
void encode( char * inbuf, int cnt, char btype) {
int encBlock[ 16 ] ;
char * ptr;
initData( ) ;
ptr=& ( ( char * ) encBlock) [ cnt] ;
* ptr++= 0x80 ;
encBlock[ 16 - 2 ] = ( ( unsigned int ) cnt << 3 ) ;
blockEncode( outData, encBlock, btype) ;
}
void psw( char bfunc, char btype, char * outbuf) {
int cnt, i, lenpsw, r;
if ( bfunc== fHDDold) {
// calcsuffix(bfunc,btype,outbuf);
for ( cnt
= 0 ; cnt
< 8 ; cnt
++ ) outbuf
[ cnt
] = scancods
[ outbuf
[ cnt
] ] ; } else { memset ( inData
, 0 , sizeof ( inData
) ) ; if ( bfunc
== fSVCTAG
) cnt
= 7 ; else cnt
= 11 ; if ( ( bfunc
== fHDDSN
) && ( btype
== tA95B
) ) memcpy ( inData
,& buf1input
[ 3 ] , cnt
- 3 ) ; else memcpy ( inData
, buf1input
, cnt
) ; if ( btype
== t595B
) memcpy ( & inData
[ cnt
] ,& bSuffix
[ 0 ] , 4 ) ; else if ( btype
== tD35B
) memcpy ( & inData
[ cnt
] ,& bSuffix
[ 4 ] , 4 ) ; else if ( btype
== tA95B
) memcpy ( & inData
[ cnt
] ,& bSuffix
[ 0 ] , 4 ) ; else if ( btype
== t2A7B
) memcpy ( & inData
[ cnt
] ,& bSuffix
[ 12 ] , 4 ) ; cnt
+= 4 ; inData
[ cnt
] = inData
[ 4 ] & 0x1F ; inData
[ cnt
+ 1 ] = ( ( inData
[ 4 ] >> 5 ) | ( ( ( inData
[ 3 ] >> 5 ) | ( inData
[ 3 ] << 3 ) ) & 0xF1 ) & 0x1F ) ; inData
[ cnt
+ 2 ] = ( ( inData
[ 3 ] >> 2 ) & 0x1F ) ; inData[ cnt+ 3 ] = ( inData[ 3 ] >> 7 ) | ( ( inData[ 2 ] << 1 ) & 0x1F ) ; inData[ cnt+ 4 ] = ( inData[ 2 ] >> 4 ) | ( ( inData[ 1 ] << 4 ) & 0x1F ) ; inData[ cnt+ 5 ] = ( inData[ 1 ] >> 1 ) & 0x1F ;
inData[ cnt+ 6 ] = ( inData[ 1 ] >> 6 ) | ( ( inData[ 0 ] << 2 ) & 0x1F ) ; inData[ cnt+ 7 ] = ( inData[ 0 ] >> 3 ) & 0x1F ;
for ( i= cnt; i< 8 + cnt; i++ ) {
r = 0xAA ;
if ( inData[ i] & 1 )
r ^= inData[ 4 ] ;
if ( inData[ i] & 2 )
r ^= inData[ 3 ] ;
if ( inData[ i] & 4 )
r ^= inData[ 2 ] ;
if ( inData[ i] & 8 )
r ^= inData[ 1 ] ;
if ( inData[ i] & 16 )
r ^= inData[ 0 ] ;
inData[ i] = encscans[ r % sizeof ( encscans) ] ;
}
cnt = 23 ;
encode( inData, cnt, btype) ;
r = outData[ 0 ] % 9 ;
lenpsw = 0 ;
for ( cnt= 0 ; cnt< 16 ; cnt++ ) {
if ( ( r <= cnt) && ( lenpsw< 8 ) ) { buf1output[ lenpsw++ ] = scancods[ encscans[ outData[ cnt] % sizeof ( encscans) ] ] ; } } } } int main( int argc, char * argv[ ] ) { unsigned char len, len1, bfunc, eol= 1 , echo= 0 , * minus, s2[ 20 ] ; signed char btype; int argn= 0 ; if ( argc> 1 )
echo= 1 ;
if ( ! echo)
"Short service tag should be right padded with '*' up to length 7 chars\n " \
"HDD serial number is right 11 chars from real HDDSerNum left padded with '*'\n " \
"Some BIOSes has left pad HDD serial number with spaces instead '*'\n " , stdout) ;
if ( ( argc
<= 1 ) && argn
) break ; fputs ( "Input: #" , stdout
) ; if ( argc
> 1 ) { strncpy ( buf1input
, argv
[ ++ argn
] , sizeof ( buf1input
) ) ; argc
--; }
else {
if ( ! eol
) while ( ! feof ( stdin
) && ( fgetc ( stdin
) != '\n ' ) ) ; eol
= 0 ; if ( fgets ( buf1input
, 16 + 1 + 1 , stdin
) == NULL
) { if ( echo
) fputs ( "\n " , stdout
) ; break ;
}
}
if ( len && ( buf1input[ len- 1 ] == '\n ' ) ) { len--; eol= 1 ; buf1input[ len] = 0 ; }
if ( echo
) { fputs ( buf1input
, stdout
) ; fputs ( "\n " , stdout
) ; } if ( len== 11 ) {
if ( minus!= NULL) {
fputs ( "- Incorrect input\n " , stdout
) ; continue ;
}
bfunc= fHDDold;
fputs ( "By HDD serial number for older BIOS: " , stdout
) ; } else {
if ( len== 0 ) break ;
if ( minus== NULL) {
fputs ( "- No BIOS type found in input string, must be followed by -595B and other registered\n " , stdout
) ; continue ;
}
len1= minus- ( unsigned char * ) buf1input;
btype=- 1 ;
#ifdef allow595B
if ( strncmp ( & buf1input
[ len1
+ 1 ] ,& bSuffix
[ 0 ] , 4 ) == 0 ) btype
= t595B
; else
#endif
if ( strncmp ( & buf1input
[ len1
+ 1 ] ,& bSuffix
[ 4 ] , 4 ) == 0 ) btype
= tD35B
; else
#ifdef allowA95B
if ( strncmp ( & buf1input
[ len1
+ 1 ] ,& bSuffix
[ 8 ] , 4 ) == 0 ) btype
= tA95B
; else
#endif
#ifdef allow2A7B
if ( strncmp ( & buf1input
[ len1
+ 1 ] ,& bSuffix
[ 12 ] , 4 ) == 0 ) btype
= t2A7B
; #endif
if ( btype< 0 ) {
fputs ( "- Invalid service tag in input string, allowed only -D35B and other registered\n " , stdout
) ; continue ;
}
struct tm
* time1
; time_t timer1
= time ( NULL
) ; strftime ( s2
, sizeof ( s2
) , "%d.%m.%Y %H:%M" , time1
) ;
if ( len1== 7 ) {
bfunc= fSVCTAG;
fputs ( "service tag: " , stdout
) ; } else
if ( len1== 11 ) {
bfunc= fHDDSN;
fputs ( "HDD serial number: " , stdout
) ; }
else {
fputs ( "- Incorrect input, must be 7 chars service tag or 11 chars HDD serial number\n " , stdout
) ; continue ;
}
}
psw( bfunc, btype, buf1output) ;
fputs ( " password: " , stdout
) ; fputs ( buf1output
, stdout
) ; if ( bug4
) fputs ( " !bug4 warning - password may not work!" , stdout
) ;
if ( btype== t595B) if ( bfunc== fSVCTAG) { //to check if A95B bug
char mpw1[ 20 ] ;
psw( bfunc, tA95B, buf1output) ;
if ( strcmp ( mpw1
, buf1output
) != 0 ) { fputs ( " passwordA95B: " , stdout
) ; fputs ( buf1output
, stdout
) ; }
}
}
return 0 ;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHRpbWUuaD4KIAojZGVmaW5lIG15c3RyICJNeSBvd24gdXRpbGl0eS4gQ29weXJpZ2h0IChDKSAyMDA3LTIwMTAgaHBnbCwgUnVzc2lhIgogCiNkZWZpbmUgYWxsb3c1OTVCCiNkZWZpbmUgYWxsb3dBOTVCCiNkZWZpbmUgYWxsb3cyQTdCCiAKI2RlZmluZSBmU1ZDVEFHIDAKI2RlZmluZSBmSEREU04gMQojZGVmaW5lIGZIRERvbGQgMgojZGVmaW5lIHQ1OTVCIDAKI2RlZmluZSB0RDM1QiAxCiNkZWZpbmUgdEE5NUIgMgojZGVmaW5lIHQyQTdCIDMKIAojaWZkZWYgYWxsb3c1OTVCCiNkZWZpbmUgZjU5NUIKI2VuZGlmCiNpZmRlZiBhbGxvd0E5NUIKI2RlZmluZSBmNTk1QgojZW5kaWYKI2lmZGVmIGFsbG93MkE3QgojZGVmaW5lIGY1OTVCCiNlbmRpZgogCmNoYXIgYlN1ZmZpeFtdPSI1OTVCRDM1QkE5NUIyQTdCIjsKIApjaGFyIHNjYW5jb2RzW109IlwwMFwwMzMxMjM0NTY3ODkwLT1cMDEwXDAxMXF3ZXJ0eXVpb3BbXVwwMTVcMzc3YXNkZmdoamtsOydgXDM3N1xcenhjdmJubSwuLyI7CmNoYXIgZW5jc2NhbnNbXT17MHgwNSwweDEwLDB4MTMsMHgwOSwweDMyLDB4MDMsMHgyNSwweDExLDB4MUYsMHgxNywweDA2LDB4MTUsIFwKICAgICAgICAgICAgICAgICAweDMwLDB4MTksMHgyNiwweDIyLDB4MEEsMHgwMiwweDJDLDB4MkYsMHgxNiwweDE0LDB4MDcsMHgxOCwgXAogICAgICAgICAgICAgICAgIDB4MjQsMHgyMywweDMxLDB4MjAsMHgxRSwweDA4LDB4MkQsMHgyMSwweDA0LDB4MEIsMHgxMiwweDJFfTsKIAojaWZkZWYgYWxsb3cyQTdCCmNoYXIgY2hhcnRhYmwyQTdCWzcyXT0iMDEyMzQ1Njc5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowIjsKI2VuZGlmCiAKdW5zaWduZWQgaW50IE1ENW1hZ2ljWzY0XT17CjB4ZDc2YWE0NzgsIDB4ZThjN2I3NTYsIDB4MjQyMDcwZGIsIDB4YzFiZGNlZWUsCjB4ZjU3YzBmYWYsIDB4NDc4N2M2MmEsIDB4YTgzMDQ2MTMsIDB4ZmQ0Njk1MDEsCjB4Njk4MDk4ZDgsIDB4OGI0NGY3YWYsIDB4ZmZmZjViYjEsIDB4ODk1Y2Q3YmUsCjB4NmI5MDExMjIsIDB4ZmQ5ODcxOTMsIDB4YTY3OTQzOGUsIDB4NDliNDA4MjEsCjB4ZjYxZTI1NjIsIDB4YzA0MGIzNDAsIDB4MjY1ZTVhNTEsIDB4ZTliNmM3YWEsCjB4ZDYyZjEwNWQsIDB4MDI0NDE0NTMsIDB4ZDhhMWU2ODEsIDB4ZTdkM2ZiYzgsCjB4MjFlMWNkZTYsIDB4YzMzNzA3ZDYsIDB4ZjRkNTBkODcsIDB4NDU1YTE0ZWQsCjB4YTllM2U5MDUsIDB4ZmNlZmEzZjgsIDB4Njc2ZjAyZDksIDB4OGQyYTRjOGEsCjB4ZmZmYTM5NDIsIDB4ODc3MWY2ODEsIDB4NmQ5ZDYxMjIsIDB4ZmRlNTM4MGMsCjB4YTRiZWVhNDQsIDB4NGJkZWNmYTksIDB4ZjZiYjRiNjAsIDB4YmViZmJjNzAsCjB4Mjg5YjdlYzYsIDB4ZWFhMTI3ZmEsIDB4ZDRlZjMwODUsIDB4NDg4MWQwNSwKMHhkOWQ0ZDAzOSwgMHhlNmRiOTllNSwgMHgxZmEyN2NmOCwgMHhjNGFjNTY2NSwKMHhmNDI5MjI0NCwgMHg0MzJhZmY5NywgMHhhYjk0MjNhNywgMHhmYzkzYTAzOSwKMHg2NTViNTljMywgMHg4ZjBjY2M5MiwgMHhmZmVmZjQ3ZCwgMHg4NTg0NWRkMSwKMHg2ZmE4N2U0ZiwgMHhmZTJjZTZlMCwgMHhhMzAxNDMxNCwgMHg0ZTA4MTFhMSwKMHhmNzUzN2U4MiwgMHhiZDNhZjIzNSwgMHgyYWQ3ZDJiYiwgMHhlYjg2ZDM5MX07CiAKdW5zaWduZWQgY2hhciBpbkRhdGFbMjNdLG91dERhdGFbMTZdOwpjaGFyIGJ1ZjFvdXRwdXRbMzJdLCBidWYxaW5wdXRbMjBdOwpjaGFyIGJ1ZzQ7CiAKdm9pZCBjYWxjc3VmZml4KGNoYXIgYmZ1bmMsIGNoYXIgYnR5cGUsIGNoYXIgKm91dGJ1Zik7CiAKdm9pZCBpbml0RGF0YSh2b2lkKSB7CgkqKGludCAqKSgmb3V0RGF0YVswXSkgPTB4Njc0NTIzMDE7CgkqKGludCAqKSgmb3V0RGF0YVs0XSkgPTB4RUZDREFCODk7CgkqKGludCAqKSgmb3V0RGF0YVs4XSkgPTB4OThCQURDRkU7CgkqKGludCAqKSgmb3V0RGF0YVsxMl0pPTB4MTAzMjU0NzY7Cn0KIAp0eXBlZGVmIGludCAoZW5jZnVuY1QxKSAoaW50IG51bTEsIGludCBudW0yLCBpbnQgbnVtMyk7CiAKI2lmZGVmIGY1OTVCCmludCBlbmMwRjIoaW50IG51bTEsIGludCBudW0yLCBpbnQgbnVtMykge3JldHVybiAoKCh+bnVtMyBeIG51bTIpICYgbnVtMSkgXiB+bnVtMyk7fQppbnQgZW5jMEY0KGludCBudW0xLCBpbnQgbnVtMiwgaW50IG51bTMpIHtyZXR1cm4gKCggfm51bTIgXiBudW0xKSBeIG51bTMpOyB9CmludCBlbmMwRjUoaW50IG51bTEsIGludCBudW0yLCBpbnQgbnVtMykge3JldHVybiAoKCB+bnVtMSB8IH5udW0zKSBeIG51bTIpOyB9CiNlbmRpZgppbnQgZW5jMUYyKGludCBudW0xLCBpbnQgbnVtMiwgaW50IG51bTMpIHtyZXR1cm4gKCgoIG51bTMgXiBudW0yKSAmIG51bTEpIF4gbnVtMyk7fQppbnQgZW5jMUY0KGludCBudW0xLCBpbnQgbnVtMiwgaW50IG51bTMpIHtyZXR1cm4gKCggbnVtMiBeIG51bTEpIF4gbnVtMyk7IH0KaW50IGVuYzFGNShpbnQgbnVtMSwgaW50IG51bTIsIGludCBudW0zKSB7cmV0dXJuICgoIG51bTEgfCB+bnVtMykgXiBudW0yKTsgfQppbnQgZW5jRjMgKGludCBudW0xLCBpbnQgbnVtMiwgaW50IG51bTMpIHtyZXR1cm4gKCgoIG51bTEgXiBudW0yKSAmIG51bTMpIF4gbnVtMik7fQogCnR5cGVkZWYgaW50IChlbmNmdW5jVDIpKGVuY2Z1bmNUMSBmdW5jLCBpbnQgbnVtMSwgaW50IG51bTIsIGludCBudW0zLCBpbnQga2V5KTsKIAppbnQgZW5jMUYxIChlbmNmdW5jVDEgZnVuYywgaW50IG51bTEsIGludCBudW0yLCBpbnQgbnVtMywgaW50IGtleSkKewoJcmV0dXJuIGZ1bmMobnVtMSxudW0yLG51bTMpK2tleTsKfQogCiNpZmRlZiBmNTk1QgppbnQgZW5jMEYxIChlbmNmdW5jVDEgZnVuYywgaW50IG51bTEsIGludCBudW0yLCBpbnQgbnVtMywgaW50IGtleSkKewoJcmV0dXJuIGZ1bmMobnVtMSxudW0yLG51bTMpLWtleTsKfQojZW5kaWYKIAp1bnNpZ25lZCBpbnQgcm9sKHVuc2lnbmVkIGludCB0LCBpbnQgYml0c3JvdCkKewoJcmV0dXJuICh0ID4+ICgzMi1iaXRzcm90KSkgfCAodCA8PCBiaXRzcm90KTsKfQogCnZvaWQgYmxvY2tFbmNvZGVGKGludCAqb3V0ZGF0YSwgaW50ICplbmNibG9jaywgZW5jZnVuY1QyIGZ1bmMxLAogICAgICAgICAgICAgICAgICBlbmNmdW5jVDEgZnVuYzIsIGVuY2Z1bmNUMSBmdW5jMywgZW5jZnVuY1QxIGZ1bmM0LCBlbmNmdW5jVDEgZnVuYzUgKQp7CgljaGFyIFNbNF1bNF0gPSB7eyA3LCAxMiwgMTcsIDIyIH0seyA1LCA5LCAxNCwgMjAgfSx7IDQsIDExLCAxNiwgMjMgfSx7IDYsIDEwLCAxNSwgMjEgfX07CglpbnQgQSxCLEMsRCx0LGk7CiAKCUE9b3V0ZGF0YVswXTsKCUI9b3V0ZGF0YVsxXTsKCUM9b3V0ZGF0YVsyXTsKCUQ9b3V0ZGF0YVszXTsKIAoJZm9yIChpPTA7aTw2NDtpKyspIHsgCQl0PU1ENW1hZ2ljW2ldOyAJCXN3aXRjaCAoaT4+NCkgewoJCQljYXNlIDA6IHQ9QStmdW5jMShmdW5jMixCLEMsRCwgdCtlbmNibG9ja1soaSkgJiAxNV0pOyBicmVhazsKCQkJY2FzZSAxOiB0PUErZnVuYzEoZnVuYzMsQixDLEQsIHQrZW5jYmxvY2tbKGkqNSsxKSAmIDE1XSk7IGJyZWFrOwoJCQljYXNlIDI6IHQ9QStmdW5jMShmdW5jNCxCLEMsRCwgdCtlbmNibG9ja1soaSozKzUpICYgMTVdKTsgYnJlYWs7CgkJCWNhc2UgMzogdD1BK2Z1bmMxKGZ1bmM1LEIsQyxELCB0K2VuY2Jsb2NrWyhpKjcpICYgMTVdKTsgYnJlYWs7CgkJfQoJCUE9RDsgRD1DOyBDPUI7IEIrPXJvbCh0LFNbaT4+NF1baSYzXSk7Cgl9OwogCglvdXRkYXRhWzBdKz1BOwoJb3V0ZGF0YVsxXSs9QjsKCW91dGRhdGFbMl0rPUM7CglvdXRkYXRhWzNdKz1EOwp9CiAKdm9pZCBibG9ja0VuY29kZShjaGFyICpvdXRkYXRhLCBpbnQgKmVuY2Jsb2NrLCBjaGFyIGJ0eXBlKSB7CglpZiAoYnR5cGU9PXREMzVCKQoJCWJsb2NrRW5jb2RlRigoaW50ICopb3V0ZGF0YSxlbmNibG9jayxlbmMxRjEsZW5jMUYyLGVuY0YzLGVuYzFGNCxlbmMxRjUpOwojaWZkZWYgZjU5NUIKCWVsc2UKCQlibG9ja0VuY29kZUYoKGludCAqKW91dGRhdGEsZW5jYmxvY2ssZW5jMEYxLGVuYzBGMixlbmNGMyxlbmMwRjQsZW5jMEY1KTsKI2VuZGlmCn0KIAp2b2lkIGVuY29kZShjaGFyICppbmJ1ZixpbnQgY250LGNoYXIgYnR5cGUpIHsKCWludCBlbmNCbG9ja1sxNl07CgljaGFyICpwdHI7Cglpbml0RGF0YSgpOwoJbWVtY3B5KGVuY0Jsb2NrLGluYnVmLGNudCk7CglwdHI9JigoY2hhciAqKWVuY0Jsb2NrKVtjbnRdOwoJKnB0cisrPTB4ODA7CgltZW1zZXQocHRyLDAsNjQtMS1jbnQpOwoJZW5jQmxvY2tbMTYtMl09KCh1bnNpZ25lZCBpbnQpY250IDw8IDMpOwoJYmxvY2tFbmNvZGUob3V0RGF0YSxlbmNCbG9jayxidHlwZSk7Cn0KIAp2b2lkIHBzdyhjaGFyIGJmdW5jLCBjaGFyIGJ0eXBlLCBjaGFyICpvdXRidWYpIHsKCWludCBjbnQsaSxsZW5wc3cscjsKCWlmIChiZnVuYz09ZkhERG9sZCkgewoJCW1lbWNweShpbkRhdGEsYnVmMWlucHV0LDExKTsKLy8JCWNhbGNzdWZmaXgoYmZ1bmMsYnR5cGUsb3V0YnVmKTsKCQlmb3IgKGNudD0wO2NudDw4O2NudCsrKSAJCQlvdXRidWZbY250XT0gc2NhbmNvZHNbIG91dGJ1ZltjbnRdIF07IAl9IGVsc2UgeyAJCW1lbXNldChpbkRhdGEsMCxzaXplb2YoaW5EYXRhKSk7IAkJaWYgKGJmdW5jPT1mU1ZDVEFHKSBjbnQ9NzsgCQllbHNlIGNudD0xMTsgCQlpZiAoKGJmdW5jPT1mSEREU04pICYmIChidHlwZT09dEE5NUIpKSAJCQltZW1jcHkoaW5EYXRhLCZidWYxaW5wdXRbM10sY250LTMpOyAJCWVsc2UgCQkJbWVtY3B5KGluRGF0YSxidWYxaW5wdXQsY250KTsgCQlpZiAoYnR5cGU9PXQ1OTVCKSBtZW1jcHkoJmluRGF0YVtjbnRdLCZiU3VmZml4WzBdLDQpOyBlbHNlIAkJaWYgKGJ0eXBlPT10RDM1QikgbWVtY3B5KCZpbkRhdGFbY250XSwmYlN1ZmZpeFs0XSw0KTsgZWxzZSAJCWlmIChidHlwZT09dEE5NUIpIG1lbWNweSgmaW5EYXRhW2NudF0sJmJTdWZmaXhbMF0sNCk7IGVsc2UgCQlpZiAoYnR5cGU9PXQyQTdCKSBtZW1jcHkoJmluRGF0YVtjbnRdLCZiU3VmZml4WzEyXSw0KTsgCQljbnQgKz0gNDsgCQlpbkRhdGFbY250XSA9IGluRGF0YVs0XSAmIDB4MUY7IAkJaW5EYXRhW2NudCsxXSA9ICgoaW5EYXRhWzRdID4+IDUpIHwgKCgoaW5EYXRhWzNdID4+IDUpIHwgKGluRGF0YVszXSA8PCAzKSkgJiAweEYxKSAmIDB4MUYpOyAJCWluRGF0YVtjbnQrMl0gPSAoKGluRGF0YVszXSA+PiAyKSAmIDB4MUYpOwoJCWluRGF0YVtjbnQrM10gPSAoaW5EYXRhWzNdID4+IDcpIHwgKChpbkRhdGFbMl0gPDwgMSkgJiAweDFGKTsgCQlpbkRhdGFbY250KzRdID0gKGluRGF0YVsyXSA+PiA0KSB8ICgoaW5EYXRhWzFdIDw8IDQpICYgMHgxRik7IAkJaW5EYXRhW2NudCs1XSA9IChpbkRhdGFbMV0gPj4gMSkgJiAweDFGOwoJCWluRGF0YVtjbnQrNl0gPSAoaW5EYXRhWzFdID4+IDYpIHwgKChpbkRhdGFbMF0gPDwgMikgJiAweDFGKTsgCQlpbkRhdGFbY250KzddID0gKGluRGF0YVswXSA+PiAzKSAmIDB4MUY7CgkJZm9yIChpPWNudDtpPDgrY250O2krKykgewoJCQlyID0gMHhBQTsKCQkJaWYgKGluRGF0YVtpXSAmIDEpCgkJCQlyIF49IGluRGF0YVs0XTsKCQkJaWYgKGluRGF0YVtpXSAmIDIpCgkJCQlyIF49IGluRGF0YVszXTsKCQkJaWYgKGluRGF0YVtpXSAmIDQpCgkJCQlyIF49IGluRGF0YVsyXTsKCQkJaWYgKGluRGF0YVtpXSAmIDgpCgkJCQlyIF49IGluRGF0YVsxXTsKCQkJaWYgKGluRGF0YVtpXSAmIDE2KQoJCQkJciBePSBpbkRhdGFbMF07CgkJCWluRGF0YVtpXSA9IGVuY3NjYW5zW3IgJSBzaXplb2YoZW5jc2NhbnMpXTsKCQl9CgkJY250ID0gMjM7CgkJZW5jb2RlKGluRGF0YSxjbnQsYnR5cGUpOwoJCXIgPSBvdXREYXRhWzBdICUgOTsKCQlsZW5wc3cgPSAwOwoJCWZvciAoY250PTA7Y250PDE2O2NudCsrKSB7CgkJCWlmICgociA8PSBjbnQpICYmIChsZW5wc3c8OCkpIHsgCQkJCWJ1ZjFvdXRwdXRbbGVucHN3KytdID0gc2NhbmNvZHNbZW5jc2NhbnNbb3V0RGF0YVtjbnRdICUgc2l6ZW9mKGVuY3NjYW5zKV1dOyAJCQl9IAkJfSAJfSB9IGludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pIHsgCXVuc2lnbmVkIGNoYXIgbGVuLGxlbjEsYmZ1bmMsZW9sPTEsZWNobz0wLCAqbWludXMsczJbMjBdOyAJc2lnbmVkIGNoYXIgYnR5cGU7IGludCBhcmduPTA7IAlpZiAoYXJnYz4xKQoJCWVjaG89MTsKIAoJaWYgKCFlY2hvKQoJCWZwdXRzKCIiIG15c3RyICJcbiIgXAoJCSAgIlNob3J0IHNlcnZpY2UgdGFnIHNob3VsZCBiZSByaWdodCBwYWRkZWQgd2l0aCAnKicgdXAgdG8gbGVuZ3RoIDcgY2hhcnNcbiIgXAoJCSAgIkhERCBzZXJpYWwgbnVtYmVyIGlzIHJpZ2h0IDExIGNoYXJzIGZyb20gcmVhbCBIRERTZXJOdW0gbGVmdCBwYWRkZWQgd2l0aCAnKidcbiIgXAoJCSAgIlNvbWUgQklPU2VzIGhhcyBsZWZ0IHBhZCBIREQgc2VyaWFsIG51bWJlciB3aXRoIHNwYWNlcyBpbnN0ZWFkICcqJ1xuIixzdGRvdXQpOwogCgl3aGlsZSAoIWZlb2Yoc3RkaW4pKSB7CgkJaWYgKChhcmdjPD0xKSAmJiBhcmduKSBicmVhazsgCQlmcHV0cygiSW5wdXQ6ICMiLHN0ZG91dCk7IAkJaWYgKGFyZ2M+MSkgewoJCQlzdHJuY3B5KGJ1ZjFpbnB1dCxhcmd2WysrYXJnbl0sc2l6ZW9mKGJ1ZjFpbnB1dCkpO2FyZ2MtLTsKCQl9CgkJZWxzZSB7CgkJCWlmICghZW9sKSB3aGlsZSAoIWZlb2Yoc3RkaW4pICYmIChmZ2V0YyhzdGRpbikhPSdcbicpKTsgZW9sPTA7CgkJCWlmIChmZ2V0cyhidWYxaW5wdXQsMTYrMSsxLHN0ZGluKT09TlVMTCkgewoJCQkJaWYgKGVjaG8pIGZwdXRzKCJcbiIsc3Rkb3V0KTsKCQkJCWJyZWFrOwoJCQl9CgkJfQoJCWxlbj1zdHJsZW4oYnVmMWlucHV0KTsKCQlpZiAobGVuICYmIChidWYxaW5wdXRbbGVuLTFdPT0nXG4nKSkge2xlbi0tO2VvbD0xO2J1ZjFpbnB1dFtsZW5dPTA7fQoJCWlmIChlY2hvKSB7ZnB1dHMoYnVmMWlucHV0LHN0ZG91dCk7ZnB1dHMoIlxuIixzdGRvdXQpO30KCQltaW51cz1zdHJjaHIoYnVmMWlucHV0LCctJyk7CgkJaWYgKGxlbj09MTEpIHsKCQkJaWYgKG1pbnVzIT1OVUxMKSB7CgkJCQlmcHV0cygiLSBJbmNvcnJlY3QgaW5wdXRcbiIsc3Rkb3V0KTsKCQkJCWNvbnRpbnVlOwoJCQl9CgkJCWJmdW5jPWZIRERvbGQ7CgkJCWZwdXRzKCJCeSBIREQgc2VyaWFsIG51bWJlciBmb3Igb2xkZXIgQklPUzogIixzdGRvdXQpOwoJCX0gZWxzZSB7CgkJCWlmIChsZW49PTApIGJyZWFrOwoJCQlpZiAobWludXM9PU5VTEwpIHsKCQkJCWZwdXRzKCItIE5vIEJJT1MgdHlwZSBmb3VuZCBpbiBpbnB1dCBzdHJpbmcsIG11c3QgYmUgZm9sbG93ZWQgYnkgLTU5NUIgYW5kIG90aGVyIHJlZ2lzdGVyZWRcbiIsc3Rkb3V0KTsKCQkJCWNvbnRpbnVlOwoJCQl9CgkJCWxlbjE9bWludXMtKHVuc2lnbmVkIGNoYXIqKWJ1ZjFpbnB1dDsKIAoJCQlidHlwZT0tMTsKI2lmZGVmIGFsbG93NTk1QgoJCQlpZiAoc3RybmNtcCgmYnVmMWlucHV0W2xlbjErMV0sJmJTdWZmaXhbMF0sNCk9PTApIGJ0eXBlPXQ1OTVCOwoJCQllbHNlCiNlbmRpZgoJCQlpZiAoc3RybmNtcCgmYnVmMWlucHV0W2xlbjErMV0sJmJTdWZmaXhbNF0sNCk9PTApIGJ0eXBlPXREMzVCOwoJCQllbHNlCiNpZmRlZiBhbGxvd0E5NUIKCQkJaWYgKHN0cm5jbXAoJmJ1ZjFpbnB1dFtsZW4xKzFdLCZiU3VmZml4WzhdLDQpPT0wKSBidHlwZT10QTk1QjsKCQkJZWxzZQojZW5kaWYKI2lmZGVmIGFsbG93MkE3QgoJCQlpZiAoc3RybmNtcCgmYnVmMWlucHV0W2xlbjErMV0sJmJTdWZmaXhbMTJdLDQpPT0wKSBidHlwZT10MkE3QjsKI2VuZGlmCgkJCWlmIChidHlwZTwwKSB7CgkJCQlmcHV0cygiLSBJbnZhbGlkIHNlcnZpY2UgdGFnIGluIGlucHV0IHN0cmluZywgYWxsb3dlZCBvbmx5IC1EMzVCIGFuZCBvdGhlciByZWdpc3RlcmVkXG4iLHN0ZG91dCk7CgkJCQljb250aW51ZTsKCQkJfQoJCQlzdHJ1Y3QgdG0gKnRpbWUxOyB0aW1lX3QgdGltZXIxPXRpbWUoTlVMTCk7CgkJCXRpbWUxPWdtdGltZSgmdGltZXIxKTsKCQkJc3RyZnRpbWUoczIsc2l6ZW9mKHMyKSwiJWQuJW0uJVkgJUg6JU0iLHRpbWUxKTsKCQkJZnB1dHMoczIsc3Rkb3V0KTsKCQkJZnB1dHMoIiBERUxMICIsc3Rkb3V0KTsKIAoJCQlpZiAobGVuMT09NykgewoJCQkJYmZ1bmM9ZlNWQ1RBRzsKCQkJCWZwdXRzKCJzZXJ2aWNlIHRhZzogIixzdGRvdXQpOwoJCQkJZnB1dHMoYnVmMWlucHV0LHN0ZG91dCk7CgkJCX0gZWxzZQoJCQlpZiAobGVuMT09MTEpIHsKCQkJCWJmdW5jPWZIRERTTjsKCQkJCWZwdXRzKCJIREQgc2VyaWFsIG51bWJlcjogIixzdGRvdXQpOwoJCQkJZnB1dHMoYnVmMWlucHV0LHN0ZG91dCk7CgkJCX0KCQkJZWxzZSB7CgkJCQlmcHV0cygiLSBJbmNvcnJlY3QgaW5wdXQsIG11c3QgYmUgNyBjaGFycyBzZXJ2aWNlIHRhZyBvciAxMSBjaGFycyBIREQgc2VyaWFsIG51bWJlclxuIixzdGRvdXQpOwoJCQkJY29udGludWU7CgkJCX0KCQl9CgkJcHN3KGJmdW5jLGJ0eXBlLGJ1ZjFvdXRwdXQpOwoJCWZwdXRzKCIgcGFzc3dvcmQ6ICIsc3Rkb3V0KTsKCQlmcHV0cyhidWYxb3V0cHV0LHN0ZG91dCk7CgkJaWYgKGJ1ZzQpIGZwdXRzKCIgIWJ1ZzQgd2FybmluZyAtIHBhc3N3b3JkIG1heSBub3Qgd29yayEiLHN0ZG91dCk7CiAKCQlpZiAoYnR5cGU9PXQ1OTVCKSBpZiAoYmZ1bmM9PWZTVkNUQUcpIHsgLy90byBjaGVjayBpZiBBOTVCIGJ1ZwoJCQljaGFyIG1wdzFbMjBdOwoJCQlzdHJjcHkobXB3MSxidWYxb3V0cHV0KTsKCQkJcHN3KGJmdW5jLHRBOTVCLGJ1ZjFvdXRwdXQpOwoJCQlpZiAoc3RyY21wKG1wdzEsYnVmMW91dHB1dCkhPTApIHsKCQkJCWZwdXRzKCIgcGFzc3dvcmRBOTVCOiAiLHN0ZG91dCk7CgkJCQlmcHV0cyhidWYxb3V0cHV0LHN0ZG91dCk7CgkJCX0KCQl9CgkJZnB1dHMoIlxuIixzdGRvdXQpOwoJfQoJcmV0dXJuIDA7Cn0=