dump.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #include <nlusctl.h>
  2. #include <format.h>
  3. #include <string.h>
  4. #include <output.h>
  5. #include <util.h>
  6. static int is_nest(struct ucattr* at)
  7. {
  8. void* buf = uc_payload(at);
  9. int len = uc_paylen(at);
  10. void* p = buf;
  11. void* e = buf + len;
  12. while(p < e) {
  13. struct ucattr* at = p;
  14. int alen = at->len;
  15. int skip = (alen + 3) & ~3;
  16. if(!skip) break;
  17. p += skip;
  18. }
  19. return (p == e);
  20. }
  21. static char* fmt_chr(char* p, char* e, byte c)
  22. {
  23. if(c < 20 || c >= 0x7F)
  24. p = fmtchar(p, e, '.');
  25. else
  26. p = fmtchar(p, e, c);
  27. return p;
  28. }
  29. static char* fmt_bytes(char* p, char* e, byte* data, int len)
  30. {
  31. int i;
  32. p = fmtstr(p, e, "[ ");
  33. for(i = 0; i < len; i++) {
  34. p = fmtbyte(p, e, data[i]);
  35. p = fmtchar(p, e, ' ');
  36. }
  37. p = fmtstr(p, e, "] ");
  38. for(i = 0; i < len; i++) {
  39. p = fmt_chr(p, e, data[i]);
  40. }
  41. return p;
  42. }
  43. static void prefix(struct bufout* bo, int lvl)
  44. {
  45. for(int i = 0; i < lvl; i++)
  46. bufout(bo, " ", 2);
  47. }
  48. static void hexline(struct bufout* bo, int lvl, byte* data, int len)
  49. {
  50. int i;
  51. prefix(bo, lvl);
  52. FMTBUF(p, e, buf, 128);
  53. p = fmtstr(p, e, "# ");
  54. for(i = 0; i < 16; i++) {
  55. if(i < len)
  56. p = fmtbyte(p, e, data[i]);
  57. else
  58. p = fmtstr(p, e, " ");
  59. p = fmtstr(p, e, " ");
  60. }
  61. p = fmtstr(p, e, " ");
  62. for(i = 0; i < 16; i++) {
  63. if(i < len)
  64. p = fmt_chr(p, e, data[i]);
  65. else
  66. p = fmtstr(p, e, " ");
  67. }
  68. FMTENL(p, e);
  69. bufout(bo, buf, p - buf);
  70. }
  71. static void dump_data(struct bufout* bo, int lvl, struct ucattr* at)
  72. {
  73. byte* data = uc_payload(at);
  74. int i, len = uc_paylen(at);
  75. int lines = len / 16;
  76. int trail = len % 16;
  77. int count = 0;
  78. for(i = 0; i < lines; i++) {
  79. hexline(bo, lvl, data + count, 16);
  80. count += 16;
  81. } if(trail > 0) {
  82. hexline(bo, lvl, data + count, trail);
  83. }
  84. }
  85. static void dump_attr(struct bufout* bo, int lvl, struct ucattr* at);
  86. static void dump_nest(struct bufout* bo, int lvl, struct ucattr* at)
  87. {
  88. struct ucattr* bt;
  89. for(bt = uc_get_0(at); bt; bt = uc_get_n(at, bt))
  90. dump_attr(bo, lvl, bt);
  91. }
  92. static void dump_attr(struct bufout* bo, int lvl, struct ucattr* at)
  93. {
  94. int paylen = uc_paylen(at);
  95. void* payload = uc_payload(at);
  96. prefix(bo, lvl);
  97. FMTBUF(p, e, buf, 120);
  98. p = fmtstr(p, e, "ATTR ");
  99. p = fmtint(p, e, at->key);
  100. if(paylen <= 0) {
  101. p = fmtstr(p, e, " flag");
  102. } else if(paylen <= 8) {
  103. p = fmtstr(p, e, " ");
  104. p = fmt_bytes(p, e, payload, paylen);
  105. } else {
  106. p = fmtstr(p, e, " +");
  107. p = fmtint(p, e, paylen);
  108. }
  109. FMTENL(p, e);
  110. bufout(bo, buf, p - buf);
  111. if(paylen <= 8)
  112. return;
  113. if(is_nest(at))
  114. dump_nest(bo, lvl + 1, at);
  115. else
  116. dump_data(bo, lvl + 1, at);
  117. }
  118. void uc_dump(struct ucattr* msg)
  119. {
  120. byte output[2048];
  121. struct bufout bo;
  122. bufoutset(&bo, STDERR, output, sizeof(output));
  123. int code = uc_repcode(msg);
  124. int paylen = uc_paylen(msg);
  125. FMTBUF(p, e, buf, 80);
  126. p = fmtstr(p, e, "NLUS ");
  127. p = fmtint(p, e, code);
  128. if(paylen > 0) {
  129. p = fmtstr(p, e, " +");
  130. p = fmtuint(p, e, paylen);
  131. };
  132. FMTENL(p, e);
  133. bufout(&bo, buf, p - buf);
  134. if(is_nest(msg)) {
  135. struct ucattr* at;
  136. for(at = uc_get_0(msg); at; at = uc_get_n(msg, at))
  137. dump_attr(&bo, 1, at);
  138. } else {
  139. dump_data(&bo, 1, msg);
  140. }
  141. bufoutflush(&bo);
  142. }