int recv_sb_msdp(struct session *ses, int cplen, unsigned char *src) { char buf[BUFFER_SIZE], var[BUFFER_SIZE], val[BUFFER_SIZE]; char *pto; int i, nest, state; var[0] = val[0] = i = nest = state = 0; if (skip_sb(ses, cplen, src) > cplen) { return cplen + 1; } while (i < cplen && src[i] != SE) { switch (src[i]) { case MSDP_VAR: i++; pto = buf; while (i < cplen && src[i] > 4 && src[i] != IAC) { *pto++ = src[i++]; } *pto = 0; substitute(ses, buf, var, SUB_SEC); state = MSDP_STATE_NEW; break; case MSDP_VAL: pto = val; while (i < cplen) { switch (src[i]) { case MSDP_VAR: if (nest == 0) { goto end_val; } if (state == MSDP_STATE_VAL) { *pto++ = '}'; } *pto++ = '{'; state = MSDP_STATE_VAR; break; case MSDP_VAL: if (state == MSDP_STATE_VAR) { *pto++ = '}'; *pto++ = '{'; state = MSDP_STATE_VAL; } else if (state == MSDP_STATE_VAL) { *pto++ = COMMAND_SEPARATOR; } else { state = MSDP_STATE_VAL; } break; case MSDP_OPEN: if (++nest > 1) { *pto++ = '{'; } state = MSDP_STATE_NEW; break; case MSDP_CLOSE: if (--nest > 0) { *pto++ = '}'; } if (state == MSDP_STATE_VAL) { *pto++ = '}'; } state = MSDP_STATE_NEW; break; case IAC: goto end_val; case '\\': *pto++ = '\\'; *pto++ = '\\'; break; case '{': *pto++ = '\\'; *pto++ = 'x'; *pto++ = '7'; *pto++ = 'B'; break; case '}': *pto++ = '\\'; *pto++ = 'x'; *pto++ = '7'; *pto++ = 'D'; break; case COMMAND_SEPARATOR: *pto++ = '\\'; *pto++ = COMMAND_SEPARATOR; break; default: *pto++ = src[i]; break; } i++; } end_val: *pto = 0; telopt_debug(ses, "IAC SB MSDP VAR (%s) %*s VAL (%s)", var, 20 - strlen(var), "", val); check_all_events(ses, 0, 2, "IAC SB MSDP", var, val); break; default: i++; break; } } telopt_debug(ses, "IAC SB MSDP IAC SE"); check_all_events(ses, 0, 0, "IAC SB MSDP IAC SE"); return UMIN(i + 1, cplen); }