LyogUHJpdmF0ZSB2ZXJzaW9uIG9mIHRoZSBsaWJjICptbnRlbnQoKSByb3V0aW5lcy4gKi8KLyogTm90ZSBzbGlnaHRseSBkaWZmZXJlbnQgcHJvdG90eXBlcy4gKi8KCi8qIDE5OTktMDItMjIgQXJrYWRpdXN6IE1ptmtpZXdpY3ogPG1pc2lla0BwbGQuT1JHLlBMPgogKiAtIGFkZGVkIE5hdGl2ZSBMYW5ndWFnZSBTdXBwb3J0CiAqLwoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4JCS8qIGZvciBpbmRleCAqLwojaW5jbHVkZSA8Y3R5cGUuaD4JCS8qIGZvciBpc2RpZ2l0ICovCiNpbmNsdWRlIDxzeXMvc3RhdC5oPgkJLyogZm9yIHVtYXNrICovCiNpbmNsdWRlICJtb3VudF9tbnRlbnQuaCIKI2luY2x1ZGUgInN1bmRyaWVzLmgiCQkvKiBmb3IgeG1hbGxvYyAqLwojaW5jbHVkZSAibmxzLmgiCgovKiBVbmZvcnR1bmF0ZWx5IHRoZSBjbGFzc2ljYWwgVW5peCAvZXRjL210YWIgYW5kIC9ldGMvZnN0YWIKICAgZG8gbm90IGhhbmRsZSBkaXJlY3RvcnkgbmFtZXMgY29udGFpbmluZyBzcGFjZXMuCiAgIEhlcmUgd2UgbWFuZ2xlIHRoZW0sIHJlcGxhY2luZyBhIHNwYWNlIGJ5IFwwNDAuCiAgIFdoYXQgZG8gb3RoZXIgVW5pY2VzIGRvPyAqLwoKc3RhdGljIHVuc2lnbmVkIGNoYXIgbmVlZF9lc2NhcGluZ1tdID0geyAnICcsICdcdCcsICdcbicsICdcXCcgfTsKCnN0YXRpYyBjaGFyICoKbWFuZ2xlKGNvbnN0IGNoYXIgKnMpIHsKCWNoYXIgKnNzLCAqc3A7CglpbnQgbjsKCgluID0gc3RybGVuKHMpOwoJc3MgPSBzcCA9IHhtYWxsb2MoNCpuKzEpOwoJd2hpbGUoMSkgewoJCWZvciAobiA9IDA7IG4gPCBzaXplb2YobmVlZF9lc2NhcGluZyk7IG4rKykgewoJCQlpZiAoKnMgPT0gbmVlZF9lc2NhcGluZ1tuXSkgewoJCQkJKnNwKysgPSAnXFwnOwoJCQkJKnNwKysgPSAnMCcgKyAoKCpzICYgMDMwMCkgPj4gNik7CgkJCQkqc3ArKyA9ICcwJyArICgoKnMgJiAwNzApID4+IDMpOwoJCQkJKnNwKysgPSAnMCcgKyAoKnMgJiAwNyk7CgkJCQlnb3RvIG5leHQ7CgkJCX0KCQl9CgkJKnNwKysgPSAqczsKCQlpZiAoKnMgPT0gMCkKCQkJYnJlYWs7CgluZXh0OgoJCXMrKzsKCX0KCXJldHVybiBzczsKfQoKc3RhdGljIGludAppc19zcGFjZV9vcl90YWIgKGNoYXIgYykgewoJcmV0dXJuIChjID09ICcgJyB8fCBjID09ICdcdCcpOwp9CgpzdGF0aWMgY2hhciAqCnNraXBfc3BhY2VzKGNoYXIgKnMpIHsKCXdoaWxlIChpc19zcGFjZV9vcl90YWIoKnMpKQoJCXMrKzsKCXJldHVybiBzOwp9CgpzdGF0aWMgY2hhciAqCnNraXBfbm9uc3BhY2VzKGNoYXIgKnMpIHsKCXdoaWxlICgqcyAmJiAhaXNfc3BhY2Vfb3JfdGFiKCpzKSkKCQlzKys7CglyZXR1cm4gczsKfQoKI2RlZmluZSBpc29jdGFsKGEpICgoKGEpICYgfjcpID09ICcwJykKCi8qIHJldHVybnMgbWFsbG9jZWQgcG9pbnRlciAtIG5vIG1vcmUgc3RyZHVwIHJlcXVpcmVkICovCnN0YXRpYyBjaGFyICoKdW5tYW5nbGUoY2hhciAqcykgewoJY2hhciAqcmV0LCAqc3MsICpzcDsKCglzcyA9IHNraXBfbm9uc3BhY2VzKHMpOwoJcmV0ID0gc3AgPSB4bWFsbG9jKHNzLXMrMSk7Cgl3aGlsZShzICE9IHNzKSB7CgkJaWYgKCpzID09ICdcXCcgJiYgaXNvY3RhbChzWzFdKSAmJiBpc29jdGFsKHNbMl0pICYmIGlzb2N0YWwoc1szXSkpIHsKCQkJKnNwKysgPSA2NCooc1sxXSAmIDcpICsgOCooc1syXSAmIDcpICsgKHNbM10gJiA3KTsKCQkJcyArPSA0OwoJCX0gZWxzZQoJCQkqc3ArKyA9ICpzKys7Cgl9Cgkqc3AgPSAwOwoJcmV0dXJuIHJldDsKfQoKLyoKICogZnN0YXQnaW5nIHRoZSBmaWxlIGFuZCBhbGxvY2F0aW5nIGEgYnVmZmVyIGhvbGRpbmcgYWxsIG9mIGl0CiAqIG1heSBiZSBhIGJhZCBpZGVhOiBpZiB0aGUgZmlsZSBpcyAvcHJvYy9tb3VudHMsIHRoZSBzdGF0CiAqIHJldHVybnMgMC4KICogKE9uIHRoZSBvdGhlciBoYW5kLCBtYW5nbGluZyBhbmQgdW5tYW5nbGluZyBpcyBtZWFuaW5nbGVzcwogKiAgZm9yIC9wcm9jL21vdW50cy4pCiAqLwoKbW50RklMRSAqCm15X3NldG1udGVudCAoY29uc3QgY2hhciAqZmlsZSwgY2hhciAqbW9kZSkgewoJbW50RklMRSAqbWZwID0geG1hbGxvYyhzaXplb2YoKm1mcCkpOwoJbW9kZV90IG9sZF91bWFzayA9IHVtYXNrKDA3Nyk7CgoJbWZwLT5tbnRlbnRfZnAgPSBmb3BlbihmaWxlLCBtb2RlKTsKCXVtYXNrKG9sZF91bWFzayk7CgltZnAtPm1udGVudF9maWxlID0geHN0cmR1cChmaWxlKTsKCW1mcC0+bW50ZW50X2VycnMgPSAobWZwLT5tbnRlbnRfZnAgPT0gTlVMTCk7CgltZnAtPm1udGVudF9zb2Z0ZXJycyA9IDA7CgltZnAtPm1udGVudF9saW5lbm8gPSAwOwoJcmV0dXJuIG1mcDsKfQoKdm9pZApteV9lbmRtbnRlbnQgKG1udEZJTEUgKm1mcCkgewoJaWYgKG1mcCkgewoJCWlmIChtZnAtPm1udGVudF9mcCkKCQkJZmNsb3NlKG1mcC0+bW50ZW50X2ZwKTsKCQlmcmVlKG1mcC0+bW50ZW50X2ZpbGUpOwoJCWZyZWUobWZwKTsKCX0KfQoKaW50Cm15X2FkZG1udGVudCAobW50RklMRSAqbWZwLCBzdHJ1Y3QgbXlfbW50ZW50ICptbnQpIHsKCWNoYXIgKm0xLCAqbTIsICptMywgKm00OwoJaW50IHJlczsKCglpZiAoZnNlZWsgKG1mcC0+bW50ZW50X2ZwLCAwLCBTRUVLX0VORCkpCgkJcmV0dXJuIDE7CQkJLyogZmFpbHVyZSAqLwoKCW0xID0gbWFuZ2xlKG1udC0+bW50X2ZzbmFtZSk7CgltMiA9IG1hbmdsZShtbnQtPm1udF9kaXIpOwoJbTMgPSBtYW5nbGUobW50LT5tbnRfdHlwZSk7CgltNCA9IG1hbmdsZShtbnQtPm1udF9vcHRzKTsKCglyZXMgPSBmcHJpbnRmIChtZnAtPm1udGVudF9mcCwgIiVzICVzICVzICVzICVkICVkXG4iLAoJCSAgICAgICBtMSwgbTIsIG0zLCBtNCwgbW50LT5tbnRfZnJlcSwgbW50LT5tbnRfcGFzc25vKTsKCglmcmVlKG0xKTsKCWZyZWUobTIpOwoJZnJlZShtMyk7CglmcmVlKG00KTsKCXJldHVybiAocmVzIDwgMCkgPyAxIDogMDsKfQoKLyogUmVhZCB0aGUgbmV4dCBlbnRyeSBmcm9tIHRoZSBmaWxlIGZwLiBTdG9wIHJlYWRpbmcgYXQgYW4gaW5jb3JyZWN0IGVudHJ5LiAqLwpzdHJ1Y3QgbXlfbW50ZW50ICoKbXlfZ2V0bW50ZW50IChtbnRGSUxFICptZnApIHsKCXN0YXRpYyBjaGFyIGJ1Zls0MDk2XTsKCXN0YXRpYyBzdHJ1Y3QgbXlfbW50ZW50IG1lOwoJY2hhciAqczsKCiBhZ2FpbjoKCWlmIChtZnAtPm1udGVudF9lcnJzIHx8IG1mcC0+bW50ZW50X3NvZnRlcnJzID49IEVSUl9NQVgpCgkJcmV0dXJuIE5VTEw7CgoJLyogcmVhZCB0aGUgbmV4dCBub24tYmxhbmsgbm9uLWNvbW1lbnQgbGluZSAqLwoJZG8gewoJCWlmIChmZ2V0cyAoYnVmLCBzaXplb2YoYnVmKSwgbWZwLT5tbnRlbnRfZnApID09IE5VTEwpCgkJCXJldHVybiBOVUxMOwoKCQltZnAtPm1udGVudF9saW5lbm8rKzsKCQlzID0gc3RyY2hyIChidWYsICdcbicpOwoJCWlmIChzID09IE5VTEwpIHsKCQkJLyogTWlzc2luZyBmaW5hbCBuZXdsaW5lPyAgT3RoZXJ3aXNlIGV4dHJlbWVseSAqLwoJCQkvKiBsb25nIGxpbmUgLSBhc3N1bWUgZmlsZSB3YXMgY29ycnVwdGVkICovCgkJCWlmIChmZW9mKG1mcC0+bW50ZW50X2ZwKSkgewoJCQkJZnByaW50ZihzdGRlcnIsIF8oIlttbnRlbnRdOiB3YXJuaW5nOiBubyBmaW5hbCAiCgkJCQkJIm5ld2xpbmUgYXQgdGhlIGVuZCBvZiAlc1xuIiksCgkJCQkJbWZwLT5tbnRlbnRfZmlsZSk7CgkJCQlzID0gc3RyY2hyIChidWYsIDApOwoJCQl9IGVsc2UgewoJCQkJbWZwLT5tbnRlbnRfZXJycyA9IDE7CgkJCQlnb3RvIGVycjsKCQkJfQoJCX0KCQkqcyA9IDA7CgkJaWYgKC0tcyA+PSBidWYgJiYgKnMgPT0gJ1xyJykKCQkJKnMgPSAwOwoJCXMgPSBza2lwX3NwYWNlcyhidWYpOwoJfSB3aGlsZSAoKnMgPT0gJ1wwJyB8fCAqcyA9PSAnIycpOwoKCW1lLm1udF9mc25hbWUgPSB1bm1hbmdsZShzKTsKCXMgPSBza2lwX25vbnNwYWNlcyhzKTsKCXMgPSBza2lwX3NwYWNlcyhzKTsKCW1lLm1udF9kaXIgPSB1bm1hbmdsZShzKTsKCXMgPSBza2lwX25vbnNwYWNlcyhzKTsKCXMgPSBza2lwX3NwYWNlcyhzKTsKCW1lLm1udF90eXBlID0gdW5tYW5nbGUocyk7CglzID0gc2tpcF9ub25zcGFjZXMocyk7CglzID0gc2tpcF9zcGFjZXMocyk7CgltZS5tbnRfb3B0cyA9IHVubWFuZ2xlKHMpOwoJcyA9IHNraXBfbm9uc3BhY2VzKHMpOwoJcyA9IHNraXBfc3BhY2VzKHMpOwoKCWlmIChpc2RpZ2l0KCpzKSkgewoJCW1lLm1udF9mcmVxID0gYXRvaShzKTsKCQl3aGlsZShpc2RpZ2l0KCpzKSkgcysrOwoJfSBlbHNlCgkJbWUubW50X2ZyZXEgPSAwOwoJaWYoKnMgJiYgIWlzX3NwYWNlX29yX3RhYigqcykpCgkJZ290byBlcnI7CgoJcyA9IHNraXBfc3BhY2VzKHMpOwoJaWYoaXNkaWdpdCgqcykpIHsKCQltZS5tbnRfcGFzc25vID0gYXRvaShzKTsKCQl3aGlsZShpc2RpZ2l0KCpzKSkgcysrOwoJfSBlbHNlCgkJbWUubW50X3Bhc3NubyA9IDA7CglpZigqcyAmJiAhaXNfc3BhY2Vfb3JfdGFiKCpzKSkKCQlnb3RvIGVycjsKCgkvKiBhbGxvdyBtb3JlIHN0dWZmLCBlLmcuIGNvbW1lbnRzLCBvbiB0aGlzIGxpbmUgKi8KCglyZXR1cm4gJm1lOwoKIGVycjoKCW1mcC0+bW50ZW50X3NvZnRlcnJzKys7CglmcHJpbnRmKHN0ZGVyciwgXygiW21udGVudF06IGxpbmUgJWQgaW4gJXMgaXMgYmFkJXNcbiIpLAoJCW1mcC0+bW50ZW50X2xpbmVubywgbWZwLT5tbnRlbnRfZmlsZSwKCQkobWZwLT5tbnRlbnRfZXJycyB8fCBtZnAtPm1udGVudF9zb2Z0ZXJycyA+PSBFUlJfTUFYKSA/CgkJXygiOyByZXN0IG9mIGZpbGUgaWdub3JlZCIpIDogIiIpOwoJZ290byBhZ2FpbjsKfQo=