I2luY2x1ZGUgImNhY2hlLmgiCiNpbmNsdWRlICJyZWZzLmgiCiNpbmNsdWRlICJwa3QtbGluZS5oIgojaW5jbHVkZSA8c3lzL3dhaXQuaD4KCnN0YXRpYyBjb25zdCBjaGFyIGNsb25lX3BhY2tfdXNhZ2VbXSA9ICJnaXQtY2xvbmUtcGFjayBbaG9zdDpdZGlyZWN0b3J5IFtoZWFkc10qIjsKc3RhdGljIGNvbnN0IGNoYXIgKmV4ZWMgPSAiZ2l0LXVwbG9hZC1wYWNrIjsKCnN0cnVjdCByZWYgewoJc3RydWN0IHJlZiAqbmV4dDsKCXVuc2lnbmVkIGNoYXIgc2hhMVsyMF07CgljaGFyIG5hbWVbMF07Cn07CgpzdGF0aWMgc3RydWN0IHJlZiAqZ2V0X3JlbW90ZV9yZWZzKGludCBmZCwgaW50IG5yX21hdGNoLCBjaGFyICoqbWF0Y2gpCnsKCXN0cnVjdCByZWYgKnJlZl9saXN0ID0gTlVMTCwgKipuZXh0X3JlZiA9ICZyZWZfbGlzdDsKCglmb3IgKDs7KSB7CgkJc3RhdGljIGNoYXIgbGluZVsxMDAwXTsKCQl1bnNpZ25lZCBjaGFyIHNoYTFbMjBdOwoJCXN0cnVjdCByZWYgKnJlZjsKCQljaGFyICpyZWZuYW1lOwoJCWludCBsZW47CgoJCWxlbiA9IHBhY2tldF9yZWFkX2xpbmUoZmQsIGxpbmUsIHNpemVvZihsaW5lKSk7CgkJaWYgKCFsZW4pCgkJCWJyZWFrOwoJCWlmIChsaW5lW2xlbi0xXSA9PSAnXG4nKQoJCQlsaW5lWy0tbGVuXSA9IDA7CgkJaWYgKGxlbiA8IDQyIHx8IGdldF9zaGExX2hleChsaW5lLCBzaGExKSkKCQkJZGllKCJnaXQtZmV0Y2gtcGFjazogcHJvdG9jb2wgZXJyb3IgLSBleHBlY3RlZCByZWYgZGVzY3JpcHRvciwgZ290ICclc6QnIiwgbGluZSk7CgkJcmVmbmFtZSA9IGxpbmUrNDE7CgkJbGVuID0gbGVuLTQwOwoJCWlmIChucl9tYXRjaCAmJiAhcGF0aF9tYXRjaChyZWZuYW1lLCBucl9tYXRjaCwgbWF0Y2gpKQoJCQljb250aW51ZTsKCQlyZWYgPSB4bWFsbG9jKHNpemVvZihzdHJ1Y3QgcmVmKSArIGxlbik7CgkJcmVmLT5uZXh0ID0gTlVMTDsKCQltZW1jcHkocmVmLT5zaGExLCBzaGExLCAyMCk7CgkJbWVtY3B5KHJlZi0+bmFtZSwgcmVmbmFtZSwgbGVuKTsKCQkqbmV4dF9yZWYgPSByZWY7CgkJbmV4dF9yZWYgPSAmcmVmLT5uZXh0OwoJfQoJcmV0dXJuIHJlZl9saXN0Owp9CgpzdGF0aWMgdm9pZCBjbG9uZV9oYW5kc2hha2UoaW50IGZkWzJdLCBzdHJ1Y3QgcmVmICpyZWYpCnsKCXVuc2lnbmVkIGNoYXIgc2hhMVsyMF07CgoJd2hpbGUgKHJlZikgewoJCXBhY2tldF93cml0ZShmZFsxXSwgIndhbnQgJXNcbiIsIHNoYTFfdG9faGV4KHJlZi0+c2hhMSkpOwoJCXJlZiA9IHJlZi0+bmV4dDsKCX0KCXBhY2tldF9mbHVzaChmZFsxXSk7CgoJLyogV2UgZG9uJ3QgaGF2ZSBudXR0aW4nICovCglwYWNrZXRfd3JpdGUoZmRbMV0sICJkb25lXG4iKTsKCWlmIChnZXRfYWNrKGZkWzBdLCBzaGExKSkKCQllcnJvcigiSHVoISBnaXQtY2xvbmUtcGFjayBnb3QgcG9zaXRpdmUgYWNrIGZvciAlcyIsIHNoYTFfdG9faGV4KHNoYTEpKTsKfQoKc3RhdGljIGludCBpc19tYXN0ZXIoc3RydWN0IHJlZiAqcmVmKQp7CglyZXR1cm4gIXN0cmNtcChyZWYtPm5hbWUsICJyZWZzL2hlYWRzL21hc3RlciIpOwp9CgpzdGF0aWMgdm9pZCB3cml0ZV9vbmVfcmVmKHN0cnVjdCByZWYgKnJlZikKewoJY2hhciAqcGF0aCA9IGdpdF9wYXRoKHJlZi0+bmFtZSk7CglpbnQgZmQ7CgljaGFyICpoZXg7CgoJaWYgKHNhZmVfY3JlYXRlX2xlYWRpbmdfZGlyZWN0b3JpZXMocGF0aCkpCgkJZGllKCJ1bmFibGUgdG8gY3JlYXRlIGxlYWRpbmcgZGlyZWN0b3J5IGZvciAlcyIsIHJlZi0+bmFtZSk7CglmZCA9IG9wZW4ocGF0aCwgT19DUkVBVCB8IE9fRVhDTCB8IE9fV1JPTkxZLCAwNjY2KTsKCWlmIChmZCA8IDApCgkJZGllKCJ1bmFibGUgdG8gY3JlYXRlIHJlZiAlcyIsIHJlZi0+bmFtZSk7CgloZXggPSBzaGExX3RvX2hleChyZWYtPnNoYTEpOwoJaGV4WzQwXSA9ICdcbic7CglpZiAod3JpdGUoZmQsIGhleCwgNDEpICE9IDQxKQoJCWRpZSgidW5hYmxlIHRvIHdyaXRlIHJlZiAlcyIsIHJlZi0+bmFtZSk7CgljbG9zZShmZCk7Cn0KCnN0YXRpYyB2b2lkIHdyaXRlX3JlZnMoc3RydWN0IHJlZiAqcmVmKQp7CglzdHJ1Y3QgcmVmICpoZWFkID0gTlVMTCwgKmhlYWRfcHRyLCAqbWFzdGVyX3JlZjsKCWNoYXIgKmhlYWRfcGF0aDsKCglpZiAoIXN0cmNtcChyZWYtPm5hbWUsICJIRUFEIikpIHsKCQloZWFkID0gcmVmOwoJCXJlZiA9IHJlZi0+bmV4dDsKCX0KCWhlYWRfcHRyID0gTlVMTDsKCW1hc3Rlcl9yZWYgPSBOVUxMOwoJd2hpbGUgKHJlZikgewoJCWlmIChpc19tYXN0ZXIocmVmKSkKCQkJbWFzdGVyX3JlZiA9IHJlZjsKCQlpZiAoaGVhZCAmJiAhbWVtY21wKHJlZi0+c2hhMSwgaGVhZC0+c2hhMSwgMjApKSB7CgkJCWlmICghaGVhZF9wdHIgfHwgcmVmID09IG1hc3Rlcl9yZWYpCgkJCQloZWFkX3B0ciA9IHJlZjsKCQl9CgkJd3JpdGVfb25lX3JlZihyZWYpOwoJCXJlZiA9IHJlZi0+bmV4dDsKCX0KCWlmICghaGVhZCkKCQlyZXR1cm47CgoJaGVhZF9wYXRoID0gZ2l0X3BhdGgoIkhFQUQiKTsKCWlmICghaGVhZF9wdHIpIHsKCQkvKgoJCSAqIElmIHdlIGhhZCBhIG1hc3RlciByZWYsIGFuZCBpdCB3YXNuJ3QgSEVBRCwgd2UgbmVlZCB0byB1bmRvIHRoZQoJCSAqIHN5bWxpbmssIGFuZCB3cml0ZSBhIHN0YW5kYWxvbmUgSEVBRC4gR2l2ZSBhIHdhcm5pbmcsIGJlY2F1c2UgdGhhdCdzCgkJICogcmVhbGx5IHJlYWxseSB3cm9uZy4KCQkgKi8KCQlpZiAobWFzdGVyX3JlZikgewoJCQllcnJvcigiSEVBRCBkb2Vzbid0IHBvaW50IHRvIGFueSByZWZzISBNYWtpbmcgc3RhbmRhbG9uZSBIRUFEIik7CgkJCXVubGluayhoZWFkX3BhdGgpOwoJCX0KCQl3cml0ZV9vbmVfcmVmKGhlYWQpOwoJCXJldHVybjsKCX0KCgkvKiBXZSByZXNldCB0byB0aGUgbWFzdGVyIGJyYW5jaCBpZiBpdCdzIGF2YWlsYWJsZSAqLwoJaWYgKG1hc3Rlcl9yZWYpCgkJcmV0dXJuOwoKCS8qCgkgKiBVaGh1aC4gT3RoZXIgZW5kIGRpZG4ndCBoYXZlIG1hc3Rlci4gV2Ugc3RhcnQgSEVBRCBvZmYgd2l0aAoJICogdGhlIGZpcnN0IGJyYW5jaCB3aXRoIHRoZSBzYW1lIHZhbHVlLgoJICovCgl1bmxpbmsoaGVhZF9wYXRoKTsKCWlmIChzeW1saW5rKGhlYWRfcHRyLT5uYW1lLCBoZWFkX3BhdGgpIDwgMCkKCQlkaWUoInVuYWJsZSB0byBsaW5rIEhFQUQgdG8gJXMiLCBoZWFkX3B0ci0+bmFtZSk7Cn0KCnN0YXRpYyBpbnQgY2xvbmVfcGFjayhpbnQgZmRbMl0sIGludCBucl9tYXRjaCwgY2hhciAqKm1hdGNoKQp7CglzdHJ1Y3QgcmVmICpyZWZzOwoJaW50IHN0YXR1czsKCXBpZF90IHBpZDsKCglyZWZzID0gZ2V0X3JlbW90ZV9yZWZzKGZkWzBdLCBucl9tYXRjaCwgbWF0Y2gpOwoJaWYgKCFyZWZzKSB7CgkJcGFja2V0X2ZsdXNoKGZkWzFdKTsKCQlkaWUoIm5vIG1hdGNoaW5nIHJlbW90ZSBoZWFkIik7Cgl9CgljbG9uZV9oYW5kc2hha2UoZmQsIHJlZnMpOwoJcGlkID0gZm9yaygpOwoJaWYgKHBpZCA8IDApCgkJZGllKCJnaXQtY2xvbmUtcGFjazogdW5hYmxlIHRvIGZvcmsgb2ZmIGdpdC11bnBhY2stb2JqZWN0cyIpOwoJaWYgKCFwaWQpIHsKCQljbG9zZShmZFsxXSk7CgkJZHVwMihmZFswXSwgMCk7CgkJY2xvc2UoZmRbMF0pOwoJCWV4ZWNscCgiZ2l0LXVucGFjay1vYmplY3RzIiwgImdpdC11bnBhY2stb2JqZWN0cyIsIE5VTEwpOwoJCWRpZSgiZ2l0LXVucGFjay1vYmplY3RzIGV4ZWMgZmFpbGVkIik7Cgl9CgljbG9zZShmZFswXSk7CgljbG9zZShmZFsxXSk7Cgl3aGlsZSAod2FpdHBpZChwaWQsICZzdGF0dXMsIDApIDwgMCkgewoJCWlmIChlcnJubyAhPSBFSU5UUikKCQkJZGllKCJ3YWl0aW5nIGZvciBnaXQtdW5wYWNrLW9iamVjdHM6ICVzIiwgc3RyZXJyb3IoZXJybm8pKTsKCX0KCWlmIChXSUZFWElURUQoc3RhdHVzKSkgewoJCWludCBjb2RlID0gV0VYSVRTVEFUVVMoc3RhdHVzKTsKCQlpZiAoY29kZSkKCQkJZGllKCJnaXQtdW5wYWNrLW9iamVjdHMgZGllZCB3aXRoIGVycm9yIGNvZGUgJWQiLCBjb2RlKTsKCQl3cml0ZV9yZWZzKHJlZnMpOwoJCXJldHVybiAwOwoJfQoJaWYgKFdJRlNJR05BTEVEKHN0YXR1cykpIHsKCQlpbnQgc2lnID0gV1RFUk1TSUcoc3RhdHVzKTsKCQlkaWUoImdpdC11bnBhY2stb2JqZWN0cyBkaWVkIG9mIHNpZ25hbCAlZCIsIHNpZyk7Cgl9CglkaWUoIlNoZXJsb2NrIEhvbG1lcyEgZ2l0LXVucGFjay1vYmplY3RzIGRpZWQgb2YgdW5uYXR1cmFsIGNhdXNlcyAlZCEiLCBzdGF0dXMpOwp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpCnsKCWludCBpLCByZXQsIG5yX2hlYWRzOwoJY2hhciAqZGVzdCA9IE5VTEwsICoqaGVhZHM7CglpbnQgZmRbMl07CglwaWRfdCBwaWQ7CgoJbnJfaGVhZHMgPSAwOwoJaGVhZHMgPSBOVUxMOwoJZm9yIChpID0gMTsgaSA8IGFyZ2M7IGkrKykgewoJCWNoYXIgKmFyZyA9IGFyZ3ZbaV07CgoJCWlmICgqYXJnID09ICctJykgewoJCQkvKiBBcmd1bWVudHMgZ28gaGVyZSAqLwoJCQl1c2FnZShjbG9uZV9wYWNrX3VzYWdlKTsKCQl9CgkJZGVzdCA9IGFyZzsKCQloZWFkcyA9IGFyZ3YgKyBpICsgMTsKCQlucl9oZWFkcyA9IGFyZ2MgLSBpIC0gMTsKCQlicmVhazsKCX0KCWlmICghZGVzdCkKCQl1c2FnZShjbG9uZV9wYWNrX3VzYWdlKTsKCXBpZCA9IGdpdF9jb25uZWN0KGZkLCBkZXN0LCBleGVjKTsKCWlmIChwaWQgPCAwKQoJCXJldHVybiAxOwoJcmV0ID0gY2xvbmVfcGFjayhmZCwgbnJfaGVhZHMsIGhlYWRzKTsKCWNsb3NlKGZkWzBdKTsKCWNsb3NlKGZkWzFdKTsKCWZpbmlzaF9jb25uZWN0KHBpZCk7CglyZXR1cm4gcmV0Owp9Cg==