LyogU2hhcmVkIGxpYnJhcnkgYWRkLW9uIHRvIGlwdGFibGVzIHRvIGFkZCBsaW1pdCBzdXBwb3J0LgogKgogKiBK6XL0bWUgZGUgVml2aWUgICA8ZGV2aXZpZUBpbmZvLmVuc2VyYi51LWJvcmRlYXV4LmZyPgogKiBIZXJ26SBFeWNoZW5uZSAgIDxleWNoZW5uZUBpbmZvLmVuc2VyYi51LWJvcmRlYXV4LmZyPgogKi8KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8Z2V0b3B0Lmg+CiNpbmNsdWRlIDxpcHRhYmxlcy5oPgojaW5jbHVkZSA8c3RkZGVmLmg+CiNpbmNsdWRlIDxsaW51eC9uZXRmaWx0ZXJfaXB2NC9pcF90YWJsZXMuaD4KI2luY2x1ZGUgPGxpbnV4L25ldGZpbHRlcl9pcHY0L2lwdF9saW1pdC5oPgoKI2RlZmluZSBJUFRfTElNSVRfQVZHCSIzL2hvdXIiCiNkZWZpbmUgSVBUX0xJTUlUX0JVUlNUCTUKCi8qIEZ1bmN0aW9uIHdoaWNoIHByaW50cyBvdXQgdXNhZ2UgbWVzc2FnZS4gKi8Kc3RhdGljIHZvaWQKaGVscCh2b2lkKQp7CglwcmludGYoCiJsaW1pdCB2JXMgb3B0aW9uczpcbiIKIi0tbGltaXQgYXZnCQkJbWF4IGF2ZXJhZ2UgbWF0Y2ggcmF0ZTogZGVmYXVsdCAiSVBUX0xJTUlUX0FWRyJcbiIKIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW1BhY2tldHMgcGVyIHNlY29uZCB1bmxlc3MgZm9sbG93ZWQgYnkgXG4iCiIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC9zZWMgL21pbnV0ZSAvaG91ciAvZGF5IHBvc3RmaXhlc11cbiIKIi0tbGltaXQtYnVyc3QgbnVtYmVyCQludW1iZXIgdG8gbWF0Y2ggaW4gYSBidXJzdCwgZGVmYXVsdCAldVxuIgoiXG4iLCBORVRGSUxURVJfVkVSU0lPTiwgSVBUX0xJTUlUX0JVUlNUKTsKfQoKc3RhdGljIHN0cnVjdCBvcHRpb24gb3B0c1tdID0gewoJeyAibGltaXQiLCAxLCAwLCAnJScgfSwKCXsgImxpbWl0LWJ1cnN0IiwgMSwgMCwgJyQnIH0sCgl7IDAgfQp9OwoKc3RhdGljCmludCBwYXJzZV9yYXRlKGNvbnN0IGNoYXIgKnJhdGUsIHVfaW50MzJfdCAqdmFsKQp7Cgljb25zdCBjaGFyICpkZWxpbTsKCXVfaW50MzJfdCByOwoJdV9pbnQzMl90IG11bHQgPSAxOyAgLyogU2Vjb25kcyBieSBkZWZhdWx0LiAqLwoKCWRlbGltID0gc3RyY2hyKHJhdGUsICcvJyk7CglpZiAoZGVsaW0pIHsKCQlpZiAoc3RybGVuKGRlbGltKzEpID09IDApCgkJCXJldHVybiAwOwoKCQlpZiAoc3RybmNhc2VjbXAoZGVsaW0rMSwgInNlY29uZCIsIHN0cmxlbihkZWxpbSsxKSkgPT0gMCkKCQkJbXVsdCA9IDE7CgkJZWxzZSBpZiAoc3RybmNhc2VjbXAoZGVsaW0rMSwgIm1pbnV0ZSIsIHN0cmxlbihkZWxpbSsxKSkgPT0gMCkKCQkJbXVsdCA9IDYwOwoJCWVsc2UgaWYgKHN0cm5jYXNlY21wKGRlbGltKzEsICJob3VyIiwgc3RybGVuKGRlbGltKzEpKSA9PSAwKQoJCQltdWx0ID0gNjAqNjA7CgkJZWxzZSBpZiAoc3RybmNhc2VjbXAoZGVsaW0rMSwgImRheSIsIHN0cmxlbihkZWxpbSsxKSkgPT0gMCkKCQkJbXVsdCA9IDI0KjYwKjYwOwoJCWVsc2UKCQkJcmV0dXJuIDA7Cgl9CglyID0gYXRvaShyYXRlKTsKCWlmICghcikKCQlyZXR1cm4gMDsKCgkvKiBUaGlzIHdvdWxkIGdldCBtYXBwZWQgdG8gaW5maW5pdGUgKDEvZGF5IGlzIG1pbmltdW0gdGhleQogICAgICAgICAgIGNhbiBzcGVjaWZ5LCBzbyB3ZSdyZSBvayBhdCB0aGF0IGVuZCkuICovCglpZiAociAvIG11bHQgPiBJUFRfTElNSVRfU0NBTEUpCgkJZXhpdF9lcnJvcihQQVJBTUVURVJfUFJPQkxFTSwgIlJhdGUgdG9vIGZhc3QgYCVzJ1xuIiwgcmF0ZSk7CgoJKnZhbCA9IElQVF9MSU1JVF9TQ0FMRSAqIG11bHQgLyByOwoJcmV0dXJuIDE7Cn0KCi8qIEluaXRpYWxpemUgdGhlIG1hdGNoLiAqLwpzdGF0aWMgdm9pZAppbml0KHN0cnVjdCBpcHRfZW50cnlfbWF0Y2ggKm0sIHVuc2lnbmVkIGludCAqbmZjYWNoZSkKewoJc3RydWN0IGlwdF9yYXRlaW5mbyAqciA9IChzdHJ1Y3QgaXB0X3JhdGVpbmZvICopbS0+ZGF0YTsKCglwYXJzZV9yYXRlKElQVF9MSU1JVF9BVkcsICZyLT5hdmcpOwoJci0+YnVyc3QgPSBJUFRfTElNSVRfQlVSU1Q7CgoJLyogQ2FuJ3QgY2FjaGUgdGhpcyAqLwoJKm5mY2FjaGUgfD0gTkZDX1VOS05PV047Cn0KCi8qIEZJWE1FOiBoYW5kbGUgb3ZlcmZsb3c6CglpZiAoci0+YXZnKnItPmJ1cnN0L3ItPmJ1cnN0ICE9IHItPmF2ZykKCQlleGl0X2Vycm9yKFBBUkFNRVRFUl9QUk9CTEVNLAoJCQkgICAiU29ycnk6IGJ1cnN0IHRvbyBsYXJnZSBmb3IgdGhhdCBhdmcgcmF0ZS5cbiIpOwoqLwoKLyogRnVuY3Rpb24gd2hpY2ggcGFyc2VzIGNvbW1hbmQgb3B0aW9uczsgcmV0dXJucyB0cnVlIGlmIGl0CiAgIGF0ZSBhbiBvcHRpb24gKi8Kc3RhdGljIGludApwYXJzZShpbnQgYywgY2hhciAqKmFyZ3YsIGludCBpbnZlcnQsIHVuc2lnbmVkIGludCAqZmxhZ3MsCiAgICAgIGNvbnN0IHN0cnVjdCBpcHRfZW50cnkgKmVudHJ5LAogICAgICB1bnNpZ25lZCBpbnQgKm5mY2FjaGUsCiAgICAgIHN0cnVjdCBpcHRfZW50cnlfbWF0Y2ggKiptYXRjaCkKewoJc3RydWN0IGlwdF9yYXRlaW5mbyAqciA9IChzdHJ1Y3QgaXB0X3JhdGVpbmZvICopKCptYXRjaCktPmRhdGE7CglpbnQgbnVtOwoKCXN3aXRjaChjKSB7CgljYXNlICclJzoKCQlpZiAoY2hlY2tfaW52ZXJzZShvcHRhcmcsICZpbnZlcnQpKQoJCQlleGl0X2Vycm9yKFBBUkFNRVRFUl9QUk9CTEVNLAoJCQkJICAgIlVuZXhwZWN0ZWQgYCEnIGFmdGVyIC0tbGltaXQiKTsKCQlpZiAoIXBhcnNlX3JhdGUob3B0YXJnLCAmci0+YXZnKSkKCQkJZXhpdF9lcnJvcihQQVJBTUVURVJfUFJPQkxFTSwKCQkJCSAgICJiYWQgcmF0ZSBgJXMnIiwgb3B0YXJnKTsKCQlicmVhazsKCgljYXNlICckJzoKCQlpZiAoY2hlY2tfaW52ZXJzZShvcHRhcmcsICZpbnZlcnQpKQoJCQlleGl0X2Vycm9yKFBBUkFNRVRFUl9QUk9CTEVNLAoJCQkJICAgIlVuZXhwZWN0ZWQgYCEnIGFmdGVyIC0tbGltaXQtYnVyc3QiKTsKCgkJbnVtID0gc3RyaW5nX3RvX251bWJlcihvcHRhcmcsIDAsIDEwMDAwKTsKCQlpZiAobnVtIDw9IDApCgkJCWV4aXRfZXJyb3IoUEFSQU1FVEVSX1BST0JMRU0sCgkJCQkgICAiYmFkIC0tbGltaXQtYnVyc3QgYCVzJyIsIG9wdGFyZyk7CgkJci0+YnVyc3QgPSBudW07CgkJYnJlYWs7CgoJZGVmYXVsdDoKCQlyZXR1cm4gMDsKCX0KCglyZXR1cm4gMTsKfQoKLyogRmluYWwgY2hlY2s7IG5vdGhpbmcuICovCnN0YXRpYyB2b2lkIGZpbmFsX2NoZWNrKHVuc2lnbmVkIGludCBmbGFncykKewp9CgpzdGF0aWMgc3RydWN0IHJhdGVzCnsKCWNvbnN0IGNoYXIgKm5hbWU7Cgl1X2ludDMyX3QgbXVsdDsKfSByYXRlc1tdID0geyB7ICJkYXkiLCBJUFRfTElNSVRfU0NBTEUqMjQqNjAqNjAgfSwKCSAgICAgIHsgImhvdXIiLCBJUFRfTElNSVRfU0NBTEUqNjAqNjAgfSwKCSAgICAgIHsgIm1pbiIsIElQVF9MSU1JVF9TQ0FMRSo2MCB9LAoJICAgICAgeyAic2VjIiwgSVBUX0xJTUlUX1NDQUxFIH0gfTsKCnN0YXRpYyB2b2lkIHByaW50X3JhdGUodV9pbnQzMl90IHBlcmlvZCkKewoJdW5zaWduZWQgaW50IGk7CgoJZm9yIChpID0gMTsgaSA8IHNpemVvZihyYXRlcykvc2l6ZW9mKHN0cnVjdCByYXRlcyk7IGkrKykgewoJCWlmIChwZXJpb2QgPiByYXRlc1tpXS5tdWx0CgkJICAgIHx8IHJhdGVzW2ldLm11bHQgJSBwZXJpb2QgIT0gMCkKCQkJYnJlYWs7Cgl9CgoJcHJpbnRmKCIldS8lcyAiLCByYXRlc1tpLTFdLm11bHQgLyBwZXJpb2QsIHJhdGVzW2ktMV0ubmFtZSk7Cn0KCi8qIFByaW50cyBvdXQgdGhlIG1hdGNoaW5mby4gKi8Kc3RhdGljIHZvaWQKcHJpbnQoY29uc3Qgc3RydWN0IGlwdF9pcCAqaXAsCiAgICAgIGNvbnN0IHN0cnVjdCBpcHRfZW50cnlfbWF0Y2ggKm1hdGNoLAogICAgICBpbnQgbnVtZXJpYykKewoJc3RydWN0IGlwdF9yYXRlaW5mbyAqciA9IChzdHJ1Y3QgaXB0X3JhdGVpbmZvICopbWF0Y2gtPmRhdGE7CglwcmludGYoImxpbWl0OiBhdmcgIik7IHByaW50X3JhdGUoci0+YXZnKTsKCXByaW50ZigiYnVyc3QgJXUgIiwgci0+YnVyc3QpOwp9CgovKiBGSVhNRTogTWFrZSBtaW5pbWFsaXN0OiBvbmx5IHByaW50IHJhdGUgaWYgbm90IGRlZmF1bHQgLS1SUiAqLwpzdGF0aWMgdm9pZCBzYXZlKGNvbnN0IHN0cnVjdCBpcHRfaXAgKmlwLCBjb25zdCBzdHJ1Y3QgaXB0X2VudHJ5X21hdGNoICptYXRjaCkKewoJc3RydWN0IGlwdF9yYXRlaW5mbyAqciA9IChzdHJ1Y3QgaXB0X3JhdGVpbmZvICopbWF0Y2gtPmRhdGE7CgoJcHJpbnRmKCItLWxpbWl0ICIpOyBwcmludF9yYXRlKHItPmF2Zyk7CglpZiAoci0+YnVyc3QgIT0gSVBUX0xJTUlUX0JVUlNUKQoJCXByaW50ZigiLS1saW1pdC1idXJzdCAldSAiLCByLT5idXJzdCk7Cn0KCnN0cnVjdCBpcHRhYmxlc19tYXRjaCBsaW1pdAo9IHsgTlVMTCwKICAgICJsaW1pdCIsCiAgICBORVRGSUxURVJfVkVSU0lPTiwKICAgIElQVF9BTElHTihzaXplb2Yoc3RydWN0IGlwdF9yYXRlaW5mbykpLAogICAgb2Zmc2V0b2Yoc3RydWN0IGlwdF9yYXRlaW5mbywgcHJldiksCiAgICAmaGVscCwKICAgICZpbml0LAogICAgJnBhcnNlLAogICAgJmZpbmFsX2NoZWNrLAogICAgJnByaW50LAogICAgJnNhdmUsCiAgICBvcHRzCn07Cgp2b2lkIF9pbml0KHZvaWQpCnsKCXJlZ2lzdGVyX21hdGNoKCZsaW1pdCk7Cn0K