diff options
Diffstat (limited to 'pack.c')
-rw-r--r-- | pack.c | 143 |
1 files changed, 143 insertions, 0 deletions
@@ -0,0 +1,143 @@ +#include <u.h> +#include <libc.h> +#include "dat.h" +#include "fns.h" + +/* + * these routines were taken directly from ssh(1). + * they serve as a reference. + */ + +static int +vpack(uchar *p, int n, char *fmt, va_list a) +{ + uchar *p0 = p, *e = p+n; + u32int u; +// mpint *m; + void *s; + int c; + + for(;;){ + switch(c = *fmt++){ + case '\0': + return p - p0; + case '_': + if(++p > e) goto err; + break; + case '.': + *va_arg(a, void**) = p; + break; + case 'b': + if(p >= e) goto err; + *p++ = va_arg(a, int); + break; + case 'm': +// m = va_arg(a, mpint*); +// u = (mpsignif(m)+8)/8; + if(p+4 > e) goto err; +// PUT4(p, u), p += 4; + if(u > e-p) goto err; +// mptober(m, p, u), p += u; + break; + case '[': + case 's': + s = va_arg(a, void*); + u = va_arg(a, int); + if(c == 's'){ + if(p+4 > e) goto err; +// PUT4(p, u), p += 4; + } + if(u > e-p) goto err; + memmove(p, s, u); + p += u; + break; + case 'u': + u = va_arg(a, int); + if(p+4 > e) goto err; +// PUT4(p, u), p += 4; + break; + } + } +err: + return -1; +} + +static int +vunpack(uchar *p, int n, char *fmt, va_list a) +{ + uchar *p0 = p, *e = p+n; + u32int u; +// mpint *m; + void *s; + + for(;;){ + switch(*fmt++){ + case '\0': + return p - p0; + case '_': + if(++p > e) goto err; + break; + case '.': + *va_arg(a, void**) = p; + break; + case 'b': + if(p >= e) goto err; + *va_arg(a, int*) = *p++; + break; + case 'm': + if(p+4 > e) goto err; +// u = GET4(p), p += 4; + if(u > e-p) goto err; +// m = va_arg(a, mpint*); +// betomp(p, u, m), p += u; + break; + case 's': + if(p+4 > e) goto err; +// u = GET4(p), p += 4; + if(u > e-p) goto err; + *va_arg(a, void**) = p; + *va_arg(a, int*) = u; + p += u; + break; + case '[': + s = va_arg(a, void*); + u = va_arg(a, int); + if(u > e-p) goto err; + memmove(s, p, u); + p += u; + break; + case 'u': + if(p+4 > e) goto err; +// u = GET4(p); + *va_arg(a, int*) = u; + p += 4; + break; + } + } +err: + return -1; +} + +int +pack(uchar *p, int n, char *fmt, ...) +{ + va_list a; + + va_start(a, fmt); + n = vpack(p, n, fmt, a); + va_end(a); + + return n; +} + +int +unpack(uchar *p, int n, char *fmt, ...) +{ + va_list a; + + va_start(a, fmt); + n = vunpack(p, n, fmt, a); + va_end(a); + + return n; +} |