drawterm-20110822.orig/0000755000175000017500000000000011765221005014070 5ustar tinchotinchodrawterm-20110822.orig/libauthsrv/0000755000175000017500000000000011245145712016256 5ustar tinchotinchodrawterm-20110822.orig/libauthsrv/nvcsum.c0000644000175000017500000000030011245145712017726 0ustar tinchotincho#include #include #include uchar nvcsum(void *vmem, int n) { uchar *mem, sum; int i; sum = 9; mem = vmem; for(i = 0; i < n; i++) sum += mem[i]; return sum; } drawterm-20110822.orig/libauthsrv/convPR2M.c0000644000175000017500000000106311245145712020030 0ustar tinchotincho#include #include #include #define CHAR(x) *p++ = f->x #define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 #define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(p, f->x, n); p += n int convPR2M(Passwordreq *f, char *ap, char *key) { int n; uchar *p; p = (uchar*)ap; CHAR(num); STRING(old, ANAMELEN); STRING(new, ANAMELEN); CHAR(changesecret); STRING(secret, SECRETLEN); n = p - (uchar*)ap; if(key) encrypt(key, ap, n); return n; } drawterm-20110822.orig/libauthsrv/authdial.c0000644000175000017500000000130711245145712020216 0ustar tinchotincho#include #include #include #include #include int authdial(char *netroot, char *dom) { char server[Ndbvlen]; Ndbtuple *nt; if(dom != nil){ /* look up an auth server in an authentication domain */ nt = csgetval(netroot, "authdom", dom, "auth", server); /* if that didn't work, just try the IP domain */ if(nt == nil) nt = csgetval(netroot, "dom", dom, "auth", server); if(nt == nil){ werrstr("no auth server found for %s", dom); return -1; } ndbfree(nt); return dial(netmkaddr(server, netroot, "ticket"), 0, 0, 0); } else { /* look for one relative to my machine */ return dial(netmkaddr("$auth", netroot, "ticket"), 0, 0, 0); } } drawterm-20110822.orig/libauthsrv/convM2A.c0000644000175000017500000000072611245145712017674 0ustar tinchotincho#include #include #include #define CHAR(x) f->x = *p++ #define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 #define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(f->x, p, n); p += n void convM2A(char *ap, Authenticator *f, char *key) { uchar *p; if(key) decrypt(key, ap, AUTHENTLEN); p = (uchar*)ap; CHAR(num); STRING(chal, CHALLEN); LONG(id); USED(p); } drawterm-20110822.orig/libauthsrv/convM2TR.c0000644000175000017500000000115111245145712020032 0ustar tinchotincho#include #include #include #define CHAR(x) f->x = *p++ #define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 #define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(f->x, p, n); p += n void convM2TR(char *ap, Ticketreq *f) { uchar *p; p = (uchar*)ap; CHAR(type); STRING(authid, ANAMELEN); f->authid[ANAMELEN-1] = 0; STRING(authdom, DOMLEN); f->authdom[DOMLEN-1] = 0; STRING(chal, CHALLEN); STRING(hostid, ANAMELEN); f->hostid[ANAMELEN-1] = 0; STRING(uid, ANAMELEN); f->uid[ANAMELEN-1] = 0; USED(p); } drawterm-20110822.orig/libauthsrv/readnvram.c0000644000175000017500000002037611245145712020411 0ustar tinchotincho#include #include #include static long finddosfile(int, char*); static int check(void *x, int len, uchar sum, char *msg) { if(nvcsum(x, len) == sum) return 0; memset(x, 0, len); fprint(2, "%s\n", msg); return 1; } /* * get key info out of nvram. since there isn't room in the PC's nvram use * a disk partition there. */ static struct { char *cputype; char *file; int off; int len; } nvtab[] = { "sparc", "#r/nvram", 1024+850, sizeof(Nvrsafe), "pc", "#S/sdC0/nvram", 0, sizeof(Nvrsafe), "pc", "#S/sdC0/9fat", -1, sizeof(Nvrsafe), "pc", "#S/sd00/nvram", 0, sizeof(Nvrsafe), "pc", "#S/sd00/9fat", -1, sizeof(Nvrsafe), "pc", "#S/sd01/nvram", 0, sizeof(Nvrsafe), "pc", "#S/sd01/9fat", -1, sizeof(Nvrsafe), "pc", "#f/fd0disk", -1, 512, /* 512: #f requires whole sector reads */ "pc", "#f/fd1disk", -1, 512, "mips", "#r/nvram", 1024+900, sizeof(Nvrsafe), "power", "#F/flash/flash0", 0x300000, sizeof(Nvrsafe), "power", "#r/nvram", 4352, sizeof(Nvrsafe), /* OK for MTX-604e */ "debug", "/tmp/nvram", 0, sizeof(Nvrsafe), }; static char* readcons(char *prompt, char *def, int raw, char *buf, int nbuf) { int fdin, fdout, ctl, n, m; char line[10]; fdin = open("/dev/cons", OREAD); if(fdin < 0) fdin = 0; fdout = open("/dev/cons", OWRITE); if(fdout < 0) fdout = 1; if(def != nil) fprint(fdout, "%s[%s]: ", prompt, def); else fprint(fdout, "%s: ", prompt); if(raw){ ctl = open("/dev/consctl", OWRITE); if(ctl >= 0) write(ctl, "rawon", 5); } else ctl = -1; m = 0; for(;;){ n = read(fdin, line, 1); if(n == 0){ close(ctl); werrstr("readcons: EOF"); return nil; } if(n < 0){ close(ctl); werrstr("can't read cons"); return nil; } if(line[0] == 0x7f) exits(0); if(n == 0 || line[0] == '\n' || line[0] == '\r'){ if(raw){ write(ctl, "rawoff", 6); write(fdout, "\n", 1); close(ctl); } buf[m] = '\0'; if(buf[0]=='\0' && def) strcpy(buf, def); return buf; } if(line[0] == '\b'){ if(m > 0) m--; }else if(line[0] == 0x15){ /* ^U: line kill */ m = 0; if(def != nil) fprint(fdout, "%s[%s]: ", prompt, def); else fprint(fdout, "%s: ", prompt); }else{ if(m >= nbuf-1){ fprint(fdout, "line too long\n"); m = 0; if(def != nil) fprint(fdout, "%s[%s]: ", prompt, def); else fprint(fdout, "%s: ", prompt); }else buf[m++] = line[0]; } } return buf; /* how does this happen */ } /* * get key info out of nvram. since there isn't room in the PC's nvram use * a disk partition there. */ int readnvram(Nvrsafe *safep, int flag) { char buf[1024], in[128], *cputype, *nvrfile, *nvrlen, *nvroff, *v[2]; int fd, err, i, safeoff, safelen; Nvrsafe *safe; err = 0; memset(safep, 0, sizeof(*safep)); nvrfile = getenv("nvram"); cputype = getenv("cputype"); if(cputype == nil) cputype = "mips"; if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0) cputype = "pc"; safe = (Nvrsafe*)buf; fd = -1; safeoff = -1; safelen = -1; if(nvrfile != nil){ /* accept device and device!file */ i = gettokens(nvrfile, v, nelem(v), "!"); fd = open(v[0], ORDWR); safelen = sizeof(Nvrsafe); if(strstr(v[0], "/9fat") == nil) safeoff = 0; nvrlen = getenv("nvrlen"); if(nvrlen != nil) safelen = atoi(nvrlen); nvroff = getenv("nvroff"); if(nvroff != nil){ if(strcmp(nvroff, "dos") == 0) safeoff = -1; else safeoff = atoi(nvroff); } if(safeoff < 0 && fd >= 0){ safelen = 512; safeoff = finddosfile(fd, i == 2 ? v[1] : "plan9.nvr"); if(safeoff < 0){ close(fd); fd = -1; } } free(nvrfile); if(nvrlen != nil) free(nvrlen); if(nvroff != nil) free(nvroff); }else{ for(i=0; imachkey, DESKEYLEN, safe->machsum, "bad nvram key"); // err |= check(safe->config, CONFIGLEN, safe->configsum, "bad secstore key"); err |= check(safe->authid, ANAMELEN, safe->authidsum, "bad authentication id"); err |= check(safe->authdom, DOMLEN, safe->authdomsum, "bad authentication domain"); } if((flag&NVwrite) || (err && (flag&NVwriteonerr))){ readcons("authid", nil, 0, safe->authid, sizeof(safe->authid)); readcons("authdom", nil, 0, safe->authdom, sizeof(safe->authdom)); readcons("secstore key", nil, 1, safe->config, sizeof(safe->config)); for(;;){ if(readcons("password", nil, 1, in, sizeof in) == nil) goto Out; if(passtokey(safe->machkey, in)) break; } safe->machsum = nvcsum(safe->machkey, DESKEYLEN); safe->configsum = nvcsum(safe->config, CONFIGLEN); safe->authidsum = nvcsum(safe->authid, sizeof(safe->authid)); safe->authdomsum = nvcsum(safe->authdom, sizeof(safe->authdom)); *(Nvrsafe*)buf = *safe; if(seek(fd, safeoff, 0) < 0 || write(fd, buf, safelen) != safelen){ fprint(2, "can't write key to nvram: %r\n"); err = 1; }else err = 0; } Out: close(fd); return err ? -1 : 0; } typedef struct Dosboot Dosboot; struct Dosboot{ uchar magic[3]; /* really an xx86 JMP instruction */ uchar version[8]; uchar sectsize[2]; uchar clustsize; uchar nresrv[2]; uchar nfats; uchar rootsize[2]; uchar volsize[2]; uchar mediadesc; uchar fatsize[2]; uchar trksize[2]; uchar nheads[2]; uchar nhidden[4]; uchar bigvolsize[4]; uchar driveno; uchar reserved0; uchar bootsig; uchar volid[4]; uchar label[11]; uchar type[8]; }; #define GETSHORT(p) (((p)[1]<<8) | (p)[0]) #define GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p))) typedef struct Dosdir Dosdir; struct Dosdir { char name[8]; char ext[3]; uchar attr; uchar reserved[10]; uchar time[2]; uchar date[2]; uchar start[2]; uchar length[4]; }; static char* dosparse(char *from, char *to, int len) { char c; memset(to, ' ', len); if(from == 0) return 0; while(len-- > 0){ c = *from++; if(c == '.') return from; if(c == 0) break; if(c >= 'a' && c <= 'z') *to++ = c + 'A' - 'a'; else *to++ = c; } return 0; } /* * return offset of first file block * * This is a very simplistic dos file system. It only * works on floppies, only looks in the root, and only * returns a pointer to the first block of a file. * * This exists for cpu servers that have no hard disk * or nvram to store the key on. * * Please don't make this any smarter: it stays resident * and I'ld prefer not to waste the space on something that * runs only at boottime -- presotto. */ static long finddosfile(int fd, char *file) { uchar secbuf[512]; char name[8]; char ext[3]; Dosboot *b; Dosdir *root, *dp; int nroot, sectsize, rootoff, rootsects, n; /* dos'ize file name */ file = dosparse(file, name, 8); dosparse(file, ext, 3); /* read boot block, check for sanity */ b = (Dosboot*)secbuf; if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf)) return -1; if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90) return -1; sectsize = GETSHORT(b->sectsize); if(sectsize != 512) return -1; rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize; if(seek(fd, rootoff, 0) < 0) return -1; nroot = GETSHORT(b->rootsize); rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize; if(rootsects <= 0 || rootsects > 64) return -1; /* * read root. it is contiguous to make stuff like * this easier */ root = malloc(rootsects*sectsize); if(read(fd, root, rootsects*sectsize) != rootsects*sectsize) return -1; n = -1; for(dp = root; dp < &root[nroot]; dp++) if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){ n = GETSHORT(dp->start); break; } free(root); if(n < 0) return -1; /* * dp->start is in cluster units, not sectors. The first * cluster is cluster 2 which starts immediately after the * root directory */ return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize; } drawterm-20110822.orig/libauthsrv/_asrdresp.c0000644000175000017500000000155211245145712020407 0ustar tinchotincho#include #include #include static char *pbmsg = "AS protocol botch"; int _asrdresp(int fd, char *buf, int len) { int n; char error[64]; if(read(fd, buf, 1) != 1){ werrstr(pbmsg); return -1; } n = len; switch(buf[0]){ case AuthOK: if(readn(fd, buf, len) != len){ werrstr(pbmsg); return -1; } break; case AuthErr: if(readn(fd, error, sizeof error) != sizeof error){ werrstr(pbmsg); return -1; } error[sizeof error-1] = '\0'; werrstr("remote: %s", error); return -1; case AuthOKvar: if(readn(fd, error, 5) != 5){ werrstr(pbmsg); return -1; } error[5] = 0; n = atoi(error); if(n <= 0 || n > len){ werrstr(pbmsg); return -1; } memset(buf, 0, len); if(readn(fd, buf, n) != n){ werrstr(pbmsg); return -1; } break; default: werrstr(pbmsg); return -1; } return n; } drawterm-20110822.orig/libauthsrv/convM2PR.c0000644000175000017500000000114211245145712020026 0ustar tinchotincho#include #include #include #define CHAR(x) f->x = *p++ #define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 #define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(f->x, p, n); p += n void convM2PR(char *ap, Passwordreq *f, char *key) { uchar *p; p = (uchar*)ap; if(key) decrypt(key, ap, PASSREQLEN); CHAR(num); STRING(old, ANAMELEN); f->old[ANAMELEN-1] = 0; STRING(new, ANAMELEN); f->new[ANAMELEN-1] = 0; CHAR(changesecret); STRING(secret, SECRETLEN); f->secret[SECRETLEN-1] = 0; USED(p); } drawterm-20110822.orig/libauthsrv/convA2M.c0000644000175000017500000000076511245145712017677 0ustar tinchotincho#include #include #include #define CHAR(x) *p++ = f->x #define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 #define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(p, f->x, n); p += n int convA2M(Authenticator *f, char *ap, char *key) { int n; uchar *p; p = (uchar*)ap; CHAR(num); STRING(chal, CHALLEN); LONG(id); n = p - (uchar*)ap; if(key) encrypt(key, ap, n); return n; } drawterm-20110822.orig/libauthsrv/convT2M.c0000644000175000017500000000105611245145712017714 0ustar tinchotincho#include #include #include #define CHAR(x) *p++ = f->x #define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 #define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(p, f->x, n); p += n int convT2M(Ticket *f, char *ap, char *key) { int n; uchar *p; p = (uchar*)ap; CHAR(num); STRING(chal, CHALLEN); STRING(cuid, ANAMELEN); STRING(suid, ANAMELEN); STRING(key, DESKEYLEN); n = p - (uchar*)ap; if(key) encrypt(key, ap, n); return n; } drawterm-20110822.orig/libauthsrv/Makefile0000644000175000017500000000054311245145712017720 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libauthsrv.a OFILES=\ _asgetticket.$O\ _asrdresp.$O\ convA2M.$O\ convM2A.$O\ convM2PR.$O\ convM2T.$O\ convM2TR.$O\ convPR2M.$O\ convT2M.$O\ convTR2M.$O\ nvcsum.$O\ opasstokey.$O\ passtokey.$O\ default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/libauthsrv/passtokey.c0000644000175000017500000000100511245145712020440 0ustar tinchotincho#include #include #include int passtokey(char *key, char *p) { uchar buf[ANAMELEN], *t; int i, n; n = strlen(p); if(n >= ANAMELEN) n = ANAMELEN-1; memset(buf, ' ', 8); t = buf; strncpy((char*)t, p, n); t[n] = 0; memset(key, 0, DESKEYLEN); for(;;){ for(i = 0; i < DESKEYLEN; i++) key[i] = (t[i] >> i) + (t[i+1] << (8 - (i+1))); if(n <= 8) return 1; n -= 8; t += 8; if(n < 8){ t -= 8 - n; n = 8; } encrypt(key, t, 8); } return 1; /* not reached */ } drawterm-20110822.orig/libauthsrv/opasstokey.c0000644000175000017500000000070011245145712020620 0ustar tinchotincho#include #include #include int opasstokey(char *key, char *p) { uchar t[10]; int c, n; n = strlen(p); memset(t, ' ', sizeof t); if(n < 5) return 0; if(n > 10) n = 10; strncpy((char*)t, p, n); if(n >= 9){ c = p[8] & 0xf; if(n == 10) c += p[9] << 4; for(n = 0; n < 8; n++) if(c & (1 << n)) t[n] -= ' '; } for(n = 0; n < 7; n++) key[n] = (t[n] >> n) + (t[n+1] << (8 - (n+1))); return 1; } drawterm-20110822.orig/libauthsrv/convM2T.c0000644000175000017500000000110311245145712017705 0ustar tinchotincho#include #include #include #define CHAR(x) f->x = *p++ #define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2 #define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(f->x, p, n); p += n void convM2T(char *ap, Ticket *f, char *key) { uchar *p; if(key) decrypt(key, ap, TICKETLEN); p = (uchar*)ap; CHAR(num); STRING(chal, CHALLEN); STRING(cuid, ANAMELEN); f->cuid[ANAMELEN-1] = 0; STRING(suid, ANAMELEN); f->suid[ANAMELEN-1] = 0; STRING(key, DESKEYLEN); USED(p); } drawterm-20110822.orig/libauthsrv/convTR2M.c0000644000175000017500000000106211245145712020033 0ustar tinchotincho#include #include #include #define CHAR(x) *p++ = f->x #define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2 #define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4 #define LONG(x) VLONG(f->x) #define STRING(x,n) memmove(p, f->x, n); p += n int convTR2M(Ticketreq *f, char *ap) { int n; uchar *p; p = (uchar*)ap; CHAR(type); STRING(authid, 28); /* BUG */ STRING(authdom, DOMLEN); STRING(chal, CHALLEN); STRING(hostid, 28); /* BUG */ STRING(uid, 28); /* BUG */ n = p - (uchar*)ap; return n; } drawterm-20110822.orig/libauthsrv/_asgetticket.c0000644000175000017500000000043011245145712021065 0ustar tinchotincho#include #include #include static char *pbmsg = "AS protocol botch"; int _asgetticket(int fd, char *trbuf, char *tbuf) { if(write(fd, trbuf, TICKREQLEN) < 0){ close(fd); werrstr(pbmsg); return -1; } return _asrdresp(fd, tbuf, 2*TICKETLEN); } drawterm-20110822.orig/gui-x11/0000755000175000017500000000000011416512642015266 5ustar tinchotinchodrawterm-20110822.orig/gui-x11/keysym2ucs-x11.c0000644000175000017500000020270011245145711020157 0ustar tinchotincho/* $XFree86: xc/programs/xterm/keysym2ucs.c,v 1.5 2001/06/18 19:09:26 dickey Exp $ * This module converts keysym values into the corresponding ISO 10646 * (UCS, Unicode) values. * * The array keysymtab[] contains pairs of X11 keysym values for graphical * characters and the corresponding Unicode value. The function * keysym2ucs() maps a keysym onto a Unicode value using a binary search, * therefore keysymtab[] must remain SORTED by keysym value. * * The keysym -> UTF-8 conversion will hopefully one day be provided * by Xlib via XmbLookupString() and should ideally not have to be * done in X applications. But we are not there yet. * * We allow to represent any UCS character in the range U-00000000 to * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff. * This admittedly does not cover the entire 31-bit space of UCS, but * it does cover all of the characters up to U-10FFFF, which can be * represented by UTF-16, and more, and it is very unlikely that higher * UCS codes will ever be assigned by ISO. So to get Unicode character * U+ABCD you can directly use keysym 0x0100abcd. * * NOTE: The comments in the table below contain the actual character * encoded in UTF-8, so for viewing and editing best use an editor in * UTF-8 mode. * * Author: Markus G. Kuhn , University of Cambridge, April 2001 * * Special thanks to Richard Verhoeven for preparing * an initial draft of the mapping table. * * This software is in the public domain. Share and enjoy! * * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl) */ #ifndef KEYSYM2UCS_INCLUDED #include "keysym2ucs.h" #define VISIBLE /* */ #else #define VISIBLE static #endif static struct codepair { unsigned short keysym; unsigned short ucs; } keysymtab[] = { { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ { 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ { 0x08a1, 0x23b7 }, /* leftradical ⎷ ??? */ { 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ { 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */ { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ { 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ ??? */ { 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ ??? */ { 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ ??? */ { 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ ??? */ { 0x08ab, 0x239b }, /* topleftparens ⎛ ??? */ { 0x08ac, 0x239d }, /* botleftparens ⎝ ??? */ { 0x08ad, 0x239e }, /* toprightparens ⎞ ??? */ { 0x08ae, 0x23a0 }, /* botrightparens ⎠ ??? */ { 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */ { 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */ /* 0x08b1 topleftsummation ? ??? */ /* 0x08b2 botleftsummation ? ??? */ /* 0x08b3 topvertsummationconnector ? ??? */ /* 0x08b4 botvertsummationconnector ? ??? */ /* 0x08b5 toprightsummation ? ??? */ /* 0x08b6 botrightsummation ? ??? */ /* 0x08b7 rightmiddlesummation ? ??? */ { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ { 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */ { 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */ { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ { 0x08dd, 0x222a }, /* union ∪ UNION */ { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ /* 0x09df blank ? ??? */ { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ { 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */ { 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */ { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ { 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */ { 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */ { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ { 0x0aaa, 0x2013 }, /* endash – EN DASH */ /* 0x0aac signifblank ? ??? */ { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ { 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */ { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ /* 0x0abd decimalpoint ? ??? */ { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ /* 0x0abf marker ? ??? */ { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ /* 0x0acb trademarkincircle ? ??? */ { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ { 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */ { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ /* 0x0ada hexagram ? ??? */ { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ { 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */ { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ { 0x0af1, 0x2020 }, /* dagger † DAGGER */ { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ { 0x0afc, 0x2038 }, /* caret ‸ CARET */ { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ /* 0x0aff cursor ? ??? */ { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ { 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */ { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */ { 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */ { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ { 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */ { 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */ { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ /* 0x0dde Thai_maihanakat_maitho ? ??? */ { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ { 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */ { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ { 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */ { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ { 0x13a4, 0x20ac }, /* Euro € EURO SIGN */ { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ }; VISIBLE long keysym2ucs(KeySym keysym) { int min = 0; int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; int mid; /* first check for Latin-1 characters (1:1 mapping) */ if ((keysym >= 0x0020 && keysym <= 0x007e) || (keysym >= 0x00a0 && keysym <= 0x00ff)) return keysym; /* also check for directly encoded 24-bit UCS characters */ if ((keysym & 0xff000000) == 0x01000000) return keysym & 0x00ffffff; /* binary search in table */ while (max >= min) { mid = (min + max) / 2; if (keysymtab[mid].keysym < keysym) min = mid + 1; else if (keysymtab[mid].keysym > keysym) max = mid - 1; else { /* found it */ return keysymtab[mid].ucs; } } /* no matching Unicode value found */ return -1; } drawterm-20110822.orig/gui-x11/Makefile0000644000175000017500000000024211245145711016723 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libgui.a OFILES=\ x11.$O\ keysym2ucs-x11.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) drawterm-20110822.orig/gui-x11/x11.c0000644000175000017500000010501511416512642016045 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include #include #include #include #include "screen.h" #define argv0 "drawterm" typedef struct Cursor Cursor; #undef long #define Font XFont #define Screen XScreen #define Display XDisplay #define Cursor XCursor #include #include #include #include #include #include #include "keysym2ucs.h" #undef Font #undef Screen #undef Display #undef Cursor #define long int /* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */ #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) enum { PMundef = ~0 /* undefined pixmap id */ }; /* * Structure pointed to by X field of Memimage */ typedef struct Xmem Xmem; struct Xmem { int pmid; /* pixmap id for screen ldepth instance */ XImage *xi; /* local image if we currenty have the data */ int dirty; Rectangle dirtyr; Rectangle r; uintptr pc; /* who wrote into xi */ }; static int xgcfillcolor; static int xgcfillcolor0; static int xgcsimplecolor0; static int xgcsimplepm0; static XDisplay* xdisplay; /* used holding draw lock */ static int xtblbit; static int plan9tox11[256]; /* Values for mapping between */ static int x11toplan9[256]; /* X11 and Plan 9 */ static GC xgcfill, xgccopy, xgcsimplesrc, xgczero, xgcreplsrc; static GC xgcfill0, xgccopy0, xgcsimplesrc0, xgczero0, xgcreplsrc0; static ulong xscreenchan; static Drawable xscreenid; static Visual *xvis; static int xdraw(Memdrawparam*); #define glenda_width 48 #define glenda_height 48 static unsigned short glenda_bits[] = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffe9, 0xffff, 0x7fff, 0xffae, 0xffff, 0xffff, 0xffbe, 0xffff, 0x1fff, 0xff3f, 0xffff, 0xbfff, 0xfe6e, 0xffff, 0xbbff, 0xfcce, 0xffff, 0xffff, 0xf98c, 0xffff, 0xe5ff, 0xf31b, 0xffff, 0x87ff, 0xe617, 0xffff, 0x05ff, 0xdf37, 0xffff, 0x0fff, 0x7ffe, 0xffff, 0x1bff, 0xfffc, 0xfffa, 0x37ff, 0xfffc, 0xfffb, 0xd7ff, 0xfffc, 0xfff7, 0xcfff, 0xffff, 0xfff7, 0xcfff, 0xffff, 0xffef, 0xdfff, 0xffff, 0xffef, 0xafff, 0xffff, 0xffdf, 0xefff, 0xffff, 0xfff3, 0xdfff, 0xefff, 0xffd3, 0xdfff, 0xc7ff, 0xffdf, 0xefff, 0xefff, 0xffef, 0xcfff, 0xffff, 0xffcf, 0xdfff, 0xffff, 0xffd9, 0x9fff, 0x7fff, 0xffd0, 0xbfff, 0xffff, 0xffd7, 0x7fff, 0xbfff, 0xffd0, 0x3fff, 0x3fff, 0xffd9, 0x7fff, 0x3fff, 0xffcb, 0x3fff, 0xffff, 0xffdc, 0x3fff, 0xffff, 0xffdf, 0x3fff, 0xffff, 0xff9f, 0x3fff, 0xffff, 0xffdf, 0x8fff, 0xffff, 0xff9f, 0xa7ff, 0xffff, 0xffdf, 0xe3ff, 0xffff, 0xffcf, 0xe9ff, 0xffff, 0xffcf, 0xf1ff, 0xffff, 0xffef, 0xf3ff, 0xffff, 0xffe7, 0xf9ff, 0xffff, 0xffe7, 0x53ff, 0xffff, 0xffe1, 0x07ff, 0x7ffc, 0xffc6, 0x17ff, 0xeff0, 0xffee, 0xffff, 0xc781, 0xffe5, 0xffff, 0x8807, 0xffe0, 0xffff, 0x003f, 0xfff0, 0xffff, 0x1fff, 0xfffe }; /* * Synchronize images between X bitmaps and in-memory bitmaps. */ static void addrect(Rectangle *rp, Rectangle r) { if(rp->min.x >= rp->max.x) *rp = r; else combinerect(rp, r); } static XImage* getXdata(Memimage *m, Rectangle r) { uchar *p; int x, y; Xmem *xm; Point xdelta, delta; Point tp; xm = m->X; if(xm == nil) return nil; assert(xm != nil && xm->xi != nil); if(xm->dirty == 0) return xm->xi; r = xm->dirtyr; if(Dx(r)==0 || Dy(r)==0) return xm->xi; delta = subpt(r.min, m->r.min); tp = xm->r.min; /* avoid unaligned access on digital unix */ xdelta = subpt(r.min, tp); XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r), AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y); if(xtblbit && m->chan == CMAP8) for(y=r.min.y; ydirty = 0; xm->dirtyr = Rect(0,0,0,0); return xm->xi; } static void putXdata(Memimage *m, Rectangle r) { Xmem *xm; XImage *xi; GC g; Point xdelta, delta; Point tp; int x, y; uchar *p; xm = m->X; if(xm == nil) return; assert(xm != nil); assert(xm->xi != nil); xi = xm->xi; g = (m->chan == GREY1) ? xgccopy0 : xgccopy; delta = subpt(r.min, m->r.min); tp = xm->r.min; /* avoid unaligned access on digital unix */ xdelta = subpt(r.min, tp); if(xtblbit && m->chan == CMAP8) for(y=r.min.y; ypmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r)); if(xtblbit && m->chan == CMAP8) for(y=r.min.y; yX) != nil){ xm->dirty = 1; addrect(&xm->dirtyr, r); } } Memimage* xallocmemimage(Rectangle r, ulong chan, int pmid) { Memimage *m; Xmem *xm; XImage *xi; int offset; int d; m = _allocmemimage(r, chan); if(m == nil) return nil; if(chan != GREY1 && chan != xscreenchan) return m; d = m->depth; xm = mallocz(sizeof(Xmem), 1); if(pmid != PMundef) xm->pmid = pmid; else xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d); if(m->depth == 24) offset = r.min.x&(4-1); else offset = r.min.x&(31/m->depth); r.min.x -= offset; assert(wordsperline(r, m->depth) <= m->width); xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0, (char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong)); if(xi == nil){ _freememimage(m); return nil; } xm->xi = xi; xm->pc = getcallerpc(&r); xm->r = r; /* * Set the parameters of the XImage so its memory looks exactly like a * Memimage, so we can call _memimagedraw on the same data. All frame * buffers we've seen, and Plan 9's graphics code, require big-endian * bits within bytes, but little endian byte order within pixels. */ xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth; xi->byte_order = LSBFirst; xi->bitmap_bit_order = MSBFirst; xi->bitmap_pad = 32; xm->r = Rect(0,0,0,0); XInitImage(xi); XFlush(xdisplay); m->X = xm; return m; } void xfillcolor(Memimage *m, Rectangle r, ulong v) { GC gc; Xmem *dxm; dxm = m->X; assert(dxm != nil); r = rectsubpt(r, m->r.min); if(m->chan == GREY1){ gc = xgcfill0; if(xgcfillcolor0 != v){ XSetForeground(xdisplay, gc, v); xgcfillcolor0 = v; } }else{ if(m->chan == CMAP8 && xtblbit) v = plan9tox11[v]; gc = xgcfill; if(xgcfillcolor != v){ XSetForeground(xdisplay, gc, v); xgcfillcolor = v; } } XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, Dx(r), Dy(r)); } /* * Replacements for libmemdraw routines. * (They've been underscored.) */ Memimage* allocmemimage(Rectangle r, ulong chan) { return xallocmemimage(r, chan, PMundef); } void freememimage(Memimage *m) { Xmem *xm; if(m == nil) return; if(m->data->ref == 1){ if((xm = m->X) != nil){ if(xm->xi){ xm->xi->data = nil; XFree(xm->xi); } XFreePixmap(xdisplay, xm->pmid); free(xm); m->X = nil; } } _freememimage(m); } void memfillcolor(Memimage *m, ulong val) { _memfillcolor(m, val); if(m->X){ if((val & 0xFF) == 0xFF) xfillcolor(m, m->r, _rgbatoimg(m, val)); else putXdata(m, m->r); } } int loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int n; n = _loadmemimage(i, r, data, ndata); if(n > 0 && i->X) putXdata(i, r); return n; } int cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int n; n = _cloadmemimage(i, r, data, ndata); if(n > 0 && i->X) putXdata(i, r); return n; } ulong pixelbits(Memimage *m, Point p) { if(m->X) getXdata(m, Rect(p.x, p.y, p.x+1, p.y+1)); return _pixelbits(m, p); } void memimageinit(void) { static int didinit = 0; if(didinit) return; didinit = 1; _memimageinit(); xfillcolor(memblack, memblack->r, 0); xfillcolor(memwhite, memwhite->r, 1); } void memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op) { Memdrawparam *par; if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil) return; _memimagedraw(par); if(!xdraw(par)) putXdata(dst, par->r); } static int xdraw(Memdrawparam *par) { int dy, dx; unsigned m; Memimage *src, *dst, *mask; Xmem *dxm, *sxm, *mxm; GC gc; Rectangle r, sr, mr; ulong sdval; dx = Dx(par->r); dy = Dy(par->r); src = par->src; dst = par->dst; mask = par->mask; r = par->r; sr = par->sr; mr = par->mr; sdval = par->sdval; /* * drawterm was distributed for years with * "return 0;" right here. * maybe we should give up on all this? */ if((dxm = dst->X) == nil) return 0; /* * If we have an opaque mask and source is one opaque pixel we can convert to the * destination format and just XFillRectangle. */ m = Simplesrc|Simplemask|Fullmask; if((par->state&m)==m){ xfillcolor(dst, r, sdval); dirtyXdata(dst, par->r); return 1; } /* * If no source alpha, an opaque mask, we can just copy the * source onto the destination. If the channels are the same and * the source is not replicated, XCopyArea suffices. */ m = Simplemask|Fullmask; if((par->state&(m|Replsrc))==m && src->chan == dst->chan && src->X){ sxm = src->X; r = rectsubpt(r, dst->r.min); sr = rectsubpt(sr, src->r.min); if(dst->chan == GREY1) gc = xgccopy0; else gc = xgccopy; XCopyArea(xdisplay, sxm->pmid, dxm->pmid, gc, sr.min.x, sr.min.y, dx, dy, r.min.x, r.min.y); dirtyXdata(dst, par->r); return 1; } /* * If no source alpha, a 1-bit mask, and a simple source * we can just copy through the mask onto the destination. */ if(dst->X && mask->X && !(mask->flags&Frepl) && mask->chan == GREY1 && (par->state&Simplesrc)){ Point p; mxm = mask->X; r = rectsubpt(r, dst->r.min); mr = rectsubpt(mr, mask->r.min); p = subpt(r.min, mr.min); if(dst->chan == GREY1){ gc = xgcsimplesrc0; if(xgcsimplecolor0 != sdval){ XSetForeground(xdisplay, gc, sdval); xgcsimplecolor0 = sdval; } if(xgcsimplepm0 != mxm->pmid){ XSetStipple(xdisplay, gc, mxm->pmid); xgcsimplepm0 = mxm->pmid; } }else{ /* somehow this doesn't work on rob's mac gc = xgcsimplesrc; if(dst->chan == CMAP8 && xtblbit) sdval = plan9tox11[sdval]; if(xgcsimplecolor != sdval){ XSetForeground(xdisplay, gc, sdval); xgcsimplecolor = sdval; } if(xgcsimplepm != mxm->pmid){ XSetStipple(xdisplay, gc, mxm->pmid); xgcsimplepm = mxm->pmid; } */ return 0; } XSetTSOrigin(xdisplay, gc, p.x, p.y); XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, dx, dy); dirtyXdata(dst, par->r); return 1; } return 0; } /* * X11 window management and kernel hooks. * Oh, how I loathe this code! */ static XColor map[256]; /* Plan 9 colormap array */ static XColor map7[128]; /* Plan 9 colormap array */ static uchar map7to8[128][2]; static Colormap xcmap; /* Default shared colormap */ extern int mousequeue; /* for copy/paste, lifted from plan9ports */ static Atom clipboard; static Atom utf8string; static Atom targets; static Atom text; static Atom compoundtext; static Drawable xdrawable; static void xexpose(XEvent*); static void xmouse(XEvent*); static void xkeyboard(XEvent*); static void xmapping(XEvent*); static void xdestroy(XEvent*); static void xselect(XEvent*, XDisplay*); static void xproc(void*); static Memimage* xinitscreen(void); static void initmap(Window); static GC creategc(Drawable); static void graphicscmap(XColor*); static int xscreendepth; static XDisplay* xkmcon; /* used only in xproc */ static XDisplay* xsnarfcon; /* used holding clip.lk */ static ulong xblack; static ulong xwhite; static int putsnarf, assertsnarf; Memimage *gscreen; Screeninfo screen; void flushmemscreen(Rectangle r) { assert(!drawcanqlock()); if(r.min.x >= r.max.x || r.min.y >= r.max.y) return; XCopyArea(xdisplay, xscreenid, xdrawable, xgccopy, r.min.x, r.min.y, Dx(r), Dy(r), r.min.x, r.min.y); XFlush(xdisplay); } void screeninit(void) { _memmkcmap(); gscreen = xinitscreen(); kproc("xscreen", xproc, nil); memimageinit(); terminit(); drawqlock(); flushmemscreen(gscreen->r); drawqunlock(); } uchar* attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X) { *r = gscreen->r; *chan = gscreen->chan; *depth = gscreen->depth; *width = gscreen->width; *X = gscreen->X; *softscreen = 1; return gscreen->data->bdata; } static int revbyte(int b) { int r; r = 0; r |= (b&0x01) << 7; r |= (b&0x02) << 5; r |= (b&0x04) << 3; r |= (b&0x08) << 1; r |= (b&0x10) >> 1; r |= (b&0x20) >> 3; r |= (b&0x40) >> 5; r |= (b&0x80) >> 7; return r; } void mouseset(Point xy) { drawqlock(); XWarpPointer(xdisplay, None, xdrawable, 0, 0, 0, 0, xy.x, xy.y); XFlush(xdisplay); drawqunlock(); } static XCursor xcursor; void setcursor(void) { XCursor xc; XColor fg, bg; Pixmap xsrc, xmask; int i; uchar src[2*16], mask[2*16]; for(i=0; i<2*16; i++){ src[i] = revbyte(cursor.set[i]); mask[i] = revbyte(cursor.set[i] | cursor.clr[i]); } drawqlock(); fg = map[0]; bg = map[255]; xsrc = XCreateBitmapFromData(xdisplay, xdrawable, (char*)src, 16, 16); xmask = XCreateBitmapFromData(xdisplay, xdrawable, (char*)mask, 16, 16); xc = XCreatePixmapCursor(xdisplay, xsrc, xmask, &fg, &bg, -cursor.offset.x, -cursor.offset.y); if(xc != 0) { XDefineCursor(xdisplay, xdrawable, xc); if(xcursor != 0) XFreeCursor(xdisplay, xcursor); xcursor = xc; } XFreePixmap(xdisplay, xsrc); XFreePixmap(xdisplay, xmask); XFlush(xdisplay); drawqunlock(); } void cursorarrow(void) { drawqlock(); if(xcursor != 0){ XFreeCursor(xdisplay, xcursor); xcursor = 0; } XUndefineCursor(xdisplay, xdrawable); XFlush(xdisplay); drawqunlock(); } static void xproc(void *arg) { ulong mask; XEvent event; mask = KeyPressMask| ButtonPressMask| ButtonReleaseMask| PointerMotionMask| Button1MotionMask| Button2MotionMask| Button3MotionMask| Button4MotionMask| Button5MotionMask| ExposureMask| StructureNotifyMask; XSelectInput(xkmcon, xdrawable, mask); for(;;) { //XWindowEvent(xkmcon, xdrawable, mask, &event); XNextEvent(xkmcon, &event); xselect(&event, xkmcon); xkeyboard(&event); xmouse(&event); xexpose(&event); xmapping(&event); xdestroy(&event); } } static int shutup(XDisplay *d, XErrorEvent *e) { char buf[200]; iprint("X error: error code=%d, request_code=%d, minor=%d\n", e->error_code, e->request_code, e->minor_code); XGetErrorText(d, e->error_code, buf, sizeof(buf)); iprint("%s\n", buf); USED(d); USED(e); return 0; } static int panicshutup(XDisplay *d) { panic("x error"); return -1; } static Memimage* xinitscreen(void) { Memimage *gscreen; int i, xsize, ysize, pmid; char *argv[2]; char *disp_val; Window rootwin; Rectangle r; XWMHints hints; XScreen *screen; XVisualInfo xvi; int rootscreennum; XTextProperty name; XClassHint classhints; XSizeHints normalhints; XSetWindowAttributes attrs; XPixmapFormatValues *pfmt; int n; Pixmap icon_pixmap; xscreenid = 0; xdrawable = 0; xdisplay = XOpenDisplay(NULL); if(xdisplay == 0){ iprint("xinitscreen: XOpenDisplay: %r [DISPLAY=%s]\n", getenv("DISPLAY")); exit(0); } XSetErrorHandler(shutup); XSetIOErrorHandler(panicshutup); rootscreennum = DefaultScreen(xdisplay); rootwin = DefaultRootWindow(xdisplay); xscreendepth = DefaultDepth(xdisplay, rootscreennum); if(XMatchVisualInfo(xdisplay, rootscreennum, 16, TrueColor, &xvi) || XMatchVisualInfo(xdisplay, rootscreennum, 16, DirectColor, &xvi)){ xvis = xvi.visual; xscreendepth = 16; xtblbit = 1; } else if(XMatchVisualInfo(xdisplay, rootscreennum, 24, TrueColor, &xvi) || XMatchVisualInfo(xdisplay, rootscreennum, 24, DirectColor, &xvi)){ xvis = xvi.visual; xscreendepth = 24; xtblbit = 1; } else if(XMatchVisualInfo(xdisplay, rootscreennum, 8, PseudoColor, &xvi) || XMatchVisualInfo(xdisplay, rootscreennum, 8, StaticColor, &xvi)){ if(xscreendepth > 8) panic("drawterm: can't deal with colormapped depth %d screens\n", xscreendepth); xvis = xvi.visual; xscreendepth = 8; } else{ if(xscreendepth != 8) panic("drawterm: can't deal with depth %d screens\n", xscreendepth); xvis = DefaultVisual(xdisplay, rootscreennum); } /* * xscreendepth is only the number of significant pixel bits, * not the total. We need to walk the display list to find * how many actual bits are being used per pixel. */ xscreenchan = 0; /* not a valid channel */ pfmt = XListPixmapFormats(xdisplay, &n); for(i=0; iclass != StaticColor){ graphicscmap(map); initmap(rootwin); } r.min = ZP; r.max.x = WidthOfScreen(screen); r.max.y = HeightOfScreen(screen); xsize = Dx(r)*3/4; ysize = Dy(r)*3/4; attrs.colormap = xcmap; attrs.background_pixel = 0; attrs.border_pixel = 0; /* attrs.override_redirect = 1;*/ /* WM leave me alone! |CWOverrideRedirect */ xdrawable = XCreateWindow(xdisplay, rootwin, 0, 0, xsize, ysize, 0, xscreendepth, InputOutput, xvis, CWBackPixel|CWBorderPixel|CWColormap, &attrs); /* load the given bitmap data and create an X pixmap containing it. */ icon_pixmap = XCreateBitmapFromData(xdisplay, rootwin, (char *)glenda_bits, glenda_width, glenda_height); /* * set up property as required by ICCCM */ name.value = (uchar*)"drawterm"; name.encoding = XA_STRING; name.format = 8; name.nitems = strlen((char*)name.value); normalhints.flags = USSize|PMaxSize; normalhints.max_width = Dx(r); normalhints.max_height = Dy(r); normalhints.width = xsize; normalhints.height = ysize; hints.flags = IconPixmapHint |InputHint|StateHint; hints.input = 1; hints.initial_state = NormalState; hints.icon_pixmap = icon_pixmap; classhints.res_name = "drawterm"; classhints.res_class = "Drawterm"; argv[0] = "drawterm"; argv[1] = nil; XSetWMProperties(xdisplay, xdrawable, &name, /* XA_WM_NAME property for ICCCM */ &name, /* XA_WM_ICON_NAME */ argv, /* XA_WM_COMMAND */ 1, /* argc */ &normalhints, /* XA_WM_NORMAL_HINTS */ &hints, /* XA_WM_HINTS */ &classhints); /* XA_WM_CLASS */ XFlush(xdisplay); /* * put the window on the screen */ XMapWindow(xdisplay, xdrawable); XFlush(xdisplay); xscreenid = XCreatePixmap(xdisplay, xdrawable, Dx(r), Dy(r), xscreendepth); gscreen = xallocmemimage(r, xscreenchan, xscreenid); xgcfill = creategc(xscreenid); XSetFillStyle(xdisplay, xgcfill, FillSolid); xgccopy = creategc(xscreenid); xgcsimplesrc = creategc(xscreenid); XSetFillStyle(xdisplay, xgcsimplesrc, FillStippled); xgczero = creategc(xscreenid); xgcreplsrc = creategc(xscreenid); XSetFillStyle(xdisplay, xgcreplsrc, FillTiled); pmid = XCreatePixmap(xdisplay, xdrawable, 1, 1, 1); xgcfill0 = creategc(pmid); XSetForeground(xdisplay, xgcfill0, 0); XSetFillStyle(xdisplay, xgcfill0, FillSolid); xgccopy0 = creategc(pmid); xgcsimplesrc0 = creategc(pmid); XSetFillStyle(xdisplay, xgcsimplesrc0, FillStippled); xgczero0 = creategc(pmid); xgcreplsrc0 = creategc(pmid); XSetFillStyle(xdisplay, xgcreplsrc0, FillTiled); XFreePixmap(xdisplay, pmid); XSetForeground(xdisplay, xgccopy, plan9tox11[0]); XFillRectangle(xdisplay, xscreenid, xgccopy, 0, 0, xsize, ysize); xkmcon = XOpenDisplay(NULL); if(xkmcon == 0){ disp_val = getenv("DISPLAY"); if(disp_val == 0) disp_val = "not set"; iprint("drawterm: open %r, DISPLAY is %s\n", disp_val); exit(0); } xsnarfcon = XOpenDisplay(NULL); if(xsnarfcon == 0){ disp_val = getenv("DISPLAY"); if(disp_val == 0) disp_val = "not set"; iprint("drawterm: open %r, DISPLAY is %s\n", disp_val); exit(0); } clipboard = XInternAtom(xkmcon, "CLIPBOARD", False); utf8string = XInternAtom(xkmcon, "UTF8_STRING", False); targets = XInternAtom(xkmcon, "TARGETS", False); text = XInternAtom(xkmcon, "TEXT", False); compoundtext = XInternAtom(xkmcon, "COMPOUND_TEXT", False); xblack = screen->black_pixel; xwhite = screen->white_pixel; return gscreen; } static void graphicscmap(XColor *map) { int r, g, b, cr, cg, cb, v, num, den, idx, v7, idx7; for(r=0; r!=4; r++) { for(g = 0; g != 4; g++) { for(b = 0; b!=4; b++) { for(v = 0; v!=4; v++) { den=r; if(g > den) den=g; if(b > den) den=b; /* divide check -- pick grey shades */ if(den==0) cr=cg=cb=v*17; else { num=17*(4*den+v); cr=r*num/den; cg=g*num/den; cb=b*num/den; } idx = r*64 + v*16 + ((g*4 + b + v - r) & 15); map[idx].red = cr*0x0101; map[idx].green = cg*0x0101; map[idx].blue = cb*0x0101; map[idx].pixel = idx; map[idx].flags = DoRed|DoGreen|DoBlue; v7 = v >> 1; idx7 = r*32 + v7*16 + g*4 + b; if((v & 1) == v7){ map7to8[idx7][0] = idx; if(den == 0) { /* divide check -- pick grey shades */ cr = ((255.0/7.0)*v7)+0.5; cg = cr; cb = cr; } else { num=17*15*(4*den+v7*2)/14; cr=r*num/den; cg=g*num/den; cb=b*num/den; } map7[idx7].red = cr*0x0101; map7[idx7].green = cg*0x0101; map7[idx7].blue = cb*0x0101; map7[idx7].pixel = idx7; map7[idx7].flags = DoRed|DoGreen|DoBlue; } else map7to8[idx7][1] = idx; } } } } } /* * Initialize and install the drawterm colormap as a private colormap for this * application. Drawterm gets the best colors here when it has the cursor focus. */ static void initmap(Window w) { XColor c; int i; ulong p, pp; char buf[30]; if(xscreendepth <= 1) return; if(xscreendepth >= 24) { /* The pixel value returned from XGetPixel needs to * be converted to RGB so we can call rgb2cmap() * to translate between 24 bit X and our color. Unfortunately, * the return value appears to be display server endian * dependant. Therefore, we run some heuristics to later * determine how to mask the int value correctly. * Yeah, I know we can look at xvis->byte_order but * some displays say MSB even though they run on LSB. * Besides, this is more anal. */ if(xscreendepth != DefaultDepth(xdisplay, DefaultScreen(xdisplay))) xcmap = XCreateColormap(xdisplay, w, xvis, AllocNone); c = map[19]; /* find out index into colormap for our RGB */ if(!XAllocColor(xdisplay, xcmap, &c)) panic("drawterm: screen-x11 can't alloc color"); p = c.pixel; pp = rgb2cmap((p>>16)&0xff,(p>>8)&0xff,p&0xff); if(pp!=map[19].pixel) { /* check if endian is other way */ pp = rgb2cmap(p&0xff,(p>>8)&0xff,(p>>16)&0xff); if(pp!=map[19].pixel) panic("cannot detect x server byte order"); switch(xscreenchan){ case RGB24: xscreenchan = BGR24; break; case XRGB32: xscreenchan = XBGR32; break; default: panic("don't know how to byteswap channel %s", chantostr(buf, xscreenchan)); break; } } } else if(xvis->class == TrueColor || xvis->class == DirectColor) { } else if(xvis->class == PseudoColor) { if(xtblbit == 0){ xcmap = XCreateColormap(xdisplay, w, xvis, AllocAll); XStoreColors(xdisplay, xcmap, map, 256); for(i = 0; i < 256; i++) { plan9tox11[i] = i; x11toplan9[i] = i; } } else { for(i = 0; i < 128; i++) { c = map7[i]; if(!XAllocColor(xdisplay, xcmap, &c)) { iprint("drawterm: can't alloc colors in default map, don't use -7\n"); exit(0); } plan9tox11[map7to8[i][0]] = c.pixel; plan9tox11[map7to8[i][1]] = c.pixel; x11toplan9[c.pixel] = map7to8[i][0]; } } } else panic("drawterm: unsupported visual class %d\n", xvis->class); } static void xdestroy(XEvent *e) { XDestroyWindowEvent *xe; if(e->type != DestroyNotify) return; xe = (XDestroyWindowEvent*)e; if(xe->window == xdrawable) exit(0); } static void xmapping(XEvent *e) { XMappingEvent *xe; if(e->type != MappingNotify) return; xe = (XMappingEvent*)e; USED(xe); } /* * Disable generation of GraphicsExpose/NoExpose events in the GC. */ static GC creategc(Drawable d) { XGCValues gcv; gcv.function = GXcopy; gcv.graphics_exposures = False; return XCreateGC(xdisplay, d, GCFunction|GCGraphicsExposures, &gcv); } static void xexpose(XEvent *e) { Rectangle r; XExposeEvent *xe; if(e->type != Expose) return; xe = (XExposeEvent*)e; r.min.x = xe->x; r.min.y = xe->y; r.max.x = xe->x + xe->width; r.max.y = xe->y + xe->height; drawflushr(r); } static void xkeyboard(XEvent *e) { KeySym k; /* * I tried using XtGetActionKeysym, but it didn't seem to * do case conversion properly * (at least, with Xterminal servers and R4 intrinsics) */ if(e->xany.type != KeyPress) return; XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL); if(k == XK_Multi_key || k == NoSymbol) return; if(k&0xFF00){ switch(k){ case XK_BackSpace: case XK_Tab: case XK_Escape: case XK_Delete: case XK_KP_0: case XK_KP_1: case XK_KP_2: case XK_KP_3: case XK_KP_4: case XK_KP_5: case XK_KP_6: case XK_KP_7: case XK_KP_8: case XK_KP_9: case XK_KP_Divide: case XK_KP_Multiply: case XK_KP_Subtract: case XK_KP_Add: case XK_KP_Decimal: k &= 0x7F; break; case XK_Linefeed: k = '\r'; break; case XK_KP_Space: k = ' '; break; case XK_Home: case XK_KP_Home: k = Khome; break; case XK_Left: case XK_KP_Left: k = Kleft; break; case XK_Up: case XK_KP_Up: k = Kup; break; case XK_Down: case XK_KP_Down: k = Kdown; break; case XK_Right: case XK_KP_Right: k = Kright; break; case XK_Page_Down: case XK_KP_Page_Down: k = Kpgdown; break; case XK_End: case XK_KP_End: k = Kend; break; case XK_Page_Up: case XK_KP_Page_Up: k = Kpgup; break; case XK_Insert: case XK_KP_Insert: k = Kins; break; case XK_KP_Enter: case XK_Return: k = '\n'; break; case XK_Alt_L: case XK_Alt_R: k = Kalt; break; case XK_F1: case XK_F2: case XK_F3: case XK_F4: case XK_F5: case XK_F6: case XK_F7: case XK_F8: case XK_F9: case XK_F10: case XK_F11: case XK_F12: k = KF|(k - XK_F1 + 1); break; case XK_Shift_L: case XK_Shift_R: case XK_Control_L: case XK_Control_R: case XK_Caps_Lock: case XK_Shift_Lock: case XK_Meta_L: case XK_Meta_R: case XK_Super_L: case XK_Super_R: case XK_Hyper_L: case XK_Hyper_R: return; default: /* not ISO-1 or tty control */ if(k>0xff){ k = keysym2ucs(k); /* supplied by X */ if(k == -1) return; } break; } } /* Compensate for servers that call a minus a hyphen */ if(k == XK_hyphen) k = XK_minus; /* Do control mapping ourselves if translator doesn't */ if(e->xkey.state&ControlMask && k != Kalt) k &= 0x9f; if(k == NoSymbol) { return; } kbdputc(kbdq, k); } static void xmouse(XEvent *e) { Mousestate ms; int i, s; XButtonEvent *be; XMotionEvent *me; if(putsnarf != assertsnarf){ assertsnarf = putsnarf; XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime); if(clipboard != None) XSetSelectionOwner(xkmcon, clipboard, xdrawable, CurrentTime); XFlush(xkmcon); } switch(e->type){ case ButtonPress: be = (XButtonEvent *)e; /* * Fake message, just sent to make us announce snarf. * Apparently state and button are 16 and 8 bits on * the wire, since they are truncated by the time they * get to us. */ if(be->send_event && (~be->state&0xFFFF)==0 && (~be->button&0xFF)==0) return; ms.xy.x = be->x; ms.xy.y = be->y; s = be->state; ms.msec = be->time; switch(be->button){ case 1: s |= Button1Mask; break; case 2: s |= Button2Mask; break; case 3: s |= Button3Mask; break; case 4: s |= Button4Mask; break; case 5: s |= Button5Mask; break; } break; case ButtonRelease: be = (XButtonEvent *)e; ms.xy.x = be->x; ms.xy.y = be->y; ms.msec = be->time; s = be->state; switch(be->button){ case 1: s &= ~Button1Mask; break; case 2: s &= ~Button2Mask; break; case 3: s &= ~Button3Mask; break; case 4: s &= ~Button4Mask; break; case 5: s &= ~Button5Mask; break; } break; case MotionNotify: me = (XMotionEvent *)e; s = me->state; ms.xy.x = me->x; ms.xy.y = me->y; ms.msec = me->time; break; default: return; } ms.buttons = 0; if(s & Button1Mask) ms.buttons |= 1; if(s & Button2Mask) ms.buttons |= 2; if(s & Button3Mask) ms.buttons |= 4; if(s & Button4Mask) ms.buttons |= 8; if(s & Button5Mask) ms.buttons |= 16; lock(&mouse.lk); i = mouse.wi; if(mousequeue) { if(i == mouse.ri || mouse.lastb != ms.buttons || mouse.trans) { mouse.wi = (i+1)%Mousequeue; if(mouse.wi == mouse.ri) mouse.ri = (mouse.ri+1)%Mousequeue; mouse.trans = mouse.lastb != ms.buttons; } else { i = (i-1+Mousequeue)%Mousequeue; } } else { mouse.wi = (i+1)%Mousequeue; mouse.ri = i; } mouse.queue[i] = ms; mouse.lastb = ms.buttons; unlock(&mouse.lk); wakeup(&mouse.r); } void getcolor(ulong i, ulong *r, ulong *g, ulong *b) { ulong v; v = cmap2rgb(i); *r = (v>>16)&0xFF; *g = (v>>8)&0xFF; *b = v&0xFF; } void setcolor(ulong i, ulong r, ulong g, ulong b) { /* no-op */ } int atlocalconsole(void) { char *p, *q; char buf[128]; p = getenv("DRAWTERM_ATLOCALCONSOLE"); if(p && atoi(p) == 1) return 1; p = getenv("DISPLAY"); if(p == nil) return 0; /* extract host part */ q = strchr(p, ':'); if(q == nil) return 0; *q = 0; if(strcmp(p, "") == 0) return 1; /* try to match against system name (i.e. for ssh) */ if(gethostname(buf, sizeof buf) == 0){ if(strcmp(p, buf) == 0) return 1; if(strncmp(p, buf, strlen(p)) == 0 && buf[strlen(p)]=='.') return 1; } return 0; } /* * Cut and paste. Just couldn't stand to make this simple... */ typedef struct Clip Clip; struct Clip { char buf[SnarfSize]; QLock lk; }; Clip clip; #undef long /* sic */ #undef ulong static char* _xgetsnarf(XDisplay *xd) { uchar *data, *xdata; Atom clipboard, type, prop; unsigned long lastlen; unsigned long dummy, len; int fmt, i; Window w; qlock(&clip.lk); /* * Have we snarfed recently and the X server hasn't caught up? */ if(putsnarf != assertsnarf) goto mine; /* * Is there a primary selection (highlighted text in an xterm)? */ clipboard = XA_PRIMARY; w = XGetSelectionOwner(xd, XA_PRIMARY); if(w == xdrawable){ mine: data = (uchar*)strdup(clip.buf); goto out; } /* * If not, is there a clipboard selection? */ if(w == None && clipboard != None){ clipboard = clipboard; w = XGetSelectionOwner(xd, clipboard); if(w == xdrawable) goto mine; } /* * If not, give up. */ if(w == None){ data = nil; goto out; } /* * We should be waiting for SelectionNotify here, but it might never * come, and we have no way to time out. Instead, we will clear * local property #1, request our buddy to fill it in for us, and poll * until he's done or we get tired of waiting. * * We should try to go for utf8string instead of XA_STRING, * but that would add to the polling. */ prop = 1; XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime); XFlush(xd); lastlen = 0; for(i=0; i<10 || (lastlen!=0 && i<30); i++){ usleep(100*1000); XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType, &type, &fmt, &dummy, &len, &data); if(lastlen == len && len > 0) break; lastlen = len; } if(i == 10){ data = nil; goto out; } /* get the property */ data = nil; XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(unsigned long), 0, AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); if((type != XA_STRING && type != utf8string) || len == 0){ if(xdata) XFree(xdata); data = nil; }else{ if(xdata){ data = (uchar*)strdup((char*)xdata); XFree(xdata); }else data = nil; } out: qunlock(&clip.lk); return (char*)data; } static void _xputsnarf(XDisplay *xd, char *data) { XButtonEvent e; if(strlen(data) >= SnarfSize) return; qlock(&clip.lk); strcpy(clip.buf, data); /* leave note for mouse proc to assert selection ownership */ putsnarf++; /* send mouse a fake event so snarf is announced */ memset(&e, 0, sizeof e); e.type = ButtonPress; e.window = xdrawable; e.state = ~0; e.button = ~0; XSendEvent(xd, xdrawable, True, ButtonPressMask, (XEvent*)&e); XFlush(xd); qunlock(&clip.lk); } static void xselect(XEvent *e, XDisplay *xd) { char *name; XEvent r; XSelectionRequestEvent *xe; Atom a[4]; if(e->xany.type != SelectionRequest) return; memset(&r, 0, sizeof r); xe = (XSelectionRequestEvent*)e; if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n", xe->target, xe->requestor, xe->property, xe->selection); r.xselection.property = xe->property; if(xe->target == targets){ a[0] = XA_STRING; a[1] = utf8string; a[2] = text; a[3] = compoundtext; XChangeProperty(xd, xe->requestor, xe->property, xe->target, 8, PropModeReplace, (uchar*)a, sizeof a); }else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){ text: /* if the target is STRING we're supposed to reply with Latin1 XXX */ qlock(&clip.lk); XChangeProperty(xd, xe->requestor, xe->property, xe->target, 8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf)); qunlock(&clip.lk); }else{ name = XGetAtomName(xd, xe->target); if(name == nil) iprint("XGetAtomName %d failed\n", xe->target); if(name){ if(strcmp(name, "TIMESTAMP") == 0){ /* nothing */ }else if(strncmp(name, "image/", 6) == 0){ /* nothing */ }else if(strcmp(name, "text/html") == 0){ /* nothing */ }else if(strcmp(name, "text/plain") == 0 || strcmp(name, "text/plain;charset=UTF-8") == 0){ goto text; }else iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target); } r.xselection.property = None; } r.xselection.display = xe->display; /* r.xselection.property filled above */ r.xselection.target = xe->target; r.xselection.type = SelectionNotify; r.xselection.requestor = xe->requestor; r.xselection.time = xe->time; r.xselection.send_event = True; r.xselection.selection = xe->selection; XSendEvent(xd, xe->requestor, False, 0, &r); XFlush(xd); } char* clipread(void) { return _xgetsnarf(xsnarfcon); } int clipwrite(char *buf) { _xputsnarf(xsnarfcon, buf); return 0; } drawterm-20110822.orig/gui-x11/keysym2ucs.h0000644000175000017500000000036411245145711017557 0ustar tinchotincho/* $XFree86: xc/programs/xterm/keysym2ucs.h,v 1.1 1999/06/12 15:37:18 dawes Exp $ */ /* * This module converts keysym values into the corresponding ISO 10646-1 * (UCS, Unicode) values. */ #include long keysym2ucs(KeySym keysym); drawterm-20110822.orig/Make.pthread0000644000175000017500000000064511245145711016325 0ustar tinchotincho# Unix #PTHREAD= # for Mac PTHREAD=-pthread -DPTHREAD AR=ar AS=no-as-here RANLIB=ranlib X11=/usr/X11R6 CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm # AUDIO=none AUDIO=unix all: default libmachdep.a: (cd posix-port && make) drawterm-20110822.orig/cpu.c0000644000175000017500000003366311506541252015040 0ustar tinchotincho/* * cpu.c - Make a connection to a cpu server * * Invoked by listen as 'cpu -R | -N service net netdir' * by users as 'cpu [-h system] [-c cmd args ...]' */ #include #include #include #include #include #include #include "args.h" #include "drawterm.h" #define Maxfdata 8192 #define MaxStr 128 static void fatal(int, char*, ...); static void usage(void); static void writestr(int, char*, char*, int); static int readstr(int, char*, int); static char *rexcall(int*, char*, char*); static char *keyspec = ""; static AuthInfo *p9any(int); #define system csystem static char *system; static int cflag; extern int dbg; extern char* base; // fs base for devroot static char *srvname = "ncpu"; static char *ealgs = "rc4_256 sha1"; /* message size for exportfs; may be larger so we can do big graphics in CPU window */ static int msgsize = Maxfdata+IOHDRSZ; /* authentication mechanisms */ static int netkeyauth(int); static int netkeysrvauth(int, char*); static int p9auth(int); static int srvp9auth(int, char*); char *authserver; typedef struct AuthMethod AuthMethod; struct AuthMethod { char *name; /* name of method */ int (*cf)(int); /* client side authentication */ int (*sf)(int, char*); /* server side authentication */ } authmethod[] = { { "p9", p9auth, srvp9auth,}, { "netkey", netkeyauth, netkeysrvauth,}, // { "none", noauth, srvnoauth,}, { 0 } }; AuthMethod *am = authmethod; /* default is p9 */ char *p9authproto = "p9any"; int setam(char*); void exits(char *s) { print("\ngoodbye\n"); for(;;) osyield(); } void usage(void) { fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n"); exits("usage"); } int fdd; int mountfactotum(void) { int fd; if((fd = dialfactotum()) < 0) return -1; if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){ fprint(2, "mount factotum: %r\n"); return -1; } if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){ fprint(2, "open /mnt/factotum/ctl: %r\n"); return -1; } close(fd); return 0; } void cpumain(int argc, char **argv) { char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s; int fd, ms, data; /* see if we should use a larger message size */ fd = open("/dev/draw", OREAD); if(fd > 0){ ms = iounit(fd); if(msgsize < ms+IOHDRSZ) msgsize = ms+IOHDRSZ; close(fd); } user = getenv("USER"); secstoreserver = nil; authserver = getenv("auth"); if(authserver == nil) authserver = "auth"; system = getenv("cpu"); if(system == nil) system = "cpu"; ARGBEGIN{ case 'a': authserver = EARGF(usage()); break; case 'c': system = EARGF(usage()); break; case 'd': dbg++; break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'C': cflag++; cmd[0] = '!'; cmd[1] = '\0'; while((p = ARGF()) != nil) { strcat(cmd, " "); strcat(cmd, p); } break; case 'k': keyspec = EARGF(usage()); break; case 'r': base = EARGF(usage()); break; case 's': secstoreserver = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; default: usage(); }ARGEND; if(argc != 0) usage(); if(user == nil) user = readcons("user", nil, 0); if(mountfactotum() < 0){ if(secstoreserver == nil) secstoreserver = authserver; if(havesecstore(secstoreserver, user)){ s = secstorefetch(secstoreserver, user, nil); if(s){ if(strlen(s) >= sizeof secstorebuf) sysfatal("secstore data too big"); strcpy(secstorebuf, s); } } } if((err = rexcall(&data, system, srvname))) fatal(1, "%s: %s", err, system); /* Tell the remote side the command to execute and where our working directory is */ if(cflag) writestr(data, cmd, "command", 0); if(getcwd(dat, sizeof(dat)) == 0) writestr(data, "NO", "dir", 0); else writestr(data, dat, "dir", 0); /* * Wait for the other end to execute and start our file service * of /mnt/term */ if(readstr(data, buf, sizeof(buf)) < 0) fatal(1, "waiting for FS: %r"); if(strncmp("FS", buf, 2) != 0) { print("remote cpu: %s", buf); exits(buf); } if(readstr(data, buf, sizeof buf) < 0) fatal(1, "waiting for remote export: %r"); if(strcmp(buf, "/") != 0){ print("remote cpu: %s" , buf); exits(buf); } write(data, "OK", 2); /* Begin serving the gnot namespace */ exportfs(data, msgsize); fatal(1, "starting exportfs"); } void fatal(int syserr, char *fmt, ...) { Fmt f; char *str; va_list arg; fmtstrinit(&f); fmtprint(&f, "cpu: "); va_start(arg, fmt); fmtvprint(&f, fmt, arg); va_end(arg); if(syserr) fmtprint(&f, ": %r"); fmtprint(&f, "\n"); str = fmtstrflush(&f); write(2, str, strlen(str)); exits(str); } char *negstr = "negotiating authentication method"; char bug[256]; char* rexcall(int *fd, char *host, char *service) { char *na; char dir[MaxStr]; char err[ERRMAX]; char msg[MaxStr]; int n; na = netmkaddr(host, "tcp", "17010"); if((*fd = dial(na, 0, dir, 0)) < 0) return "can't dial"; /* negotiate authentication mechanism */ if(ealgs != nil) snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); else snprint(msg, sizeof(msg), "%s", am->name); writestr(*fd, msg, negstr, 0); n = readstr(*fd, err, sizeof err); if(n < 0) return negstr; if(*err){ werrstr(err); return negstr; } /* authenticate */ *fd = (*am->cf)(*fd); if(*fd < 0) return "can't authenticate"; return 0; } void writestr(int fd, char *str, char *thing, int ignore) { int l, n; l = strlen(str); n = write(fd, str, l+1); if(!ignore && n < 0) fatal(1, "writing network: %s", thing); } int readstr(int fd, char *str, int len) { int n; while(len) { n = read(fd, str, 1); if(n < 0) return -1; if(*str == '\0') return 0; str++; len--; } return -1; } static int readln(char *buf, int n) { int i; char *p; n--; /* room for \0 */ p = buf; for(i=0; isecret, ai->nsecret); if(ealgs == nil) return fd; /* exchange random numbers */ for(i = 0; i < 4; i++) key[i] = fastrand(); if(write(fd, key, 4) != 4) return -1; if(readn(fd, key+12, 4) != 4) return -1; /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); /* set up encryption */ i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); if(i < 0) werrstr("can't establish ssl connection: %r"); return i; } int authdial(char *net, char *dom) { int fd; fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0); //print("authdial %d\n", fd); return fd; } static int getastickets(Ticketreq *tr, char *trbuf, char *tbuf) { int asfd, rv; char *dom; dom = tr->authdom; asfd = authdial(nil, dom); if(asfd < 0) return -1; rv = _asgetticket(asfd, trbuf, tbuf); close(asfd); return rv; } static int mkserverticket(Ticketreq *tr, char *authkey, char *tbuf) { int i; Ticket t; if(strcmp(tr->authid, tr->hostid) != 0) return -1; memset(&t, 0, sizeof(t)); memmove(t.chal, tr->chal, CHALLEN); strcpy(t.cuid, tr->uid); strcpy(t.suid, tr->uid); for(i=0; i= 0) return 0; return mkserverticket(tr, key, tbuf); } /* * prompt user for a key. don't care about memory leaks, runs standalone */ static Attr* promptforkey(char *params) { char *v; int fd; Attr *a, *attr; char *def; fd = open("/dev/cons", ORDWR); if(fd < 0) sysfatal("opening /dev/cons: %r"); attr = _parseattr(params); fprint(fd, "\n!Adding key:"); for(a=attr; a; a=a->next) if(a->type != AttrQuery && a->name[0] != '!') fprint(fd, " %q=%q", a->name, a->val); fprint(fd, "\n"); for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]=='!') continue; def = nil; if(strcmp(v, "user") == 0) def = getuser(); a->val = readcons(v, def, 0); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]!='!') continue; def = nil; if(strcmp(v+1, "user") == 0) def = getuser(); a->val = readcons(v+1, def, 1); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } fprint(fd, "!\n"); close(fd); return attr; } /* * send a key to the mounted factotum */ static int sendkey(Attr *attr) { int fd, rv; char buf[1024]; fd = open("/mnt/factotum/ctl", ORDWR); if(fd < 0) sysfatal("opening /mnt/factotum/ctl: %r"); rv = fprint(fd, "key %A\n", attr); read(fd, buf, sizeof buf); close(fd); return rv; } int askuser(char *params) { Attr *attr; fmtinstall('A', _attrfmt); attr = promptforkey(params); if(attr == nil) sysfatal("no key supplied"); if(sendkey(attr) < 0) sysfatal("sending key to factotum: %r"); return 0; } AuthInfo* p9anyfactotum(int fd, int afd) { return auth_proxy(fd, askuser, "proto=p9any role=client %s", keyspec); } AuthInfo* p9any(int fd) { char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u; char *pass; char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN]; char authkey[DESKEYLEN]; Authenticator auth; int afd, i, n, v2; Ticketreq tr; Ticket t; AuthInfo *ai; if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) return p9anyfactotum(fd, afd); werrstr(""); if(readstr(fd, buf, sizeof buf) < 0) fatal(1, "cannot read p9any negotiation"); bbuf = buf; v2 = 0; if(strncmp(buf, "v.2 ", 4) == 0){ v2 = 1; bbuf += 4; } if((p = strchr(bbuf, ' '))) *p = 0; p = bbuf; if((dom = strchr(p, '@')) == nil) fatal(1, "bad p9any domain"); *dom++ = 0; if(strcmp(p, "p9sk1") != 0) fatal(1, "server did not offer p9sk1"); sprint(buf2, "%s %s", p, dom); if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1) fatal(1, "cannot write user/domain choice in p9any"); if(v2){ if(readstr(fd, buf, sizeof buf) < 0) fatal(1, "cannot read OK in p9any: got %d %s", n, buf); if(memcmp(buf, "OK\0", 3) != 0) fatal(1, "did not get OK in p9any"); } for(i=0; i 0) n += i; buf[n] = 0; werrstr(""); fatal(0, "server says: %s", buf); } convM2A(tbuf, &auth, t.key); if(auth.num != AuthAs || memcmp(auth.chal, cchal, CHALLEN) != 0 || auth.id != 0){ print("?you and auth server agree about password.\n"); print("?server is confused.\n"); fatal(0, "server lies got %llux.%d want %llux.%d", *(vlong*)auth.chal, auth.id, *(vlong*)cchal, 0); } //print("i am %s there.\n", t.suid); ai = mallocz(sizeof(AuthInfo), 1); ai->secret = mallocz(8, 1); des56to64((uchar*)t.key, ai->secret); ai->nsecret = 8; ai->suid = strdup(t.suid); ai->cuid = strdup(t.cuid); memset(authkey, 0, sizeof authkey); return ai; } /* static int noauth(int fd) { ealgs = nil; return fd; } static int srvnoauth(int fd, char *user) { strecpy(user, user+MaxStr, getuser()); ealgs = nil; return fd; } */ void loghex(uchar *p, int n) { char buf[100]; int i; for(i = 0; i < n; i++) sprint(buf+2*i, "%2.2ux", p[i]); // syslog(0, "cpu", buf); } static int srvp9auth(int fd, char *user) { return -1; } /* * set authentication mechanism */ int setam(char *name) { for(am = authmethod; am->name != nil; am++) if(strcmp(am->name, name) == 0) return 0; am = authmethod; return -1; } /* * set authentication mechanism and encryption/hash algs * int setamalg(char *s) { ealgs = strchr(s, ' '); if(ealgs != nil) *ealgs++ = 0; return setam(s); } */ drawterm-20110822.orig/posix-factotum.c0000644000175000017500000000353011245145712017222 0ustar tinchotincho#include #include #include #include #include #include #include #include #include #include #include "drawterm.h" #undef socket #undef connect #undef getenv #undef access char* getuser(void) { static char user[64]; struct passwd *pw; pw = getpwuid(getuid()); if(pw == nil) return "none"; strecpy(user, user+sizeof user, pw->pw_name); return user; } /* * Absent other hints, it works reasonably well to use * the X11 display name as the name space identifier. * This is how sam's B has worked since the early days. * Since most programs using name spaces are also using X, * this still seems reasonable. Terminal-only sessions * can set $NAMESPACE. */ static char* nsfromdisplay(void) { char *disp, *p; if((disp = getenv("DISPLAY")) == nil){ werrstr("$DISPLAY not set"); return nil; } /* canonicalize: xxx:0.0 => xxx:0 */ p = strrchr(disp, ':'); if(p){ p++; while(isdigit((uchar)*p)) p++; if(strcmp(p, ".0") == 0) *p = 0; } return smprint("/tmp/ns.%s.%s", getuser(), disp); } char* getns(void) { char *ns; ns = getenv("NAMESPACE"); if(ns == nil) ns = nsfromdisplay(); if(ns == nil){ werrstr("$NAMESPACE not set, %r"); return nil; } return ns; } int dialfactotum(void) { int fd; struct sockaddr_un su; char *name; name = smprint("%s/factotum", getns()); if(name == nil || access(name, 0) < 0) return -1; memset(&su, 0, sizeof su); su.sun_family = AF_UNIX; if(strlen(name)+1 > sizeof su.sun_path){ werrstr("socket name too long"); return -1; } strcpy(su.sun_path, name); if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){ werrstr("socket: %r"); return -1; } if(connect(fd, (struct sockaddr*)&su, sizeof su) < 0){ werrstr("connect %s: %r", name); close(fd); return -1; } return lfdfd(fd); } drawterm-20110822.orig/Make.config0000644000175000017500000000005011245145711016131 0ustar tinchotinchoAUDIO=none include $(ROOT)/Make.$(CONF) drawterm-20110822.orig/kern/0000755000175000017500000000000011510255052015024 5ustar tinchotinchodrawterm-20110822.orig/kern/allocb.c0000644000175000017500000000615011245145711016433 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" enum { Hdrspc = 64, /* leave room for high-level headers */ Bdead = 0x51494F42, /* "QIOB" */ }; struct { Lock lk; ulong bytes; } ialloc; static Block* _allocb(int size) { Block *b; uintptr addr; if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil) return nil; b->next = nil; b->list = nil; b->free = 0; b->flag = 0; /* align start of data portion by rounding up */ addr = (uintptr)b; addr = ROUND(addr + sizeof(Block), BLOCKALIGN); b->base = (uchar*)addr; /* align end of data portion by rounding down */ b->lim = ((uchar*)b) + sizeof(Block)+size+Hdrspc; addr = (uintptr)(b->lim); addr = addr & ~(BLOCKALIGN-1); b->lim = (uchar*)addr; /* leave sluff at beginning for added headers */ b->rp = b->lim - ROUND(size, BLOCKALIGN); if(b->rp < b->base) panic("_allocb"); b->wp = b->rp; return b; } Block* allocb(int size) { Block *b; /* * Check in a process and wait until successful. * Can still error out of here, though. */ if(up == nil) panic("allocb without up: %p\n", getcallerpc(&size)); if((b = _allocb(size)) == nil){ panic("allocb: no memory for %d bytes\n", size); } setmalloctag(b, getcallerpc(&size)); return b; } Block* iallocb(int size) { Block *b; static int m1, m2; if(ialloc.bytes > conf.ialloc){ if((m1++%10000)==0) print("iallocb: limited %lud/%lud\n", ialloc.bytes, conf.ialloc); return 0; } if((b = _allocb(size)) == nil){ if((m2++%10000)==0) print("iallocb: no memory %lud/%lud\n", ialloc.bytes, conf.ialloc); return nil; } setmalloctag(b, getcallerpc(&size)); b->flag = BINTR; ilock(&ialloc.lk); ialloc.bytes += b->lim - b->base; iunlock(&ialloc.lk); return b; } void freeb(Block *b) { void *dead = (void*)Bdead; if(b == nil) return; /* * drivers which perform non cache coherent DMA manage their own buffer * pool of uncached buffers and provide their own free routine. */ if(b->free) { b->free(b); return; } if(b->flag & BINTR) { ilock(&ialloc.lk); ialloc.bytes -= b->lim - b->base; iunlock(&ialloc.lk); } /* poison the block in case someone is still holding onto it */ b->next = dead; b->rp = dead; b->wp = dead; b->lim = dead; b->base = dead; free(b); } void checkb(Block *b, char *msg) { void *dead = (void*)Bdead; if(b == dead) panic("checkb b %s %lux", msg, b); if(b->base == dead || b->lim == dead || b->next == dead || b->rp == dead || b->wp == dead){ print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n", b->base, b->lim, b->next); print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp); panic("checkb dead: %s\n", msg); } if(b->base > b->lim) panic("checkb 0 %s %lux %lux", msg, b->base, b->lim); if(b->rp < b->base) panic("checkb 1 %s %lux %lux", msg, b->base, b->rp); if(b->wp < b->base) panic("checkb 2 %s %lux %lux", msg, b->base, b->wp); if(b->rp > b->lim) panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim); if(b->wp > b->lim) panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim); } void iallocsummary(void) { print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc); } drawterm-20110822.orig/kern/dev.c0000644000175000017500000002051311245145711015754 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" extern ulong kerndate; void mkqid(Qid *q, vlong path, ulong vers, int type) { q->type = type; q->vers = vers; q->path = path; } int devno(int c, int user) { int i; for(i = 0; devtab[i] != nil; i++) { if(devtab[i]->dc == c) return i; } if(user == 0) panic("devno %C 0x%ux", c, c); return -1; } void devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db) { db->name = n; if(c->flag&CMSG) qid.type |= QTMOUNT; db->qid = qid; db->type = devtab[c->type]->dc; db->dev = c->dev; db->mode = perm; db->mode |= qid.type << 24; db->atime = seconds(); db->mtime = kerndate; db->length = length; db->uid = user; db->gid = eve; db->muid = user; } /* * (here, Devgen is the prototype; devgen is the function in dev.c.) * * a Devgen is expected to return the directory entry for ".." * if you pass it s==DEVDOTDOT (-1). otherwise... * * there are two contradictory rules. * * (i) if c is a directory, a Devgen is expected to list its children * as you iterate s. * * (ii) whether or not c is a directory, a Devgen is expected to list * its siblings as you iterate s. * * devgen always returns the list of children in the root * directory. thus it follows (i) when c is the root and (ii) otherwise. * many other Devgens follow (i) when c is a directory and (ii) otherwise. * * devwalk assumes (i). it knows that devgen breaks (i) * for children that are themselves directories, and explicitly catches them. * * devstat assumes (ii). if the Devgen in question follows (i) * for this particular c, devstat will not find the necessary info. * with our particular Devgen functions, this happens only for * directories, so devstat makes something up, assuming * c->name, c->qid, eve, DMDIR|0555. * * devdirread assumes (i). the callers have to make sure * that the Devgen satisfies (i) for the chan being read. */ /* * the zeroth element of the table MUST be the directory itself for .. */ int devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) { if(tab == 0) return -1; if(i == DEVDOTDOT){ /* nothing */ }else if(name){ for(i=1; i= ntab) return -1; tab += i; } devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp); return 1; } void devreset(void) { } void devinit(void) { } void devshutdown(void) { } Chan* devattach(int tc, char *spec) { Chan *c; char *buf; c = newchan(); mkqid(&c->qid, 0, 0, QTDIR); c->type = devno(tc, 0); if(spec == nil) spec = ""; buf = smalloc(4+strlen(spec)+1); sprint(buf, "#%C%s", tc, spec); c->name = newcname(buf); free(buf); return c; } Chan* devclone(Chan *c) { Chan *nc; if(c->flag & COPEN) panic("clone of open file type %C\n", devtab[c->type]->dc); nc = newchan(); nc->type = c->type; nc->dev = c->dev; nc->mode = c->mode; nc->qid = c->qid; nc->offset = c->offset; nc->umh = nil; nc->mountid = c->mountid; nc->aux = c->aux; nc->pgrpid = c->pgrpid; nc->mid = c->mid; nc->mqid = c->mqid; nc->mcp = c->mcp; return nc; } Walkqid* devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen) { int i, j, alloc; Walkqid *wq; char *n; Dir dir; if(nname > 0) isdir(c); alloc = 0; wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); if(waserror()){ if(alloc && wq->clone!=nil) cclose(wq->clone); free(wq); return nil; } if(nc == nil){ nc = devclone(c); nc->type = 0; /* device doesn't know about this channel yet */ alloc = 1; } wq->clone = nc; for(j=0; jqid.type&QTDIR)){ if(j==0) error(Enotdir); goto Done; } n = name[j]; if(strcmp(n, ".") == 0){ Accept: wq->qid[wq->nqid++] = nc->qid; continue; } if(strcmp(n, "..") == 0){ if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){ print("devgen walk .. in dev%s %llux broken\n", devtab[nc->type]->name, nc->qid.path); error("broken devgen"); } nc->qid = dir.qid; goto Accept; } /* * Ugly problem: If we're using devgen, make sure we're * walking the directory itself, represented by the first * entry in the table, and not trying to step into a sub- * directory of the table, e.g. /net/net. Devgen itself * should take care of the problem, but it doesn't have * the necessary information (that we're doing a walk). */ if(gen==devgen && nc->qid.path!=tab[0].qid.path) goto Notfound; for(i=0;; i++) { switch((*gen)(nc, n, tab, ntab, i, &dir)){ case -1: Notfound: if(j == 0) error(Enonexist); kstrcpy(up->errstr, Enonexist, ERRMAX); goto Done; case 0: continue; case 1: if(strcmp(n, dir.name) == 0){ nc->qid = dir.qid; goto Accept; } continue; } } } /* * We processed at least one name, so will return some data. * If we didn't process all nname entries succesfully, we drop * the cloned channel and return just the Qids of the walks. */ Done: poperror(); if(wq->nqid < nname){ if(alloc) cclose(wq->clone); wq->clone = nil; }else if(wq->clone){ /* attach cloned channel to same device */ wq->clone->type = c->type; } return wq; } int devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen) { int i; Dir dir; char *p, *elem; for(i=0;; i++) switch((*gen)(c, nil, tab, ntab, i, &dir)){ case -1: if(c->qid.type & QTDIR){ if(c->name == nil) elem = "???"; else if(strcmp(c->name->s, "/") == 0) elem = "/"; else for(elem=p=c->name->s; *p; p++) if(*p == '/') elem = p+1; devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir); n = convD2M(&dir, db, n); if(n == 0) error(Ebadarg); return n; } print("devstat %C %llux\n", devtab[c->type]->dc, c->qid.path); error(Enonexist); case 0: break; case 1: if(c->qid.path == dir.qid.path) { if(c->flag&CMSG) dir.mode |= DMMOUNT; n = convD2M(&dir, db, n); if(n == 0) error(Ebadarg); return n; } break; } error(Egreg); /* not reached? */ return -1; } long devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen) { long m, dsz; struct{ Dir d; char slop[100]; }dir; for(m=0; mdri++) { switch((*gen)(c, nil, tab, ntab, c->dri, &dir.d)){ case -1: return m; case 0: break; case 1: dsz = convD2M(&dir.d, (uchar*)d, n-m); if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */ if(m == 0) error(Eshort); return m; } m += dsz; d += dsz; break; } } return m; } /* * error(Eperm) if open permission not granted for up->user. */ void devpermcheck(char *fileuid, ulong perm, int omode) { ulong t; static int access[] = { 0400, 0200, 0600, 0100 }; if(strcmp(up->user, fileuid) == 0) perm <<= 0; else if(strcmp(up->user, eve) == 0) perm <<= 3; else perm <<= 6; t = access[omode&3]; if((t&perm) != t) error(Eperm); } Chan* devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen) { int i; Dir dir; for(i=0;; i++) { switch((*gen)(c, nil, tab, ntab, i, &dir)){ case -1: goto Return; case 0: break; case 1: if(c->qid.path == dir.qid.path) { devpermcheck(dir.uid, dir.mode, omode); goto Return; } break; } } Return: c->offset = 0; if((c->qid.type&QTDIR) && omode!=OREAD) error(Eperm); c->mode = openmode(omode); c->flag |= COPEN; return c; } void devcreate(Chan *c, char *name, int mode, ulong perm) { USED(c); USED(name); USED(mode); USED(perm); error(Eperm); } Block* devbread(Chan *c, long n, ulong offset) { Block *bp; bp = allocb(n); if(bp == 0) error(Enomem); if(waserror()) { freeb(bp); nexterror(); } bp->wp += devtab[c->type]->read(c, bp->wp, n, offset); poperror(); return bp; } long devbwrite(Chan *c, Block *bp, ulong offset) { long n; if(waserror()) { freeb(bp); nexterror(); } n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset); poperror(); freeb(bp); return n; } void devremove(Chan *c) { USED(c); error(Eperm); } int devwstat(Chan *c, uchar *a, int n) { USED(c); USED(a); USED(n); error(Eperm); return 0; } void devpower(int a) { USED(a); error(Eperm); } int devconfig(int a, char *b, DevConf *c) { USED(a); USED(b); USED(c); error(Eperm); return 0; } drawterm-20110822.orig/kern/win32.c0000644000175000017500000002005511510255052016134 0ustar tinchotincho#include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include typedef struct Oproc Oproc; struct Oproc { int tid; HANDLE *sema; }; static int tlsx = TLS_OUT_OF_INDEXES; char *argv0; Proc* _getproc(void) { if(tlsx == TLS_OUT_OF_INDEXES) return nil; return TlsGetValue(tlsx); } void _setproc(Proc *p) { if(tlsx == TLS_OUT_OF_INDEXES){ tlsx = TlsAlloc(); if(tlsx == TLS_OUT_OF_INDEXES) panic("out of indexes"); } TlsSetValue(tlsx, p); } void oserror(void) { oserrstr(); nexterror(); } void osinit(void) { Oproc *t; static Proc firstprocCTstore; _setproc(&firstprocCTstore); t = (Oproc*)firstprocCTstore.oproc; assert(t != 0); t->tid = GetCurrentThreadId(); t->sema = CreateSemaphore(0, 0, 1000, 0); if(t->sema == 0) { oserror(); panic("could not create semaphore: %r"); } } void osnewproc(Proc *p) { Oproc *op; op = (Oproc*)p->oproc; op->sema = CreateSemaphore(0, 0, 1000, 0); if (op->sema == 0) { oserror(); panic("could not create semaphore: %r"); } } void osmsleep(int ms) { Sleep((DWORD) ms); } void osyield(void) { Sleep(0); } static DWORD WINAPI tramp(LPVOID vp); void osproc(Proc *p) { DWORD tid; if(CreateThread(0, 0, tramp, p, 0, &tid) == 0) { oserror(); panic("osproc: %r"); } Sleep(0); } static DWORD WINAPI tramp(LPVOID vp) { Proc *p = (Proc *) vp; Oproc *op = (Oproc*) p->oproc; _setproc(p); op->tid = GetCurrentThreadId(); op->sema = CreateSemaphore(0, 0, 1000, 0); if(op->sema == 0) { oserror(); panic("could not create semaphore: %r"); } (*p->fn)(p->arg); ExitThread(0); return 0; } void procsleep(void) { Proc *p; Oproc *op; p = up; op = (Oproc*)p->oproc; WaitForSingleObject(op->sema, INFINITE);} void procwakeup(Proc *p) { Oproc *op; op = (Oproc*)p->oproc; ReleaseSemaphore(op->sema, 1, 0); } void random20(uchar *p) { LARGE_INTEGER ti; int i, j; FILETIME ft; DigestState ds; vlong tsc; GetSystemTimeAsFileTime(&ft); memset(&ds, 0, sizeof ds); sha1((uchar*)&ft, sizeof(ft), 0, &ds); for(i=0; i<50; i++) { for(j=0; j<10; j++) { QueryPerformanceCounter(&ti); sha1((uchar*)&ti, sizeof(ti), 0, &ds); tsc = GetTickCount(); sha1((uchar*)&tsc, sizeof(tsc), 0, &ds); } Sleep(10); } sha1(0, 0, p, &ds); } void randominit(void) { } ulong randomread(void *v, ulong n) { int i; uchar p[20]; for(i=0; i N backslashes and end quote * 2N+1 backslashes + " ==> N backslashes + literal " * N backslashes not followed by " ==> N backslashes */ static int args(char *argv[], int n, char *p) { char *p2; int i, j, quote, nbs; for(i=0; *p && i>1); j++) *p2++ = '\\'; if(nbs&1) *p2++ = *p; else quote = !quote; } else { for(j=0; jerrstr, ERRMAX); } long showfilewrite(char *a, int n) { Rune *action, *arg, *cmd; static Rune Lopen[] = { 'o', 'p', 'e', 'n', 0 }; cmd = runesmprint("%.*s", n, a); if(cmd == nil) error("out of memory"); if(cmd[runestrlen(cmd)-1] == '\n') cmd[runestrlen(cmd)] = 0; p = runestrchr(cmd, ' '); if(p){ action = cmd; *p++ = 0; arg = p; }else{ action = Lopen; arg = cmd; } ShellExecute(0, 0, action, arg, 0, SW_SHOWNORMAL); return n; } drawterm-20110822.orig/kern/term.c0000644000175000017500000000757211245145712016160 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include #include #include "screen.h" #define MINX 8 #define Backgnd 0xFF /* white */ Memsubfont *memdefont; struct{ Point pos; int bwid; }out; Lock screenlock; Memimage *conscol; Memimage *back; extern Memimage *gscreen; static Rectangle flushr; static Rectangle window; static Point curpos; static int h; static void termscreenputs(char*, int); static void screenflush(void) { drawflushr(flushr); flushr = Rect(10000, 10000, -10000, -10000); } static void addflush(Rectangle r) { if(flushr.min.x >= flushr.max.x) flushr = r; else combinerect(&flushr, r); } static void screenwin(void) { Point p; char *greet; Memimage *grey; drawqlock(); back = memwhite; conscol = memblack; memfillcolor(gscreen, 0x444488FF); h = memdefont->height; window.min = addpt(gscreen->r.min, Pt(20,20)); window.max.x = window.min.x + Dx(gscreen->r)*3/4-40; window.max.y = window.min.y + Dy(gscreen->r)*3/4-100; memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); window = insetrect(window, 4); memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); /* a lot of work to get a grey color */ grey = allocmemimage(Rect(0,0,1,1), CMAP8); grey->flags |= Frepl; grey->clipr = gscreen->r; memfillcolor(grey, 0xAAAAAAFF); memimagedraw(gscreen, Rect(window.min.x, window.min.y, window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S); freememimage(grey); window = insetrect(window, 5); greet = " Plan 9 Console "; p = addpt(window.min, Pt(10, 0)); memimagestring(gscreen, p, conscol, ZP, memdefont, greet); window.min.y += h+6; curpos = window.min; window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; flushmemscreen(gscreen->r); drawqunlock(); } void terminit(void) { memdefont = getmemdefont(); out.pos.x = MINX; out.pos.y = 0; out.bwid = memdefont->info[' '].width; screenwin(); screenputs = termscreenputs; } static void scroll(void) { int o; Point p; Rectangle r; o = 8*h; r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); p = Pt(window.min.x, window.min.y+o); memimagedraw(gscreen, r, gscreen, p, nil, p, S); r = Rpt(Pt(window.min.x, window.max.y-o), window.max); memimagedraw(gscreen, r, back, ZP, nil, ZP, S); flushmemscreen(gscreen->r); curpos.y -= o; } static void screenputc(char *buf) { Point p; int w, pos; Rectangle r; static int *xp; static int xbuf[256]; if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) xp = xbuf; switch(buf[0]) { case '\n': if(curpos.y+h >= window.max.y) scroll(); curpos.y += h; screenputc("\r"); break; case '\r': xp = xbuf; curpos.x = window.min.x; break; case '\t': p = memsubfontwidth(memdefont, " "); w = p.x; *xp++ = curpos.x; pos = (curpos.x-window.min.x)/w; pos = 8-(pos%8); r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h); memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); addflush(r); curpos.x += pos*w; break; case '\b': if(xp <= xbuf) break; xp--; r = Rect(*xp, curpos.y, curpos.x, curpos.y + h); memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); addflush(r); curpos.x = *xp; break; default: p = memsubfontwidth(memdefont, buf); w = p.x; if(curpos.x >= window.max.x-w) screenputc("\n"); *xp++ = curpos.x; r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h); memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); addflush(r); curpos.x += w; } } static void termscreenputs(char *s, int n) { int i, locked; Rune r; char buf[4]; lock(&screenlock); locked = drawcanqlock(); while(n > 0){ i = chartorune(&r, s); if(i == 0){ s++; --n; continue; } memmove(buf, s, i); buf[i] = 0; n -= i; s += i; screenputc(buf); } if(locked) drawqunlock(); screenflush(); unlock(&screenlock); } drawterm-20110822.orig/kern/devip.c0000644000175000017500000003736011245145711016315 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devip.h" void hnputl(void *p, unsigned long v); void hnputs(void *p, unsigned short v); unsigned long nhgetl(void *p); unsigned short nhgets(void *p); unsigned long parseip(char *to, char *from); void csclose(Chan*); long csread(Chan*, void*, long, vlong); long cswrite(Chan*, void*, long, vlong); void osipinit(void); enum { Qtopdir = 1, /* top level directory */ Qcs, Qprotodir, /* directory for a protocol */ Qclonus, Qconvdir, /* directory for a conversation */ Qdata, Qctl, Qstatus, Qremote, Qlocal, Qlisten, MAXPROTO = 4 }; #define TYPE(x) ((int)((x).path & 0xf)) #define CONV(x) ((int)(((x).path >> 4)&0xfff)) #define PROTO(x) ((int)(((x).path >> 16)&0xff)) #define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y)) typedef struct Proto Proto; typedef struct Conv Conv; struct Conv { int x; Ref r; int sfd; int perm; char owner[KNAMELEN]; char* state; ulong laddr; ushort lport; ulong raddr; ushort rport; int restricted; char cerr[KNAMELEN]; Proto* p; }; struct Proto { Lock l; int x; int stype; char name[KNAMELEN]; int nc; int maxconv; Conv** conv; Qid qid; }; static int np; static Proto proto[MAXPROTO]; int eipfmt(Fmt*); static Conv* protoclone(Proto*, char*, int); static void setladdr(Conv*); int ipgen(Chan *c, char *nname, Dirtab *d, int nd, int s, Dir *dp) { Qid q; Conv *cv; char *p; USED(nname); q.vers = 0; q.type = 0; switch(TYPE(c->qid)) { case Qtopdir: if(s >= 1+np) return -1; if(s == 0){ q.path = QID(s, 0, Qcs); devdir(c, q, "cs", 0, "network", 0666, dp); }else{ s--; q.path = QID(s, 0, Qprotodir); q.type = QTDIR; devdir(c, q, proto[s].name, 0, "network", DMDIR|0555, dp); } return 1; case Qprotodir: if(s < proto[PROTO(c->qid)].nc) { cv = proto[PROTO(c->qid)].conv[s]; sprint(up->genbuf, "%d", s); q.path = QID(PROTO(c->qid), s, Qconvdir); q.type = QTDIR; devdir(c, q, up->genbuf, 0, cv->owner, DMDIR|0555, dp); return 1; } s -= proto[PROTO(c->qid)].nc; switch(s) { default: return -1; case 0: p = "clone"; q.path = QID(PROTO(c->qid), 0, Qclonus); break; } devdir(c, q, p, 0, "network", 0555, dp); return 1; case Qconvdir: cv = proto[PROTO(c->qid)].conv[CONV(c->qid)]; switch(s) { default: return -1; case 0: q.path = QID(PROTO(c->qid), CONV(c->qid), Qdata); devdir(c, q, "data", 0, cv->owner, cv->perm, dp); return 1; case 1: q.path = QID(PROTO(c->qid), CONV(c->qid), Qctl); devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp); return 1; case 2: p = "status"; q.path = QID(PROTO(c->qid), CONV(c->qid), Qstatus); break; case 3: p = "remote"; q.path = QID(PROTO(c->qid), CONV(c->qid), Qremote); break; case 4: p = "local"; q.path = QID(PROTO(c->qid), CONV(c->qid), Qlocal); break; case 5: p = "listen"; q.path = QID(PROTO(c->qid), CONV(c->qid), Qlisten); break; } devdir(c, q, p, 0, cv->owner, 0444, dp); return 1; } return -1; } static void newproto(char *name, int type, int maxconv) { int l; Proto *p; if(np >= MAXPROTO) { print("no %s: increase MAXPROTO", name); return; } p = &proto[np]; strcpy(p->name, name); p->stype = type; p->qid.path = QID(np, 0, Qprotodir); p->qid.type = QTDIR; p->x = np++; p->maxconv = maxconv; l = sizeof(Conv*)*(p->maxconv+1); p->conv = mallocz(l, 1); if(p->conv == 0) panic("no memory"); } void ipinit(void) { osipinit(); newproto("udp", S_UDP, 10); newproto("tcp", S_TCP, 30); fmtinstall('I', eipfmt); fmtinstall('E', eipfmt); } Chan * ipattach(char *spec) { Chan *c; c = devattach('I', spec); c->qid.path = QID(0, 0, Qtopdir); c->qid.type = QTDIR; c->qid.vers = 0; return c; } static Walkqid* ipwalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, 0, 0, ipgen); } int ipstat(Chan *c, uchar *dp, int n) { return devstat(c, dp, n, 0, 0, ipgen); } Chan * ipopen(Chan *c, int omode) { Proto *p; ulong raddr; ushort rport; int perm, sfd; Conv *cv, *lcv; omode &= 3; perm = 0; switch(omode) { case OREAD: perm = 4; break; case OWRITE: perm = 2; break; case ORDWR: perm = 6; break; } switch(TYPE(c->qid)) { default: break; case Qtopdir: case Qprotodir: case Qconvdir: case Qstatus: case Qremote: case Qlocal: if(omode != OREAD) error(Eperm); break; case Qclonus: p = &proto[PROTO(c->qid)]; cv = protoclone(p, up->user, -1); if(cv == 0) error(Enodev); c->qid.path = QID(p->x, cv->x, Qctl); c->qid.vers = 0; break; case Qdata: case Qctl: p = &proto[PROTO(c->qid)]; lock(&p->l); cv = p->conv[CONV(c->qid)]; lock(&cv->r.lk); if((perm & (cv->perm>>6)) != perm) { if(strcmp(up->user, cv->owner) != 0 || (perm & cv->perm) != perm) { unlock(&cv->r.lk); unlock(&p->l); error(Eperm); } } cv->r.ref++; if(cv->r.ref == 1) { memmove(cv->owner, up->user, KNAMELEN); cv->perm = 0660; } unlock(&cv->r.lk); unlock(&p->l); break; case Qlisten: p = &proto[PROTO(c->qid)]; lcv = p->conv[CONV(c->qid)]; sfd = so_accept(lcv->sfd, &raddr, &rport); cv = protoclone(p, up->user, sfd); if(cv == 0) { close(sfd); error(Enodev); } cv->raddr = raddr; cv->rport = rport; setladdr(cv); cv->state = "Established"; c->qid.path = QID(p->x, cv->x, Qctl); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void ipclose(Chan *c) { Conv *cc; switch(TYPE(c->qid)) { case Qcs: csclose(c); break; case Qdata: case Qctl: if((c->flag & COPEN) == 0) break; cc = proto[PROTO(c->qid)].conv[CONV(c->qid)]; if(decref(&cc->r) != 0) break; strcpy(cc->owner, "network"); cc->perm = 0666; cc->state = "Closed"; cc->laddr = 0; cc->raddr = 0; cc->lport = 0; cc->rport = 0; close(cc->sfd); break; } } long ipread(Chan *ch, void *a, long n, vlong offset) { int r; Conv *c; Proto *x; uchar ip[4]; char buf[128], *p; /*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/ p = a; switch(TYPE(ch->qid)) { default: error(Eperm); case Qcs: return csread(ch, a, n, offset); case Qprotodir: case Qtopdir: case Qconvdir: return devdirread(ch, a, n, 0, 0, ipgen); case Qctl: sprint(buf, "%d", CONV(ch->qid)); return readstr(offset, p, n, buf); case Qremote: c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; hnputl(ip, c->raddr); sprint(buf, "%I!%d\n", ip, c->rport); return readstr(offset, p, n, buf); case Qlocal: c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; hnputl(ip, c->laddr); sprint(buf, "%I!%d\n", ip, c->lport); return readstr(offset, p, n, buf); case Qstatus: x = &proto[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; sprint(buf, "%s/%d %d %s \n", c->p->name, c->x, c->r.ref, c->state); return readstr(offset, p, n, buf); case Qdata: c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; r = so_recv(c->sfd, a, n, 0); if(r < 0){ oserrstr(); nexterror(); } return r; } } static void setladdr(Conv *c) { so_getsockname(c->sfd, &c->laddr, &c->lport); } static void setlport(Conv *c) { if(c->restricted == 0 && c->lport == 0) return; so_bind(c->sfd, c->restricted, c->lport); } static void setladdrport(Conv *c, char *str) { char *p, addr[4]; p = strchr(str, '!'); if(p == 0) { p = str; c->laddr = 0; } else { *p++ = 0; parseip(addr, str); c->laddr = nhgetl((uchar*)addr); } if(*p == '*') c->lport = 0; else c->lport = atoi(p); setlport(c); } static char* setraddrport(Conv *c, char *str) { char *p, addr[4]; p = strchr(str, '!'); if(p == 0) return "malformed address"; *p++ = 0; parseip(addr, str); c->raddr = nhgetl((uchar*)addr); c->rport = atoi(p); p = strchr(p, '!'); if(p) { if(strcmp(p, "!r") == 0) c->restricted = 1; } return 0; } long ipwrite(Chan *ch, void *a, long n, vlong offset) { Conv *c; Proto *x; int r, nf; char *p, *fields[3], buf[128]; switch(TYPE(ch->qid)) { default: error(Eperm); case Qcs: return cswrite(ch, a, n, offset); case Qctl: x = &proto[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; if(n > sizeof(buf)-1) n = sizeof(buf)-1; memmove(buf, a, n); buf[n] = '\0'; nf = tokenize(buf, fields, 3); if(strcmp(fields[0], "connect") == 0){ switch(nf) { default: error("bad args to connect"); case 2: p = setraddrport(c, fields[1]); if(p != 0) error(p); break; case 3: p = setraddrport(c, fields[1]); if(p != 0) error(p); c->lport = atoi(fields[2]); setlport(c); break; } so_connect(c->sfd, c->raddr, c->rport); setladdr(c); c->state = "Established"; return n; } if(strcmp(fields[0], "announce") == 0) { switch(nf){ default: error("bad args to announce"); case 2: setladdrport(c, fields[1]); break; } so_listen(c->sfd); c->state = "Announced"; return n; } if(strcmp(fields[0], "bind") == 0){ switch(nf){ default: error("bad args to bind"); case 2: c->lport = atoi(fields[1]); break; } setlport(c); return n; } error("bad control message"); case Qdata: x = &proto[PROTO(ch->qid)]; c = x->conv[CONV(ch->qid)]; r = so_send(c->sfd, a, n, 0); if(r < 0){ oserrstr(); nexterror(); } return r; } return n; } static Conv* protoclone(Proto *p, char *user, int nfd) { Conv *c, **pp, **ep; c = 0; lock(&p->l); if(waserror()) { unlock(&p->l); nexterror(); } ep = &p->conv[p->maxconv]; for(pp = p->conv; pp < ep; pp++) { c = *pp; if(c == 0) { c = mallocz(sizeof(Conv), 1); if(c == 0) error(Enomem); lock(&c->r.lk); c->r.ref = 1; c->p = p; c->x = pp - p->conv; p->nc++; *pp = c; break; } lock(&c->r.lk); if(c->r.ref == 0) { c->r.ref++; break; } unlock(&c->r.lk); } if(pp >= ep) { unlock(&p->l); poperror(); return 0; } strcpy(c->owner, user); c->perm = 0660; c->state = "Closed"; c->restricted = 0; c->laddr = 0; c->raddr = 0; c->lport = 0; c->rport = 0; c->sfd = nfd; if(nfd == -1) c->sfd = so_socket(p->stype); unlock(&c->r.lk); unlock(&p->l); poperror(); return c; } enum { Isprefix= 16, }; uchar prefixvals[256] = { /*0x00*/ 0 | Isprefix, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x80*/ 1 | Isprefix, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0xC0*/ 2 | Isprefix, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0xE0*/ 3 | Isprefix, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0xF0*/ 4 | Isprefix, 0, 0, 0, 0, 0, 0, 0, /*0xF8*/ 5 | Isprefix, 0, 0, 0, /*0xFC*/ 6 | Isprefix, 0, /*0xFE*/ 7 | Isprefix, /*0xFF*/ 8 | Isprefix, }; int eipfmt(Fmt *f) { char buf[5*8]; static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; static char *ifmt = "%d.%d.%d.%d"; uchar *p, ip[16]; ulong ul; switch(f->r) { case 'E': /* Ethernet address */ p = va_arg(f->args, uchar*); snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); return fmtstrcpy(f, buf); case 'I': ul = va_arg(f->args, ulong); hnputl(ip, ul); snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]); return fmtstrcpy(f, buf); } return fmtstrcpy(f, "(eipfmt)"); } void hnputl(void *p, unsigned long v) { unsigned char *a; a = p; a[0] = v>>24; a[1] = v>>16; a[2] = v>>8; a[3] = v; } void hnputs(void *p, unsigned short v) { unsigned char *a; a = p; a[0] = v>>8; a[1] = v; } unsigned long nhgetl(void *p) { unsigned char *a; a = p; return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); } unsigned short nhgets(void *p) { unsigned char *a; a = p; return (a[0]<<8)|(a[1]<<0); } #define CLASS(p) ((*(unsigned char*)(p))>>6) unsigned long parseip(char *to, char *from) { int i; char *p; p = from; memset(to, 0, 4); for(i = 0; i < 4 && *p; i++){ to[i] = strtoul(p, &p, 10); if(*p != '.' && *p != 0){ memset(to, 0, 4); return 0; } if(*p == '.') p++; } switch(CLASS(to)){ case 0: /* class A - 1 byte net */ case 1: if(i == 3){ to[3] = to[2]; to[2] = to[1]; to[1] = 0; } else if (i == 2){ to[3] = to[1]; to[1] = 0; } break; case 2: /* class B - 2 byte net */ if(i == 3){ to[3] = to[2]; to[2] = 0; } break; } return nhgetl(to); } void csclose(Chan *c) { free(c->aux); } long csread(Chan *c, void *a, long n, vlong offset) { if(c->aux == nil) return 0; return readstr(offset, a, n, c->aux); } static struct { char *name; uint num; } tab[] = { "cs", 1, "echo", 7, "discard", 9, "systat", 11, "daytime", 13, "netstat", 15, "chargen", 19, "ftp-data", 20, "ftp", 21, "ssh", 22, "telnet", 23, "smtp", 25, "time", 37, "whois", 43, "dns", 53, "domain", 53, "uucp", 64, "gopher", 70, "rje", 77, "finger", 79, "http", 80, "link", 87, "supdup", 95, "hostnames", 101, "iso-tsap", 102, "x400", 103, "x400-snd", 104, "csnet-ns", 105, "pop-2", 109, "pop3", 110, "portmap", 111, "uucp-path", 117, "nntp", 119, "netbios", 139, "imap4", 143, "NeWS", 144, "print-srv", 170, "z39.50", 210, "fsb", 400, "sysmon", 401, "proxy", 402, "proxyd", 404, "https", 443, "cifs", 445, "ssmtp", 465, "rexec", 512, "login", 513, "shell", 514, "printer", 515, "courier", 530, "cscan", 531, "uucp", 540, "snntp", 563, "9fs", 564, "whoami", 565, "guard", 566, "ticket", 567, "dlsftp", 666, "fmclient", 729, "imaps", 993, "pop3s", 995, "ingreslock", 1524, "pptp", 1723, "nfs", 2049, "webster", 2627, "weather", 3000, "secstore", 5356, "Xdisplay", 6000, "styx", 6666, "mpeg", 6667, "rstyx", 6668, "infdb", 6669, "infsigner", 6671, "infcsigner", 6672, "inflogin", 6673, "bandt", 7330, "face", 32000, "dhashgate", 11978, "exportfs", 17007, "rexexec", 17009, "ncpu", 17010, "cpu", 17013, "glenglenda1", 17020, "glenglenda2", 17021, "glenglenda3", 17022, "glenglenda4", 17023, "glenglenda5", 17024, "glenglenda6", 17025, "glenglenda7", 17026, "glenglenda8", 17027, "glenglenda9", 17028, "glenglenda10", 17029, "flyboy", 17032, "dlsftp", 17033, "venti", 17034, "wiki", 17035, "vica", 17036, 0 }; static int lookupport(char *s) { int i; char buf[10], *p; i = strtol(s, &p, 0); if(*s && *p == 0) return i; i = so_getservbyname(s, "tcp", buf); if(i != -1) return atoi(buf); for(i=0; tab[i].name; i++) if(strcmp(s, tab[i].name) == 0) return tab[i].num; return 0; } static ulong lookuphost(char *s) { char to[4]; ulong ip; memset(to, 0, sizeof to); parseip(to, s); ip = nhgetl(to); if(ip != 0) return ip; if((s = hostlookup(s)) == nil) return 0; parseip(to, s); ip = nhgetl(to); free(s); return ip; } long cswrite(Chan *c, void *a, long n, vlong offset) { char *f[4]; char *s, *ns; ulong ip; int nf, port; s = malloc(n+1); if(s == nil) error(Enomem); if(waserror()){ free(s); nexterror(); } memmove(s, a, n); s[n] = 0; nf = getfields(s, f, nelem(f), 0, "!"); if(nf != 3) error("can't translate"); port = lookupport(f[2]); if(port <= 0) error("no translation for port found"); ip = lookuphost(f[1]); if(ip == 0) error("no translation for host found"); ns = smprint("/net/%s/clone %I!%d", f[0], ip, port); if(ns == nil) error(Enomem); free(c->aux); c->aux = ns; poperror(); free(s); return n; } Dev ipdevtab = { 'I', "ip", devreset, ipinit, devshutdown, ipattach, ipwalk, ipstat, ipopen, devcreate, ipclose, ipread, devbread, ipwrite, devbwrite, devremove, devwstat, }; drawterm-20110822.orig/kern/devip-posix.c0000644000175000017500000000664011245145711017452 0ustar tinchotincho#include #include #include #include #include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devip.h" #undef listen #undef accept #undef bind void osipinit(void) { char buf[1024]; gethostname(buf, sizeof(buf)); kstrdup(&sysname, buf); } int so_socket(int type) { int fd, one; switch(type) { default: error("bad protocol type"); case S_TCP: type = SOCK_STREAM; break; case S_UDP: type = SOCK_DGRAM; break; } fd = socket(AF_INET, type, 0); if(fd < 0) oserror(); one = 1; if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){ oserrstr(); print("setsockopt: %r"); } return fd; } void so_connect(int fd, unsigned long raddr, unsigned short rport) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; hnputs(&sin.sin_port, rport); hnputl(&sin.sin_addr.s_addr, raddr); if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) oserror(); } void so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) { socklen_t len; struct sockaddr_in sin; len = sizeof(sin); if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) oserror(); if(sin.sin_family != AF_INET || len != sizeof(sin)) error("not AF_INET"); *laddr = nhgetl(&sin.sin_addr.s_addr); *lport = nhgets(&sin.sin_port); } void so_listen(int fd) { if(listen(fd, 5) < 0) oserror(); } int so_accept(int fd, unsigned long *raddr, unsigned short *rport) { int nfd; socklen_t len; struct sockaddr_in sin; len = sizeof(sin); nfd = accept(fd, (struct sockaddr*)&sin, &len); if(nfd < 0) oserror(); if(sin.sin_family != AF_INET || len != sizeof(sin)) error("not AF_INET"); *raddr = nhgetl(&sin.sin_addr.s_addr); *rport = nhgets(&sin.sin_port); return nfd; } void so_bind(int fd, int su, unsigned short port) { int i, one; struct sockaddr_in sin; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ oserrstr(); print("setsockopt: %r"); } if(su) { for(i = 600; i < 1024; i++) { memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = i; if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) return; } oserror(); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; hnputs(&sin.sin_port, port); if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) oserror(); } int so_gethostbyname(char *host, char**hostv, int n) { int i; char buf[32]; unsigned char *p; struct hostent *hp; hp = gethostbyname(host); if(hp == 0) return 0; for(i = 0; hp->h_addr_list[i] && i < n; i++) { p = (unsigned char*)hp->h_addr_list[i]; sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); hostv[i] = strdup(buf); if(hostv[i] == 0) break; } return i; } char* hostlookup(char *host) { char buf[100]; uchar *p; struct hostent *he; he = gethostbyname(host); if(he != 0 && he->h_addr_list[0]) { p = (uchar*)he->h_addr_list[0]; sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); } else strcpy(buf, host); return strdup(buf); } int so_getservbyname(char *service, char *net, char *port) { struct servent *s; s = getservbyname(service, net); if(s == 0) return -1; sprint(port, "%d", nhgets(&s->s_port)); return 0; } int so_send(int fd, void *d, int n, int f) { return send(fd, d, n, f); } int so_recv(int fd, void *d, int n, int f) { return recv(fd, d, n, f); } drawterm-20110822.orig/kern/data.c0000644000175000017500000000064711245145711016115 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" Proc *up; Conf conf = { 1, 100, 0, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 1024*1024*1024, 0, }; char *eve = "eve"; ulong kerndate; int cpuserver; char hostdomain[] = "drawterm.net"; drawterm-20110822.orig/kern/waserror.c0000644000175000017500000000057611245145712017052 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" Label* pwaserror(void) { if(up->nerrlab == NERR) panic("error stack overflow"); return &up->errlab[up->nerrlab++]; } void nexterror(void) { longjmp(up->errlab[--up->nerrlab].buf, 1); } void error(char *e) { kstrcpy(up->errstr, e, ERRMAX); setjmp(up->errlab[NERR-1].buf); nexterror(); } drawterm-20110822.orig/kern/rwlock.c0000644000175000017500000000117211245145712016500 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" void rlock(RWlock *l) { qlock(&l->x); /* wait here for writers and exclusion */ lock(&l->lk); l->readers++; canqlock(&l->k); /* block writers if we are the first reader */ unlock(&l->lk); qunlock(&l->x); } void runlock(RWlock *l) { lock(&l->lk); if(--l->readers == 0) /* last reader out allows writers */ qunlock(&l->k); unlock(&l->lk); } void wlock(RWlock *l) { qlock(&l->x); /* wait here for writers and exclusion */ qlock(&l->k); /* wait here for last reader */ } void wunlock(RWlock *l) { qunlock(&l->k); qunlock(&l->x); } drawterm-20110822.orig/kern/procinit.c0000644000175000017500000000201711245145712017025 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" Rgrp *thergrp; void procinit0(void) { Proc *p; p = newproc(); p->fgrp = dupfgrp(nil); p->rgrp = newrgrp(); p->pgrp = newpgrp(); _setproc(p); up->slash = namec("#/", Atodir, 0, 0); cnameclose(up->slash->name); up->slash->name = newcname("/"); up->dot = cclone(up->slash); } Ref pidref; Proc* newproc(void) { Proc *p; p = mallocz(sizeof(Proc), 1); p->pid = incref(&pidref); strcpy(p->user, eve); p->syserrstr = p->errbuf0; p->errstr = p->errbuf1; strcpy(p->text, "drawterm"); osnewproc(p); return p; } int kproc(char *name, void (*fn)(void*), void *arg) { Proc *p; p = newproc(); p->fn = fn; p->arg = arg; p->slash = cclone(up->slash); p->dot = cclone(up->dot); p->rgrp = up->rgrp; if(p->rgrp) incref(&p->rgrp->ref); p->pgrp = up->pgrp; if(up->pgrp) incref(&up->pgrp->ref); p->fgrp = up->fgrp; if(p->fgrp) incref(&p->fgrp->ref); strecpy(p->text, p->text+sizeof p->text, name); osproc(p); return p->pid; } drawterm-20110822.orig/kern/chan.c0000644000175000017500000007163111245145711016116 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" int chandebug=0; /* toggled by sysr1 */ QLock chanprint; /* probably asking for trouble (deadlocks) -rsc */ int domount(Chan**, Mhead**); void dumpmount(void) /* DEBUGGING */ { Pgrp *pg; Mount *t; Mhead **h, **he, *f; if(up == nil){ print("no process for dumpmount\n"); return; } pg = up->pgrp; if(pg == nil){ print("no pgrp for dumpmount\n"); return; } rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); nexterror(); } he = &pg->mnthash[MNTHASH]; for(h = pg->mnthash; h < he; h++) { for(f = *h; f; f = f->hash) { print("head: %p: %s 0x%llux.%lud %C %lud -> \n", f, f->from->name->s, f->from->qid.path, f->from->qid.vers, devtab[f->from->type]->dc, f->from->dev); for(t = f->mount; t; t = t->next) print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->name->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev); } } poperror(); runlock(&pg->ns); } char* c2name(Chan *c) /* DEBUGGING */ { if(c == nil) return ""; if(c->name == nil) return ""; if(c->name->s == nil) return ""; return c->name->s; } enum { CNAMESLOP = 20 }; struct { Lock lk; int fid; Chan *free; Chan *list; }chanalloc; typedef struct Elemlist Elemlist; struct Elemlist { char *name; /* copy of name, so '/' can be overwritten */ int nelems; char **elems; int *off; int mustbedir; }; #define SEP(c) ((c) == 0 || (c) == '/') void cleancname(Cname*); int isdotdot(char *p) { return p[0]=='.' && p[1]=='.' && p[2]=='\0'; } int incref(Ref *r) { int x; lock(&r->lk); x = ++r->ref; unlock(&r->lk); return x; } int decref(Ref *r) { int x; lock(&r->lk); x = --r->ref; unlock(&r->lk); if(x < 0) panic("decref, pc=0x%p", getcallerpc(&r)); return x; } /* * Rather than strncpy, which zeros the rest of the buffer, kstrcpy * truncates if necessary, always zero terminates, does not zero fill, * and puts ... at the end of the string if it's too long. Usually used to * save a string in up->genbuf; */ void kstrcpy(char *s, char *t, int ns) { int nt; nt = strlen(t); if(nt+1 <= ns){ memmove(s, t, nt+1); return; } /* too long */ if(ns < 4){ /* but very short! */ strncpy(s, t, ns); return; } /* truncate with ... at character boundary (very rare case) */ memmove(s, t, ns-4); ns -= 4; s[ns] = '\0'; /* look for first byte of UTF-8 sequence by skipping continuation bytes */ while(ns>0 && (s[--ns]&0xC0)==0x80) ; strcpy(s+ns, "..."); } int emptystr(char *s) { if(s == nil) return 1; if(s[0] == '\0') return 1; return 0; } /* * Atomically replace *p with copy of s */ void kstrdup(char **p, char *s) { int n; char *t, *prev; n = strlen(s)+1; /* if it's a user, we can wait for memory; if not, something's very wrong */ if(up){ t = smalloc(n); setmalloctag(t, getcallerpc(&p)); }else{ t = malloc(n); if(t == nil) panic("kstrdup: no memory"); } memmove(t, s, n); prev = *p; *p = t; free(prev); } void chandevreset(void) { int i; for(i=0; devtab[i] != nil; i++) devtab[i]->reset(); } void chandevinit(void) { int i; for(i=0; devtab[i] != nil; i++) devtab[i]->init(); } void chandevshutdown(void) { int i; /* shutdown in reverse order */ for(i=0; devtab[i] != nil; i++) ; for(i--; i >= 0; i--) devtab[i]->shutdown(); } Chan* newchan(void) { Chan *c; lock(&chanalloc.lk); c = chanalloc.free; if(c != 0) chanalloc.free = c->next; unlock(&chanalloc.lk); if(c == nil) { c = smalloc(sizeof(Chan)); lock(&chanalloc.lk); c->fid = ++chanalloc.fid; c->link = chanalloc.list; chanalloc.list = c; unlock(&chanalloc.lk); } /* if you get an error before associating with a dev, close calls rootclose, a nop */ c->type = 0; c->flag = 0; c->ref.ref = 1; c->dev = 0; c->offset = 0; c->iounit = 0; c->umh = 0; c->uri = 0; c->dri = 0; c->aux = 0; c->mchan = 0; c->mcp = 0; c->mux = 0; memset(&c->mqid, 0, sizeof(c->mqid)); c->name = 0; return c; } static Ref ncname; Cname* newcname(char *s) { Cname *n; int i; n = smalloc(sizeof(Cname)); i = strlen(s); n->len = i; n->alen = i+CNAMESLOP; n->s = smalloc(n->alen); memmove(n->s, s, i+1); n->ref.ref = 1; incref(&ncname); return n; } void cnameclose(Cname *n) { if(n == nil) return; if(decref(&n->ref)) return; decref(&ncname); free(n->s); free(n); } Cname* addelem(Cname *n, char *s) { int i, a; char *t; Cname *new; if(s[0]=='.' && s[1]=='\0') return n; if(n->ref.ref > 1){ /* copy on write */ new = newcname(n->s); cnameclose(n); n = new; } i = strlen(s); if(n->len+1+i+1 > n->alen){ a = n->len+1+i+1 + CNAMESLOP; t = smalloc(a); memmove(t, n->s, n->len+1); free(n->s); n->s = t; n->alen = a; } if(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/') /* don't insert extra slash if one is present */ n->s[n->len++] = '/'; memmove(n->s+n->len, s, i+1); n->len += i; if(isdotdot(s)) cleancname(n); return n; } void chanfree(Chan *c) { c->flag = CFREE; if(c->umh != nil){ putmhead(c->umh); c->umh = nil; } if(c->umc != nil){ cclose(c->umc); c->umc = nil; } if(c->mux != nil){ muxclose(c->mux); c->mux = nil; } if(c->mchan != nil){ cclose(c->mchan); c->mchan = nil; } cnameclose(c->name); lock(&chanalloc.lk); c->next = chanalloc.free; chanalloc.free = c; unlock(&chanalloc.lk); } void cclose(Chan *c) { if(c->flag&CFREE) panic("cclose %p", getcallerpc(&c)); if(decref(&c->ref)) return; if(!waserror()){ devtab[c->type]->close(c); poperror(); } chanfree(c); } /* * Make sure we have the only copy of c. (Copy on write.) */ Chan* cunique(Chan *c) { Chan *nc; if(c->ref.ref != 1) { nc = cclone(c); cclose(c); c = nc; } return c; } int eqqid(Qid a, Qid b) { return a.path==b.path && a.vers==b.vers; } int eqchan(Chan *a, Chan *b, int pathonly) { if(a->qid.path != b->qid.path) return 0; if(!pathonly && a->qid.vers!=b->qid.vers) return 0; if(a->type != b->type) return 0; if(a->dev != b->dev) return 0; return 1; } int eqchantdqid(Chan *a, int type, int dev, Qid qid, int pathonly) { if(a->qid.path != qid.path) return 0; if(!pathonly && a->qid.vers!=qid.vers) return 0; if(a->type != type) return 0; if(a->dev != dev) return 0; return 1; } Mhead* newmhead(Chan *from) { Mhead *mh; mh = smalloc(sizeof(Mhead)); mh->ref.ref = 1; mh->from = from; incref(&from->ref); /* n = from->name->len; if(n >= sizeof(mh->fromname)) n = sizeof(mh->fromname)-1; memmove(mh->fromname, from->name->s, n); mh->fromname[n] = 0; */ return mh; } int cmount(Chan **newp, Chan *old, int flag, char *spec) { Pgrp *pg; int order, flg; Mhead *m, **l, *mh; Mount *nm, *f, *um, **h; Chan *new; if(QTDIR & (old->qid.type^(*newp)->qid.type)) error(Emount); if(old->umh)print("cmount old extra umh\n"); order = flag&MORDER; if((old->qid.type&QTDIR)==0 && order != MREPL) error(Emount); new = *newp; mh = new->umh; /* * Not allowed to bind when the old directory * is itself a union. (Maybe it should be allowed, but I don't see * what the semantics would be.) * * We need to check mh->mount->next to tell unions apart from * simple mount points, so that things like * mount -c fd /root * bind -c /root / * work. The check of mount->mflag catches things like * mount fd /root * bind -c /root / * * This is far more complicated than it should be, but I don't * see an easier way at the moment. -rsc */ if((flag&MCREATE) && mh && mh->mount && (mh->mount->next || !(mh->mount->mflag&MCREATE))) error(Emount); pg = up->pgrp; wlock(&pg->ns); l = &MOUNTH(pg, old->qid); for(m = *l; m; m = m->hash) { if(eqchan(m->from, old, 1)) break; l = &m->hash; } if(m == nil) { /* * nothing mounted here yet. create a mount * head and add to the hash table. */ m = newmhead(old); *l = m; /* * if this is a union mount, add the old * node to the mount chain. */ if(order != MREPL) m->mount = newmount(m, old, 0, 0); } wlock(&m->lock); if(waserror()){ wunlock(&m->lock); nexterror(); } wunlock(&pg->ns); nm = newmount(m, new, flag, spec); if(mh != nil && mh->mount != nil) { /* * copy a union when binding it onto a directory */ flg = order; if(order == MREPL) flg = MAFTER; h = &nm->next; um = mh->mount; for(um = um->next; um; um = um->next) { f = newmount(m, um->to, flg, um->spec); *h = f; h = &f->next; } } if(m->mount && order == MREPL) { mountfree(m->mount); m->mount = 0; } if(flag & MCREATE) nm->mflag |= MCREATE; if(m->mount && order == MAFTER) { for(f = m->mount; f->next; f = f->next) ; f->next = nm; } else { for(f = nm; f->next; f = f->next) ; f->next = m->mount; m->mount = nm; } wunlock(&m->lock); poperror(); return nm->mountid; } void cunmount(Chan *mnt, Chan *mounted) { Pgrp *pg; Mhead *m, **l; Mount *f, **p; if(mnt->umh) /* should not happen */ print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh); /* * It _can_ happen that mounted->umh is non-nil, * because mounted is the result of namec(Aopen) * (see sysfile.c:/^sysunmount). * If we open a union directory, it will have a umh. * Although surprising, this is okay, since the * cclose will take care of freeing the umh. */ pg = up->pgrp; wlock(&pg->ns); l = &MOUNTH(pg, mnt->qid); for(m = *l; m; m = m->hash) { if(eqchan(m->from, mnt, 1)) break; l = &m->hash; } if(m == 0) { wunlock(&pg->ns); error(Eunmount); } wlock(&m->lock); if(mounted == 0) { *l = m->hash; wunlock(&pg->ns); mountfree(m->mount); m->mount = nil; cclose(m->from); wunlock(&m->lock); putmhead(m); return; } p = &m->mount; for(f = *p; f; f = f->next) { /* BUG: Needs to be 2 pass */ if(eqchan(f->to, mounted, 1) || (f->to->mchan && eqchan(f->to->mchan, mounted, 1))) { *p = f->next; f->next = 0; mountfree(f); if(m->mount == nil) { *l = m->hash; cclose(m->from); wunlock(&m->lock); wunlock(&pg->ns); putmhead(m); return; } wunlock(&m->lock); wunlock(&pg->ns); return; } p = &f->next; } wunlock(&m->lock); wunlock(&pg->ns); error(Eunion); } Chan* cclone(Chan *c) { Chan *nc; Walkqid *wq; wq = devtab[c->type]->walk(c, nil, nil, 0); if(wq == nil) error("clone failed"); nc = wq->clone; free(wq); nc->name = c->name; if(c->name) incref(&c->name->ref); return nc; } int findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid) { Pgrp *pg; Mhead *m; pg = up->pgrp; rlock(&pg->ns); for(m = MOUNTH(pg, qid); m; m = m->hash){ rlock(&m->lock); if(m->from == nil){ print("m %p m->from 0\n", m); runlock(&m->lock); continue; } if(eqchantdqid(m->from, type, dev, qid, 1)) { runlock(&pg->ns); if(mp != nil){ incref(&m->ref); if(*mp != nil) putmhead(*mp); *mp = m; } if(*cp != nil) cclose(*cp); incref(&m->mount->to->ref); *cp = m->mount->to; runlock(&m->lock); return 1; } runlock(&m->lock); } runlock(&pg->ns); return 0; } int domount(Chan **cp, Mhead **mp) { return findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid); } Chan* undomount(Chan *c, Cname *name) { Chan *nc; Pgrp *pg; Mount *t; Mhead **h, **he, *f; pg = up->pgrp; rlock(&pg->ns); if(waserror()) { runlock(&pg->ns); nexterror(); } he = &pg->mnthash[MNTHASH]; for(h = pg->mnthash; h < he; h++) { for(f = *h; f; f = f->hash) { if(strcmp(f->from->name->s, name->s) != 0) continue; for(t = f->mount; t; t = t->next) { if(eqchan(c, t->to, 1)) { /* * We want to come out on the left hand side of the mount * point using the element of the union that we entered on. * To do this, find the element that has a from name of * c->name->s. */ if(strcmp(t->head->from->name->s, name->s) != 0) continue; nc = t->head->from; incref(&nc->ref); cclose(c); c = nc; break; } } } } poperror(); runlock(&pg->ns); return c; } /* * Either walks all the way or not at all. No partial results in *cp. * *nerror is the number of names to display in an error message. */ static char Edoesnotexist[] = "does not exist"; int walk(Chan **cp, char **names, int nnames, int nomount, int *nerror) { int dev, dotdot, i, n, nhave, ntry, type; Chan *c, *nc; Cname *cname; Mount *f; Mhead *mh, *nmh; Walkqid *wq; c = *cp; incref(&c->ref); cname = c->name; incref(&cname->ref); mh = nil; /* * While we haven't gotten all the way down the path: * 1. step through a mount point, if any * 2. send a walk request for initial dotdot or initial prefix without dotdot * 3. move to the first mountpoint along the way. * 4. repeat. * * An invariant is that each time through the loop, c is on the undomount * side of the mount point, and c's name is cname. */ for(nhave=0; nhaveqid.type&QTDIR)==0){ if(nerror) *nerror = nhave; cnameclose(cname); cclose(c); strcpy(up->errstr, Enotdir); if(mh != nil) {print("walk 1\n"); putmhead(mh); } return -1; } ntry = nnames - nhave; if(ntry > MAXWELEM) ntry = MAXWELEM; dotdot = 0; for(i=0; itype; dev = c->dev; if((wq = devtab[type]->walk(c, nil, names+nhave, ntry)) == nil){ /* try a union mount, if any */ if(mh && !nomount){ /* * mh->mount == c, so start at mh->mount->next */ rlock(&mh->lock); for(f = mh->mount->next; f; f = f->next) if((wq = devtab[f->to->type]->walk(f->to, nil, names+nhave, ntry)) != nil) break; runlock(&mh->lock); if(f != nil){ type = f->to->type; dev = f->to->dev; } } if(wq == nil){ cclose(c); cnameclose(cname); if(nerror) *nerror = nhave+1; if(mh != nil) putmhead(mh); return -1; } } nmh = nil; if(dotdot) { assert(wq->nqid == 1); assert(wq->clone != nil); cname = addelem(cname, ".."); nc = undomount(wq->clone, cname); n = 1; } else { nc = nil; if(!nomount) for(i=0; inqid && iqid[i])) break; if(nc == nil){ /* no mount points along path */ if(wq->clone == nil){ cclose(c); cnameclose(cname); if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){ if(nerror) *nerror = nhave+wq->nqid+1; strcpy(up->errstr, Edoesnotexist); }else{ if(nerror) *nerror = nhave+wq->nqid; strcpy(up->errstr, Enotdir); } free(wq); if(mh != nil) putmhead(mh); return -1; } n = wq->nqid; nc = wq->clone; }else{ /* stopped early, at a mount point */ if(wq->clone != nil){ cclose(wq->clone); wq->clone = nil; } n = i+1; } for(i=0; iumh != nil){ //BUG print("walk umh\n"); putmhead(c->umh); c->umh = nil; } cnameclose(c->name); c->name = cname; cclose(*cp); *cp = c; if(nerror) *nerror = 0; return 0; } /* * c is a mounted non-creatable directory. find a creatable one. */ Chan* createdir(Chan *c, Mhead *m) { Chan *nc; Mount *f; rlock(&m->lock); if(waserror()) { runlock(&m->lock); nexterror(); } for(f = m->mount; f; f = f->next) { if(f->mflag&MCREATE) { nc = cclone(f->to); runlock(&m->lock); poperror(); cclose(c); return nc; } } error(Enocreate); return 0; } void saveregisters(void) { } /* * In place, rewrite name to compress multiple /, eliminate ., and process .. */ void cleancname(Cname *n) { char *p; if(n->s[0] == '#'){ p = strchr(n->s, '/'); if(p == nil) return; cleanname(p); /* * The correct name is #i rather than #i/, * but the correct name of #/ is #/. */ if(strcmp(p, "/")==0 && n->s[1] != '/') *p = '\0'; }else cleanname(n->s); n->len = strlen(n->s); } static void growparse(Elemlist *e) { char **new; int *inew; enum { Delta = 8 }; if(e->nelems % Delta == 0){ new = smalloc((e->nelems+Delta) * sizeof(char*)); memmove(new, e->elems, e->nelems*sizeof(char*)); free(e->elems); e->elems = new; inew = smalloc((e->nelems+Delta+1) * sizeof(int)); memmove(inew, e->off, e->nelems*sizeof(int)); free(e->off); e->off = inew; } } /* * The name is known to be valid. * Copy the name so slashes can be overwritten. * An empty string will set nelem=0. * A path ending in / or /. or /.//./ etc. will have * e.mustbedir = 1, so that we correctly * reject, e.g., "/adm/users/." when /adm/users is a file * rather than a directory. */ static void parsename(char *name, Elemlist *e) { char *slash; kstrdup(&e->name, name); name = e->name; e->nelems = 0; e->elems = nil; e->off = smalloc(sizeof(int)); e->off[0] = skipslash(name) - name; for(;;){ name = skipslash(name); if(*name=='\0'){ e->mustbedir = 1; break; } growparse(e); e->elems[e->nelems++] = name; slash = utfrune(name, '/'); if(slash == nil){ e->off[e->nelems] = name+strlen(name) - e->name; e->mustbedir = 0; break; } e->off[e->nelems] = slash - e->name; *slash++ = '\0'; name = slash; } } void* mymemrchr(void *va, int c, long n) { uchar *a, *e; a = va; for(e=a+n-1; e>a; e--) if(*e == c) return e; return nil; } /* * Turn a name into a channel. * &name[0] is known to be a valid address. It may be a kernel address. * * Opening with amode Aopen, Acreate, or Aremove guarantees * that the result will be the only reference to that particular fid. * This is necessary since we might pass the result to * devtab[]->remove(). * * Opening Atodir, Amount, or Aaccess does not guarantee this. * * Opening Aaccess can, under certain conditions, return a * correct Chan* but with an incorrect Cname attached. * Since the functions that open Aaccess (sysstat, syswstat, sys_stat) * do not use the Cname*, this avoids an unnecessary clone. */ Chan* namec(char *aname, int amode, int omode, ulong perm) { int n, prefix, len, t, nomount, npath; Chan *c, *cnew; Cname *cname; Elemlist e; Rune r; Mhead *m; char *createerr, tmperrbuf[ERRMAX]; char *name; name = aname; if(name[0] == '\0') error("empty file name"); validname(name, 1); /* * Find the starting off point (the current slash, the root of * a device tree, or the current dot) as well as the name to * evaluate starting there. */ nomount = 0; switch(name[0]){ case '/': c = up->slash; incref(&c->ref); break; case '#': nomount = 1; up->genbuf[0] = '\0'; n = 0; while(*name!='\0' && (*name != '/' || n < 2)){ if(n >= sizeof(up->genbuf)-1) error(Efilename); up->genbuf[n++] = *name++; } up->genbuf[n] = '\0'; /* * noattach is sandboxing. * * the OK exceptions are: * | it only gives access to pipes you create * d this process's file descriptors * e this process's environment * the iffy exceptions are: * c time and pid, but also cons and consctl * p control of your own processes (and unfortunately * any others left unprotected) */ n = chartorune(&r, up->genbuf+1)+1; /* actually / is caught by parsing earlier */ if(utfrune("M", r)) error(Enoattach); if(up->pgrp->noattach && utfrune("|decp", r)==nil) error(Enoattach); t = devno(r, 1); if(t == -1) error(Ebadsharp); c = devtab[t]->attach(up->genbuf+n); break; default: c = up->dot; incref(&c->ref); break; } prefix = name - aname; e.name = nil; e.elems = nil; e.off = nil; e.nelems = 0; if(waserror()){ cclose(c); free(e.name); free(e.elems); free(e.off); //dumpmount(); nexterror(); } /* * Build a list of elements in the path. */ parsename(name, &e); /* * On create, .... */ if(amode == Acreate){ /* perm must have DMDIR if last element is / or /. */ if(e.mustbedir && !(perm&DMDIR)){ npath = e.nelems; strcpy(tmperrbuf, "create without DMDIR"); goto NameError; } /* don't try to walk the last path element just yet. */ if(e.nelems == 0) error(Eexist); e.nelems--; } if(walk(&c, e.elems, e.nelems, nomount, &npath) < 0){ if(npath < 0 || npath > e.nelems){ print("namec %s walk error npath=%d\n", aname, npath); nexterror(); } strcpy(tmperrbuf, up->errstr); NameError: len = prefix+e.off[npath]; if(len < ERRMAX/3 || (name=mymemrchr(aname, '/', len))==nil || name==aname) snprint(up->genbuf, sizeof up->genbuf, "%.*s", len, aname); else snprint(up->genbuf, sizeof up->genbuf, "...%.*s", (int)(len-(name-aname)), name); snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, tmperrbuf); nexterror(); } if(e.mustbedir && !(c->qid.type&QTDIR)){ npath = e.nelems; strcpy(tmperrbuf, "not a directory"); goto NameError; } if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR)){ npath = e.nelems; error("cannot exec directory"); } switch(amode){ case Aaccess: if(!nomount) domount(&c, nil); break; case Abind: m = nil; if(!nomount) domount(&c, &m); if(c->umh != nil) putmhead(c->umh); c->umh = m; break; case Aremove: case Aopen: Open: /* save the name; domount might change c */ cname = c->name; incref(&cname->ref); m = nil; if(!nomount) domount(&c, &m); /* our own copy to open or remove */ c = cunique(c); /* now it's our copy anyway, we can put the name back */ cnameclose(c->name); c->name = cname; switch(amode){ case Aremove: putmhead(m); break; case Aopen: case Acreate: if(c->umh != nil){ print("cunique umh Open\n"); putmhead(c->umh); c->umh = nil; } /* only save the mount head if it's a multiple element union */ if(m && m->mount && m->mount->next) c->umh = m; else putmhead(m); /* save registers else error() in open has wrong value of c saved */ saveregisters(); if(omode == OEXEC) c->flag &= ~CCACHE; c = devtab[c->type]->open(c, omode&~OCEXEC); if(omode & OCEXEC) c->flag |= CCEXEC; if(omode & ORCLOSE) c->flag |= CRCLOSE; break; } break; case Atodir: /* * Directories (e.g. for cd) are left before the mount point, * so one may mount on / or . and see the effect. */ if(!(c->qid.type & QTDIR)) error(Enotdir); break; case Amount: /* * When mounting on an already mounted upon directory, * one wants subsequent mounts to be attached to the * original directory, not the replacement. Don't domount. */ break; case Acreate: /* * We've already walked all but the last element. * If the last exists, try to open it OTRUNC. * If omode&OEXCL is set, just give up. */ e.nelems++; if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){ if(omode&OEXCL) error(Eexist); omode |= OTRUNC; goto Open; } /* * The semantics of the create(2) system call are that if the * file exists and can be written, it is to be opened with truncation. * On the other hand, the create(5) message fails if the file exists. * If we get two create(2) calls happening simultaneously, * they might both get here and send create(5) messages, but only * one of the messages will succeed. To provide the expected create(2) * semantics, the call with the failed message needs to try the above * walk again, opening for truncation. This correctly solves the * create/create race, in the sense that any observable outcome can * be explained as one happening before the other. * The create/create race is quite common. For example, it happens * when two rc subshells simultaneously update the same * environment variable. * * The implementation still admits a create/create/remove race: * (A) walk to file, fails * (B) walk to file, fails * (A) create file, succeeds, returns * (B) create file, fails * (A) remove file, succeeds, returns * (B) walk to file, return failure. * * This is hardly as common as the create/create race, and is really * not too much worse than what might happen if (B) got a hold of a * file descriptor and then the file was removed -- either way (B) can't do * anything with the result of the create call. So we don't care about this race. * * Applications that care about more fine-grained decision of the races * can use the OEXCL flag to get at the underlying create(5) semantics; * by default we provide the common case. * * We need to stay behind the mount point in case we * need to do the first walk again (should the create fail). * * We also need to cross the mount point and find the directory * in the union in which we should be creating. * * The channel staying behind is c, the one moving forward is cnew. */ m = nil; cnew = nil; /* is this assignment necessary? */ if(!waserror()){ /* try create */ if(!nomount && findmount(&cnew, &m, c->type, c->dev, c->qid)) cnew = createdir(cnew, m); else{ cnew = c; incref(&cnew->ref); } /* * We need our own copy of the Chan because we're * about to send a create, which will move it. Once we have * our own copy, we can fix the name, which might be wrong * if findmount gave us a new Chan. */ cnew = cunique(cnew); cnameclose(cnew->name); cnew->name = c->name; incref(&cnew->name->ref); devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm); poperror(); if(omode & OCEXEC) cnew->flag |= CCEXEC; if(omode & ORCLOSE) cnew->flag |= CRCLOSE; if(m) putmhead(m); cclose(c); c = cnew; c->name = addelem(c->name, e.elems[e.nelems-1]); break; }else{ /* create failed */ cclose(cnew); if(m) putmhead(m); if(omode & OEXCL) nexterror(); /* save error */ createerr = up->errstr; up->errstr = tmperrbuf; /* note: we depend that walk does not error */ if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){ up->errstr = createerr; error(createerr); /* report true error */ } up->errstr = createerr; omode |= OTRUNC; goto Open; } panic("namec: not reached"); default: panic("unknown namec access %d\n", amode); } poperror(); /* place final element in genbuf for e.g. exec */ if(e.nelems > 0) kstrcpy(up->genbuf, e.elems[e.nelems-1], sizeof up->genbuf); else kstrcpy(up->genbuf, ".", sizeof up->genbuf); free(e.name); free(e.elems); free(e.off); return c; } /* * name is valid. skip leading / and ./ as much as possible */ char* skipslash(char *name) { while(name[0]=='/' || (name[0]=='.' && (name[1]==0 || name[1]=='/'))) name++; return name; } char isfrog[256]={ /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0 */ /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0x08 */ /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 */ /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 1, /* 0x28 (1 is '/', 0x2F) */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 1, /* 0x78 (1 is DEL, 0x7F) */ }; /* * Check that the name * a) is in valid memory. * b) is shorter than 2^16 bytes, so it can fit in a 9P string field. * c) contains no frogs. * The first byte is known to be addressible by the requester, so the * routine works for kernel and user memory both. * The parameter slashok flags whether a slash character is an error * or a valid character. */ void validname(char *aname, int slashok) { char *ename, *name; int c; Rune r; name = aname; /* if(((ulong)name & KZERO) != KZERO) { p = name; t = BY2PG-((ulong)p&(BY2PG-1)); while((ename=vmemchr(p, 0, t)) == nil) { p += t; t = BY2PG; } }else */ ename = memchr(name, 0, (1<<16)); if(ename==nil || ename-name>=(1<<16)) error("name too long"); while(*name){ /* all characters above '~' are ok */ c = *(uchar*)name; if(c >= Runeself) name += chartorune(&r, name); else{ if(isfrog[c]) if(!slashok || c!='/'){ snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname); error(up->genbuf); } name++; } } } void isdir(Chan *c) { if(c->qid.type & QTDIR) return; error(Enotdir); } /* * This is necessary because there are many * pointers to the top of a given mount list: * * - the mhead in the namespace hash table * - the mhead in chans returned from findmount: * used in namec and then by unionread. * - the mhead in chans returned from createdir: * used in the open/create race protect, which is gone. * * The RWlock in the Mhead protects the mount list it contains. * The mount list is deleted when we cunmount. * The RWlock ensures that nothing is using the mount list at that time. * * It is okay to replace c->mh with whatever you want as * long as you are sure you have a unique reference to it. * * This comment might belong somewhere else. */ void putmhead(Mhead *m) { if(m && decref(&m->ref) == 0){ m->mount = (Mount*)0xCafeBeef; free(m); } } drawterm-20110822.orig/kern/netif.h0000644000175000017500000000560611245145712016317 0ustar tinchotinchotypedef struct Etherpkt Etherpkt; typedef struct Netaddr Netaddr; typedef struct Netfile Netfile; typedef struct Netif Netif; enum { Nmaxaddr= 64, Nmhash= 31, Ncloneqid= 1, Naddrqid, N2ndqid, N3rdqid, Ndataqid, Nctlqid, Nstatqid, Ntypeqid, Nifstatqid, }; /* * Macros to manage Qid's used for multiplexed devices */ #define NETTYPE(x) (((ulong)x)&0x1f) #define NETID(x) ((((ulong)x))>>5) #define NETQID(i,t) ((((ulong)i)<<5)|(t)) /* * one per multiplexed connection */ struct Netfile { QLock lk; int inuse; ulong mode; char owner[KNAMELEN]; int type; /* multiplexor type */ int prom; /* promiscuous mode */ int scan; /* base station scanning interval */ int bridge; /* bridge mode */ int headersonly; /* headers only - no data */ uchar maddr[8]; /* bitmask of multicast addresses requested */ int nmaddr; /* number of multicast addresses */ Queue *in; /* input buffer */ }; /* * a network address */ struct Netaddr { Netaddr *next; /* allocation chain */ Netaddr *hnext; uchar addr[Nmaxaddr]; int ref; }; /* * a network interface */ struct Netif { QLock lk; /* multiplexing */ char name[KNAMELEN]; /* for top level directory */ int nfile; /* max number of Netfiles */ Netfile **f; /* about net */ int limit; /* flow control */ int alen; /* address length */ int mbps; /* megabits per sec */ uchar addr[Nmaxaddr]; uchar bcast[Nmaxaddr]; Netaddr *maddr; /* known multicast addresses */ int nmaddr; /* number of known multicast addresses */ Netaddr *mhash[Nmhash]; /* hash table of multicast addresses */ int prom; /* number of promiscuous opens */ int scan; /* number of base station scanners */ int all; /* number of -1 multiplexors */ /* statistics */ int misses; int inpackets; int outpackets; int crcs; /* input crc errors */ int oerrs; /* output errors */ int frames; /* framing errors */ int overflows; /* packet overflows */ int buffs; /* buffering errors */ int soverflows; /* software overflow */ /* routines for touching the hardware */ void *arg; void (*promiscuous)(void*, int); void (*multicast)(void*, uchar*, int); void (*scanbs)(void*, uint); /* scan for base stations */ }; void netifinit(Netif*, char*, int, ulong); Walkqid* netifwalk(Netif*, Chan*, Chan*, char **, int); Chan* netifopen(Netif*, Chan*, int); void netifclose(Netif*, Chan*); long netifread(Netif*, Chan*, void*, long, ulong); Block* netifbread(Netif*, Chan*, long, ulong); long netifwrite(Netif*, Chan*, void*, long); int netifwstat(Netif*, Chan*, uchar*, int); int netifstat(Netif*, Chan*, uchar*, int); int activemulti(Netif*, uchar*, int); /* * Ethernet specific */ enum { Eaddrlen= 6, ETHERMINTU = 60, /* minimum transmit size */ ETHERMAXTU = 1514, /* maximum transmit size */ ETHERHDRSIZE = 14, /* size of an ethernet header */ }; struct Etherpkt { uchar d[Eaddrlen]; uchar s[Eaddrlen]; uchar type[2]; uchar data[1500]; }; drawterm-20110822.orig/kern/qio.c0000644000175000017500000005570211245145712015777 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" static ulong padblockcnt; static ulong concatblockcnt; static ulong pullupblockcnt; static ulong copyblockcnt; static ulong consumecnt; static ulong producecnt; static ulong qcopycnt; static int debugging; #define QDEBUG if(0) /* * IO queues */ struct Queue { Lock lk; Block* bfirst; /* buffer */ Block* blast; int len; /* bytes allocated to queue */ int dlen; /* data bytes in queue */ int limit; /* max bytes in queue */ int inilim; /* initial limit */ int state; int noblock; /* true if writes return immediately when q full */ int eof; /* number of eofs read by user */ void (*kick)(void*); /* restart output */ void (*bypass)(void*, Block*); /* bypass queue altogether */ void* arg; /* argument to kick */ QLock rlock; /* mutex for reading processes */ Rendez rr; /* process waiting to read */ QLock wlock; /* mutex for writing processes */ Rendez wr; /* process waiting to write */ char err[ERRMAX]; }; enum { Maxatomic = 64*1024, }; uint qiomaxatomic = Maxatomic; void ixsummary(void) { debugging ^= 1; iallocsummary(); print("pad %lud, concat %lud, pullup %lud, copy %lud\n", padblockcnt, concatblockcnt, pullupblockcnt, copyblockcnt); print("consume %lud, produce %lud, qcopy %lud\n", consumecnt, producecnt, qcopycnt); } /* * free a list of blocks */ void freeblist(Block *b) { Block *next; for(; b != 0; b = next){ next = b->next; b->next = 0; freeb(b); } } /* * pad a block to the front (or the back if size is negative) */ Block* padblock(Block *bp, int size) { int n; Block *nbp; QDEBUG checkb(bp, "padblock 1"); if(size >= 0){ if(bp->rp - bp->base >= size){ bp->rp -= size; return bp; } if(bp->next) panic("padblock 0x%p", getcallerpc(&bp)); n = BLEN(bp); padblockcnt++; nbp = allocb(size+n); nbp->rp += size; nbp->wp = nbp->rp; memmove(nbp->wp, bp->rp, n); nbp->wp += n; freeb(bp); nbp->rp -= size; } else { size = -size; if(bp->next) panic("padblock 0x%p", getcallerpc(&bp)); if(bp->lim - bp->wp >= size) return bp; n = BLEN(bp); padblockcnt++; nbp = allocb(size+n); memmove(nbp->wp, bp->rp, n); nbp->wp += n; freeb(bp); } QDEBUG checkb(nbp, "padblock 1"); return nbp; } /* * return count of bytes in a string of blocks */ int blocklen(Block *bp) { int len; len = 0; while(bp) { len += BLEN(bp); bp = bp->next; } return len; } /* * return count of space in blocks */ int blockalloclen(Block *bp) { int len; len = 0; while(bp) { len += BALLOC(bp); bp = bp->next; } return len; } /* * copy the string of blocks into * a single block and free the string */ Block* concatblock(Block *bp) { int len; Block *nb, *f; if(bp->next == 0) return bp; nb = allocb(blocklen(bp)); for(f = bp; f; f = f->next) { len = BLEN(f); memmove(nb->wp, f->rp, len); nb->wp += len; } concatblockcnt += BLEN(nb); freeblist(bp); QDEBUG checkb(nb, "concatblock 1"); return nb; } /* * make sure the first block has at least n bytes */ Block* pullupblock(Block *bp, int n) { int i; Block *nbp; /* * this should almost always be true, it's * just to avoid every caller checking. */ if(BLEN(bp) >= n) return bp; /* * if not enough room in the first block, * add another to the front of the list. */ if(bp->lim - bp->rp < n){ nbp = allocb(n); nbp->next = bp; bp = nbp; } /* * copy bytes from the trailing blocks into the first */ n -= BLEN(bp); while((nbp = bp->next)){ i = BLEN(nbp); if(i > n) { memmove(bp->wp, nbp->rp, n); pullupblockcnt++; bp->wp += n; nbp->rp += n; QDEBUG checkb(bp, "pullupblock 1"); return bp; } else { /* shouldn't happen but why crash if it does */ if(i < 0){ print("pullup negative length packet\n"); i = 0; } memmove(bp->wp, nbp->rp, i); pullupblockcnt++; bp->wp += i; bp->next = nbp->next; nbp->next = 0; freeb(nbp); n -= i; if(n == 0){ QDEBUG checkb(bp, "pullupblock 2"); return bp; } } } freeb(bp); return 0; } /* * make sure the first block has at least n bytes */ Block* pullupqueue(Queue *q, int n) { Block *b; if(BLEN(q->bfirst) >= n) return q->bfirst; q->bfirst = pullupblock(q->bfirst, n); for(b = q->bfirst; b != nil && b->next != nil; b = b->next) ; q->blast = b; return q->bfirst; } /* * trim to len bytes starting at offset */ Block * trimblock(Block *bp, int offset, int len) { ulong l; Block *nb, *startb; QDEBUG checkb(bp, "trimblock 1"); if(blocklen(bp) < offset+len) { freeblist(bp); return nil; } while((l = BLEN(bp)) < offset) { offset -= l; nb = bp->next; bp->next = nil; freeb(bp); bp = nb; } startb = bp; bp->rp += offset; while((l = BLEN(bp)) < len) { len -= l; bp = bp->next; } bp->wp -= (BLEN(bp) - len); if(bp->next) { freeblist(bp->next); bp->next = nil; } return startb; } /* * copy 'count' bytes into a new block */ Block* copyblock(Block *bp, int count) { int l; Block *nbp; QDEBUG checkb(bp, "copyblock 0"); nbp = allocb(count); for(; count > 0 && bp != 0; bp = bp->next){ l = BLEN(bp); if(l > count) l = count; memmove(nbp->wp, bp->rp, l); nbp->wp += l; count -= l; } if(count > 0){ memset(nbp->wp, 0, count); nbp->wp += count; } copyblockcnt++; QDEBUG checkb(nbp, "copyblock 1"); return nbp; } Block* adjustblock(Block* bp, int len) { int n; Block *nbp; if(len < 0){ freeb(bp); return nil; } if(bp->rp+len > bp->lim){ nbp = copyblock(bp, len); freeblist(bp); QDEBUG checkb(nbp, "adjustblock 1"); return nbp; } n = BLEN(bp); if(len > n) memset(bp->wp, 0, len-n); bp->wp = bp->rp+len; QDEBUG checkb(bp, "adjustblock 2"); return bp; } /* * throw away up to count bytes from a * list of blocks. Return count of bytes * thrown away. */ int pullblock(Block **bph, int count) { Block *bp; int n, bytes; bytes = 0; if(bph == nil) return 0; while(*bph != nil && count != 0) { bp = *bph; n = BLEN(bp); if(count < n) n = count; bytes += n; count -= n; bp->rp += n; QDEBUG checkb(bp, "pullblock "); if(BLEN(bp) == 0) { *bph = bp->next; bp->next = nil; freeb(bp); } } return bytes; } /* * get next block from a queue, return null if nothing there */ Block* qget(Queue *q) { int dowakeup; Block *b; /* sync with qwrite */ ilock(&q->lk); b = q->bfirst; if(b == nil){ q->state |= Qstarve; iunlock(&q->lk); return nil; } q->bfirst = b->next; b->next = 0; q->len -= BALLOC(b); q->dlen -= BLEN(b); QDEBUG checkb(b, "qget"); /* if writer flow controlled, restart */ if((q->state & Qflow) && q->len < q->limit/2){ q->state &= ~Qflow; dowakeup = 1; } else dowakeup = 0; iunlock(&q->lk); if(dowakeup) wakeup(&q->wr); return b; } /* * throw away the next 'len' bytes in the queue */ int qdiscard(Queue *q, int len) { Block *b; int dowakeup, n, sofar; ilock(&q->lk); for(sofar = 0; sofar < len; sofar += n){ b = q->bfirst; if(b == nil) break; QDEBUG checkb(b, "qdiscard"); n = BLEN(b); if(n <= len - sofar){ q->bfirst = b->next; b->next = 0; q->len -= BALLOC(b); q->dlen -= BLEN(b); freeb(b); } else { n = len - sofar; b->rp += n; q->dlen -= n; } } /* * if writer flow controlled, restart * * This used to be * q->len < q->limit/2 * but it slows down tcp too much for certain write sizes. * I really don't understand it completely. It may be * due to the queue draining so fast that the transmission * stalls waiting for the app to produce more data. - presotto */ if((q->state & Qflow) && q->len < q->limit){ q->state &= ~Qflow; dowakeup = 1; } else dowakeup = 0; iunlock(&q->lk); if(dowakeup) wakeup(&q->wr); return sofar; } /* * Interrupt level copy out of a queue, return # bytes copied. */ int qconsume(Queue *q, void *vp, int len) { Block *b; int n, dowakeup; uchar *p = vp; Block *tofree = nil; /* sync with qwrite */ ilock(&q->lk); for(;;) { b = q->bfirst; if(b == 0){ q->state |= Qstarve; iunlock(&q->lk); return -1; } QDEBUG checkb(b, "qconsume 1"); n = BLEN(b); if(n > 0) break; q->bfirst = b->next; q->len -= BALLOC(b); /* remember to free this */ b->next = tofree; tofree = b; }; if(n < len) len = n; memmove(p, b->rp, len); consumecnt += n; b->rp += len; q->dlen -= len; /* discard the block if we're done with it */ if((q->state & Qmsg) || len == n){ q->bfirst = b->next; b->next = 0; q->len -= BALLOC(b); q->dlen -= BLEN(b); /* remember to free this */ b->next = tofree; tofree = b; } /* if writer flow controlled, restart */ if((q->state & Qflow) && q->len < q->limit/2){ q->state &= ~Qflow; dowakeup = 1; } else dowakeup = 0; iunlock(&q->lk); if(dowakeup) wakeup(&q->wr); if(tofree != nil) freeblist(tofree); return len; } int qpass(Queue *q, Block *b) { int dlen, len, dowakeup; /* sync with qread */ dowakeup = 0; ilock(&q->lk); if(q->len >= q->limit){ freeblist(b); iunlock(&q->lk); return -1; } if(q->state & Qclosed){ freeblist(b); iunlock(&q->lk); return BALLOC(b); } /* add buffer to queue */ if(q->bfirst) q->blast->next = b; else q->bfirst = b; len = BALLOC(b); dlen = BLEN(b); QDEBUG checkb(b, "qpass"); while(b->next){ b = b->next; QDEBUG checkb(b, "qpass"); len += BALLOC(b); dlen += BLEN(b); } q->blast = b; q->len += len; q->dlen += dlen; if(q->len >= q->limit/2) q->state |= Qflow; if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } iunlock(&q->lk); if(dowakeup) wakeup(&q->rr); return len; } int qpassnolim(Queue *q, Block *b) { int dlen, len, dowakeup; /* sync with qread */ dowakeup = 0; ilock(&q->lk); if(q->state & Qclosed){ freeblist(b); iunlock(&q->lk); return BALLOC(b); } /* add buffer to queue */ if(q->bfirst) q->blast->next = b; else q->bfirst = b; len = BALLOC(b); dlen = BLEN(b); QDEBUG checkb(b, "qpass"); while(b->next){ b = b->next; QDEBUG checkb(b, "qpass"); len += BALLOC(b); dlen += BLEN(b); } q->blast = b; q->len += len; q->dlen += dlen; if(q->len >= q->limit/2) q->state |= Qflow; if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } iunlock(&q->lk); if(dowakeup) wakeup(&q->rr); return len; } /* * if the allocated space is way out of line with the used * space, reallocate to a smaller block */ Block* packblock(Block *bp) { Block **l, *nbp; int n; for(l = &bp; *l; l = &(*l)->next){ nbp = *l; n = BLEN(nbp); if((n<<2) < BALLOC(nbp)){ *l = allocb(n); memmove((*l)->wp, nbp->rp, n); (*l)->wp += n; (*l)->next = nbp->next; freeb(nbp); } } return bp; } int qproduce(Queue *q, void *vp, int len) { Block *b; int dowakeup; uchar *p = vp; /* sync with qread */ dowakeup = 0; ilock(&q->lk); /* no waiting receivers, room in buffer? */ if(q->len >= q->limit){ q->state |= Qflow; iunlock(&q->lk); return -1; } /* save in buffer */ b = iallocb(len); if(b == 0){ iunlock(&q->lk); return 0; } memmove(b->wp, p, len); producecnt += len; b->wp += len; if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->blast = b; /* b->next = 0; done by iallocb() */ q->len += BALLOC(b); q->dlen += BLEN(b); QDEBUG checkb(b, "qproduce"); if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } if(q->len >= q->limit) q->state |= Qflow; iunlock(&q->lk); if(dowakeup) wakeup(&q->rr); return len; } /* * copy from offset in the queue */ Block* qcopy(Queue *q, int len, ulong offset) { int sofar; int n; Block *b, *nb; uchar *p; nb = allocb(len); ilock(&q->lk); /* go to offset */ b = q->bfirst; for(sofar = 0; ; sofar += n){ if(b == nil){ iunlock(&q->lk); return nb; } n = BLEN(b); if(sofar + n > offset){ p = b->rp + offset - sofar; n -= offset - sofar; break; } QDEBUG checkb(b, "qcopy"); b = b->next; } /* copy bytes from there */ for(sofar = 0; sofar < len;){ if(n > len - sofar) n = len - sofar; memmove(nb->wp, p, n); qcopycnt += n; sofar += n; nb->wp += n; b = b->next; if(b == nil) break; n = BLEN(b); p = b->rp; } iunlock(&q->lk); return nb; } /* * called by non-interrupt code */ Queue* qopen(int limit, int msg, void (*kick)(void*), void *arg) { Queue *q; q = malloc(sizeof(Queue)); if(q == 0) return 0; q->limit = q->inilim = limit; q->kick = kick; q->arg = arg; q->state = msg; q->state |= Qstarve; q->eof = 0; q->noblock = 0; return q; } /* open a queue to be bypassed */ Queue* qbypass(void (*bypass)(void*, Block*), void *arg) { Queue *q; q = malloc(sizeof(Queue)); if(q == 0) return 0; q->limit = 0; q->arg = arg; q->bypass = bypass; q->state = 0; return q; } static int notempty(void *a) { Queue *q = a; return (q->state & Qclosed) || q->bfirst != 0; } /* * wait for the queue to be non-empty or closed. * called with q ilocked. */ static int qwait(Queue *q) { /* wait for data */ for(;;){ if(q->bfirst != nil) break; if(q->state & Qclosed){ if(++q->eof > 3) return -1; if(*q->err && strcmp(q->err, Ehungup) != 0) return -1; return 0; } q->state |= Qstarve; /* flag requesting producer to wake me */ iunlock(&q->lk); sleep(&q->rr, notempty, q); ilock(&q->lk); } return 1; } /* * add a block list to a queue */ void qaddlist(Queue *q, Block *b) { /* queue the block */ if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->len += blockalloclen(b); q->dlen += blocklen(b); while(b->next) b = b->next; q->blast = b; } /* * called with q ilocked */ Block* qremove(Queue *q) { Block *b; b = q->bfirst; if(b == nil) return nil; q->bfirst = b->next; b->next = nil; q->dlen -= BLEN(b); q->len -= BALLOC(b); QDEBUG checkb(b, "qremove"); return b; } /* * copy the contents of a string of blocks into * memory. emptied blocks are freed. return * pointer to first unconsumed block. */ Block* bl2mem(uchar *p, Block *b, int n) { int i; Block *next; for(; b != nil; b = next){ i = BLEN(b); if(i > n){ memmove(p, b->rp, n); b->rp += n; return b; } memmove(p, b->rp, i); n -= i; p += i; b->rp += i; next = b->next; freeb(b); } return nil; } /* * copy the contents of memory into a string of blocks. * return nil on error. */ Block* mem2bl(uchar *p, int len) { int n; Block *b, *first, **l; first = nil; l = &first; if(waserror()){ freeblist(first); nexterror(); } do { n = len; if(n > Maxatomic) n = Maxatomic; *l = b = allocb(n); /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */ memmove(b->wp, p, n); b->wp += n; p += n; len -= n; l = &b->next; } while(len > 0); poperror(); return first; } /* * put a block back to the front of the queue * called with q ilocked */ void qputback(Queue *q, Block *b) { b->next = q->bfirst; if(q->bfirst == nil) q->blast = b; q->bfirst = b; q->len += BALLOC(b); q->dlen += BLEN(b); } /* * flow control, get producer going again * called with q ilocked */ static void qwakeup_iunlock(Queue *q) { int dowakeup = 0; /* if writer flow controlled, restart */ if((q->state & Qflow) && q->len < q->limit/2){ q->state &= ~Qflow; dowakeup = 1; } iunlock(&q->lk); /* wakeup flow controlled writers */ if(dowakeup){ if(q->kick) q->kick(q->arg); wakeup(&q->wr); } } /* * get next block from a queue (up to a limit) */ Block* qbread(Queue *q, int len) { Block *b, *nb; int n; qlock(&q->rlock); if(waserror()){ qunlock(&q->rlock); nexterror(); } ilock(&q->lk); switch(qwait(q)){ case 0: /* queue closed */ iunlock(&q->lk); qunlock(&q->rlock); poperror(); return nil; case -1: /* multiple reads on a closed queue */ iunlock(&q->lk); error(q->err); } /* if we get here, there's at least one block in the queue */ b = qremove(q); n = BLEN(b); /* split block if it's too big and this is not a message queue */ nb = b; if(n > len){ if((q->state&Qmsg) == 0){ n -= len; b = allocb(n); memmove(b->wp, nb->rp+len, n); b->wp += n; qputback(q, b); } nb->wp = nb->rp + len; } /* restart producer */ qwakeup_iunlock(q); poperror(); qunlock(&q->rlock); return nb; } /* * read a queue. if no data is queued, post a Block * and wait on its Rendez. */ long qread(Queue *q, void *vp, int len) { Block *b, *first, **l; int m, n; qlock(&q->rlock); if(waserror()){ qunlock(&q->rlock); nexterror(); } ilock(&q->lk); again: switch(qwait(q)){ case 0: /* queue closed */ iunlock(&q->lk); qunlock(&q->rlock); poperror(); return 0; case -1: /* multiple reads on a closed queue */ iunlock(&q->lk); error(q->err); } /* if we get here, there's at least one block in the queue */ if(q->state & Qcoalesce){ /* when coalescing, 0 length blocks just go away */ b = q->bfirst; if(BLEN(b) <= 0){ freeb(qremove(q)); goto again; } /* grab the first block plus as many * following blocks as will completely * fit in the read. */ n = 0; l = &first; m = BLEN(b); for(;;) { *l = qremove(q); l = &b->next; n += m; b = q->bfirst; if(b == nil) break; m = BLEN(b); if(n+m > len) break; } } else { first = qremove(q); n = BLEN(first); } /* copy to user space outside of the ilock */ iunlock(&q->lk); b = bl2mem(vp, first, len); ilock(&q->lk); /* take care of any left over partial block */ if(b != nil){ n -= BLEN(b); if(q->state & Qmsg) freeb(b); else qputback(q, b); } /* restart producer */ qwakeup_iunlock(q); poperror(); qunlock(&q->rlock); return n; } static int qnotfull(void *a) { Queue *q = a; return q->len < q->limit || (q->state & Qclosed); } ulong noblockcnt; /* * add a block to a queue obeying flow control */ long qbwrite(Queue *q, Block *b) { int n, dowakeup; n = BLEN(b); if(q->bypass){ (*q->bypass)(q->arg, b); return n; } dowakeup = 0; qlock(&q->wlock); if(waserror()){ if(b != nil) freeb(b); qunlock(&q->wlock); nexterror(); } ilock(&q->lk); /* give up if the queue is closed */ if(q->state & Qclosed){ iunlock(&q->lk); error(q->err); } /* if nonblocking, don't queue over the limit */ if(q->len >= q->limit){ if(q->noblock){ iunlock(&q->lk); freeb(b); noblockcnt += n; qunlock(&q->wlock); poperror(); return n; } } /* queue the block */ if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->blast = b; b->next = 0; q->len += BALLOC(b); q->dlen += n; QDEBUG checkb(b, "qbwrite"); b = nil; /* make sure other end gets awakened */ if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } iunlock(&q->lk); /* get output going again */ if(q->kick && (dowakeup || (q->state&Qkick))) q->kick(q->arg); /* wakeup anyone consuming at the other end */ if(dowakeup){ wakeup(&q->rr); /* if we just wokeup a higher priority process, let it run */ /* p = wakeup(&q->rr); if(p != nil && p->priority > up->priority) sched(); */ } /* * flow control, wait for queue to get below the limit * before allowing the process to continue and queue * more. We do this here so that postnote can only * interrupt us after the data has been queued. This * means that things like 9p flushes and ssl messages * will not be disrupted by software interrupts. * * Note - this is moderately dangerous since a process * that keeps getting interrupted and rewriting will * queue infinite crud. */ for(;;){ if(q->noblock || qnotfull(q)) break; ilock(&q->lk); q->state |= Qflow; iunlock(&q->lk); sleep(&q->wr, qnotfull, q); } USED(b); qunlock(&q->wlock); poperror(); return n; } /* * write to a queue. only Maxatomic bytes at a time is atomic. */ int qwrite(Queue *q, void *vp, int len) { int n, sofar; Block *b; uchar *p = vp; QDEBUG if(!islo()) print("qwrite hi %p\n", getcallerpc(&q)); sofar = 0; do { n = len-sofar; if(n > Maxatomic) n = Maxatomic; b = allocb(n); /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */ if(waserror()){ freeb(b); nexterror(); } memmove(b->wp, p+sofar, n); poperror(); b->wp += n; qbwrite(q, b); sofar += n; } while(sofar < len && (q->state & Qmsg) == 0); return len; } /* * used by print() to write to a queue. Since we may be splhi or not in * a process, don't qlock. */ int qiwrite(Queue *q, void *vp, int len) { int n, sofar, dowakeup; Block *b; uchar *p = vp; dowakeup = 0; sofar = 0; do { n = len-sofar; if(n > Maxatomic) n = Maxatomic; b = iallocb(n); if(b == nil) break; memmove(b->wp, p+sofar, n); b->wp += n; ilock(&q->lk); QDEBUG checkb(b, "qiwrite"); if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->blast = b; q->len += BALLOC(b); q->dlen += n; if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } iunlock(&q->lk); if(dowakeup){ if(q->kick) q->kick(q->arg); wakeup(&q->rr); } sofar += n; } while(sofar < len && (q->state & Qmsg) == 0); return sofar; } /* * be extremely careful when calling this, * as there is no reference accounting */ void qfree(Queue *q) { qclose(q); free(q); } /* * Mark a queue as closed. No further IO is permitted. * All blocks are released. */ void qclose(Queue *q) { Block *bfirst; if(q == nil) return; /* mark it */ ilock(&q->lk); q->state |= Qclosed; q->state &= ~(Qflow|Qstarve); strcpy(q->err, Ehungup); bfirst = q->bfirst; q->bfirst = 0; q->len = 0; q->dlen = 0; q->noblock = 0; iunlock(&q->lk); /* free queued blocks */ freeblist(bfirst); /* wake up readers/writers */ wakeup(&q->rr); wakeup(&q->wr); } /* * Mark a queue as closed. Wakeup any readers. Don't remove queued * blocks. */ void qhangup(Queue *q, char *msg) { /* mark it */ ilock(&q->lk); q->state |= Qclosed; if(msg == 0 || *msg == 0) strcpy(q->err, Ehungup); else strncpy(q->err, msg, ERRMAX-1); iunlock(&q->lk); /* wake up readers/writers */ wakeup(&q->rr); wakeup(&q->wr); } /* * return non-zero if the q is hungup */ int qisclosed(Queue *q) { return q->state & Qclosed; } /* * mark a queue as no longer hung up */ void qreopen(Queue *q) { ilock(&q->lk); q->state &= ~Qclosed; q->state |= Qstarve; q->eof = 0; q->limit = q->inilim; iunlock(&q->lk); } /* * return bytes queued */ int qlen(Queue *q) { return q->dlen; } /* * return space remaining before flow control */ int qwindow(Queue *q) { int l; l = q->limit - q->len; if(l < 0) l = 0; return l; } /* * return true if we can read without blocking */ int qcanread(Queue *q) { return q->bfirst!=0; } /* * change queue limit */ void qsetlimit(Queue *q, int limit) { q->limit = limit; } /* * set blocking/nonblocking */ void qnoblock(Queue *q, int onoff) { q->noblock = onoff; } /* * flush the output queue */ void qflush(Queue *q) { Block *bfirst; /* mark it */ ilock(&q->lk); bfirst = q->bfirst; q->bfirst = 0; q->len = 0; q->dlen = 0; iunlock(&q->lk); /* free queued blocks */ freeblist(bfirst); /* wake up readers/writers */ wakeup(&q->wr); } int qfull(Queue *q) { return q->state & Qflow; } int qstate(Queue *q) { return q->state; } drawterm-20110822.orig/kern/devaudio.h0000644000175000017500000000051011245145711016776 0ustar tinchotinchoenum { Fmono = 1, Fin = 2, Fout = 4, Vaudio = 0, Vsynth, Vcd, Vline, Vmic, Vspeaker, Vtreb, Vbass, Vspeed, Vpcm, Nvol, }; void audiodevopen(void); void audiodevclose(void); int audiodevread(void*, int); int audiodevwrite(void*, int); void audiodevgetvol(int, int*, int*); void audiodevsetvol(int, int, int); drawterm-20110822.orig/kern/devpipe.c0000644000175000017500000001344711245145712016643 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "netif.h" typedef struct Pipe Pipe; struct Pipe { QLock lk; Pipe *next; int ref; ulong path; Queue *q[2]; int qref[2]; }; struct { Lock lk; ulong path; } pipealloc; enum { Qdir, Qdata0, Qdata1, }; Dirtab pipedir[] = { ".", {Qdir,0,QTDIR}, 0, DMDIR|0500, "data", {Qdata0}, 0, 0600, "data1", {Qdata1}, 0, 0600, }; #define NPIPEDIR 3 static void pipeinit(void) { if(conf.pipeqsize == 0){ if(conf.nmach > 1) conf.pipeqsize = 256*1024; else conf.pipeqsize = 32*1024; } } /* * create a pipe, no streams are created until an open */ static Chan* pipeattach(char *spec) { Pipe *p; Chan *c; c = devattach('|', spec); p = malloc(sizeof(Pipe)); if(p == 0) exhausted("memory"); p->ref = 1; p->q[0] = qopen(conf.pipeqsize, 0, 0, 0); if(p->q[0] == 0){ free(p); exhausted("memory"); } p->q[1] = qopen(conf.pipeqsize, 0, 0, 0); if(p->q[1] == 0){ free(p->q[0]); free(p); exhausted("memory"); } lock(&pipealloc.lk); p->path = ++pipealloc.path; unlock(&pipealloc.lk); mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR); c->aux = p; c->dev = 0; return c; } static int pipegen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) { Qid q; int len; Pipe *p; USED(name); if(i == DEVDOTDOT){ devdir(c, c->qid, "#|", 0, eve, DMDIR|0555, dp); return 1; } i++; /* skip . */ if(tab==0 || i>=ntab) return -1; tab += i; p = c->aux; switch((ulong)tab->qid.path){ case Qdata0: len = qlen(p->q[0]); break; case Qdata1: len = qlen(p->q[1]); break; default: len = tab->length; break; } mkqid(&q, NETQID(NETID(c->qid.path), tab->qid.path), 0, QTFILE); devdir(c, q, tab->name, len, eve, tab->perm, dp); return 1; } static Walkqid* pipewalk(Chan *c, Chan *nc, char **name, int nname) { Walkqid *wq; Pipe *p; wq = devwalk(c, nc, name, nname, pipedir, NPIPEDIR, pipegen); if(wq != nil && wq->clone != nil && wq->clone != c){ p = c->aux; qlock(&p->lk); p->ref++; if(c->flag & COPEN){ print("channel open in pipewalk\n"); switch(NETTYPE(c->qid.path)){ case Qdata0: p->qref[0]++; break; case Qdata1: p->qref[1]++; break; } } qunlock(&p->lk); } return wq; } static int pipestat(Chan *c, uchar *db, int n) { Pipe *p; Dir dir; p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdir: devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir); break; case Qdata0: devdir(c, c->qid, "data", qlen(p->q[0]), eve, 0600, &dir); break; case Qdata1: devdir(c, c->qid, "data1", qlen(p->q[1]), eve, 0600, &dir); break; default: panic("pipestat"); } n = convD2M(&dir, db, n); if(n < BIT16SZ) error(Eshortstat); return n; } /* * if the stream doesn't exist, create it */ static Chan* pipeopen(Chan *c, int omode) { Pipe *p; if(c->qid.type & QTDIR){ if(omode != OREAD) error(Ebadarg); c->mode = omode; c->flag |= COPEN; c->offset = 0; return c; } p = c->aux; qlock(&p->lk); switch(NETTYPE(c->qid.path)){ case Qdata0: p->qref[0]++; break; case Qdata1: p->qref[1]++; break; } qunlock(&p->lk); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; c->iounit = qiomaxatomic; return c; } static void pipeclose(Chan *c) { Pipe *p; p = c->aux; qlock(&p->lk); if(c->flag & COPEN){ /* * closing either side hangs up the stream */ switch(NETTYPE(c->qid.path)){ case Qdata0: p->qref[0]--; if(p->qref[0] == 0){ qhangup(p->q[1], 0); qclose(p->q[0]); } break; case Qdata1: p->qref[1]--; if(p->qref[1] == 0){ qhangup(p->q[0], 0); qclose(p->q[1]); } break; } } /* * if both sides are closed, they are reusable */ if(p->qref[0] == 0 && p->qref[1] == 0){ qreopen(p->q[0]); qreopen(p->q[1]); } /* * free the structure on last close */ p->ref--; if(p->ref == 0){ qunlock(&p->lk); free(p->q[0]); free(p->q[1]); free(p); } else qunlock(&p->lk); } static long piperead(Chan *c, void *va, long n, vlong offset) { Pipe *p; USED(offset); p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdir: return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen); case Qdata0: return qread(p->q[0], va, n); case Qdata1: return qread(p->q[1], va, n); default: panic("piperead"); } return -1; /* not reached */ } static Block* pipebread(Chan *c, long n, ulong offset) { Pipe *p; p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdata0: return qbread(p->q[0], n); case Qdata1: return qbread(p->q[1], n); } return devbread(c, n, offset); } /* * a write to a closed pipe causes a note to be sent to * the process. */ static long pipewrite(Chan *c, void *va, long n, vlong offset) { Pipe *p; USED(offset); if(!islo()) print("pipewrite hi %lux\n", getcallerpc(&c)); if(waserror()) { /* avoid notes when pipe is a mounted queue */ if((c->flag & CMSG) == 0) postnote(up, 1, "sys: write on closed pipe", NUser); nexterror(); } p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdata0: n = qwrite(p->q[1], va, n); break; case Qdata1: n = qwrite(p->q[0], va, n); break; default: panic("pipewrite"); } poperror(); return n; } static long pipebwrite(Chan *c, Block *bp, ulong offset) { long n; Pipe *p; USED(offset); if(waserror()) { /* avoid notes when pipe is a mounted queue */ if((c->flag & CMSG) == 0) postnote(up, 1, "sys: write on closed pipe", NUser); nexterror(); } p = c->aux; switch(NETTYPE(c->qid.path)){ case Qdata0: n = qbwrite(p->q[1], bp); break; case Qdata1: n = qbwrite(p->q[0], bp); break; default: n = 0; panic("pipebwrite"); } poperror(); return n; } Dev pipedevtab = { '|', "pipe", devreset, pipeinit, devshutdown, pipeattach, pipewalk, pipestat, pipeopen, devcreate, pipeclose, piperead, pipebread, pipewrite, pipebwrite, devremove, devwstat, }; drawterm-20110822.orig/kern/devfs-win32.c0000644000175000017500000002512511245146177017260 0ustar tinchotincho/* * Disable Unicode until the calls to FindFirstFile etc * are changed to use wide character strings. */ #undef UNICODE #include #include #include #include #ifndef NAME_MAX # define NAME_MAX 256 #endif #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" typedef struct DIR DIR; typedef struct Ufsinfo Ufsinfo; enum { NUID = 256, NGID = 256, MAXPATH = 1024, MAXCOMP = 128 }; struct DIR { HANDLE handle; char* path; int index; WIN32_FIND_DATA wfd; }; struct Ufsinfo { int mode; int fd; int uid; int gid; DIR* dir; ulong offset; QLock oq; char nextname[NAME_MAX]; }; DIR* opendir(char*); int readdir(char*, DIR*); void closedir(DIR*); void rewinddir(DIR*); char *base = "c:/."; static Qid fsqid(char*, struct stat *); static void fspath(Chan*, char*, char*); // static void fsperm(Chan*, int); static ulong fsdirread(Chan*, uchar*, int, ulong); static int fsomode(int); static int chown(char *path, int uid, int); /* clumsy hack, but not worse than the Path stuff in the last one */ static char* uc2name(Chan *c) { char *s; if(c->name == nil) return "/"; s = c2name(c); if(s[0]=='#' && s[1]=='U') return s+2; return s; } static char* lastelem(Chan *c) { char *s, *t; s = uc2name(c); if((t = strrchr(s, '/')) == nil) return s; if(t[1] == 0) return t; return t+1; } static Chan* fsattach(char *spec) { Chan *c; struct stat stbuf; static int devno; Ufsinfo *uif; if(stat(base, &stbuf) < 0) error(strerror(errno)); c = devattach('U', spec); uif = mallocz(sizeof(Ufsinfo), 1); uif->gid = stbuf.st_gid; uif->uid = stbuf.st_uid; uif->mode = stbuf.st_mode; c->aux = uif; c->dev = devno++; c->qid.type = QTDIR; /*print("fsattach %s\n", c2name(c));*/ return c; } static Chan* fsclone(Chan *c, Chan *nc) { Ufsinfo *uif; uif = mallocz(sizeof(Ufsinfo), 1); *uif = *(Ufsinfo*)c->aux; nc->aux = uif; return nc; } static int fswalk1(Chan *c, char *name) { struct stat stbuf; char path[MAXPATH]; Ufsinfo *uif; fspath(c, name, path); /* print("** fs walk '%s' -> %s\n", path, name); */ if(stat(path, &stbuf) < 0) return 0; uif = c->aux; uif->gid = stbuf.st_gid; uif->uid = stbuf.st_uid; uif->mode = stbuf.st_mode; c->qid = fsqid(path, &stbuf); return 1; } extern Cname* addelem(Cname*, char*); static Walkqid* fswalk(Chan *c, Chan *nc, char **name, int nname) { int i; Cname *cname; Walkqid *wq; if(nc != nil) panic("fswalk: nc != nil"); wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); nc = devclone(c); cname = c->name; incref(&cname->ref); fsclone(c, nc); wq->clone = nc; for(i=0; iname = cname; if(fswalk1(nc, name[i]) == 0) break; cname = addelem(cname, name[i]); wq->qid[i] = nc->qid; } nc->name = cname; if(i != nname){ cclose(nc); wq->clone = nil; } wq->nqid = i; return wq; } static int fsstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; char path[MAXPATH]; if(n < BIT16SZ) error(Eshortstat); fspath(c, 0, path); if(stat(path, &stbuf) < 0) error(strerror(errno)); d.name = lastelem(c); d.uid = "unknown"; d.gid = "unknown"; d.muid = "unknown"; d.qid = c->qid; d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; return convD2M(&d, buf, n); } static Chan* fsopen(Chan *c, int mode) { char path[MAXPATH]; int m, isdir; Ufsinfo *uif; /*print("fsopen %s\n", c2name(c));*/ m = mode & (OTRUNC|3); switch(m) { case 0: break; case 1: case 1|16: break; case 2: case 0|16: case 2|16: break; case 3: break; default: error(Ebadarg); } isdir = c->qid.type & QTDIR; if(isdir && mode != OREAD) error(Eperm); m = fsomode(m & 3); c->mode = openmode(mode); uif = c->aux; fspath(c, 0, path); if(isdir) { uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { if(mode & OTRUNC) m |= O_TRUNC; uif->fd = open(path, m|_O_BINARY, 0666); if(uif->fd < 0) error(strerror(errno)); } uif->offset = 0; c->offset = 0; c->flag |= COPEN; return c; } static void fscreate(Chan *c, char *name, int mode, ulong perm) { int fd, m; char path[MAXPATH]; struct stat stbuf; Ufsinfo *uif; m = fsomode(mode&3); fspath(c, name, path); uif = c->aux; if(perm & DMDIR) { if(m) error(Eperm); if(mkdir(path) < 0) error(strerror(errno)); fd = open(path, 0); if(fd >= 0) { chmod(path, perm & 0777); chown(path, uif->uid, uif->uid); } close(fd); uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666); if(fd >= 0) { if(m != 1) { close(fd); fd = open(path, m|_O_BINARY); } chmod(path, perm & 0777); chown(path, uif->uid, uif->gid); } if(fd < 0) error(strerror(errno)); uif->fd = fd; } if(stat(path, &stbuf) < 0) error(strerror(errno)); c->qid = fsqid(path, &stbuf); c->offset = 0; c->flag |= COPEN; c->mode = openmode(mode); } static void fsclose(Chan *c) { Ufsinfo *uif; uif = c->aux; if(c->flag & COPEN) { if(c->qid.type & QTDIR) closedir(uif->dir); else close(uif->fd); } free(uif); } static long fsread(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; /*print("fsread %s\n", c2name(c));*/ if(c->qid.type & QTDIR) return fsdirread(c, va, n, offset); uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = read(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static long fswrite(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = write(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static void fsremove(Chan *c) { int n; char path[MAXPATH]; fspath(c, 0, path); if(c->qid.type & QTDIR) n = rmdir(path); else n = remove(path); if(n < 0) error(strerror(errno)); } static int fswstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; char old[MAXPATH], new[MAXPATH]; char strs[MAXPATH*3], *p; Ufsinfo *uif; if (convM2D(buf, n, &d, strs) != n) error(Ebadstat); fspath(c, 0, old); if(stat(old, &stbuf) < 0) error(strerror(errno)); uif = c->aux; // if(uif->uid != stbuf.st_uid) // error(Eowner); if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) { fspath(c, 0, old); strcpy(new, old); p = strrchr(new, '/'); strcpy(p+1, d.name); if(rename(old, new) < 0) error(strerror(errno)); } fspath(c, 0, old); if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { if(chmod(old, d.mode&0777) < 0) error(strerror(errno)); uif->mode &= ~0777; uif->mode |= d.mode&0777; } /* p = name2pass(gid, d.gid); if(p == 0) error(Eunknown); if(p->id != stbuf.st_gid) { if(chown(old, stbuf.st_uid, p->id) < 0) error(sys_errlist[errno]); uif->gid = p->id; } */ return n; } static Qid fsqid(char *p, struct stat *st) { Qid q; int dev; ulong h; static int nqdev; static uchar *qdev; if(qdev == 0) qdev = mallocz(65536U, 1); q.type = 0; if((st->st_mode&S_IFMT) == S_IFDIR) q.type = QTDIR; dev = st->st_dev & 0xFFFFUL; if(qdev[dev] == 0) qdev[dev] = ++nqdev; h = 0; while(*p != '\0') h += *p++ * 13; q.path = (vlong)qdev[dev]<<32; q.path |= h; q.vers = st->st_mtime; return q; } static void fspath(Chan *c, char *ext, char *path) { strcpy(path, base); strcat(path, "/"); strcat(path, uc2name(c)); if(ext) { strcat(path, "/"); strcat(path, ext); } cleanname(path); } static int isdots(char *name) { if(name[0] != '.') return 0; if(name[1] == '\0') return 1; if(name[1] != '.') return 0; if(name[2] == '\0') return 1; return 0; } static int p9readdir(char *name, Ufsinfo *uif) { if(uif->nextname[0]){ strcpy(name, uif->nextname); uif->nextname[0] = 0; return 1; } return readdir(name, uif->dir); } static ulong fsdirread(Chan *c, uchar *va, int count, ulong offset) { int i; Dir d; long n; char de[NAME_MAX]; struct stat stbuf; char path[MAXPATH], dirpath[MAXPATH]; Ufsinfo *uif; /*print("fsdirread %s\n", c2name(c));*/ i = 0; uif = c->aux; errno = 0; if(uif->offset != offset) { if(offset != 0) error("bad offset in fsdirread"); uif->offset = offset; /* sync offset */ uif->nextname[0] = 0; rewinddir(uif->dir); } fspath(c, 0, dirpath); while(i+BIT16SZ < count) { if(!p9readdir(de, uif)) break; if(de[0]==0 || isdots(de)) continue; d.name = de; sprint(path, "%s/%s", dirpath, de); memset(&stbuf, 0, sizeof stbuf); if(stat(path, &stbuf) < 0) { print("dir: bad path %s\n", path); /* but continue... probably a bad symlink */ } d.uid = "unknown"; d.gid = "unknown"; d.muid = "unknown"; d.qid = fsqid(path, &stbuf); d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; n = convD2M(&d, (uchar*)va+i, count-i); if(n == BIT16SZ){ strcpy(uif->nextname, de); break; } i += n; } /*print("got %d\n", i);*/ uif->offset += i; return i; } static int fsomode(int m) { switch(m) { case 0: /* OREAD */ case 3: /* OEXEC */ return 0; case 1: /* OWRITE */ return 1; case 2: /* ORDWR */ return 2; } error(Ebadarg); return 0; } void closedir(DIR *d) { FindClose(d->handle); free(d->path); } int readdir(char *name, DIR *d) { if(d->index != 0) { if(FindNextFile(d->handle, &d->wfd) == FALSE) return 0; } strcpy(name, (char*)d->wfd.cFileName); d->index++; return 1; } void rewinddir(DIR *d) { FindClose(d->handle); d->handle = FindFirstFile(d->path, &d->wfd); d->index = 0; } static int chown(char *path, int uid, int perm) { /* panic("chown"); */ return 0; } DIR* opendir(char *p) { DIR *d; char path[MAX_PATH]; snprint(path, sizeof(path), "%s/*.*", p); d = mallocz(sizeof(DIR), 1); if(d == 0) return 0; d->index = 0; d->handle = FindFirstFile(path, &d->wfd); if(d->handle == INVALID_HANDLE_VALUE) { free(d); return 0; } d->path = strdup(path); return d; } Dev fsdevtab = { 'U', "fs", devreset, devinit, devshutdown, fsattach, fswalk, fsstat, fsopen, fscreate, fsclose, fsread, devbread, fswrite, devbwrite, fsremove, fswstat, }; drawterm-20110822.orig/kern/devaudio-none.c0000644000175000017500000000116411245145711017734 0ustar tinchotincho/* * Linux and BSD */ #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devaudio.h" /* maybe this should return -1 instead of sysfatal */ void audiodevopen(void) { error("no audio support"); } void audiodevclose(void) { error("no audio support"); } int audiodevread(void *a, int n) { error("no audio support"); return -1; } int audiodevwrite(void *a, int n) { error("no audio support"); return -1; } void audiodevsetvol(int what, int left, int right) { error("no audio support"); } void audiodevgetvol(int what, int *left, int *right) { error("no audio support"); } drawterm-20110822.orig/kern/devfs-posix.c0000644000175000017500000002303211245145711017444 0ustar tinchotincho#include "u.h" #include #include #include #include #include #include /* for remove, rename */ #include #ifndef NAME_MAX # define NAME_MAX 256 #endif #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" typedef struct Ufsinfo Ufsinfo; enum { NUID = 256, NGID = 256, MAXPATH = 1024, MAXCOMP = 128 }; struct Ufsinfo { int mode; int fd; int uid; int gid; DIR* dir; vlong offset; QLock oq; char nextname[NAME_MAX]; }; char *base = "/"; static Qid fsqid(char*, struct stat *); static void fspath(Chan*, char*, char*); static ulong fsdirread(Chan*, uchar*, int, ulong); static int fsomode(int); /* clumsy hack, but not worse than the Path stuff in the last one */ static char* uc2name(Chan *c) { char *s; if(c->name == nil) return "/"; s = c2name(c); if(s[0]=='#' && s[1]=='U') return s+2; return s; } static char* lastelem(Chan *c) { char *s, *t; s = uc2name(c); if((t = strrchr(s, '/')) == nil) return s; if(t[1] == 0) return t; return t+1; } static Chan* fsattach(char *spec) { Chan *c; struct stat stbuf; static int devno; Ufsinfo *uif; if(stat(base, &stbuf) < 0) error(strerror(errno)); c = devattach('U', spec); uif = mallocz(sizeof(Ufsinfo), 1); uif->mode = stbuf.st_mode; uif->uid = stbuf.st_uid; uif->gid = stbuf.st_gid; c->aux = uif; c->dev = devno++; c->qid.type = QTDIR; /*print("fsattach %s\n", c2name(c));*/ return c; } static Chan* fsclone(Chan *c, Chan *nc) { Ufsinfo *uif; uif = mallocz(sizeof(Ufsinfo), 1); *uif = *(Ufsinfo*)c->aux; nc->aux = uif; return nc; } static int fswalk1(Chan *c, char *name) { struct stat stbuf; char path[MAXPATH]; Ufsinfo *uif; fspath(c, name, path); /*print("** fs walk '%s' -> %s\n", path, name); */ if(stat(path, &stbuf) < 0) return 0; uif = c->aux; uif->mode = stbuf.st_mode; uif->uid = stbuf.st_uid; uif->gid = stbuf.st_gid; c->qid = fsqid(path, &stbuf); return 1; } extern Cname* addelem(Cname*, char*); static Walkqid* fswalk(Chan *c, Chan *nc, char **name, int nname) { int i; Cname *cname; Walkqid *wq; if(nc != nil) panic("fswalk: nc != nil"); wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); nc = devclone(c); cname = c->name; incref(&cname->ref); fsclone(c, nc); wq->clone = nc; for(i=0; iname = cname; if(fswalk1(nc, name[i]) == 0) break; cname = addelem(cname, name[i]); wq->qid[i] = nc->qid; } nc->name = cname; if(i != nname){ cclose(nc); wq->clone = nil; } wq->nqid = i; return wq; } static int fsstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; char path[MAXPATH]; if(n < BIT16SZ) error(Eshortstat); fspath(c, 0, path); if(stat(path, &stbuf) < 0) error(strerror(errno)); d.name = lastelem(c); d.uid = "unknown"; d.gid = "unknown"; d.muid = "unknown"; d.qid = c->qid; d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; return convD2M(&d, buf, n); } static Chan* fsopen(Chan *c, int mode) { char path[MAXPATH]; int m, isdir; Ufsinfo *uif; /*print("fsopen %s\n", c2name(c));*/ m = mode & (OTRUNC|3); switch(m) { case 0: break; case 1: case 1|16: break; case 2: case 0|16: case 2|16: break; case 3: break; default: error(Ebadarg); } isdir = c->qid.type & QTDIR; if(isdir && mode != OREAD) error(Eperm); m = fsomode(m & 3); c->mode = openmode(mode); uif = c->aux; fspath(c, 0, path); if(isdir) { uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { if(mode & OTRUNC) m |= O_TRUNC; uif->fd = open(path, m, 0666); if(uif->fd < 0) error(strerror(errno)); } uif->offset = 0; c->offset = 0; c->flag |= COPEN; return c; } static void fscreate(Chan *c, char *name, int mode, ulong perm) { int fd, m; char path[MAXPATH]; struct stat stbuf; Ufsinfo *uif; m = fsomode(mode&3); fspath(c, name, path); uif = c->aux; if(perm & DMDIR) { if(m) error(Eperm); if(mkdir(path, perm & 0777) < 0) error(strerror(errno)); fd = open(path, 0); if(fd >= 0) { chmod(path, perm & 0777); chown(path, uif->uid, uif->uid); } close(fd); uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666); if(fd >= 0) { if(m != 1) { close(fd); fd = open(path, m); } chmod(path, perm & 0777); chown(path, uif->uid, uif->gid); } if(fd < 0) error(strerror(errno)); uif->fd = fd; } if(stat(path, &stbuf) < 0) error(strerror(errno)); c->qid = fsqid(path, &stbuf); c->offset = 0; c->flag |= COPEN; c->mode = openmode(mode); } static void fsclose(Chan *c) { Ufsinfo *uif; uif = c->aux; if(c->flag & COPEN) { if(c->qid.type & QTDIR) closedir(uif->dir); else close(uif->fd); } free(uif); } static long fsread(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; /*print("fsread %s\n", c2name(c));*/ if(c->qid.type & QTDIR) return fsdirread(c, va, n, offset); uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = read(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static long fswrite(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = write(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static void fsremove(Chan *c) { int n; char path[MAXPATH]; fspath(c, 0, path); if(c->qid.type & QTDIR) n = rmdir(path); else n = remove(path); if(n < 0) error(strerror(errno)); } int fswstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; char old[MAXPATH], new[MAXPATH]; char strs[MAXPATH*3], *p; Ufsinfo *uif; if(convM2D(buf, n, &d, strs) != n) error(Ebadstat); fspath(c, 0, old); if(stat(old, &stbuf) < 0) error(strerror(errno)); uif = c->aux; if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) { fspath(c, 0, old); strcpy(new, old); p = strrchr(new, '/'); strcpy(p+1, d.name); if(rename(old, new) < 0) error(strerror(errno)); } fspath(c, 0, old); if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { if(chmod(old, d.mode&0777) < 0) error(strerror(errno)); uif->mode &= ~0777; uif->mode |= d.mode&0777; } /* p = name2pass(gid, d.gid); if(p == 0) error(Eunknown); if(p->id != stbuf.st_gid) { if(chown(old, stbuf.st_uid, p->id) < 0) error(strerror(errno)); uif->gid = p->id; } */ return n; } static Qid fsqid(char *p, struct stat *st) { Qid q; int dev; ulong h; static int nqdev; static uchar *qdev; if(qdev == 0) qdev = mallocz(65536U, 1); q.type = 0; if((st->st_mode&S_IFMT) == S_IFDIR) q.type = QTDIR; dev = st->st_dev & 0xFFFFUL; if(qdev[dev] == 0) qdev[dev] = ++nqdev; h = 0; while(*p != '\0') h += *p++ * 13; q.path = (vlong)qdev[dev]<<32; q.path |= h; q.vers = st->st_mtime; return q; } static void fspath(Chan *c, char *ext, char *path) { strcpy(path, base); strcat(path, "/"); strcat(path, uc2name(c)); if(ext){ strcat(path, "/"); strcat(path, ext); } cleanname(path); } static int isdots(char *name) { if(name[0] != '.') return 0; if(name[1] == '\0') return 1; if(name[1] != '.') return 0; if(name[2] == '\0') return 1; return 0; } static int p9readdir(char *name, Ufsinfo *uif) { struct dirent *de; if(uif->nextname[0]){ strcpy(name, uif->nextname); uif->nextname[0] = 0; return 1; } de = readdir(uif->dir); if(de == NULL) return 0; strcpy(name, de->d_name); return 1; } static ulong fsdirread(Chan *c, uchar *va, int count, ulong offset) { int i; Dir d; long n; char de[NAME_MAX]; struct stat stbuf; char path[MAXPATH], dirpath[MAXPATH]; Ufsinfo *uif; /*print("fsdirread %s\n", c2name(c));*/ i = 0; uif = c->aux; errno = 0; if(uif->offset != offset) { if(offset != 0) error("bad offset in fsdirread"); uif->offset = offset; /* sync offset */ uif->nextname[0] = 0; rewinddir(uif->dir); } fspath(c, 0, dirpath); while(i+BIT16SZ < count) { if(!p9readdir(de, uif)) break; if(de[0]==0 || isdots(de)) continue; d.name = de; sprint(path, "%s/%s", dirpath, de); memset(&stbuf, 0, sizeof stbuf); if(stat(path, &stbuf) < 0) { /* fprint(2, "dir: bad path %s\n", path); */ /* but continue... probably a bad symlink */ } d.uid = "unknown"; d.gid = "unknown"; d.muid = "unknown"; d.qid = fsqid(path, &stbuf); d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; n = convD2M(&d, (uchar*)va+i, count-i); if(n == BIT16SZ){ strcpy(uif->nextname, de); break; } i += n; } /*print("got %d\n", i);*/ uif->offset += i; return i; } static int fsomode(int m) { switch(m) { case 0: /* OREAD */ case 3: /* OEXEC */ return 0; case 1: /* OWRITE */ return 1; case 2: /* ORDWR */ return 2; } error(Ebadarg); return 0; } Dev fsdevtab = { 'U', "fs", devreset, devinit, devshutdown, fsattach, fswalk, fsstat, fsopen, fscreate, fsclose, fsread, devbread, fswrite, devbwrite, fsremove, fswstat, }; drawterm-20110822.orig/kern/rendez.c0000644000175000017500000000241511245145712016467 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" void sleep(Rendez *r, int (*f)(void*), void *arg) { int s; s = splhi(); lock(&r->lk); lock(&up->rlock); if(r->p){ print("double sleep %lud %lud\n", r->p->pid, up->pid); dumpstack(); } /* * Wakeup only knows there may be something to do by testing * r->p in order to get something to lock on. * Flush that information out to memory in case the sleep is * committed. */ r->p = up; if((*f)(arg) || up->notepending){ /* * if condition happened or a note is pending * never mind */ r->p = nil; unlock(&up->rlock); unlock(&r->lk); } else { /* * now we are committed to * change state and call scheduler */ up->state = Wakeme; up->r = r; /* statistics */ /* m->cs++; */ unlock(&up->rlock); unlock(&r->lk); procsleep(); } if(up->notepending) { up->notepending = 0; splx(s); error(Eintr); } splx(s); } Proc* wakeup(Rendez *r) { Proc *p; int s; s = splhi(); lock(&r->lk); p = r->p; if(p != nil){ lock(&p->rlock); if(p->state != Wakeme || p->r != r) panic("wakeup: state"); r->p = nil; p->r = nil; p->state = Running; procwakeup(p); unlock(&p->rlock); } unlock(&r->lk); splx(s); return p; } drawterm-20110822.orig/kern/uart.c0000644000175000017500000000026211245145712016151 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" extern int panicking; void uartputs(char *s, int n) { if(panicking) write(1, s, n); } drawterm-20110822.orig/kern/screen.h0000644000175000017500000000233211245145712016462 0ustar tinchotinchotypedef struct Mouseinfo Mouseinfo; typedef struct Mousestate Mousestate; typedef struct Cursorinfo Cursorinfo; typedef struct Screeninfo Screeninfo; #define Mousequeue 16 /* queue can only have Mousequeue-1 elements */ #define Mousewindow 500 /* mouse event window in millisec */ struct Mousestate { int buttons; Point xy; ulong msec; }; struct Mouseinfo { Lock lk; Mousestate queue[Mousequeue]; int ri, wi; int lastb; int trans; int open; Rendez r; }; struct Cursorinfo { Lock lk; Point offset; uchar clr[2*16]; uchar set[2*16]; }; struct Screeninfo { Lock lk; Memimage *newsoft; int reshaped; int depth; int dibtype; }; extern Memimage *gscreen; extern Mouseinfo mouse; extern Cursorinfo cursor; extern Screeninfo screen; void screeninit(void); void screenload(Rectangle, int, uchar *, Point, int); void getcolor(ulong, ulong*, ulong*, ulong*); void setcolor(ulong, ulong, ulong, ulong); void refreshrect(Rectangle); void cursorarrow(void); void setcursor(void); void mouseset(Point); void drawflushr(Rectangle); void flushmemscreen(Rectangle); uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*, void**); void drawqlock(void); void drawqunlock(void); int drawcanqlock(void); void terminit(void); drawterm-20110822.orig/kern/devdraw.c0000644000175000017500000012464311245146177016652 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #define Image IMAGE #include #include #include #include #include "screen.h" enum { Qtopdir = 0, Qnew, Q3rd, Q2nd, Qcolormap, Qctl, Qdata, Qrefresh, }; /* * Qid path is: * 4 bits of file type (qids above) * 24 bits of mux slot number +1; 0 means not attached to client */ #define QSHIFT 4 /* location in qid of client # */ #define QID(q) ((((ulong)(q).path)&0x0000000F)>>0) #define CLIENTPATH(q) ((((ulong)q)&0x7FFFFFF0)>>QSHIFT) #define CLIENT(q) CLIENTPATH((q).path) #define NHASH (1<<5) #define HASHMASK (NHASH-1) #define IOUNIT (64*1024) typedef struct Client Client; typedef struct Draw Draw; typedef struct DImage DImage; typedef struct DScreen DScreen; typedef struct CScreen CScreen; typedef struct FChar FChar; typedef struct Refresh Refresh; typedef struct Refx Refx; typedef struct DName DName; ulong blanktime = 30; /* in minutes; a half hour */ struct Draw { QLock lk; int clientid; int nclient; Client** client; int nname; DName* name; int vers; int softscreen; int blanked; /* screen turned off */ ulong blanktime; /* time of last operation */ ulong savemap[3*256]; }; struct Client { Ref r; DImage* dimage[NHASH]; CScreen* cscreen; Refresh* refresh; Rendez refrend; uchar* readdata; int nreaddata; int busy; int clientid; int slot; int refreshme; int infoid; int op; }; struct Refresh { DImage* dimage; Rectangle r; Refresh* next; }; struct Refx { Client* client; DImage* dimage; }; struct DName { char *name; Client *client; DImage* dimage; int vers; }; struct FChar { int minx; /* left edge of bits */ int maxx; /* right edge of bits */ uchar miny; /* first non-zero scan-line */ uchar maxy; /* last non-zero scan-line + 1 */ schar left; /* offset of baseline */ uchar width; /* width of baseline */ }; /* * Reference counts in DImages: * one per open by original client * one per screen image or fill * one per image derived from this one by name */ struct DImage { int id; int ref; char *name; int vers; Memimage* image; int ascent; int nfchar; FChar* fchar; DScreen* dscreen; /* 0 if not a window */ DImage* fromname; /* image this one is derived from, by name */ DImage* next; }; struct CScreen { DScreen* dscreen; CScreen* next; }; struct DScreen { int id; int public; int ref; DImage *dimage; DImage *dfill; Memscreen* screen; Client* owner; DScreen* next; }; static Draw sdraw; static Memimage *screenimage; static Memdata screendata; static Rectangle flushrect; static int waste; static DScreen* dscreen; extern void flushmemscreen(Rectangle); void drawmesg(Client*, void*, int); void drawuninstall(Client*, int); void drawfreedimage(DImage*); Client* drawclientofpath(ulong); static char Enodrawimage[] = "unknown id for draw image"; static char Enodrawscreen[] = "unknown id for draw screen"; static char Eshortdraw[] = "short draw message"; static char Eshortread[] = "draw read too short"; static char Eimageexists[] = "image id in use"; static char Escreenexists[] = "screen id in use"; static char Edrawmem[] = "image memory allocation failed"; static char Ereadoutside[] = "readimage outside image"; static char Ewriteoutside[] = "writeimage outside image"; static char Enotfont[] = "image not a font"; static char Eindex[] = "character index out of range"; static char Enoclient[] = "no such draw client"; /* static char Edepth[] = "image has bad depth"; */ static char Enameused[] = "image name in use"; static char Enoname[] = "no image with that name"; static char Eoldname[] = "named image no longer valid"; static char Enamed[] = "image already has name"; static char Ewrongname[] = "wrong name for image"; int drawcanqlock(void) { return canqlock(&sdraw.lk); } void drawqlock(void) { qlock(&sdraw.lk); } void drawqunlock(void) { qunlock(&sdraw.lk); } static int drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp) { int t; Qid q; ulong path; Client *cl; USED(name); USED(dt); USED(ndt); q.vers = 0; if(s == DEVDOTDOT){ switch(QID(c->qid)){ case Qtopdir: case Q2nd: mkqid(&q, Qtopdir, 0, QTDIR); devdir(c, q, "#i", 0, eve, 0500, dp); break; case Q3rd: cl = drawclientofpath(c->qid.path); if(cl == nil) strcpy(up->genbuf, "??"); else sprint(up->genbuf, "%d", cl->clientid); mkqid(&q, Q2nd, 0, QTDIR); devdir(c, q, up->genbuf, 0, eve, 0500, dp); break; default: panic("drawwalk %llux", c->qid.path); } return 1; } /* * Top level directory contains the name of the device. */ t = QID(c->qid); if(t == Qtopdir){ switch(s){ case 0: mkqid(&q, Q2nd, 0, QTDIR); devdir(c, q, "draw", 0, eve, 0555, dp); break; default: return -1; } return 1; } /* * Second level contains "new" plus all the clients. */ if(t == Q2nd || t == Qnew){ if(s == 0){ mkqid(&q, Qnew, 0, QTFILE); devdir(c, q, "new", 0, eve, 0666, dp); } else if(s <= sdraw.nclient){ cl = sdraw.client[s-1]; if(cl == 0) return 0; sprint(up->genbuf, "%d", cl->clientid); mkqid(&q, (s<genbuf, 0, eve, 0555, dp); return 1; } else return -1; return 1; } /* * Third level. */ path = c->qid.path&~((1<qid.vers; q.type = QTFILE; switch(s){ case 0: q.path = path|Qcolormap; devdir(c, q, "colormap", 0, eve, 0600, dp); break; case 1: q.path = path|Qctl; devdir(c, q, "ctl", 0, eve, 0600, dp); break; case 2: q.path = path|Qdata; devdir(c, q, "data", 0, eve, 0600, dp); break; case 3: q.path = path|Qrefresh; devdir(c, q, "refresh", 0, eve, 0400, dp); break; default: return -1; } return 1; } static int drawrefactive(void *a) { Client *c; c = a; return c->refreshme || c->refresh!=0; } static void drawrefreshscreen(DImage *l, Client *client) { while(l != nil && l->dscreen == nil) l = l->fromname; if(l != nil && l->dscreen->owner != client) l->dscreen->owner->refreshme = 1; } static void drawrefresh(Memimage *m, Rectangle r, void *v) { Refx *x; DImage *d; Client *c; Refresh *ref; USED(m); if(v == 0) return; x = v; c = x->client; d = x->dimage; for(ref=c->refresh; ref; ref=ref->next) if(ref->dimage == d){ combinerect(&ref->r, r); return; } ref = malloc(sizeof(Refresh)); if(ref){ ref->dimage = d; ref->r = r; ref->next = c->refresh; c->refresh = ref; } } static void addflush(Rectangle r) { int abb, ar, anbb; Rectangle nbb; if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r)) return; if(flushrect.min.x >= flushrect.max.x){ flushrect = r; waste = 0; return; } nbb = flushrect; combinerect(&nbb, r); ar = Dx(r)*Dy(r); abb = Dx(flushrect)*Dy(flushrect); anbb = Dx(nbb)*Dy(nbb); /* * Area of new waste is area of new bb minus area of old bb, * less the area of the new segment, which we assume is not waste. * This could be negative, but that's OK. */ waste += anbb-abb - ar; if(waste < 0) waste = 0; /* * absorb if: * total area is small * waste is less than half total area * rectangles touch */ if(anbb<=1024 || waste*2layer; if(l == nil) return; do{ if(l->screen->image->data != screenimage->data) return; r = rectaddpt(r, l->delta); l = l->screen->image->layer; }while(l); addflush(r); } void drawflush(void) { if(flushrect.min.x < flushrect.max.x) flushmemscreen(flushrect); flushrect = Rect(10000, 10000, -10000, -10000); } void drawflushr(Rectangle r) { qlock(&sdraw.lk); flushmemscreen(r); qunlock(&sdraw.lk); } static int drawcmp(char *a, char *b, int n) { if(strlen(a) != n) return 1; return memcmp(a, b, n); } DName* drawlookupname(int n, char *str) { DName *name, *ename; name = sdraw.name; ename = &name[sdraw.nname]; for(; namename, str, n) == 0) return name; return 0; } int drawgoodname(DImage *d) { DName *n; /* if window, validate the screen's own images */ if(d->dscreen) if(drawgoodname(d->dscreen->dimage) == 0 || drawgoodname(d->dscreen->dfill) == 0) return 0; if(d->name == nil) return 1; n = drawlookupname(strlen(d->name), d->name); if(n==nil || n->vers!=d->vers) return 0; return 1; } DImage* drawlookup(Client *client, int id, int checkname) { DImage *d; d = client->dimage[id&HASHMASK]; while(d){ if(d->id == id){ if(checkname && !drawgoodname(d)) error(Eoldname); return d; } d = d->next; } return 0; } DScreen* drawlookupdscreen(int id) { DScreen *s; s = dscreen; while(s){ if(s->id == id) return s; s = s->next; } return 0; } DScreen* drawlookupscreen(Client *client, int id, CScreen **cs) { CScreen *s; s = client->cscreen; while(s){ if(s->dscreen->id == id){ *cs = s; return s->dscreen; } s = s->next; } error(Enodrawscreen); return 0; } Memimage* drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen) { DImage *d; d = malloc(sizeof(DImage)); if(d == 0) return 0; d->id = id; d->ref = 1; d->name = 0; d->vers = 0; d->image = i; d->nfchar = 0; d->fchar = 0; d->fromname = 0; d->dscreen = dscreen; d->next = client->dimage[id&HASHMASK]; client->dimage[id&HASHMASK] = d; return i; } Memscreen* drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public) { Memscreen *s; CScreen *c; c = malloc(sizeof(CScreen)); if(dimage && dimage->image && dimage->image->chan == 0) panic("bad image %p in drawinstallscreen", dimage->image); if(c == 0) return 0; if(d == 0){ d = malloc(sizeof(DScreen)); if(d == 0){ free(c); return 0; } s = malloc(sizeof(Memscreen)); if(s == 0){ free(c); free(d); return 0; } s->frontmost = 0; s->rearmost = 0; d->dimage = dimage; if(dimage){ s->image = dimage->image; dimage->ref++; } d->dfill = dfill; if(dfill){ s->fill = dfill->image; dfill->ref++; } d->ref = 0; d->id = id; d->screen = s; d->public = public; d->next = dscreen; d->owner = client; dscreen = d; } c->dscreen = d; d->ref++; c->next = client->cscreen; client->cscreen = c; return d->screen; } void drawdelname(DName *name) { int i; i = name-sdraw.name; memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName)); sdraw.nname--; } void drawfreedscreen(DScreen *this) { DScreen *ds, *next; this->ref--; if(this->ref < 0) print("negative ref in drawfreedscreen\n"); if(this->ref > 0) return; ds = dscreen; if(ds == this){ dscreen = this->next; goto Found; } while((next = ds->next)){ /* assign = */ if(next == this){ ds->next = this->next; goto Found; } ds = next; } error(Enodrawimage); Found: if(this->dimage) drawfreedimage(this->dimage); if(this->dfill) drawfreedimage(this->dfill); free(this->screen); free(this); } void drawfreedimage(DImage *dimage) { int i; Memimage *l; DScreen *ds; dimage->ref--; if(dimage->ref < 0) print("negative ref in drawfreedimage\n"); if(dimage->ref > 0) return; /* any names? */ for(i=0; ifromname){ /* acquired by name; owned by someone else*/ drawfreedimage(dimage->fromname); goto Return; } if(dimage->image == screenimage) /* don't free the display */ goto Return; ds = dimage->dscreen; if(ds){ l = dimage->image; if(l->data == screenimage->data) addflush(l->layer->screenr); if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */ free(l->layer->refreshptr); l->layer->refreshptr = nil; if(drawgoodname(dimage)) memldelete(l); else memlfree(l); drawfreedscreen(ds); }else freememimage(dimage->image); Return: free(dimage->fchar); free(dimage); } void drawuninstallscreen(Client *client, CScreen *this) { CScreen *cs, *next; cs = client->cscreen; if(cs == this){ client->cscreen = this->next; drawfreedscreen(this->dscreen); free(this); return; } while((next = cs->next)){ /* assign = */ if(next == this){ cs->next = this->next; drawfreedscreen(this->dscreen); free(this); return; } cs = next; } } void drawuninstall(Client *client, int id) { DImage *d, *next; d = client->dimage[id&HASHMASK]; if(d == 0) error(Enodrawimage); if(d->id == id){ client->dimage[id&HASHMASK] = d->next; drawfreedimage(d); return; } while((next = d->next)){ /* assign = */ if(next->id == id){ d->next = next->next; drawfreedimage(next); return; } d = next; } error(Enodrawimage); } void drawaddname(Client *client, DImage *di, int n, char *str) { DName *name, *ename, *new, *t; name = sdraw.name; ename = &name[sdraw.nname]; for(; namename, str, n) == 0) error(Enameused); t = smalloc((sdraw.nname+1)*sizeof(DName)); memmove(t, sdraw.name, sdraw.nname*sizeof(DName)); free(sdraw.name); sdraw.name = t; new = &sdraw.name[sdraw.nname++]; new->name = smalloc(n+1); memmove(new->name, str, n); new->name[n] = 0; new->dimage = di; new->client = client; new->vers = ++sdraw.vers; } Client* drawnewclient(void) { Client *cl, **cp; int i; for(i=0; islot = i; cl->clientid = ++sdraw.clientid; cl->op = SoverD; sdraw.client[i] = cl; return cl; } static int drawclientop(Client *cl) { int op; op = cl->op; cl->op = SoverD; return op; } int drawhasclients(void) { /* * if draw has ever been used, we can't resize the frame buffer, * even if all clients have exited (nclients is cumulative); it's too * hard to make work. */ return sdraw.nclient != 0; } Client* drawclientofpath(ulong path) { Client *cl; int slot; slot = CLIENTPATH(path); if(slot == 0) return nil; cl = sdraw.client[slot-1]; if(cl==0 || cl->clientid==0) return nil; return cl; } Client* drawclient(Chan *c) { Client *client; client = drawclientofpath(c->qid.path); if(client == nil) error(Enoclient); return client; } Memimage* drawimage(Client *client, uchar *a) { DImage *d; d = drawlookup(client, BGLONG(a), 1); if(d == nil) error(Enodrawimage); return d->image; } void drawrectangle(Rectangle *r, uchar *a) { r->min.x = BGLONG(a+0*4); r->min.y = BGLONG(a+1*4); r->max.x = BGLONG(a+2*4); r->max.y = BGLONG(a+3*4); } void drawpoint(Point *p, uchar *a) { p->x = BGLONG(a+0*4); p->y = BGLONG(a+1*4); } #define isvgascreen(dst) 1 Point drawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op) { FChar *fc; Rectangle r; Point sp1; static Memimage *tmp; fc = &font->fchar[index]; r.min.x = p.x+fc->left; r.min.y = p.y-(font->ascent-fc->miny); r.max.x = r.min.x+(fc->maxx-fc->minx); r.max.y = r.min.y+(fc->maxy-fc->miny); sp1.x = sp->x+fc->left; sp1.y = sp->y+fc->miny; /* * If we're drawing greyscale fonts onto a VGA screen, * it's very costly to read the screen memory to do the * alpha blending inside memdraw. If this is really a stringbg, * then rdst is the bg image (in main memory) which we can * refer to for the underlying dst pixels instead of reading dst * directly. */ if(1 || (isvgascreen(dst) && !isvgascreen(rdst) /*&& font->image->depth > 1*/)){ if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){ if(tmp) freememimage(tmp); tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan); if(tmp == nil) goto fallback; } memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S); memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op); memdraw(dst, r, tmp, ZP, memopaque, ZP, S); }else{ fallback: memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op); } p.x += fc->width; sp->x += fc->width; return p; } static int initscreenimage(void) { int width, depth; ulong chan; void *X; Rectangle r; if(screenimage != nil) return 1; screendata.base = nil; screendata.bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen, &X); if(screendata.bdata == nil && X == nil) return 0; screendata.ref = 1; screenimage = allocmemimaged(r, chan, &screendata, X); if(screenimage == nil){ /* RSC: BUG: detach screen */ return 0; } screenimage->width = width; screenimage->clipr = r; return 1; } void deletescreenimage(void) { qlock(&sdraw.lk); /* RSC: BUG: detach screen */ if(screenimage) freememimage(screenimage); screenimage = nil; qunlock(&sdraw.lk); } static Chan* drawattach(char *spec) { qlock(&sdraw.lk); if(!initscreenimage()){ qunlock(&sdraw.lk); error("no frame buffer"); } qunlock(&sdraw.lk); return devattach('i', spec); } static Walkqid* drawwalk(Chan *c, Chan *nc, char **name, int nname) { if(screendata.bdata == nil) error("no frame buffer"); return devwalk(c, nc, name, nname, 0, 0, drawgen); } static int drawstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, 0, 0, drawgen); } static Chan* drawopen(Chan *c, int omode) { Client *cl; if(c->qid.type & QTDIR){ c = devopen(c, omode, 0, 0, drawgen); c->iounit = IOUNIT; } qlock(&sdraw.lk); if(waserror()){ qunlock(&sdraw.lk); nexterror(); } if(QID(c->qid) == Qnew){ cl = drawnewclient(); if(cl == 0) error(Enodev); c->qid.path = Qctl|((cl->slot+1)<qid)){ case Qnew: break; case Qctl: cl = drawclient(c); if(cl->busy) error(Einuse); cl->busy = 1; flushrect = Rect(10000, 10000, -10000, -10000); drawinstall(cl, 0, screenimage, 0); incref(&cl->r); break; case Qcolormap: case Qdata: case Qrefresh: cl = drawclient(c); incref(&cl->r); break; } qunlock(&sdraw.lk); poperror(); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; c->iounit = IOUNIT; return c; } static void drawclose(Chan *c) { int i; DImage *d, **dp; Client *cl; Refresh *r; if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */ return; qlock(&sdraw.lk); if(waserror()){ qunlock(&sdraw.lk); nexterror(); } cl = drawclient(c); if(QID(c->qid) == Qctl) cl->busy = 0; if((c->flag&COPEN) && (decref(&cl->r)==0)){ while((r = cl->refresh)){ /* assign = */ cl->refresh = r->next; free(r); } /* free names */ for(i=0; icscreen) drawuninstallscreen(cl, cl->cscreen); /* all screens are freed, so now we can free images */ dp = cl->dimage; for(i=0; inext; drawfreedimage(d); } dp++; } sdraw.client[cl->slot] = 0; drawflush(); /* to erase visible, now dead windows */ free(cl); } qunlock(&sdraw.lk); poperror(); } long drawread(Chan *c, void *a, long n, vlong off) { int index, m; ulong red, green, blue; Client *cl; uchar *p; Refresh *r; DImage *di; Memimage *i; ulong offset = off; char buf[16]; if(c->qid.type & QTDIR) return devdirread(c, a, n, 0, 0, drawgen); cl = drawclient(c); qlock(&sdraw.lk); if(waserror()){ qunlock(&sdraw.lk); nexterror(); } switch(QID(c->qid)){ case Qctl: if(n < 12*12) error(Eshortread); if(cl->infoid < 0) error(Enodrawimage); if(cl->infoid == 0){ i = screenimage; if(i == nil) error(Enodrawimage); }else{ di = drawlookup(cl, cl->infoid, 1); if(di == nil) error(Enodrawimage); i = di->image; } n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ", cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl, i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y, i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y); cl->infoid = -1; break; case Qcolormap: drawactive(1); /* to restore map from backup */ p = malloc(4*12*256+1); if(p == 0) error(Enomem); m = 0; for(index = 0; index < 256; index++){ getcolor(index, &red, &green, &blue); m += sprint((char*)p+m, "%11d %11lud %11lud %11lud\n", index, red>>24, green>>24, blue>>24); } n = readstr(offset, a, n, (char*)p); free(p); break; case Qdata: if(cl->readdata == nil) error("no draw data"); if(n < cl->nreaddata) error(Eshortread); n = cl->nreaddata; memmove(a, cl->readdata, cl->nreaddata); free(cl->readdata); cl->readdata = nil; break; case Qrefresh: if(n < 5*4) error(Ebadarg); for(;;){ if(cl->refreshme || cl->refresh) break; qunlock(&sdraw.lk); if(waserror()){ qlock(&sdraw.lk); /* restore lock for waserror() above */ nexterror(); } sleep(&cl->refrend, drawrefactive, cl); poperror(); qlock(&sdraw.lk); } p = a; while(cl->refresh && n>=5*4){ r = cl->refresh; BPLONG(p+0*4, r->dimage->id); BPLONG(p+1*4, r->r.min.x); BPLONG(p+2*4, r->r.min.y); BPLONG(p+3*4, r->r.max.x); BPLONG(p+4*4, r->r.max.y); cl->refresh = r->next; free(r); p += 5*4; n -= 5*4; } cl->refreshme = 0; n = p-(uchar*)a; } qunlock(&sdraw.lk); poperror(); return n; } void drawwakeall(void) { Client *cl; int i; for(i=0; irefreshme || cl->refresh)) wakeup(&cl->refrend); } } static long drawwrite(Chan *c, void *a, long n, vlong offset) { char buf[128], *fields[4], *q; Client *cl; int i, m, red, green, blue, x; USED(offset); if(c->qid.type & QTDIR) error(Eisdir); cl = drawclient(c); qlock(&sdraw.lk); if(waserror()){ drawwakeall(); qunlock(&sdraw.lk); nexterror(); } switch(QID(c->qid)){ case Qctl: if(n != 4) error("unknown draw control request"); cl->infoid = BGLONG((uchar*)a); break; case Qcolormap: drawactive(1); /* to restore map from backup */ m = n; n = 0; while(m > 0){ x = m; if(x > sizeof(buf)-1) x = sizeof(buf)-1; q = memccpy(buf, a, '\n', x); if(q == 0) break; i = q-buf; n += i; a = (char*)a + i; m -= i; *q = 0; if(tokenize(buf, fields, nelem(fields)) != 4) error(Ebadarg); i = strtoul(fields[0], 0, 0); red = strtoul(fields[1], 0, 0); green = strtoul(fields[2], 0, 0); blue = strtoul(fields[3], &q, 0); if(fields[3] == q) error(Ebadarg); if(red>255 || green>255 || blue>255 || i<0 || i>255) error(Ebadarg); red |= red<<8; red |= red<<16; green |= green<<8; green |= green<<16; blue |= blue<<8; blue |= blue<<16; setcolor(i, red, green, blue); } break; case Qdata: drawmesg(cl, a, n); drawwakeall(); break; default: error(Ebadusefd); } qunlock(&sdraw.lk); poperror(); return n; } uchar* drawcoord(uchar *p, uchar *maxp, int oldx, int *newx) { int b, x; if(p >= maxp) error(Eshortdraw); b = *p++; x = b & 0x7F; if(b & 0x80){ if(p+1 >= maxp) error(Eshortdraw); x |= *p++ << 7; x |= *p++ << 15; if(x & (1<<22)) x |= ~0<<23; }else{ if(b & 0x40) x |= ~0<<7; x += oldx; } *newx = x; return p; } static void printmesg(char *fmt, uchar *a, int plsprnt) { char buf[256]; char *p, *q; int s; if(1|| plsprnt==0){ SET(s); SET(q); SET(p); USED(fmt); USED(a); p = buf; USED(p); USED(q); USED(s); return; } q = buf; *q++ = *a++; for(p=fmt; *p; p++){ switch(*p){ case 'l': q += sprint(q, " %ld", (long)BGLONG(a)); a += 4; break; case 'L': q += sprint(q, " %.8lux", (ulong)BGLONG(a)); a += 4; break; case 'R': q += sprint(q, " [%d %d %d %d]", BGLONG(a), BGLONG(a+4), BGLONG(a+8), BGLONG(a+12)); a += 16; break; case 'P': q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4)); a += 8; break; case 'b': q += sprint(q, " %d", *a++); break; case 's': q += sprint(q, " %d", BGSHORT(a)); a += 2; break; case 'S': q += sprint(q, " %.4ux", BGSHORT(a)); a += 2; break; } } *q++ = '\n'; *q = 0; iprint("%.*s", (int)(q-buf), buf); } void drawmesg(Client *client, void *av, int n) { int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush; uchar *u, *a, refresh; char *fmt; ulong value, chan; Rectangle r, clipr; Point p, q, *pp, sp; Memimage *i, *dst, *src, *mask; Memimage *l, **lp; Memscreen *scrn; DImage *font, *ll, *di, *ddst, *dsrc; DName *dn; DScreen *dscrn; FChar *fc; Refx *refx; CScreen *cs; Refreshfn reffn; a = av; m = 0; fmt = nil; if(waserror()){ if(fmt) printmesg(fmt, a, 1); /* iprint("error: %s\n", up->errstr); */ nexterror(); } while((n-=m) > 0){ USED(fmt); a += m; switch(*a){ default: error("bad draw command"); /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */ case 'b': printmesg(fmt="LLbLbRRL", a, 0); m = 1+4+4+1+4+1+4*4+4*4+4; if(n < m) error(Eshortdraw); dstid = BGLONG(a+1); scrnid = BGSHORT(a+5); refresh = a[9]; chan = BGLONG(a+10); repl = a[14]; drawrectangle(&r, a+15); drawrectangle(&clipr, a+31); value = BGLONG(a+47); if(drawlookup(client, dstid, 0)) error(Eimageexists); if(scrnid){ dscrn = drawlookupscreen(client, scrnid, &cs); scrn = dscrn->screen; if(repl || chan!=scrn->image->chan) error("image parameters incompatible with screen"); reffn = 0; switch(refresh){ case Refbackup: break; case Refnone: reffn = memlnorefresh; break; case Refmesg: reffn = drawrefresh; break; default: error("unknown refresh method"); } l = memlalloc(scrn, r, reffn, 0, value); if(l == 0) error(Edrawmem); addflush(l->layer->screenr); l->clipr = clipr; rectclip(&l->clipr, r); if(drawinstall(client, dstid, l, dscrn) == 0){ memldelete(l); error(Edrawmem); } dscrn->ref++; if(reffn){ refx = nil; if(reffn == drawrefresh){ refx = malloc(sizeof(Refx)); if(refx == 0){ drawuninstall(client, dstid); error(Edrawmem); } refx->client = client; refx->dimage = drawlookup(client, dstid, 1); } memlsetrefresh(l, reffn, refx); } continue; } i = allocmemimage(r, chan); if(i == 0) error(Edrawmem); if(repl) i->flags |= Frepl; i->clipr = clipr; if(!repl) rectclip(&i->clipr, r); if(drawinstall(client, dstid, i, 0) == 0){ freememimage(i); error(Edrawmem); } memfillcolor(i, value); continue; /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */ case 'A': printmesg(fmt="LLLb", a, 1); m = 1+4+4+4+1; if(n < m) error(Eshortdraw); dstid = BGLONG(a+1); if(dstid == 0) error(Ebadarg); if(drawlookupdscreen(dstid)) error(Escreenexists); ddst = drawlookup(client, BGLONG(a+5), 1); dsrc = drawlookup(client, BGLONG(a+9), 1); if(ddst==0 || dsrc==0) error(Enodrawimage); if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0) error(Edrawmem); continue; /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */ case 'c': printmesg(fmt="LbR", a, 0); m = 1+4+1+4*4; if(n < m) error(Eshortdraw); ddst = drawlookup(client, BGLONG(a+1), 1); if(ddst == nil) error(Enodrawimage); if(ddst->name) error("can't change repl/clipr of shared image"); dst = ddst->image; if(a[5]) dst->flags |= Frepl; drawrectangle(&dst->clipr, a+6); continue; /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */ case 'd': printmesg(fmt="LLLRPP", a, 0); m = 1+4+4+4+4*4+2*4+2*4; if(n < m) error(Eshortdraw); dst = drawimage(client, a+1); dstid = BGLONG(a+1); src = drawimage(client, a+5); mask = drawimage(client, a+9); drawrectangle(&r, a+13); drawpoint(&p, a+29); drawpoint(&q, a+37); op = drawclientop(client); memdraw(dst, r, src, p, mask, q, op); dstflush(dstid, dst, r); continue; /* toggle debugging: 'D' val[1] */ case 'D': printmesg(fmt="b", a, 0); m = 1+1; if(n < m) error(Eshortdraw); drawdebug = a[1]; continue; /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/ case 'e': case 'E': printmesg(fmt="LLPlllPll", a, 0); m = 1+4+4+2*4+4+4+4+2*4+2*4; if(n < m) error(Eshortdraw); dst = drawimage(client, a+1); dstid = BGLONG(a+1); src = drawimage(client, a+5); drawpoint(&p, a+9); e0 = BGLONG(a+17); e1 = BGLONG(a+21); if(e0<0 || e1<0) error("invalid ellipse semidiameter"); j = BGLONG(a+25); if(j < 0) error("negative ellipse thickness"); drawpoint(&sp, a+29); c = j; if(*a == 'E') c = -1; ox = BGLONG(a+37); oy = BGLONG(a+41); op = drawclientop(client); /* high bit indicates arc angles are present */ if(ox & (1U<<31)){ if((ox & (1<<30)) == 0) ox &= ~(1U<<31); memarc(dst, p, e0, e1, c, src, sp, ox, oy, op); }else memellipse(dst, p, e0, e1, c, src, sp, op); dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1)); continue; /* free: 'f' id[4] */ case 'f': printmesg(fmt="L", a, 1); m = 1+4; if(n < m) error(Eshortdraw); ll = drawlookup(client, BGLONG(a+1), 0); if(ll && ll->dscreen && ll->dscreen->owner != client) ll->dscreen->owner->refreshme = 1; drawuninstall(client, BGLONG(a+1)); continue; /* free screen: 'F' id[4] */ case 'F': printmesg(fmt="L", a, 1); m = 1+4; if(n < m) error(Eshortdraw); drawlookupscreen(client, BGLONG(a+1), &cs); drawuninstallscreen(client, cs); continue; /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */ case 'i': printmesg(fmt="Llb", a, 1); m = 1+4+4+1; if(n < m) error(Eshortdraw); dstid = BGLONG(a+1); if(dstid == 0) error("can't use display as font"); font = drawlookup(client, dstid, 1); if(font == 0) error(Enodrawimage); if(font->image->layer) error("can't use window as font"); ni = BGLONG(a+5); if(ni<=0 || ni>4096) error("bad font size (4096 chars max)"); free(font->fchar); /* should we complain if non-zero? */ font->fchar = malloc(ni*sizeof(FChar)); if(font->fchar == 0) error("no memory for font"); memset(font->fchar, 0, ni*sizeof(FChar)); font->nfchar = ni; font->ascent = a[9]; continue; /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */ case 'l': printmesg(fmt="LLSRPbb", a, 0); m = 1+4+4+2+4*4+2*4+1+1; if(n < m) error(Eshortdraw); font = drawlookup(client, BGLONG(a+1), 1); if(font == 0) error(Enodrawimage); if(font->nfchar == 0) error(Enotfont); src = drawimage(client, a+5); ci = BGSHORT(a+9); if(ci >= font->nfchar) error(Eindex); drawrectangle(&r, a+11); drawpoint(&p, a+27); memdraw(font->image, r, src, p, memopaque, p, S); fc = &font->fchar[ci]; fc->minx = r.min.x; fc->maxx = r.max.x; fc->miny = r.min.y; fc->maxy = r.max.y; fc->left = a[35]; fc->width = a[36]; continue; /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */ case 'L': printmesg(fmt="LPPlllLP", a, 0); m = 1+4+2*4+2*4+4+4+4+4+2*4; if(n < m) error(Eshortdraw); dst = drawimage(client, a+1); dstid = BGLONG(a+1); drawpoint(&p, a+5); drawpoint(&q, a+13); e0 = BGLONG(a+21); e1 = BGLONG(a+25); j = BGLONG(a+29); if(j < 0) error("negative line width"); src = drawimage(client, a+33); drawpoint(&sp, a+37); op = drawclientop(client); memline(dst, p, q, e0, e1, j, src, sp, op); /* avoid memlinebbox if possible */ if(dstid==0 || dst->layer!=nil){ /* BUG: this is terribly inefficient: update maximal containing rect*/ r = memlinebbox(p, q, e0, e1, j); dstflush(dstid, dst, insetrect(r, -(1+1+j))); } continue; /* create image mask: 'm' newid[4] id[4] */ /* * case 'm': printmesg("LL", a, 0); m = 4+4; if(n < m) error(Eshortdraw); break; * */ /* attach to a named image: 'n' dstid[4] j[1] name[j] */ case 'n': printmesg(fmt="Lz", a, 0); m = 1+4+1; if(n < m) error(Eshortdraw); j = a[5]; if(j == 0) /* give me a non-empty name please */ error(Eshortdraw); m += j; if(n < m) error(Eshortdraw); dstid = BGLONG(a+1); if(drawlookup(client, dstid, 0)) error(Eimageexists); dn = drawlookupname(j, (char*)a+6); if(dn == nil) error(Enoname); if(drawinstall(client, dstid, dn->dimage->image, 0) == 0) error(Edrawmem); di = drawlookup(client, dstid, 0); if(di == 0) error("draw: can't happen"); di->vers = dn->vers; di->name = smalloc(j+1); di->fromname = dn->dimage; di->fromname->ref++; memmove(di->name, a+6, j); di->name[j] = 0; client->infoid = dstid; continue; /* name an image: 'N' dstid[4] in[1] j[1] name[j] */ case 'N': printmesg(fmt="Lbz", a, 0); m = 1+4+1+1; if(n < m) error(Eshortdraw); c = a[5]; j = a[6]; if(j == 0) /* give me a non-empty name please */ error(Eshortdraw); m += j; if(n < m) error(Eshortdraw); di = drawlookup(client, BGLONG(a+1), 0); if(di == 0) error(Enodrawimage); if(di->name) error(Enamed); if(c) drawaddname(client, di, j, (char*)a+7); else{ dn = drawlookupname(j, (char*)a+7); if(dn == nil) error(Enoname); if(dn->dimage != di) error(Ewrongname); drawdelname(dn); } continue; /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */ case 'o': printmesg(fmt="LPP", a, 0); m = 1+4+2*4+2*4; if(n < m) error(Eshortdraw); dst = drawimage(client, a+1); if(dst->layer){ drawpoint(&p, a+5); drawpoint(&q, a+13); r = dst->layer->screenr; ni = memlorigin(dst, p, q); if(ni < 0) error("image origin failed"); if(ni > 0){ addflush(r); addflush(dst->layer->screenr); ll = drawlookup(client, BGLONG(a+1), 1); drawrefreshscreen(ll, client); } } continue; /* set compositing operator for next draw operation: 'O' op */ case 'O': printmesg(fmt="b", a, 0); m = 1+1; if(n < m) error(Eshortdraw); client->op = a[1]; continue; /* filled polygon: 'P' dstid[4] n[2] wind[4] ignore[2*4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */ /* polygon: 'p' dstid[4] n[2] end0[4] end1[4] radius[4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */ case 'p': case 'P': printmesg(fmt="LslllLPP", a, 0); m = 1+4+2+4+4+4+4+2*4; if(n < m) error(Eshortdraw); dstid = BGLONG(a+1); dst = drawimage(client, a+1); ni = BGSHORT(a+5); if(ni < 0) error("negative count in polygon"); e0 = BGLONG(a+7); e1 = BGLONG(a+11); j = 0; if(*a == 'p'){ j = BGLONG(a+15); if(j < 0) error("negative polygon line width"); } src = drawimage(client, a+19); drawpoint(&sp, a+23); drawpoint(&p, a+31); ni++; pp = malloc(ni*sizeof(Point)); if(pp == nil) error(Enomem); doflush = 0; if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data)) doflush = 1; /* simplify test in loop */ ox = oy = 0; esize = 0; u = a+m; for(y=0; y esize) esize = c; } if(y == ni-1){ c = memlineendsize(e1); if(c > esize) esize = c; } } if(*a=='P' && e0!=1 && e0 !=~0) r = dst->clipr; else if(y > 0){ r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1); combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1)); } if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */ dstflush(dstid, dst, r); } pp[y] = p; } if(y == 1) dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1)); op = drawclientop(client); if(*a == 'p') mempoly(dst, pp, ni, e0, e1, j, src, sp, op); else memfillpoly(dst, pp, ni, e0, src, sp, op); free(pp); m = u-a; continue; /* read: 'r' id[4] R[4*4] */ case 'r': printmesg(fmt="LR", a, 0); m = 1+4+4*4; if(n < m) error(Eshortdraw); i = drawimage(client, a+1); drawrectangle(&r, a+5); if(!rectinrect(r, i->r)) error(Ereadoutside); c = bytesperline(r, i->depth); c *= Dy(r); free(client->readdata); client->readdata = mallocz(c, 0); if(client->readdata == nil) error("readimage malloc failed"); client->nreaddata = memunload(i, r, client->readdata, c); if(client->nreaddata < 0){ free(client->readdata); client->readdata = nil; error("bad readimage call"); } continue; /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */ /* stringbg: 'x' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] bgid[4] bgpt[2*4] ni*(index[2]) */ case 's': case 'x': printmesg(fmt="LLLPRPs", a, 0); m = 1+4+4+4+2*4+4*4+2*4+2; if(*a == 'x') m += 4+2*4; if(n < m) error(Eshortdraw); dst = drawimage(client, a+1); dstid = BGLONG(a+1); src = drawimage(client, a+5); font = drawlookup(client, BGLONG(a+9), 1); if(font == 0) error(Enodrawimage); if(font->nfchar == 0) error(Enotfont); drawpoint(&p, a+13); drawrectangle(&r, a+21); drawpoint(&sp, a+37); ni = BGSHORT(a+45); u = a+m; m += ni*2; if(n < m) error(Eshortdraw); clipr = dst->clipr; dst->clipr = r; op = drawclientop(client); l = dst; if(*a == 'x'){ /* paint background */ l = drawimage(client, a+47); drawpoint(&q, a+51); r.min.x = p.x; r.min.y = p.y-font->ascent; r.max.x = p.x; r.max.y = r.min.y+Dy(font->image->r); j = ni; while(--j >= 0){ ci = BGSHORT(u); if(ci<0 || ci>=font->nfchar){ dst->clipr = clipr; error(Eindex); } r.max.x += font->fchar[ci].width; u += 2; } memdraw(dst, r, l, q, memopaque, ZP, op); u -= 2*ni; } q = p; while(--ni >= 0){ ci = BGSHORT(u); if(ci<0 || ci>=font->nfchar){ dst->clipr = clipr; error(Eindex); } q = drawchar(dst, l, q, src, &sp, font, ci, op); u += 2; } dst->clipr = clipr; p.y -= font->ascent; dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r))); continue; /* use public screen: 'S' id[4] chan[4] */ case 'S': printmesg(fmt="Ll", a, 0); m = 1+4+4; if(n < m) error(Eshortdraw); dstid = BGLONG(a+1); if(dstid == 0) error(Ebadarg); dscrn = drawlookupdscreen(dstid); if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client)) error(Enodrawscreen); if(dscrn->screen->image->chan != BGLONG(a+5)) error("inconsistent chan"); if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0) error(Edrawmem); continue; /* top or bottom windows: 't' top[1] nw[2] n*id[4] */ case 't': printmesg(fmt="bsL", a, 0); m = 1+1+2; if(n < m) error(Eshortdraw); nw = BGSHORT(a+2); if(nw < 0) error(Ebadarg); if(nw == 0) continue; m += nw*4; if(n < m) error(Eshortdraw); lp = malloc(nw*sizeof(Memimage*)); if(lp == 0) error(Enomem); if(waserror()){ free(lp); nexterror(); } for(j=0; jlayer == 0) error("images are not windows"); for(j=1; jlayer->screen != lp[0]->layer->screen) error("images not on same screen"); if(a[1]) memltofrontn(lp, nw); else memltorearn(lp, nw); if(lp[0]->layer->screen->image->data == screenimage->data) for(j=0; jlayer->screenr); ll = drawlookup(client, BGLONG(a+1+1+2), 1); drawrefreshscreen(ll, client); poperror(); free(lp); continue; /* visible: 'v' */ case 'v': printmesg(fmt="", a, 0); m = 1; drawflush(); continue; /* write: 'y' id[4] R[4*4] data[x*1] */ /* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */ case 'y': case 'Y': printmesg(fmt="LR", a, 0); // iprint("load %c\n", *a); m = 1+4+4*4; if(n < m) error(Eshortdraw); dstid = BGLONG(a+1); dst = drawimage(client, a+1); drawrectangle(&r, a+5); if(!rectinrect(r, dst->r)) error(Ewriteoutside); y = memload(dst, r, a+m, n-m, *a=='Y'); if(y < 0) error("bad writeimage call"); dstflush(dstid, dst, r); m += y; continue; } } poperror(); } Dev drawdevtab = { 'i', "draw", devreset, devinit, devshutdown, drawattach, drawwalk, drawstat, drawopen, devcreate, drawclose, drawread, devbread, drawwrite, devbwrite, devremove, devwstat, }; /* * On 8 bit displays, load the default color map */ void drawcmap(void) { int r, g, b, cr, cg, cb, v; int num, den; int i, j; drawactive(1); /* to restore map from backup */ for(r=0,i=0; r!=4; r++) for(v=0; v!=4; v++,i+=16){ for(g=0,j=v-r; g!=4; g++) for(b=0;b!=4;b++,j++){ den = r; if(g > den) den = g; if(b > den) den = b; if(den == 0) /* divide check -- pick grey shades */ cr = cg = cb = v*17; else{ num = 17*(4*den+v); cr = r*num/den; cg = g*num/den; cb = b*num/den; } setcolor(i+(j&15), cr*0x01010101, cg*0x01010101, cb*0x01010101); } } } void drawblankscreen(int blank) { int i, nc; ulong *p; if(blank == sdraw.blanked) return; if(!canqlock(&sdraw.lk)) return; if(!initscreenimage()){ qunlock(&sdraw.lk); return; } p = sdraw.savemap; nc = screenimage->depth > 8 ? 256 : 1<depth; /* * blankscreen uses the hardware to blank the screen * when possible. to help in cases when it is not possible, * we set the color map to be all black. */ if(blank == 0){ /* turn screen on */ for(i=0; iticks; }else{ if(blanktime && sdraw.blanktime && TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60 >= blanktime) drawblankscreen(1); } */ } int drawidletime(void) { return 0; /* return TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60; */ } drawterm-20110822.orig/kern/x0000644000175000017500000002152111245145712015225 0ustar tinchotincho#include #include #include #include #include #include /* for remove, rename */ #include #ifndef NAME_MAX # define NAME_MAX 256 #endif #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" typedef struct Ufsinfo Ufsinfo; enum { NUID = 256, NGID = 256, MAXPATH = 1024, MAXCOMP = 128 }; struct Ufsinfo { int mode; int fd; DIR* dir; ulong offset; QLock oq; char nextname[NAME_MAX]; }; char *base = "/"; static Qid fsqid(char*, struct stat *); static void fspath(Chan*, char*, char*); static ulong fsdirread(Chan*, uchar*, int, ulong); static int fsomode(int); static char* lastelem(Chan *c) { char *s, *t; s = c2name(c); if((t = strrchr(s, '/')) == nil) return s; if(t[1] == 0) return t; return t+1; } static Chan* fsattach(char *spec) { Chan *c; struct stat stbuf; static int devno; Ufsinfo *uif; if(stat(base, &stbuf) < 0) error(strerror(errno)); c = devattach('U', spec); uif = mallocz(sizeof(Ufsinfo), 1); uif->mode = stbuf.st_mode; c->aux = uif; c->dev = devno++; return c; } static Chan* fsclone(Chan *c, Chan *nc) { Ufsinfo *uif; uif = mallocz(sizeof(Ufsinfo), 1); *uif = *(Ufsinfo*)c->aux; nc->aux = uif; return nc; } static int fswalk1(Chan *c, char *name) { struct stat stbuf; char path[MAXPATH]; Ufsinfo *uif; fspath(c, name, path); /* print("** fs walk '%s' -> %s\n", path, name); */ if(stat(path, &stbuf) < 0) return 0; uif = c->aux; uif->mode = stbuf.st_mode; c->qid = fsqid(path, &stbuf); return 1; } static Walkqid* fswalk(Chan *c, Chan *nc, char **name, int nname) { int i; Walkqid *wq; if(nc != nil) panic("fswalk: nc != nil"); wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); nc = devclone(c); fsclone(c, nc); wq->clone = nc; for(i=0; iqid[i] = nc->qid; } if(i != nname){ cclose(nc); wq->clone = nil; } wq->nqid = i; return wq; } static int fsstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; char path[MAXPATH]; if(n < BIT16SZ) error(Eshortstat); fspath(c, 0, path); if(stat(path, &stbuf) < 0) error(strerror(errno)); d.name = lastelem(c); d.uid = "unknown"; d.gid = "unknown"; d.qid = c->qid; d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; return convD2M(&d, buf, n); } static Chan* fsopen(Chan *c, int mode) { char path[MAXPATH]; int m, isdir; Ufsinfo *uif; m = mode & (OTRUNC|3); switch(m) { case 0: break; case 1: case 1|16: break; case 2: case 0|16: case 2|16: break; case 3: break; default: error(Ebadarg); } isdir = c->qid.type & QTDIR; if(isdir && mode != OREAD) error(Eperm); m = fsomode(m & 3); c->mode = openmode(mode); uif = c->aux; fspath(c, 0, path); if(isdir) { uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { if(mode & OTRUNC) m |= O_TRUNC; uif->fd = open(path, m, 0666); if(uif->fd < 0) error(strerror(errno)); } uif->offset = 0; c->offset = 0; c->flag |= COPEN; return c; } static void fscreate(Chan *c, char *name, int mode, ulong perm) { int fd, m; char path[MAXPATH]; struct stat stbuf; Ufsinfo *uif; m = fsomode(mode&3); fspath(c, name, path); uif = c->aux; if(perm & DMDIR) { if(m) error(Eperm); if(mkdir(path, perm & 0777) < 0) error(strerror(errno)); fd = open(path, 0); if(fd >= 0) { chmod(path, perm & 0777); chown(path, uif->uid, uif->uid); } close(fd); uif->dir = opendir(path); if(uif->dir == 0) error(strerror(errno)); } else { fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666); if(fd >= 0) { if(m != 1) { close(fd); fd = open(path, m); } chmod(path, perm & 0777); chown(path, uif->uid, uif->gid); } if(fd < 0) error(strerror(errno)); uif->fd = fd; } if(stat(path, &stbuf) < 0) error(strerror(errno)); c->qid = fsqid(path, &stbuf); c->offset = 0; c->flag |= COPEN; c->mode = openmode(mode); } static void fsclose(Chan *c) { Ufsinfo *uif; uif = c->aux; if(c->flag & COPEN) { if(c->qid.type & QTDIR) closedir(uif->dir); else close(uif->fd); } free(uif); } static long fsread(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; if(c->qid.type & QTDIR) return fsdirread(c, va, n, offset); uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = read(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static long fswrite(Chan *c, void *va, long n, vlong offset) { int fd, r; Ufsinfo *uif; uif = c->aux; qlock(&uif->oq); if(waserror()) { qunlock(&uif->oq); nexterror(); } fd = uif->fd; if(uif->offset != offset) { r = lseek(fd, offset, 0); if(r < 0) error(strerror(errno)); uif->offset = offset; } n = write(fd, va, n); if(n < 0) error(strerror(errno)); uif->offset += n; qunlock(&uif->oq); poperror(); return n; } static void fsremove(Chan *c) { int n; char path[MAXPATH]; fspath(c, 0, path); if(c->qid.type & QTDIR) n = rmdir(path); else n = remove(path); if(n < 0) error(strerror(errno)); } void fswstat(Chan *c, uchar *buf, int n) { Dir d; struct stat stbuf; char old[MAXPATH], new[MAXPATH], dir[MAXPATH]; char strs[MAXPATH*3]; Ufsinfo *uif; if(convM2D(buf, n, &d, strs) != n) error(Ebadstat); fspath(c, 0, old); if(stat(old, &stbuf) < 0) error(strerror(errno)); uif = c->aux; if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) { fspath(c->parent, 0, dir); fspath(c, 0, old); strcpy(new, old); p = strrchr(new, '/'); strcpy(p+1, d.name); if(rename(old, new) < 0) error(strerror(errno)); } fspath(c, 0, old); if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { if(chmod(old, d.mode&0777) < 0) error(strerror(errno)); uif->mode &= ~0777; uif->mode |= d.mode&0777; } /* p = name2pass(gid, d.gid); if(p == 0) error(Eunknown); if(p->id != stbuf.st_gid) { if(chown(old, stbuf.st_uid, p->id) < 0) error(strerror(errno)); uif->gid = p->id; } */ } static Qid fsqid(char *p, struct stat *st) { Qid q; int dev; ulong h; static int nqdev; static uchar *qdev; if(qdev == 0) qdev = mallocz(65536U, 1); q.type = 0; if((st->st_mode&S_IFMT) == S_IFDIR) q.type = QTDIR; dev = st->st_dev & 0xFFFFUL; if(qdev[dev] == 0) qdev[dev] = ++nqdev; h = 0; while(*p != '\0') h += *p++ * 13; q.path = (vlong)qdev[dev]<<32; q.path |= h; q.vers = st->st_mtime; return q; } static void fspath(Chan *c, char *ext, char *path) { int i, n; char *comp[MAXCOMP]; strcpy(path, base); strcat(path, "/"); strcat(path, c2name(c)); if(ext){ strcat(path, "/"); strcat(path, ext); } cleanname(path); } static int isdots(char *name) { if(name[0] != '.') return 0; if(name[1] == '\0') return 1; if(name[1] != '.') return 0; if(name[2] == '\0') return 1; return 0; } static int p9readdir(char *name, Ufsinfo *uif) { struct dirent *de; if(uif->nextname[0]){ strcpy(name, uif->nextname); uif->nextname[0] = 0; return 1; } de = readdir(uif->dir); if(de == NULL) return 0; strcpy(name, de->d_name); return 1; } static ulong fsdirread(Chan *c, uchar *va, int count, ulong offset) { int i; Dir d; long n; char de[NAME_MAX]; struct stat stbuf; char path[MAXPATH], dirpath[MAXPATH]; Ufsinfo *uif; int n; i = 0; uif = c->aux; errno = 0; if(uif->offset != offset) { if(offset != 0) error("bad offset in fsdirread"); uif->offset = offset; /* sync offset */ uif->nextname[0] = 0; rewinddir(uif->dir); } fspath(c, 0, dirpath); while(i+BIT16SZ < count) { if(!p9readdir(de, uif)) break; if(de[0]==0 || isdots(de)) continue; d.name = de; sprint(path, "%s/%s", dirpath, de); memset(&stbuf, 0, sizeof stbuf); if(stat(path, &stbuf) < 0) { fprint(2, "dir: bad path %s\n", path); /* but continue... probably a bad symlink */ } d.uid = "unknown"; d.gid = "unknown"; d.qid = fsqid(path, &stbuf); d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777); d.atime = stbuf.st_atime; d.mtime = stbuf.st_mtime; d.length = stbuf.st_size; d.type = 'U'; d.dev = c->dev; n = convD2M(&d, (char*)va+i, count-i); if(n == BIT16SZ){ strcpy(uif->nextname, de); break; } i += n; } return i; } static int fsomode(int m) { switch(m) { case 0: /* OREAD */ case 3: /* OEXEC */ return 0; case 1: /* OWRITE */ return 1; case 2: /* ORDWR */ return 2; } error(Ebadarg); return 0; } Dev fsdevtab = { 'U', "fs", devreset, devinit, devshutdown, fsattach, fswalk, fsstat, fsopen, fscreate, fsclose, fsread, devbread, fswrite, devbwrite, fsremove, fswstat, }; drawterm-20110822.orig/kern/dat.h0000644000175000017500000002473511245145711015765 0ustar tinchotincho#define KNAMELEN 28 /* max length of name held in kernel */ #define DOMLEN 64 #define BLOCKALIGN 8 typedef struct Alarms Alarms; typedef struct Block Block; typedef struct CSN CSN; typedef struct Chan Chan; typedef struct Cmdbuf Cmdbuf; typedef struct Cmdtab Cmdtab; typedef struct Cname Cname; typedef struct Conf Conf; typedef struct Dev Dev; typedef struct Dirtab Dirtab; typedef struct Edfinterface Edfinterface; typedef struct Egrp Egrp; typedef struct Evalue Evalue; typedef struct Fgrp Fgrp; typedef struct FPsave FPsave; typedef struct DevConf DevConf; typedef struct Label Label; typedef struct List List; typedef struct Log Log; typedef struct Logflag Logflag; typedef struct Mntcache Mntcache; typedef struct Mount Mount; typedef struct Mntrpc Mntrpc; typedef struct Mntwalk Mntwalk; typedef struct Mnt Mnt; typedef struct Mhead Mhead; typedef struct Note Note; typedef struct Page Page; typedef struct Palloc Palloc; typedef struct Perf Perf; typedef struct Pgrps Pgrps; typedef struct PhysUart PhysUart; typedef struct Pgrp Pgrp; typedef struct Physseg Physseg; typedef struct Proc Proc; typedef struct Pte Pte; typedef struct Pthash Pthash; typedef struct Queue Queue; typedef struct Ref Ref; typedef struct Rendez Rendez; typedef struct Rgrp Rgrp; typedef struct RWlock RWlock; typedef struct Schedq Schedq; typedef struct Segment Segment; typedef struct Session Session; typedef struct Task Task; typedef struct Talarm Talarm; typedef struct Timer Timer; typedef struct Uart Uart; typedef struct Ureg Ureg; typedef struct Waitq Waitq; typedef struct Walkqid Walkqid; typedef int Devgen(Chan*, char*, Dirtab*, int, int, Dir*); #include "fcall.h" enum { SnarfSize = 64*1024, }; struct Conf { ulong nmach; /* processors */ ulong nproc; /* processes */ ulong monitor; /* has monitor? */ ulong npage0; /* total physical pages of memory */ ulong npage1; /* total physical pages of memory */ ulong npage; /* total physical pages of memory */ ulong upages; /* user page pool */ ulong nimage; /* number of page cache image headers */ ulong nswap; /* number of swap pages */ int nswppo; /* max # of pageouts per segment pass */ ulong base0; /* base of bank 0 */ ulong base1; /* base of bank 1 */ ulong copymode; /* 0 is copy on write, 1 is copy on reference */ ulong ialloc; /* max interrupt time allocation in bytes */ ulong pipeqsize; /* size in bytes of pipe queues */ int nuart; /* number of uart devices */ }; struct Label { jmp_buf buf; }; struct Ref { Lock lk; long ref; }; struct Rendez { Lock lk; Proc *p; }; struct RWlock /* changed from kernel */ { int readers; Lock lk; QLock x; QLock k; }; struct Talarm { Lock lk; Proc *list; }; struct Alarms { QLock lk; Proc *head; }; /* * Access types in namec & channel flags */ enum { Aaccess, /* as in stat, wstat */ Abind, /* for left-hand-side of bind */ Atodir, /* as in chdir */ Aopen, /* for i/o */ Amount, /* to be mounted or mounted upon */ Acreate, /* is to be created */ Aremove, /* will be removed by caller */ COPEN = 0x0001, /* for i/o */ CMSG = 0x0002, /* the message channel for a mount */ /* CCREATE = 0x0004, permits creation if c->mnt */ CCEXEC = 0x0008, /* close on exec */ CFREE = 0x0010, /* not in use */ CRCLOSE = 0x0020, /* remove on close */ CCACHE = 0x0080, /* client cache */ }; /* flag values */ enum { BINTR = (1<<0), BFREE = (1<<1), Bipck = (1<<2), /* ip checksum */ Budpck = (1<<3), /* udp checksum */ Btcpck = (1<<4), /* tcp checksum */ Bpktck = (1<<5), /* packet checksum */ }; struct Block { Block* next; Block* list; uchar* rp; /* first unconsumed byte */ uchar* wp; /* first empty byte */ uchar* lim; /* 1 past the end of the buffer */ uchar* base; /* start of the buffer */ void (*free)(Block*); ushort flag; ushort checksum; /* IP checksum of complete packet (minus media header) */ }; #define BLEN(s) ((s)->wp - (s)->rp) #define BALLOC(s) ((s)->lim - (s)->base) struct Chan { Ref ref; Chan* next; /* allocation */ Chan* link; vlong offset; /* in file */ ushort type; ulong dev; ushort mode; /* read/write */ ushort flag; Qid qid; int fid; /* for devmnt */ ulong iounit; /* chunk size for i/o; 0==default */ Mhead* umh; /* mount point that derived Chan; used in unionread */ Chan* umc; /* channel in union; held for union read */ QLock umqlock; /* serialize unionreads */ int uri; /* union read index */ int dri; /* devdirread index */ ulong mountid; Mntcache *mcp; /* Mount cache pointer */ Mnt *mux; /* Mnt for clients using me for messages */ void* aux; Qid pgrpid; /* for #p/notepg */ ulong mid; /* for ns in devproc */ Chan* mchan; /* channel to mounted server */ Qid mqid; /* qid of root of mount point */ Session*session; Cname *name; }; struct Cname { Ref ref; int alen; /* allocated length */ int len; /* strlen(s) */ char *s; }; struct Dev { int dc; char* name; void (*reset)(void); void (*init)(void); void (*shutdown)(void); Chan* (*attach)(char*); Walkqid* (*walk)(Chan*, Chan*, char**, int); int (*stat)(Chan*, uchar*, int); Chan* (*open)(Chan*, int); void (*create)(Chan*, char*, int, ulong); void (*close)(Chan*); long (*read)(Chan*, void*, long, vlong); Block* (*bread)(Chan*, long, ulong); long (*write)(Chan*, void*, long, vlong); long (*bwrite)(Chan*, Block*, ulong); void (*remove)(Chan*); int (*wstat)(Chan*, uchar*, int); void (*power)(int); /* power mgt: power(1) => on, power (0) => off */ int (*config)(int, char*, DevConf*); // returns nil on error }; struct Dirtab { char name[KNAMELEN]; Qid qid; vlong length; ulong perm; }; struct Walkqid { Chan *clone; int nqid; Qid qid[1]; }; enum { NSMAX = 1000, NSLOG = 7, NSCACHE = (1<ref; channels on this mount point incref(c->mchan) == Mnt.c */ Chan *c; /* Channel to file service */ Proc *rip; /* Reader in progress */ Mntrpc *queue; /* Queue of pending requests on this channel */ ulong id; /* Multiplexer id for channel check */ Mnt *list; /* Free list */ int flags; /* cache */ int msize; /* data + IOHDRSZ */ char *version; /* 9P version */ Queue *q; /* input queue */ }; enum { NUser, /* note provided externally */ NExit, /* deliver note quietly */ NDebug, /* print debug message */ }; struct Note { char msg[ERRMAX]; int flag; /* whether system posted it */ }; enum { RENDLOG = 5, RENDHASH = 1<rendhash[(s)&((1<mnthash[(qid).path&((1< variadic */ }; /* queue state bits, Qmsg, Qcoalesce, and Qkick can be set in qopen */ enum { /* Queue.state */ Qstarve = (1<<0), /* consumer starved */ Qmsg = (1<<1), /* message stream */ Qclosed = (1<<2), /* queue has been closed/hungup */ Qflow = (1<<3), /* producer flow controlled */ Qcoalesce = (1<<4), /* coallesce packets on read */ Qkick = (1<<5), /* always call the kick routine after qwrite */ }; #define DEVDOTDOT -1 extern Proc *_getproc(void); extern void _setproc(Proc*); #define up (_getproc()) drawterm-20110822.orig/kern/devcons.c0000644000175000017500000004636511245145711016654 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "keyboard.h" void (*consdebug)(void) = 0; void (*screenputs)(char*, int) = 0; Queue* kbdq; /* unprocessed console input */ Queue* lineq; /* processed console input */ Queue* serialoq; /* serial console output */ Queue* kprintoq; /* console output, for /dev/kprint */ long kprintinuse; /* test and set whether /dev/kprint is open */ Lock kprintlock; int iprintscreenputs = 0; int panicking; struct { int exiting; int machs; } active; static struct { QLock lk; int raw; /* true if we shouldn't process input */ int ctl; /* number of opens to the control file */ int x; /* index into line */ char line[1024]; /* current input line */ int count; int ctlpoff; /* a place to save up characters at interrupt time before dumping them in the queue */ Lock lockputc; char istage[1024]; char *iw; char *ir; char *ie; } kbd = { { 0 }, 0, 0, 0, { 0 }, 0, 0, { 0 }, { 0 }, kbd.istage, kbd.istage, kbd.istage + sizeof(kbd.istage), }; char *sysname; vlong fasthz; static int readtime(ulong, char*, int); static int readbintime(char*, int); static int writetime(char*, int); static int writebintime(char*, int); enum { CMreboot, CMpanic, }; Cmdtab rebootmsg[] = { CMreboot, "reboot", 0, CMpanic, "panic", 0, }; int return0(void *v) { return 0; } void printinit(void) { lineq = qopen(2*1024, 0, 0, nil); if(lineq == nil) panic("printinit"); qnoblock(lineq, 1); kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1); } int consactive(void) { if(serialoq) return qlen(serialoq) > 0; return 0; } void prflush(void) { /* ulong now; now = m->ticks; while(consactive()) if(m->ticks - now >= HZ) break; */ } /* * Print a string on the console. Convert \n to \r\n for serial * line consoles. Locking of the queues is left up to the screen * or uart code. Multi-line messages to serial consoles may get * interspersed with other messages. */ static void putstrn0(char *str, int n, int usewrite) { /* * if someone is reading /dev/kprint, * put the message there. * if not and there's an attached bit mapped display, * put the message there. * * if there's a serial line being used as a console, * put the message there. */ if(kprintoq != nil && !qisclosed(kprintoq)){ if(usewrite) qwrite(kprintoq, str, n); else qiwrite(kprintoq, str, n); }else if(screenputs != 0) screenputs(str, n); } void putstrn(char *str, int n) { putstrn0(str, n, 0); } int noprint; int print(char *fmt, ...) { int n; va_list arg; char buf[PRINTSIZE]; if(noprint) return -1; va_start(arg, fmt); n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); putstrn(buf, n); return n; } void panic(char *fmt, ...) { int n; va_list arg; char buf[PRINTSIZE]; kprintoq = nil; /* don't try to write to /dev/kprint */ if(panicking) for(;;); panicking = 1; splhi(); strcpy(buf, "panic: "); va_start(arg, fmt); n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; va_end(arg); buf[n] = '\n'; uartputs(buf, n+1); if(consdebug) (*consdebug)(); spllo(); prflush(); putstrn(buf, n+1); dumpstack(); exit(1); } int pprint(char *fmt, ...) { int n; Chan *c; va_list arg; char buf[2*PRINTSIZE]; if(up == nil || up->fgrp == nil) return 0; c = up->fgrp->fd[2]; if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) return 0; n = sprint(buf, "%s %lud: ", up->text, up->pid); va_start(arg, fmt); n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); if(waserror()) return 0; devtab[c->type]->write(c, buf, n, c->offset); poperror(); lock(&c->ref.lk); c->offset += n; unlock(&c->ref.lk); return n; } static void echoscreen(char *buf, int n) { char *e, *p; char ebuf[128]; int x; p = ebuf; e = ebuf + sizeof(ebuf) - 4; while(n-- > 0){ if(p >= e){ screenputs(ebuf, p - ebuf); p = ebuf; } x = *buf++; if(x == 0x15){ *p++ = '^'; *p++ = 'U'; *p++ = '\n'; } else *p++ = x; } if(p != ebuf) screenputs(ebuf, p - ebuf); } static void echoserialoq(char *buf, int n) { char *e, *p; char ebuf[128]; int x; p = ebuf; e = ebuf + sizeof(ebuf) - 4; while(n-- > 0){ if(p >= e){ qiwrite(serialoq, ebuf, p - ebuf); p = ebuf; } x = *buf++; if(x == '\n'){ *p++ = '\r'; *p++ = '\n'; } else if(x == 0x15){ *p++ = '^'; *p++ = 'U'; *p++ = '\n'; } else *p++ = x; } if(p != ebuf) qiwrite(serialoq, ebuf, p - ebuf); } static void echo(char *buf, int n) { static int ctrlt; int x; char *e, *p; e = buf+n; for(p = buf; p < e; p++){ switch(*p){ case 0x10: /* ^P */ if(cpuserver && !kbd.ctlpoff){ active.exiting = 1; return; } break; case 0x14: /* ^T */ ctrlt++; if(ctrlt > 2) ctrlt = 2; continue; } if(ctrlt != 2) continue; /* ^T escapes */ ctrlt = 0; switch(*p){ case 'S': x = splhi(); dumpstack(); procdump(); splx(x); return; case 's': dumpstack(); return; case 'x': xsummary(); ixsummary(); mallocsummary(); pagersummary(); return; case 'd': if(consdebug == 0) consdebug = rdb; else consdebug = 0; print("consdebug now 0x%p\n", consdebug); return; case 'D': if(consdebug == 0) consdebug = rdb; consdebug(); return; case 'p': x = spllo(); procdump(); splx(x); return; case 'q': scheddump(); return; case 'k': killbig(); return; case 'r': exit(0); return; } } qproduce(kbdq, buf, n); if(kbd.raw) return; if(screenputs != 0) echoscreen(buf, n); if(serialoq) echoserialoq(buf, n); } /* * Called by a uart interrupt for console input. * * turn '\r' into '\n' before putting it into the queue. */ int kbdcr2nl(Queue *q, int ch) { char *next; USED(q); ilock(&kbd.lockputc); /* just a mutex */ if(ch == '\r' && !kbd.raw) ch = '\n'; next = kbd.iw+1; if(next >= kbd.ie) next = kbd.istage; if(next != kbd.ir){ *kbd.iw = ch; kbd.iw = next; } iunlock(&kbd.lockputc); return 0; } static void _kbdputc(int c) { Rune r; char buf[UTFmax]; int n; r = c; n = runetochar(buf, &r); if(n == 0) return; echo(buf, n); // kbd.c = r; // qproduce(kbdq, buf, n); } /* _kbdputc, but with compose translation */ int kbdputc(Queue *q, int c) { int i; static int collecting, nk; static Rune kc[5]; if(c == Kalt){ collecting = 1; nk = 0; return 0; } if(!collecting){ _kbdputc(c); return 0; } kc[nk++] = c; c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return 0; if(c != -1) /* valid sequence */ _kbdputc(c); else for(i=0; i= size) return 0; if(off+n > size) n = size-off; memmove(buf, tmp+off, n); return n; } int readstr(ulong off, char *buf, ulong n, char *str) { int size; size = strlen(str); if(off >= size) return 0; if(off+n > size) n = size-off; memmove(buf, str+off, n); return n; } static void consinit(void) { todinit(); randominit(); /* * at 115200 baud, the 1024 char buffer takes 56 ms to process, * processing it every 22 ms should be fine */ /* addclock0link(kbdputcclock, 22); */ } static Chan* consattach(char *spec) { return devattach('c', spec); } static Walkqid* conswalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen); } static int consstat(Chan *c, uchar *dp, int n) { return devstat(c, dp, n, consdir, nelem(consdir), devgen); } static Chan* consopen(Chan *c, int omode) { c->aux = nil; c = devopen(c, omode, consdir, nelem(consdir), devgen); switch((ulong)c->qid.path){ case Qconsctl: qlock(&kbd.lk); kbd.ctl++; qunlock(&kbd.lk); break; case Qkprint: lock(&kprintlock); if(kprintinuse != 0){ c->flag &= ~COPEN; unlock(&kprintlock); error(Einuse); } kprintinuse = 1; unlock(&kprintlock); if(kprintoq == nil){ kprintoq = qopen(8*1024, Qcoalesce, 0, 0); if(kprintoq == nil){ c->flag &= ~COPEN; error(Enomem); } qnoblock(kprintoq, 1); }else qreopen(kprintoq); c->iounit = qiomaxatomic; break; case Qsecstore: if(omode == ORDWR) error(Eperm); if(omode != OREAD) memset(secstorebuf, 0, sizeof secstorebuf); break; case Qsnarf: if(omode == ORDWR) error(Eperm); if(omode == OREAD) c->aux = strdup(""); else c->aux = mallocz(SnarfSize, 1); break; } return c; } static void consclose(Chan *c) { switch((ulong)c->qid.path){ /* last close of control file turns off raw */ case Qconsctl: if(c->flag&COPEN){ qlock(&kbd.lk); if(--kbd.ctl == 0) kbd.raw = 0; qunlock(&kbd.lk); } break; /* close of kprint allows other opens */ case Qkprint: if(c->flag & COPEN){ kprintinuse = 0; qhangup(kprintoq, nil); } break; case Qsnarf: if(c->mode == OWRITE) clipwrite(c->aux); free(c->aux); break; } } static long consread(Chan *c, void *buf, long n, vlong off) { char *b; char tmp[128]; /* must be >= 6*NUMSIZE */ char *cbuf = buf; int ch, i, eol; vlong offset = off; if(n <= 0) return n; switch((ulong)c->qid.path){ case Qdir: return devdirread(c, buf, n, consdir, nelem(consdir), devgen); case Qcons: qlock(&kbd.lk); if(waserror()) { qunlock(&kbd.lk); nexterror(); } if(kbd.raw) { if(qcanread(lineq)) n = qread(lineq, buf, n); else { /* read as much as possible */ do { i = qread(kbdq, cbuf, n); cbuf += i; n -= i; } while (n>0 && qcanread(kbdq)); n = cbuf - (char*)buf; } } else { while(!qcanread(lineq)) { qread(kbdq, &kbd.line[kbd.x], 1); ch = kbd.line[kbd.x]; eol = 0; switch(ch){ case '\b': if(kbd.x) kbd.x--; break; case 0x15: kbd.x = 0; break; case '\n': case 0x04: eol = 1; default: kbd.line[kbd.x++] = ch; break; } if(kbd.x == sizeof(kbd.line) || eol){ if(ch == 0x04) kbd.x--; qwrite(lineq, kbd.line, kbd.x); kbd.x = 0; } } n = qread(lineq, buf, n); } qunlock(&kbd.lk); poperror(); return n; case Qcpunote: sleep(&up->sleep, return0, nil); case Qcputime: return 0; case Qkprint: return qread(kprintoq, buf, n); case Qpgrpid: return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE); case Qpid: return readnum((ulong)offset, buf, n, up->pid, NUMSIZE); case Qppid: return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE); case Qtime: return readtime((ulong)offset, buf, n); case Qbintime: return readbintime(buf, n); case Qhostowner: return readstr((ulong)offset, buf, n, eve); case Qhostdomain: return readstr((ulong)offset, buf, n, hostdomain); case Quser: return readstr((ulong)offset, buf, n, up->user); case Qnull: return 0; case Qsnarf: if(offset == 0){ free(c->aux); c->aux = clipread(); } if(c->aux == nil) return 0; return readstr(offset, buf, n, c->aux); case Qsecstore: return readstr(offset, buf, n, secstorebuf); case Qsysstat: return 0; case Qswap: return 0; case Qsysname: if(sysname == nil) return 0; return readstr((ulong)offset, buf, n, sysname); case Qrandom: return randomread(buf, n); case Qdrivers: b = malloc(READSTR); if(b == nil) error(Enomem); n = 0; for(i = 0; devtab[i] != nil; i++) n += snprint(b+n, READSTR-n, "#%C %s\n", devtab[i]->dc, devtab[i]->name); if(waserror()){ free(b); nexterror(); } n = readstr((ulong)offset, buf, n, b); free(b); poperror(); return n; case Qzero: memset(buf, 0, n); return n; case Qosversion: snprint(tmp, sizeof tmp, "2000"); n = readstr((ulong)offset, buf, n, tmp); return n; default: print("consread 0x%llux\n", c->qid.path); error(Egreg); } return -1; /* never reached */ } static long conswrite(Chan *c, void *va, long n, vlong off) { char buf[256]; long l, bp; char *a = va; int fd; Chan *swc; ulong offset = off; Cmdbuf *cb; Cmdtab *ct; switch((ulong)c->qid.path){ case Qcons: /* * Can't page fault in putstrn, so copy the data locally. */ l = n; while(l > 0){ bp = l; if(bp > sizeof buf) bp = sizeof buf; memmove(buf, a, bp); putstrn0(buf, bp, 1); a += bp; l -= bp; } break; case Qconsctl: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, a, n); buf[n] = 0; for(a = buf; a;){ if(strncmp(a, "rawon", 5) == 0){ qlock(&kbd.lk); if(kbd.x){ qwrite(kbdq, kbd.line, kbd.x); kbd.x = 0; } kbd.raw = 1; qunlock(&kbd.lk); } else if(strncmp(a, "rawoff", 6) == 0){ qlock(&kbd.lk); kbd.raw = 0; kbd.x = 0; qunlock(&kbd.lk); } else if(strncmp(a, "ctlpon", 6) == 0){ kbd.ctlpoff = 0; } else if(strncmp(a, "ctlpoff", 7) == 0){ kbd.ctlpoff = 1; } if((a = strchr(a, ' '))) a++; } break; case Qtime: if(!iseve()) error(Eperm); return writetime(a, n); case Qbintime: if(!iseve()) error(Eperm); return writebintime(a, n); case Qhostowner: return hostownerwrite(a, n); case Qhostdomain: return hostdomainwrite(a, n); case Quser: return userwrite(a, n); case Qnull: break; case Qreboot: if(!iseve()) error(Eperm); cb = parsecmd(a, n); if(waserror()) { free(cb); nexterror(); } ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg)); switch(ct->index) { case CMreboot: rebootcmd(cb->nf-1, cb->f+1); break; case CMpanic: panic("/dev/reboot"); } poperror(); free(cb); break; case Qsecstore: if(offset >= sizeof secstorebuf || offset+n+1 >= sizeof secstorebuf) error(Etoobig); secstoretab->qid.vers++; memmove(secstorebuf+offset, va, n); return n; case Qshowfile: return showfilewrite(a, n); case Qsnarf: if(offset >= SnarfSize || offset+n >= SnarfSize) error(Etoobig); snarftab->qid.vers++; memmove((uchar*)c->aux+offset, va, n); return n; case Qsysstat: n = 0; break; case Qswap: if(n >= sizeof buf) error(Egreg); memmove(buf, va, n); /* so we can NUL-terminate */ buf[n] = 0; /* start a pager if not already started */ if(strncmp(buf, "start", 5) == 0){ kickpager(); break; } if(cpuserver && !iseve()) error(Eperm); if(buf[0]<'0' || '9'= sizeof buf) error(Ebadarg); strncpy(buf, a, n); buf[n] = 0; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&sysname, buf); break; default: print("conswrite: 0x%llux\n", c->qid.path); error(Egreg); } return n; } Dev consdevtab = { 'c', "cons", devreset, consinit, devshutdown, consattach, conswalk, consstat, consopen, devcreate, consclose, consread, devbread, conswrite, devbwrite, devremove, devwstat, }; static uvlong uvorder = (uvlong) 0x0001020304050607ULL; static uchar* le2vlong(vlong *to, uchar *f) { uchar *t, *o; int i; t = (uchar*)to; o = (uchar*)&uvorder; for(i = 0; i < sizeof(vlong); i++) t[o[i]] = f[i]; return f+sizeof(vlong); } static uchar* vlong2le(uchar *t, vlong from) { uchar *f, *o; int i; f = (uchar*)&from; o = (uchar*)&uvorder; for(i = 0; i < sizeof(vlong); i++) t[i] = f[o[i]]; return t+sizeof(vlong); } static long order = 0x00010203; static uchar* le2long(long *to, uchar *f) { uchar *t, *o; int i; t = (uchar*)to; o = (uchar*)ℴ for(i = 0; i < sizeof(long); i++) t[o[i]] = f[i]; return f+sizeof(long); } /* static uchar* long2le(uchar *t, long from) { uchar *f, *o; int i; f = (uchar*)&from; o = (uchar*)ℴ for(i = 0; i < sizeof(long); i++) t[i] = f[o[i]]; return t+sizeof(long); } */ char *Ebadtimectl = "bad time control"; /* * like the old #c/time but with added info. Return * * secs nanosecs fastticks fasthz */ static int readtime(ulong off, char *buf, int n) { vlong nsec, ticks; long sec; char str[7*NUMSIZE]; nsec = todget(&ticks); if(fasthz == (vlong)0) fastticks((uvlong*)&fasthz); sec = nsec/((uvlong) 1000000000); snprint(str, sizeof(str), "%*.0lud %*.0llud %*.0llud %*.0llud ", NUMSIZE-1, sec, VLNUMSIZE-1, nsec, VLNUMSIZE-1, ticks, VLNUMSIZE-1, fasthz); return readstr(off, buf, n, str); } /* * set the time in seconds */ static int writetime(char *buf, int n) { char b[13]; long i; vlong now; if(n >= sizeof(b)) error(Ebadtimectl); strncpy(b, buf, n); b[n] = 0; i = strtol(b, 0, 0); if(i <= 0) error(Ebadtimectl); now = i*((vlong) 1000000000); todset(now, 0, 0); return n; } /* * read binary time info. all numbers are little endian. * ticks and nsec are syncronized. */ static int readbintime(char *buf, int n) { int i; vlong nsec, ticks; uchar *b = (uchar*)buf; i = 0; if(fasthz == (vlong)0) fastticks((uvlong*)&fasthz); nsec = todget(&ticks); if(n >= 3*sizeof(uvlong)){ vlong2le(b+2*sizeof(uvlong), fasthz); i += sizeof(uvlong); } if(n >= 2*sizeof(uvlong)){ vlong2le(b+sizeof(uvlong), ticks); i += sizeof(uvlong); } if(n >= 8){ vlong2le(b, nsec); i += sizeof(vlong); } return i; } /* * set any of the following * - time in nsec * - nsec trim applied over some seconds * - clock frequency */ static int writebintime(char *buf, int n) { uchar *p; vlong delta; long period; n--; p = (uchar*)buf + 1; switch(*buf){ case 'n': if(n < sizeof(vlong)) error(Ebadtimectl); le2vlong(&delta, p); todset(delta, 0, 0); break; case 'd': if(n < sizeof(vlong)+sizeof(long)) error(Ebadtimectl); p = le2vlong(&delta, p); le2long(&period, p); todset(-1, delta, period); break; case 'f': if(n < sizeof(uvlong)) error(Ebadtimectl); le2vlong(&fasthz, p); todsetfreq(fasthz); break; } return n; } int iprint(char *fmt, ...) { int n, s; va_list arg; char buf[PRINTSIZE]; s = splhi(); va_start(arg, fmt); n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; va_end(arg); if(screenputs != 0 && iprintscreenputs) screenputs(buf, n); #undef write write(2, buf, n); splx(s); return n; } drawterm-20110822.orig/kern/devtab.c0000644000175000017500000000104011245145712016436 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" extern Dev consdevtab; extern Dev rootdevtab; extern Dev pipedevtab; extern Dev ssldevtab; extern Dev tlsdevtab; extern Dev mousedevtab; extern Dev drawdevtab; extern Dev ipdevtab; extern Dev fsdevtab; extern Dev mntdevtab; extern Dev lfddevtab; extern Dev audiodevtab; Dev *devtab[] = { &rootdevtab, &consdevtab, &pipedevtab, &ssldevtab, &tlsdevtab, &mousedevtab, &drawdevtab, &ipdevtab, &fsdevtab, &mntdevtab, &lfddevtab, &audiodevtab, 0 }; drawterm-20110822.orig/kern/exportfs.c0000644000175000017500000003220411245145712017051 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" typedef struct Fid Fid; typedef struct Export Export; typedef struct Exq Exq; #define nil ((void*)0) enum { Nfidhash = 1, MAXRPC = MAXMSG+MAXFDATA, MAXDIRREAD = (MAXFDATA/DIRLEN)*DIRLEN }; struct Export { Ref r; Exq* work; Lock fidlock; Fid* fid[Nfidhash]; Chan* root; Chan* io; Pgrp* pgrp; int npart; char part[MAXRPC]; }; struct Fid { Fid* next; Fid** last; Chan* chan; long offset; int fid; int ref; /* fcalls using the fid; locked by Export.Lock */ int attached; /* fid attached or cloned but not clunked */ }; struct Exq { Lock lk; int nointr; int noresponse; /* don't respond to this one */ Exq* next; int shut; /* has been noted for shutdown */ Export* export; void* slave; Fcall rpc; char buf[MAXRPC]; }; struct { Lock l; Qlock qwait; Rendez rwait; Exq *head; /* work waiting for a slave */ Exq *tail; }exq; static void exshutdown(Export*); static void exflush(Export*, int, int); static void exslave(void*); static void exfree(Export*); static void exportproc(Export*); static char* Exauth(Export*, Fcall*); static char* Exattach(Export*, Fcall*); static char* Exclunk(Export*, Fcall*); static char* Excreate(Export*, Fcall*); static char* Exopen(Export*, Fcall*); static char* Exread(Export*, Fcall*); static char* Exremove(Export*, Fcall*); static char* Exstat(Export*, Fcall*); static char* Exwalk(Export*, Fcall*); static char* Exwrite(Export*, Fcall*); static char* Exwstat(Export*, Fcall*); static char* Exversion(Export*, Fcall*); static char *(*fcalls[Tmax])(Export*, Fcall*); static char Enofid[] = "no such fid"; static char Eseekdir[] = "can't seek on a directory"; static char Ereaddir[] = "unaligned read of a directory"; static int exdebug = 0; int sysexport(int fd) { Chan *c; Export *fs; if(waserror()) return -1; c = fdtochan(fd, ORDWR, 1, 1); poperror(); c->flag |= CMSG; fs = mallocz(sizeof(Export)); fs->r.ref = 1; fs->pgrp = up->pgrp; refinc(&fs->pgrp->r); refinc(&up->slash->r); fs->root = up->slash; refinc(&fs->root->r); fs->root = domount(fs->root); fs->io = c; exportproc(fs); return 0; } static void exportinit(void) { lock(&exq.l); if(fcalls[Tversion] != nil) { unlock(&exq.l); return; } fmtinstall('F', fcallfmt); fmtinstall('D', dirfmt); fmtinstall('M', dirmodefmt); fcalls[Tversion] = Exversion; fcalls[Tauth] = Exauth; fcalls[Tattach] = Exattach; fcalls[Twalk] = Exwalk; fcalls[Topen] = Exopen; fcalls[Tcreate] = Excreate; fcalls[Tread] = Exread; fcalls[Twrite] = Exwrite; fcalls[Tclunk] = Exclunk; fcalls[Tremove] = Exremove; fcalls[Tstat] = Exstat; fcalls[Twstat] = Exwstat; unlock(&exq.l); } void exportproc(Export *fs) { Exq *q; char *buf; int n, cn, len; exportinit(); for(;;){ q = mallocz(sizeof(Exq)); if(q == 0) panic("no memory"); q->rpc.data = q->buf + MAXMSG; buf = q->buf; len = MAXRPC; if(fs->npart) { memmove(buf, fs->part, fs->npart); buf += fs->npart; len -= fs->npart; goto chk; } for(;;) { if(waserror()) goto bad; n = (*devtab[fs->io->type].read)(fs->io, buf, len, 0); poperror(); if(n <= 0) goto bad; buf += n; len -= n; chk: n = buf - q->buf; /* convM2S returns size of correctly decoded message */ cn = convM2S(q->buf, &q->rpc, n); if(cn < 0){ iprint("bad message type in devmnt\n"); goto bad; } if(cn > 0) { n -= cn; if(n < 0){ iprint("negative size in devmnt"); goto bad; } fs->npart = n; if(n != 0) memmove(fs->part, q->buf+cn, n); break; } } if(exdebug) iprint("export %d <- %F\n", getpid(), &q->rpc); if(q->rpc.type == Tflush){ exflush(fs, q->rpc.tag, q->rpc.oldtag); free(q); continue; } q->export = fs; refinc(&fs->r); lock(&exq.l); if(exq.head == nil) exq.head = q; else exq.tail->next = q; q->next = nil; exq.tail = q; unlock(&exq.l); if(exq.qwait.first == nil) { n = thread("exportfs", exslave, nil); /* iprint("launch export (pid=%ux)\n", n); */ } rendwakeup(&exq.rwait); } bad: free(q); exshutdown(fs); exfree(fs); } void exflush(Export *fs, int flushtag, int tag) { Exq *q, **last; int n; Fcall fc; char buf[MAXMSG]; /* hasn't been started? */ lock(&exq.l); last = &exq.head; for(q = exq.head; q != nil; q = q->next){ if(q->export == fs && q->rpc.tag == tag){ *last = q->next; unlock(&exq.l); exfree(fs); free(q); goto Respond; } last = &q->next; } unlock(&exq.l); /* in progress? */ lock(&fs->r.l); for(q = fs->work; q != nil; q = q->next){ if(q->rpc.tag == tag && !q->noresponse){ lock(&q->lk); q->noresponse = 1; if(!q->nointr) intr(q->slave); unlock(&q->lk); unlock(&fs->r.l); goto Respond; return; } } unlock(&fs->r.l); if(exdebug) iprint("exflush: did not find rpc: %d\n", tag); Respond: fc.type = Rflush; fc.tag = flushtag; n = convS2M(&fc, buf); if(exdebug) iprint("exflush -> %F\n", &fc); if(!waserror()){ (*devtab[fs->io->type].write)(fs->io, buf, n, 0); poperror(); } } void exshutdown(Export *fs) { Exq *q, **last; lock(&exq.l); last = &exq.head; for(q = exq.head; q != nil; q = *last){ if(q->export == fs){ *last = q->next; exfree(fs); free(q); continue; } last = &q->next; } unlock(&exq.l); lock(&fs->r.l); q = fs->work; while(q != nil){ if(q->shut){ q = q->next; continue; } q->shut = 1; unlock(&fs->r.l); /* postnote(q->slave, 1, "interrupted", NUser); */ iprint("postnote 2!\n"); lock(&fs->r.l); q = fs->work; } unlock(&fs->r.l); } void exfree(Export *fs) { Fid *f, *n; int i; if(refdec(&fs->r) != 0) return; closepgrp(fs->pgrp); cclose(fs->root); cclose(fs->io); for(i = 0; i < Nfidhash; i++){ for(f = fs->fid[i]; f != nil; f = n){ if(f->chan != nil) cclose(f->chan); n = f->next; free(f); } } free(fs); } int exwork(void *a) { return exq.head != nil; } void exslave(void *a) { Export *fs; Exq *q, *t, **last; char *err; int n; /* closepgrp(up->pgrp); up->pgrp = nil; */ for(;;){ qlock(&exq.qwait); rendsleep(&exq.rwait, exwork, nil); lock(&exq.l); q = exq.head; if(q == nil) { unlock(&exq.l); qunlock(&exq.qwait); continue; } exq.head = q->next; q->slave = curthread(); unlock(&exq.l); qunlock(&exq.qwait); q->noresponse = 0; q->nointr = 0; fs = q->export; lock(&fs->r.l); q->next = fs->work; fs->work = q; unlock(&fs->r.l); up->pgrp = q->export->pgrp; if(exdebug > 1) iprint("exslave dispatch %d %F\n", getpid(), &q->rpc); if(waserror()){ iprint("exslave err %r\n"); err = up->errstr; goto Err; } if(q->rpc.type >= Tmax || !fcalls[q->rpc.type]) err = "bad fcall type"; else err = (*fcalls[q->rpc.type])(fs, &q->rpc); poperror(); Err:; q->rpc.type++; if(err){ q->rpc.type = Rerror; strncpy(q->rpc.ename, err, ERRLEN); } n = convS2M(&q->rpc, q->buf); if(exdebug) iprint("exslve %d -> %F\n", getpid(), &q->rpc); lock(&q->lk); if(q->noresponse == 0){ q->nointr = 1; clearintr(); if(!waserror()){ (*devtab[fs->io->type].write)(fs->io, q->buf, n, 0); poperror(); } } unlock(&q->lk); /* * exflush might set noresponse at this point, but * setting noresponse means don't send a response now; * it's okay that we sent a response already. */ if(exdebug > 1) iprint("exslave %d written %d\n", getpid(), q->rpc.tag); lock(&fs->r.l); last = &fs->work; for(t = fs->work; t != nil; t = t->next){ if(t == q){ *last = q->next; break; } last = &t->next; } unlock(&fs->r.l); exfree(q->export); free(q); } iprint("exslave shut down"); threadexit(); } Fid* Exmkfid(Export *fs, int fid) { ulong h; Fid *f, *nf; nf = mallocz(sizeof(Fid)); if(nf == nil) return nil; lock(&fs->fidlock); h = fid % Nfidhash; for(f = fs->fid[h]; f != nil; f = f->next){ if(f->fid == fid){ unlock(&fs->fidlock); free(nf); return nil; } } nf->next = fs->fid[h]; if(nf->next != nil) nf->next->last = &nf->next; nf->last = &fs->fid[h]; fs->fid[h] = nf; nf->fid = fid; nf->ref = 1; nf->attached = 1; nf->offset = 0; nf->chan = nil; unlock(&fs->fidlock); return nf; } Fid* Exgetfid(Export *fs, int fid) { Fid *f; ulong h; lock(&fs->fidlock); h = fid % Nfidhash; for(f = fs->fid[h]; f; f = f->next) { if(f->fid == fid){ if(f->attached == 0) break; f->ref++; unlock(&fs->fidlock); return f; } } unlock(&fs->fidlock); return nil; } void Exputfid(Export *fs, Fid *f) { lock(&fs->fidlock); f->ref--; if(f->ref == 0 && f->attached == 0){ if(f->chan != nil) cclose(f->chan); f->chan = nil; *f->last = f->next; if(f->next != nil) f->next->last = f->last; unlock(&fs->fidlock); free(f); return; } unlock(&fs->fidlock); } char* Exsession(Export *e, Fcall *rpc) { memset(rpc->authid, 0, sizeof(rpc->authid)); memset(rpc->authdom, 0, sizeof(rpc->authdom)); memset(rpc->chal, 0, sizeof(rpc->chal)); return nil; } char* Exauth(Export *e, Fcall *f) { return "authentication not required"; } char* Exattach(Export *fs, Fcall *rpc) { Fid *f; f = Exmkfid(fs, rpc->fid); if(f == nil) return Einuse; if(waserror()){ f->attached = 0; Exputfid(fs, f); return up->errstr; } f->chan = clone(fs->root, nil); poperror(); rpc->qid = f->chan->qid; Exputfid(fs, f); return nil; } char* Exclone(Export *fs, Fcall *rpc) { Fid *f, *nf; if(rpc->fid == rpc->newfid) return Einuse; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; nf = Exmkfid(fs, rpc->newfid); if(nf == nil){ Exputfid(fs, f); return Einuse; } if(waserror()){ Exputfid(fs, f); Exputfid(fs, nf); return up->errstr; } nf->chan = clone(f->chan, nil); poperror(); Exputfid(fs, f); Exputfid(fs, nf); return nil; } char* Exclunk(Export *fs, Fcall *rpc) { Fid *f; f = Exgetfid(fs, rpc->fid); if(f != nil){ f->attached = 0; Exputfid(fs, f); } return nil; } char* Exwalk(Export *fs, Fcall *rpc) { Fid *f; Chan *c; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; if(waserror()){ Exputfid(fs, f); return up->errstr; } c = walk(f->chan, rpc->name, 1); if(c == nil) error(Enonexist); poperror(); f->chan = c; rpc->qid = c->qid; Exputfid(fs, f); return nil; } char* Exopen(Export *fs, Fcall *rpc) { Fid *f; Chan *c; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; if(waserror()){ Exputfid(fs, f); return up->errstr; } c = f->chan; c = (*devtab[c->type].open)(c, rpc->mode); poperror(); f->chan = c; f->offset = 0; rpc->qid = f->chan->qid; Exputfid(fs, f); return nil; } char* Excreate(Export *fs, Fcall *rpc) { Fid *f; Chan *c; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; if(waserror()){ Exputfid(fs, f); return up->errstr; } c = f->chan; if(c->mnt && !(c->flag&CCREATE)) c = createdir(c); (*devtab[c->type].create)(c, rpc->name, rpc->mode, rpc->perm); poperror(); f->chan = c; rpc->qid = f->chan->qid; Exputfid(fs, f); return nil; } char* Exread(Export *fs, Fcall *rpc) { Fid *f; Chan *c; long off; int dir, n, seek; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; c = f->chan; dir = c->qid.path & CHDIR; if(dir){ rpc->count -= rpc->count%DIRLEN; if(rpc->offset%DIRLEN || rpc->count==0){ Exputfid(fs, f); return Ereaddir; } if(f->offset > rpc->offset){ Exputfid(fs, f); return Eseekdir; } } if(waserror()) { Exputfid(fs, f); return up->errstr; } for(;;){ n = rpc->count; seek = 0; off = rpc->offset; if(dir && f->offset != off){ off = f->offset; n = rpc->offset - off; if(n > MAXDIRREAD) n = MAXDIRREAD; seek = 1; } if(dir && c->mnt != nil) n = unionread(c, rpc->data, n); else{ c->offset = off; n = (*devtab[c->type].read)(c, rpc->data, n, off); } if(n == 0 || !seek) break; f->offset = off + n; c->offset += n; } rpc->count = n; poperror(); Exputfid(fs, f); return nil; } char* Exwrite(Export *fs, Fcall *rpc) { Fid *f; Chan *c; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; if(waserror()){ Exputfid(fs, f); return up->errstr; } c = f->chan; if(c->qid.path & CHDIR) error(Eisdir); rpc->count = (*devtab[c->type].write)(c, rpc->data, rpc->count, rpc->offset); poperror(); Exputfid(fs, f); return nil; } char* Exstat(Export *fs, Fcall *rpc) { Fid *f; Chan *c; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; if(waserror()){ Exputfid(fs, f); return up->errstr; } c = f->chan; (*devtab[c->type].stat)(c, rpc->stat); poperror(); Exputfid(fs, f); return nil; } char* Exwstat(Export *fs, Fcall *rpc) { Fid *f; Chan *c; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; if(waserror()){ Exputfid(fs, f); return up->errstr; } c = f->chan; (*devtab[c->type].wstat)(c, rpc->stat); poperror(); Exputfid(fs, f); return nil; } char* Exremove(Export *fs, Fcall *rpc) { Fid *f; Chan *c; f = Exgetfid(fs, rpc->fid); if(f == nil) return Enofid; if(waserror()){ Exputfid(fs, f); return up->errstr; } c = f->chan; (*devtab[c->type].remove)(c); poperror(); /* * chan is already clunked by remove. * however, we need to recover the chan, * and follow sysremove's lead in making to point to root. */ c->type = 0; f->attached = 0; Exputfid(fs, f); return nil; } drawterm-20110822.orig/kern/devmnt.c0000644000175000017500000005232511245145712016502 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" /* * References are managed as follows: * The channel to the server - a network connection or pipe - has one * reference for every Chan open on the server. The server channel has * c->mux set to the Mnt used for muxing control to that server. Mnts * have no reference count; they go away when c goes away. * Each channel derived from the mount point has mchan set to c, * and increfs/decrefs mchan to manage references on the server * connection. */ #define MAXRPC (IOHDRSZ+8192) struct Mntrpc { Chan* c; /* Channel for whom we are working */ Mntrpc* list; /* Free/pending list */ Fcall request; /* Outgoing file system protocol message */ Fcall reply; /* Incoming reply */ Mnt* m; /* Mount device during rpc */ Rendez r; /* Place to hang out */ uchar* rpc; /* I/O Data buffer */ uint rpclen; /* len of buffer */ Block *b; /* reply blocks */ char done; /* Rpc completed */ uvlong stime; /* start time for mnt statistics */ ulong reqlen; /* request length for mnt statistics */ ulong replen; /* reply length for mnt statistics */ Mntrpc* flushed; /* message this one flushes */ }; enum { TAGSHIFT = 5, /* ulong has to be 32 bits */ TAGMASK = (1<>TAGSHIFT, }; struct Mntalloc { Lock lk; Mnt* list; /* Mount devices in use */ Mnt* mntfree; /* Free list */ Mntrpc* rpcfree; int nrpcfree; int nrpcused; ulong id; ulong tagmask[NMASK]; }mntalloc; void mattach(Mnt*, Chan*, char*); Mnt* mntchk(Chan*); void mntdirfix(uchar*, Chan*); Mntrpc* mntflushalloc(Mntrpc*, ulong); void mntflushfree(Mnt*, Mntrpc*); void mntfree(Mntrpc*); void mntgate(Mnt*); void mntpntfree(Mnt*); void mntqrm(Mnt*, Mntrpc*); Mntrpc* mntralloc(Chan*, ulong); long mntrdwr(int, Chan*, void*, long, vlong); int mntrpcread(Mnt*, Mntrpc*); void mountio(Mnt*, Mntrpc*); void mountmux(Mnt*, Mntrpc*); void mountrpc(Mnt*, Mntrpc*); int rpcattn(void*); Chan* mntchan(void); char Esbadstat[] = "invalid directory entry received from server"; char Enoversion[] = "version not established for mount channel"; void (*mntstats)(int, Chan*, uvlong, ulong); static void mntreset(void) { mntalloc.id = 1; mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */ mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */ fmtinstall('F', fcallfmt); fmtinstall('D', dirfmt); /* We can't install %M since eipfmt does and is used in the kernel [sape] */ cinit(); } /* * Version is not multiplexed: message sent only once per connection. */ long mntversion(Chan *c, char *version, int msize, int returnlen) { Fcall f; uchar *msg; Mnt *m; char *v; long k, l; uvlong oo; char buf[128]; qlock(&c->umqlock); /* make sure no one else does this until we've established ourselves */ if(waserror()){ qunlock(&c->umqlock); nexterror(); } /* defaults */ if(msize == 0) msize = MAXRPC; if(msize > c->iounit && c->iounit != 0) msize = c->iounit; v = version; if(v == nil || v[0] == '\0') v = VERSION9P; /* validity */ if(msize < 0) error("bad iounit in version call"); if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0) error("bad 9P version specification"); m = c->mux; if(m != nil){ qunlock(&c->umqlock); poperror(); strecpy(buf, buf+sizeof buf, m->version); k = strlen(buf); if(strncmp(buf, v, k) != 0){ snprint(buf, sizeof buf, "incompatible 9P versions %s %s", m->version, v); error(buf); } if(returnlen > 0){ if(returnlen < k) error(Eshort); memmove(version, buf, k); } return k; } f.type = Tversion; f.tag = NOTAG; f.msize = msize; f.version = v; msg = malloc(8192+IOHDRSZ); if(msg == nil) exhausted("version memory"); if(waserror()){ free(msg); nexterror(); } k = convS2M(&f, msg, 8192+IOHDRSZ); if(k == 0) error("bad fversion conversion on send"); lock(&c->ref.lk); oo = c->offset; c->offset += k; unlock(&c->ref.lk); l = devtab[c->type]->write(c, msg, k, oo); if(l < k){ lock(&c->ref.lk); c->offset -= k - l; unlock(&c->ref.lk); error("short write in fversion"); } /* message sent; receive and decode reply */ k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset); if(k <= 0) error("EOF receiving fversion reply"); lock(&c->ref.lk); c->offset += k; unlock(&c->ref.lk); l = convM2S(msg, k, &f); if(l != k) error("bad fversion conversion on reply"); if(f.type != Rversion){ if(f.type == Rerror) error(f.ename); error("unexpected reply type in fversion"); } if(f.msize > msize) error("server tries to increase msize in fversion"); if(f.msize<256 || f.msize>1024*1024) error("nonsense value of msize in fversion"); k = strlen(f.version); if(strncmp(f.version, v, k) != 0) error("bad 9P version returned from server"); /* now build Mnt associated with this connection */ lock(&mntalloc.lk); m = mntalloc.mntfree; if(m != 0) mntalloc.mntfree = m->list; else { m = malloc(sizeof(Mnt)); if(m == 0) { unlock(&mntalloc.lk); exhausted("mount devices"); } } m->list = mntalloc.list; mntalloc.list = m; m->version = nil; kstrdup(&m->version, f.version); m->id = mntalloc.id++; m->q = qopen(10*MAXRPC, 0, 0, nil); m->msize = f.msize; unlock(&mntalloc.lk); if(returnlen > 0){ if(returnlen < k) error(Eshort); memmove(version, f.version, k); } poperror(); /* msg */ free(msg); lock(&m->lk); m->queue = 0; m->rip = 0; c->flag |= CMSG; c->mux = m; m->c = c; unlock(&m->lk); poperror(); /* c */ qunlock(&c->umqlock); return k; } Chan* mntauth(Chan *c, char *spec) { Mnt *m; Mntrpc *r; m = c->mux; if(m == nil){ mntversion(c, VERSION9P, MAXRPC, 0); m = c->mux; if(m == nil) error(Enoversion); } c = mntchan(); if(waserror()) { /* Close must not be called since it will * call mnt recursively */ chanfree(c); nexterror(); } r = mntralloc(0, m->msize); if(waserror()) { mntfree(r); nexterror(); } r->request.type = Tauth; r->request.afid = c->fid; r->request.uname = up->user; r->request.aname = spec; mountrpc(m, r); c->qid = r->reply.aqid; c->mchan = m->c; incref(&m->c->ref); c->mqid = c->qid; c->mode = ORDWR; poperror(); /* r */ mntfree(r); poperror(); /* c */ return c; } static Chan* mntattach(char *muxattach) { Mnt *m; Chan *c; Mntrpc *r; struct bogus{ Chan *chan; Chan *authchan; char *spec; int flags; }bogus; bogus = *((struct bogus *)muxattach); c = bogus.chan; m = c->mux; if(m == nil){ mntversion(c, nil, 0, 0); m = c->mux; if(m == nil) error(Enoversion); } c = mntchan(); if(waserror()) { /* Close must not be called since it will * call mnt recursively */ chanfree(c); nexterror(); } r = mntralloc(0, m->msize); if(waserror()) { mntfree(r); nexterror(); } r->request.type = Tattach; r->request.fid = c->fid; if(bogus.authchan == nil) r->request.afid = NOFID; else r->request.afid = bogus.authchan->fid; r->request.uname = up->user; r->request.aname = bogus.spec; mountrpc(m, r); c->qid = r->reply.qid; c->mchan = m->c; incref(&m->c->ref); c->mqid = c->qid; poperror(); /* r */ mntfree(r); poperror(); /* c */ if(bogus.flags&MCACHE) c->flag |= CCACHE; return c; } Chan* mntchan(void) { Chan *c; c = devattach('M', 0); lock(&mntalloc.lk); c->dev = mntalloc.id++; unlock(&mntalloc.lk); if(c->mchan) panic("mntchan non-zero %p", c->mchan); return c; } static Walkqid* mntwalk(Chan *c, Chan *nc, char **name, int nname) { int i, alloc; Mnt *m; Mntrpc *r; Walkqid *wq; if(nc != nil) print("mntwalk: nc != nil\n"); if(nname > MAXWELEM) error("devmnt: too many name elements"); alloc = 0; wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); if(waserror()){ if(alloc && wq->clone!=nil) cclose(wq->clone); free(wq); return nil; } alloc = 0; m = mntchk(c); r = mntralloc(c, m->msize); if(nc == nil){ nc = devclone(c); /* * Until the other side accepts this fid, we can't mntclose it. * Therefore set type to 0 for now; rootclose is known to be safe. */ nc->type = 0; alloc = 1; } wq->clone = nc; if(waserror()) { mntfree(r); nexterror(); } r->request.type = Twalk; r->request.fid = c->fid; r->request.newfid = nc->fid; r->request.nwname = nname; memmove(r->request.wname, name, nname*sizeof(char*)); mountrpc(m, r); if(r->reply.nwqid > nname) error("too many QIDs returned by walk"); if(r->reply.nwqid < nname){ if(alloc) cclose(nc); wq->clone = nil; if(r->reply.nwqid == 0){ free(wq); wq = nil; goto Return; } } /* move new fid onto mnt device and update its qid */ if(wq->clone != nil){ if(wq->clone != c){ wq->clone->type = c->type; wq->clone->mchan = c->mchan; incref(&c->mchan->ref); } if(r->reply.nwqid > 0) wq->clone->qid = r->reply.wqid[r->reply.nwqid-1]; } wq->nqid = r->reply.nwqid; for(i=0; inqid; i++) wq->qid[i] = r->reply.wqid[i]; Return: poperror(); mntfree(r); poperror(); return wq; } static int mntstat(Chan *c, uchar *dp, int n) { Mnt *m; Mntrpc *r; if(n < BIT16SZ) error(Eshortstat); m = mntchk(c); r = mntralloc(c, m->msize); if(waserror()) { mntfree(r); nexterror(); } r->request.type = Tstat; r->request.fid = c->fid; mountrpc(m, r); /* r->reply.nstat is 16 bits if(r->reply.nstat >= 1<<16) error("returned stat buffer count too large"); */ if(r->reply.nstat > n){ /* * 12/31/2002 RSC * * This should be nstat-2, which is the first two * bytes of the stat buffer. But dirstat and dirfstat * depended on getting the full nstat (they didn't * add BIT16SZ themselves). I fixed dirstat and dirfstat * but am leaving this unchanged for now. After a * few months, once enough of the relevant binaries * have been recompiled for other reasons, we can * change this to nstat-2. Devstat gets this right * (via convD2M). */ /* doesn't fit; just patch the count and return */ PBIT16((uchar*)dp, r->reply.nstat); n = BIT16SZ; }else{ n = r->reply.nstat; memmove(dp, r->reply.stat, n); validstat(dp, n); mntdirfix(dp, c); } poperror(); mntfree(r); return n; } static Chan* mntopencreate(int type, Chan *c, char *name, int omode, ulong perm) { Mnt *m; Mntrpc *r; m = mntchk(c); r = mntralloc(c, m->msize); if(waserror()) { mntfree(r); nexterror(); } r->request.type = type; r->request.fid = c->fid; r->request.mode = omode; if(type == Tcreate){ r->request.perm = perm; r->request.name = name; } mountrpc(m, r); c->qid = r->reply.qid; c->offset = 0; c->mode = openmode(omode); c->iounit = r->reply.iounit; if(c->iounit == 0 || c->iounit > m->msize-IOHDRSZ) c->iounit = m->msize-IOHDRSZ; c->flag |= COPEN; poperror(); mntfree(r); if(c->flag & CCACHE) copen(c); return c; } static Chan* mntopen(Chan *c, int omode) { return mntopencreate(Topen, c, nil, omode, 0); } static void mntcreate(Chan *c, char *name, int omode, ulong perm) { mntopencreate(Tcreate, c, name, omode, perm); } static void mntclunk(Chan *c, int t) { Mnt *m; Mntrpc *r; m = mntchk(c); r = mntralloc(c, m->msize); if(waserror()){ mntfree(r); nexterror(); } r->request.type = t; r->request.fid = c->fid; mountrpc(m, r); mntfree(r); poperror(); } void muxclose(Mnt *m) { Mntrpc *q, *r; for(q = m->queue; q; q = r) { r = q->list; mntfree(q); } m->id = 0; free(m->version); m->version = nil; mntpntfree(m); } void mntpntfree(Mnt *m) { Mnt *f, **l; Queue *q; lock(&mntalloc.lk); l = &mntalloc.list; for(f = *l; f; f = f->list) { if(f == m) { *l = m->list; break; } l = &f->list; } m->list = mntalloc.mntfree; mntalloc.mntfree = m; q = m->q; unlock(&mntalloc.lk); qfree(q); } static void mntclose(Chan *c) { mntclunk(c, Tclunk); } static void mntremove(Chan *c) { mntclunk(c, Tremove); } static int mntwstat(Chan *c, uchar *dp, int n) { Mnt *m; Mntrpc *r; m = mntchk(c); r = mntralloc(c, m->msize); if(waserror()) { mntfree(r); nexterror(); } r->request.type = Twstat; r->request.fid = c->fid; r->request.nstat = n; r->request.stat = dp; mountrpc(m, r); poperror(); mntfree(r); return n; } static long mntread(Chan *c, void *buf, long n, vlong off) { uchar *p, *e; int nc, cache, isdir, dirlen; isdir = 0; cache = c->flag & CCACHE; if(c->qid.type & QTDIR) { cache = 0; isdir = 1; } p = buf; if(cache) { nc = cread(c, buf, n, off); if(nc > 0) { n -= nc; if(n == 0) return nc; p += nc; off += nc; } n = mntrdwr(Tread, c, p, n, off); cupdate(c, p, n, off); return n + nc; } n = mntrdwr(Tread, c, buf, n, off); if(isdir) { for(e = &p[n]; p+BIT16SZ < e; p += dirlen){ dirlen = BIT16SZ+GBIT16(p); if(p+dirlen > e) break; validstat(p, dirlen); mntdirfix(p, c); } if(p != e) error(Esbadstat); } return n; } static long mntwrite(Chan *c, void *buf, long n, vlong off) { return mntrdwr(Twrite, c, buf, n, off); } long mntrdwr(int type, Chan *c, void *buf, long n, vlong off) { Mnt *m; Mntrpc *r; char *uba; int cache; ulong cnt, nr, nreq; m = mntchk(c); uba = buf; cnt = 0; cache = c->flag & CCACHE; if(c->qid.type & QTDIR) cache = 0; for(;;) { r = mntralloc(c, m->msize); if(waserror()) { mntfree(r); nexterror(); } r->request.type = type; r->request.fid = c->fid; r->request.offset = off; r->request.data = uba; nr = n; if(nr > m->msize-IOHDRSZ) nr = m->msize-IOHDRSZ; r->request.count = nr; mountrpc(m, r); nreq = r->request.count; nr = r->reply.count; if(nr > nreq) nr = nreq; if(type == Tread) r->b = bl2mem((uchar*)uba, r->b, nr); else if(cache) cwrite(c, (uchar*)uba, nr, off); poperror(); mntfree(r); off += nr; uba += nr; cnt += nr; n -= nr; if(nr != nreq || n == 0) break; } return cnt; } void mountrpc(Mnt *m, Mntrpc *r) { char *sn, *cn; int t; r->reply.tag = 0; r->reply.type = Tmax; /* can't ever be a valid message type */ mountio(m, r); t = r->reply.type; switch(t) { case Rerror: error(r->reply.ename); case Rflush: error(Eintr); default: if(t == r->request.type+1) break; sn = "?"; if(m->c->name != nil) sn = m->c->name->s; cn = "?"; if(r->c != nil && r->c->name != nil) cn = r->c->name->s; print("mnt: proc %lud: mismatch from %s %s rep 0x%lux tag %d fid %d T%d R%d rp %d\n", up->pid, sn, cn, r, r->request.tag, r->request.fid, r->request.type, r->reply.type, r->reply.tag); error(Emountrpc); } } void mountio(Mnt *m, Mntrpc *r) { int n; while(waserror()) { if(m->rip == up) mntgate(m); if(strcmp(up->errstr, Eintr) != 0){ mntflushfree(m, r); nexterror(); } r = mntflushalloc(r, m->msize); } lock(&m->lk); r->m = m; r->list = m->queue; m->queue = r; unlock(&m->lk); /* Transmit a file system rpc */ if(m->msize == 0) panic("msize"); n = convS2M(&r->request, r->rpc, m->msize); if(n < 0) panic("bad message type in mountio"); if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n) error(Emountrpc); r->stime = fastticks(nil); r->reqlen = n; /* Gate readers onto the mount point one at a time */ for(;;) { lock(&m->lk); if(m->rip == 0) break; unlock(&m->lk); sleep(&r->r, rpcattn, r); if(r->done){ poperror(); mntflushfree(m, r); return; } } m->rip = up; unlock(&m->lk); while(r->done == 0) { if(mntrpcread(m, r) < 0) error(Emountrpc); mountmux(m, r); } mntgate(m); poperror(); mntflushfree(m, r); } static int doread(Mnt *m, int len) { Block *b; while(qlen(m->q) < len){ b = devtab[m->c->type]->bread(m->c, m->msize, 0); if(b == nil) return -1; if(BLEN(b) == 0){ freeblist(b); return -1; } qaddlist(m->q, b); } return 0; } int mntrpcread(Mnt *m, Mntrpc *r) { int i, t, len, hlen; Block *b, **l, *nb; r->reply.type = 0; r->reply.tag = 0; /* read at least length, type, and tag and pullup to a single block */ if(doread(m, BIT32SZ+BIT8SZ+BIT16SZ) < 0) return -1; nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ); /* read in the rest of the message, avoid rediculous (for now) message sizes */ len = GBIT32(nb->rp); if(len > m->msize){ qdiscard(m->q, qlen(m->q)); return -1; } if(doread(m, len) < 0) return -1; /* pullup the header (i.e. everything except data) */ t = nb->rp[BIT32SZ]; switch(t){ case Rread: hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ; break; default: hlen = len; break; } nb = pullupqueue(m->q, hlen); if(convM2S(nb->rp, len, &r->reply) <= 0){ /* bad message, dump it */ print("mntrpcread: convM2S failed\n"); qdiscard(m->q, len); return -1; } /* hang the data off of the fcall struct */ l = &r->b; *l = nil; do { b = qremove(m->q); if(hlen > 0){ b->rp += hlen; len -= hlen; hlen = 0; } i = BLEN(b); if(i <= len){ len -= i; *l = b; l = &(b->next); } else { /* split block and put unused bit back */ nb = allocb(i-len); memmove(nb->wp, b->rp+len, i-len); b->wp = b->rp+len; nb->wp += i-len; qputback(m->q, nb); *l = b; return 0; } }while(len > 0); return 0; } void mntgate(Mnt *m) { Mntrpc *q; lock(&m->lk); m->rip = 0; for(q = m->queue; q; q = q->list) { if(q->done == 0) if(wakeup(&q->r)) break; } unlock(&m->lk); } void mountmux(Mnt *m, Mntrpc *r) { Mntrpc **l, *q; lock(&m->lk); l = &m->queue; for(q = *l; q; q = q->list) { /* look for a reply to a message */ if(q->request.tag == r->reply.tag) { *l = q->list; if(q != r) { /* * Completed someone else. * Trade pointers to receive buffer. */ q->reply = r->reply; q->b = r->b; r->b = nil; } q->done = 1; unlock(&m->lk); if(mntstats != 0) (*mntstats)(q->request.type, m->c, q->stime, q->reqlen + r->replen); if(q != r) wakeup(&q->r); return; } l = &q->list; } unlock(&m->lk); print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type); } /* * Create a new flush request and chain the previous * requests from it */ Mntrpc* mntflushalloc(Mntrpc *r, ulong iounit) { Mntrpc *fr; fr = mntralloc(0, iounit); fr->request.type = Tflush; if(r->request.type == Tflush) fr->request.oldtag = r->request.oldtag; else fr->request.oldtag = r->request.tag; fr->flushed = r; return fr; } /* * Free a chain of flushes. Remove each unanswered * flush and the original message from the unanswered * request queue. Mark the original message as done * and if it hasn't been answered set the reply to to * Rflush. */ void mntflushfree(Mnt *m, Mntrpc *r) { Mntrpc *fr; while(r){ fr = r->flushed; if(!r->done){ r->reply.type = Rflush; mntqrm(m, r); } if(fr) mntfree(r); r = fr; } } int alloctag(void) { int i, j; ulong v; for(i = 0; i < NMASK; i++){ v = mntalloc.tagmask[i]; if(v == ~0) continue; for(j = 0; j < 1<>TAGSHIFT] &= ~(1<<(t&TAGMASK)); } Mntrpc* mntralloc(Chan *c, ulong msize) { Mntrpc *new; lock(&mntalloc.lk); new = mntalloc.rpcfree; if(new == nil){ new = malloc(sizeof(Mntrpc)); if(new == nil) { unlock(&mntalloc.lk); exhausted("mount rpc header"); } /* * The header is split from the data buffer as * mountmux may swap the buffer with another header. */ new->rpc = mallocz(msize, 0); if(new->rpc == nil){ free(new); unlock(&mntalloc.lk); exhausted("mount rpc buffer"); } new->rpclen = msize; new->request.tag = alloctag(); } else { mntalloc.rpcfree = new->list; mntalloc.nrpcfree--; if(new->rpclen < msize){ free(new->rpc); new->rpc = mallocz(msize, 0); if(new->rpc == nil){ free(new); mntalloc.nrpcused--; unlock(&mntalloc.lk); exhausted("mount rpc buffer"); } new->rpclen = msize; } } mntalloc.nrpcused++; unlock(&mntalloc.lk); new->c = c; new->done = 0; new->flushed = nil; new->b = nil; return new; } void mntfree(Mntrpc *r) { if(r->b != nil) freeblist(r->b); lock(&mntalloc.lk); if(mntalloc.nrpcfree >= 10){ free(r->rpc); free(r); freetag(r->request.tag); } else{ r->list = mntalloc.rpcfree; mntalloc.rpcfree = r; mntalloc.nrpcfree++; } mntalloc.nrpcused--; unlock(&mntalloc.lk); } void mntqrm(Mnt *m, Mntrpc *r) { Mntrpc **l, *f; lock(&m->lk); r->done = 1; l = &m->queue; for(f = *l; f; f = f->list) { if(f == r) { *l = r->list; break; } l = &f->list; } unlock(&m->lk); } Mnt* mntchk(Chan *c) { Mnt *m; /* This routine is mostly vestiges of prior lives; now it's just sanity checking */ if(c->mchan == nil) panic("mntchk 1: nil mchan c %s\n", c2name(c)); m = c->mchan->mux; if(m == nil) print("mntchk 2: nil mux c %s c->mchan %s \n", c2name(c), c2name(c->mchan)); /* * Was it closed and reused (was error(Eshutdown); now, it can't happen) */ if(m->id == 0 || m->id >= c->dev) panic("mntchk 3: can't happen"); return m; } /* * Rewrite channel type and dev for in-flight data to * reflect local values. These entries are known to be * the first two in the Dir encoding after the count. */ void mntdirfix(uchar *dirbuf, Chan *c) { uint r; r = devtab[c->type]->dc; dirbuf += BIT16SZ; /* skip count */ PBIT16(dirbuf, r); dirbuf += BIT16SZ; PBIT32(dirbuf, c->dev); } int rpcattn(void *v) { Mntrpc *r; r = v; return r->done || r->m->rip == 0; } Dev mntdevtab = { 'M', "mnt", mntreset, devinit, devshutdown, mntattach, mntwalk, mntstat, mntopen, mntcreate, mntclose, mntread, devbread, mntwrite, devbwrite, mntremove, mntwstat, }; drawterm-20110822.orig/kern/smalloc.c0000644000175000017500000000027311245145712016632 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" void* smalloc(ulong n) { return mallocz(n, 1); } void* malloc(ulong n) { return mallocz(n, 1); } drawterm-20110822.orig/kern/error.h0000644000175000017500000000502711245145712016340 0ustar tinchotinchoextern char Enoerror[]; /* no error */ extern char Emount[]; /* inconsistent mount */ extern char Eunmount[]; /* not mounted */ extern char Eunion[]; /* not in union */ extern char Emountrpc[]; /* mount rpc error */ extern char Eshutdown[]; /* device shut down */ extern char Enocreate[]; /* mounted directory forbids creation */ extern char Enonexist[]; /* file does not exist */ extern char Eexist[]; /* file already exists */ extern char Ebadsharp[]; /* unknown device in # filename */ extern char Enotdir[]; /* not a directory */ extern char Eisdir[]; /* file is a directory */ extern char Ebadchar[]; /* bad character in file name */ extern char Efilename[]; /* file name syntax */ extern char Eperm[]; /* permission denied */ extern char Ebadusefd[]; /* inappropriate use of fd */ extern char Ebadarg[]; /* bad arg in system call */ extern char Einuse[]; /* device or object already in use */ extern char Eio[]; /* i/o error */ extern char Etoobig[]; /* read or write too large */ extern char Etoosmall[]; /* read or write too small */ extern char Enoport[]; /* network port not available */ extern char Ehungup[]; /* i/o on hungup channel */ extern char Ebadctl[]; /* bad process or channel control request */ extern char Enodev[]; /* no free devices */ extern char Eprocdied[]; /* process exited */ extern char Enochild[]; /* no living children */ extern char Eioload[]; /* i/o error in demand load */ extern char Enovmem[]; /* virtual memory allocation failed */ extern char Ebadfd[]; /* fd out of range or not open */ extern char Enofd[]; /* no free file descriptors */ extern char Eisstream[]; /* seek on a stream */ extern char Ebadexec[]; /* exec header invalid */ extern char Etimedout[]; /* connection timed out */ extern char Econrefused[]; /* connection refused */ extern char Econinuse[]; /* connection in use */ extern char Eintr[]; /* interrupted */ extern char Enomem[]; /* kernel allocate failed */ extern char Enoswap[]; /* swap space full */ extern char Esoverlap[]; /* segments overlap */ extern char Emouseset[]; /* mouse type already set */ extern char Eshort[]; /* i/o count too small */ extern char Egreg[]; /* ken has left the building */ extern char Ebadspec[]; /* bad attach specifier */ extern char Enoreg[]; /* process has no saved registers */ extern char Enoattach[]; /* mount/attach disallowed */ extern char Eshortstat[]; /* stat buffer too small */ extern char Ebadstat[]; /* malformed stat buffer */ extern char Enegoff[]; /* negative i/o offset */ extern char Ecmdargs[]; /* wrong #args in control message */ drawterm-20110822.orig/kern/stub.c0000644000175000017500000000237311245145712016160 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" void mallocsummary(void) { } void pagersummary(void) { } int iseve(void) { return 1; } void setswapchan(Chan *c) { USED(c); } void splx(int x) { USED(x); } int splhi(void) { return 0; } int spllo(void) { return 0; } void procdump(void) { } void scheddump(void) { } void killbig(void) { } void dumpstack(void) { } void xsummary(void) { } void rebootcmd(int argc, char **argv) { USED(argc); USED(argv); } void kickpager(void) { } int userwrite(char *a, int n) { error(Eperm); return 0; } vlong todget(vlong *p) { if(p) *p = 0; return 0; } void todset(vlong a, vlong b, int c) { USED(a); USED(b); USED(c); } void todsetfreq(vlong a) { USED(a); } long hostdomainwrite(char *a, int n) { USED(a); USED(n); error(Eperm); return 0; } long hostownerwrite(char *a, int n) { USED(a); USED(n); error(Eperm); return 0; } void todinit(void) { } void rdb(void) { } void setmalloctag(void *v, uintptr tag) { USED(v); USED(tag); } int postnote(Proc *p, int x, char *msg, int flag) { USED(p); USED(x); USED(msg); USED(flag); return 0; } void exhausted(char *s) { panic("out of %s", s); } uvlong fastticks(uvlong *v) { if(v) *v = 1; return 0; } drawterm-20110822.orig/kern/devip-win32.c0000644000175000017500000000672611245146177017266 0ustar tinchotincho#include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devip.h" #ifdef MSVC #pragma comment(lib, "wsock32.lib") #endif #undef listen #undef accept #undef bind void osipinit(void) { WSADATA wasdat; char buf[1024]; if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0) panic("no winsock.dll"); gethostname(buf, sizeof(buf)); kstrdup(&sysname, buf); } int so_socket(int type) { int fd, one; switch(type) { default: error("bad protocol type"); case S_TCP: type = SOCK_STREAM; break; case S_UDP: type = SOCK_DGRAM; break; } fd = socket(AF_INET, type, 0); if(fd < 0) oserror(); one = 1; if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){ oserrstr(); print("setsockopt: %s\n", up->errstr); } return fd; } void so_connect(int fd, unsigned long raddr, unsigned short rport) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; hnputs(&sin.sin_port, rport); hnputl(&sin.sin_addr.s_addr, raddr); if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) oserror(); } void so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) { int len; struct sockaddr_in sin; len = sizeof(sin); if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) oserror(); if(sin.sin_family != AF_INET || len != sizeof(sin)) error("not AF_INET"); *laddr = nhgetl(&sin.sin_addr.s_addr); *lport = nhgets(&sin.sin_port); } void so_listen(int fd) { if(listen(fd, 5) < 0) oserror(); } int so_accept(int fd, unsigned long *raddr, unsigned short *rport) { int nfd, len; struct sockaddr_in sin; len = sizeof(sin); nfd = accept(fd, (struct sockaddr*)&sin, &len); if(nfd < 0) oserror(); if(sin.sin_family != AF_INET || len != sizeof(sin)) error("not AF_INET"); *raddr = nhgetl(&sin.sin_addr.s_addr); *rport = nhgets(&sin.sin_port); return nfd; } void so_bind(int fd, int su, unsigned short port) { int i, one; struct sockaddr_in sin; one = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ oserrstr(); print("setsockopt: %s", up->errstr); } if(su) { for(i = 600; i < 1024; i++) { memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = i; if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) return; } oserror(); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; hnputs(&sin.sin_port, port); if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) oserror(); } int so_gethostbyname(char *host, char**hostv, int n) { int i; char buf[32]; unsigned char *p; struct hostent *hp; hp = gethostbyname(host); if(hp == 0) return 0; for(i = 0; hp->h_addr_list[i] && i < n; i++) { p = (unsigned char*)hp->h_addr_list[i]; sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); hostv[i] = strdup(buf); if(hostv[i] == 0) break; } return i; } char* hostlookup(char *host) { char buf[100]; uchar *p; HOSTENT *he; he = gethostbyname(host); if(he != 0 && he->h_addr_list[0]) { p = (uchar*)he->h_addr_list[0]; sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); } else strcpy(buf, host); return strdup(buf); } int so_getservbyname(char *service, char *net, char *port) { struct servent *s; s = getservbyname(service, net); if(s == 0) return -1; sprint(port, "%d", nhgets(&s->s_port)); return 0; } int so_send(int fd, void *d, int n, int f) { return send(fd, d, n, f); } int so_recv(int fd, void *d, int n, int f) { return recv(fd, d, n, f); } drawterm-20110822.orig/kern/pgrp.c0000644000175000017500000000766111245145712016160 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" static Ref pgrpid; static Ref mountid; #ifdef NOTDEF void pgrpnote(ulong noteid, char *a, long n, int flag) { Proc *p, *ep; char buf[ERRMAX]; if(n >= ERRMAX-1) error(Etoobig); memmove(buf, a, n); buf[n] = 0; p = proctab(0); ep = p+conf.nproc; for(; p < ep; p++) { if(p->state == Dead) continue; if(up != p && p->noteid == noteid && p->kp == 0) { qlock(&p->debug); if(p->pid == 0 || p->noteid != noteid){ qunlock(&p->debug); continue; } if(!waserror()) { postnote(p, 0, buf, flag); poperror(); } qunlock(&p->debug); } } } #endif Pgrp* newpgrp(void) { Pgrp *p; p = smalloc(sizeof(Pgrp)); p->ref.ref = 1; p->pgrpid = incref(&pgrpid); return p; } Rgrp* newrgrp(void) { Rgrp *r; r = smalloc(sizeof(Rgrp)); r->ref.ref = 1; return r; } void closergrp(Rgrp *r) { if(decref(&r->ref) == 0) free(r); } void closepgrp(Pgrp *p) { Mhead **h, **e, *f, *next; if(decref(&p->ref) != 0) return; qlock(&p->debug); wlock(&p->ns); p->pgrpid = -1; e = &p->mnthash[MNTHASH]; for(h = p->mnthash; h < e; h++) { for(f = *h; f; f = next) { wlock(&f->lock); cclose(f->from); mountfree(f->mount); f->mount = nil; next = f->hash; wunlock(&f->lock); putmhead(f); } } wunlock(&p->ns); qunlock(&p->debug); free(p); } void pgrpinsert(Mount **order, Mount *m) { Mount *f; m->order = 0; if(*order == 0) { *order = m; return; } for(f = *order; f; f = f->order) { if(m->mountid < f->mountid) { m->order = f; *order = m; return; } order = &f->order; } *order = m; } /* * pgrpcpy MUST preserve the mountid allocation order of the parent group */ void pgrpcpy(Pgrp *to, Pgrp *from) { int i; Mount *n, *m, **link, *order; Mhead *f, **tom, **l, *mh; wlock(&from->ns); order = 0; tom = to->mnthash; for(i = 0; i < MNTHASH; i++) { l = tom++; for(f = from->mnthash[i]; f; f = f->hash) { rlock(&f->lock); mh = newmhead(f->from); *l = mh; l = &mh->hash; link = &mh->mount; for(m = f->mount; m; m = m->next) { n = newmount(mh, m->to, m->mflag, m->spec); m->copy = n; pgrpinsert(&order, m); *link = n; link = &n->next; } runlock(&f->lock); } } /* * Allocate mount ids in the same sequence as the parent group */ lock(&mountid.lk); for(m = order; m; m = m->order) m->copy->mountid = mountid.ref++; unlock(&mountid.lk); wunlock(&from->ns); } Fgrp* dupfgrp(Fgrp *f) { Fgrp *new; Chan *c; int i; new = smalloc(sizeof(Fgrp)); if(f == nil){ new->fd = smalloc(DELTAFD*sizeof(Chan*)); new->nfd = DELTAFD; new->ref.ref = 1; return new; } lock(&f->ref.lk); /* Make new fd list shorter if possible, preserving quantization */ new->nfd = f->maxfd+1; i = new->nfd%DELTAFD; if(i != 0) new->nfd += DELTAFD - i; new->fd = malloc(new->nfd*sizeof(Chan*)); if(new->fd == 0){ unlock(&f->ref.lk); error("no memory for fgrp"); } new->ref.ref = 1; new->maxfd = f->maxfd; for(i = 0; i <= f->maxfd; i++) { if((c = f->fd[i])){ incref(&c->ref); new->fd[i] = c; } } unlock(&f->ref.lk); return new; } void closefgrp(Fgrp *f) { int i; Chan *c; if(f == 0) return; if(decref(&f->ref) != 0) return; for(i = 0; i <= f->maxfd; i++) if((c = f->fd[i])) cclose(c); free(f->fd); free(f); } Mount* newmount(Mhead *mh, Chan *to, int flag, char *spec) { Mount *m; m = smalloc(sizeof(Mount)); m->to = to; m->head = mh; incref(&to->ref); m->mountid = incref(&mountid); m->mflag = flag; if(spec != 0) kstrdup(&m->spec, spec); return m; } void mountfree(Mount *m) { Mount *f; while(m) { f = m->next; cclose(m->to); m->mountid = 0; free(m->spec); free(m); m = f; } } #ifdef NOTDEF void resrcwait(char *reason) { char *p; if(up == 0) panic("resrcwait"); p = up->psstate; if(reason) { up->psstate = reason; print("%s\n", reason); } tsleep(&up->sleep, return0, 0, 300); up->psstate = p; } #endif drawterm-20110822.orig/kern/devaudio-unix.c0000644000175000017500000000600411245145711017756 0ustar tinchotincho/* * Linux and BSD */ #include #ifdef __linux__ #include #else #include #endif #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devaudio.h" enum { Channels = 2, Rate = 44100, Bits = 16, Bigendian = 1, }; static int afd = -1; static int cfd= -1; static int speed; /* maybe this should return -1 instead of sysfatal */ void audiodevopen(void) { int t; ulong ul; afd = -1; cfd = -1; if((afd = open("/dev/dsp", OWRITE)) < 0) goto err; if((cfd = open("/dev/mixer", ORDWR)) < 0) goto err; t = Bits; if(ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &t) < 0) goto err; t = Channels-1; if(ioctl(afd, SNDCTL_DSP_STEREO, &t) < 0) goto err; speed = Rate; ul = Rate; if(ioctl(afd, SNDCTL_DSP_SPEED, &ul) < 0) goto err; return; err: if(afd >= 0) close(afd); afd = -1; oserror(); } void audiodevclose(void) { close(afd); close(cfd); afd = -1; cfd = -1; } static struct { int id9; int id; } names[] = { Vaudio, SOUND_MIXER_VOLUME, Vbass, SOUND_MIXER_BASS, Vtreb, SOUND_MIXER_TREBLE, Vline, SOUND_MIXER_LINE, Vpcm, SOUND_MIXER_PCM, Vsynth, SOUND_MIXER_SYNTH, Vcd, SOUND_MIXER_CD, Vmic, SOUND_MIXER_MIC, // "record", SOUND_MIXER_RECLEV, // "mix", SOUND_MIXER_IMIX, // "pcm2", SOUND_MIXER_ALTPCM, Vspeaker, SOUND_MIXER_SPEAKER // "line1", SOUND_MIXER_LINE1, // "line2", SOUND_MIXER_LINE2, // "line3", SOUND_MIXER_LINE3, // "digital1", SOUND_MIXER_DIGITAL1, // "digital2", SOUND_MIXER_DIGITAL2, // "digital3", SOUND_MIXER_DIGITAL3, // "phonein", SOUND_MIXER_PHONEIN, // "phoneout", SOUND_MIXER_PHONEOUT, // "radio", SOUND_MIXER_RADIO, // "video", SOUND_MIXER_VIDEO, // "monitor", SOUND_MIXER_MONITOR, // "igain", SOUND_MIXER_IGAIN, // "ogain", SOUND_MIXER_OGAIN, }; static int lookname(int id9) { int i; for(i=0; i>8)&0xFF; } int audiodevwrite(void *v, int n) { int m, tot; for(tot=0; tot #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #undef pread #undef pwrite Chan* lfdchan(int fd) { Chan *c; c = newchan(); c->type = devno('L', 0); c->aux = (void*)(uintptr)fd; c->name = newcname("fd"); c->mode = ORDWR; c->qid.type = 0; c->qid.path = 0; c->qid.vers = 0; c->dev = 0; c->offset = 0; return c; } int lfdfd(int fd) { return newfd(lfdchan(fd)); } static Chan* lfdattach(char *x) { USED(x); error(Egreg); return nil; } static Walkqid* lfdwalk(Chan *c, Chan *nc, char **name, int nname) { USED(c); USED(nc); USED(name); USED(nname); error(Egreg); return nil; } static int lfdstat(Chan *c, uchar *dp, int n) { USED(c); USED(dp); USED(n); error(Egreg); return -1; } static Chan* lfdopen(Chan *c, int omode) { USED(c); USED(omode); error(Egreg); return nil; } static void lfdclose(Chan *c) { close((int)(uintptr)c->aux); } static long lfdread(Chan *c, void *buf, long n, vlong off) { USED(off); /* can't pread on pipes */ n = read((int)(uintptr)c->aux, buf, n); if(n < 0){ iprint("error %d\n", errno); oserror(); } return n; } static long lfdwrite(Chan *c, void *buf, long n, vlong off) { USED(off); /* can't pread on pipes */ n = write((int)(uintptr)c->aux, buf, n); if(n < 0){ iprint("error %d\n", errno); oserror(); } return n; } Dev lfddevtab = { 'L', "lfd", devreset, devinit, devshutdown, lfdattach, lfdwalk, lfdstat, lfdopen, devcreate, lfdclose, lfdread, devbread, lfdwrite, devbwrite, devremove, devwstat, }; drawterm-20110822.orig/kern/cache.c0000644000175000017500000000072211245145711016241 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" void cinit(void) { } void copen(Chan *c) { USED(c); } int cread(Chan *c, uchar *buf, int len, vlong off) { USED(c); USED(buf); USED(len); USED(off); return 0; } void cupdate(Chan *c, uchar *buf, int len, vlong off) { USED(c); USED(buf); USED(len); USED(off); } void cwrite(Chan* c, uchar *buf, int len, vlong off) { USED(c); USED(buf); USED(len); USED(off); } drawterm-20110822.orig/kern/devssl.c0000644000175000017500000006352511245145712016511 0ustar tinchotincho/* * devssl - secure sockets layer */ #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "libsec.h" #define NOSPOOKS 1 typedef struct OneWay OneWay; struct OneWay { QLock q; QLock ctlq; void *state; /* encryption state */ int slen; /* hash data length */ uchar *secret; /* secret */ ulong mid; /* message id */ }; enum { /* connection states */ Sincomplete= 0, Sclear= 1, Sencrypting= 2, Sdigesting= 4, Sdigenc= Sencrypting|Sdigesting, /* encryption algorithms */ Noencryption= 0, DESCBC= 1, DESECB= 2, RC4= 3 }; typedef struct Dstate Dstate; struct Dstate { Chan *c; /* io channel */ uchar state; /* state of connection */ int ref; /* serialized by dslock for atomic destroy */ uchar encryptalg; /* encryption algorithm */ ushort blocklen; /* blocking length */ ushort diglen; /* length of digest */ DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); /* hash func */ /* for SSL format */ int max; /* maximum unpadded data per msg */ int maxpad; /* maximum padded data per msg */ /* input side */ OneWay in; Block *processed; Block *unprocessed; /* output side */ OneWay out; /* protections */ char *user; int perm; }; enum { Maxdmsg= 1<<16, Maxdstate= 128, /* must be a power of 2 */ }; Lock dslock; int dshiwat; char *dsname[Maxdstate]; Dstate *dstate[Maxdstate]; char *encalgs; char *hashalgs; enum{ Qtopdir = 1, /* top level directory */ Qprotodir, Qclonus, Qconvdir, /* directory for a conversation */ Qdata, Qctl, Qsecretin, Qsecretout, Qencalgs, Qhashalgs, }; #define TYPE(x) ((x).path & 0xf) #define CONV(x) (((x).path >> 5)&(Maxdstate-1)) #define QID(c, y) (((c)<<5) | (y)) static void ensure(Dstate*, Block**, int); static void consume(Block**, uchar*, int); static void setsecret(OneWay*, uchar*, int); static Block* encryptb(Dstate*, Block*, int); static Block* decryptb(Dstate*, Block*); static Block* digestb(Dstate*, Block*, int); static void checkdigestb(Dstate*, Block*); static Chan* buftochan(char*); static void sslhangup(Dstate*); static Dstate* dsclone(Chan *c); static void dsnew(Chan *c, Dstate **); static long sslput(Dstate *s, Block * volatile b); char *sslnames[] = { /* unused */ 0, /* topdir */ 0, /* protodir */ 0, "clone", /* convdir */ 0, "data", "ctl", "secretin", "secretout", "encalgs", "hashalgs", }; static int sslgen(Chan *c, char *n, Dirtab *d, int nd, int s, Dir *dp) { Qid q; Dstate *ds; char name[16], *p, *nm; int ft; USED(n); USED(nd); USED(d); q.type = QTFILE; q.vers = 0; ft = TYPE(c->qid); switch(ft) { case Qtopdir: if(s == DEVDOTDOT){ q.path = QID(0, Qtopdir); q.type = QTDIR; devdir(c, q, "#D", 0, eve, 0555, dp); return 1; } if(s > 0) return -1; q.path = QID(0, Qprotodir); q.type = QTDIR; devdir(c, q, "ssl", 0, eve, 0555, dp); return 1; case Qprotodir: if(s == DEVDOTDOT){ q.path = QID(0, Qtopdir); q.type = QTDIR; devdir(c, q, ".", 0, eve, 0555, dp); return 1; } if(s < dshiwat) { q.path = QID(s, Qconvdir); q.type = QTDIR; ds = dstate[s]; if(ds != 0) nm = ds->user; else nm = eve; if(dsname[s] == nil){ sprint(name, "%d", s); kstrdup(&dsname[s], name); } devdir(c, q, dsname[s], 0, nm, 0555, dp); return 1; } if(s > dshiwat) return -1; q.path = QID(0, Qclonus); devdir(c, q, "clone", 0, eve, 0555, dp); return 1; case Qconvdir: if(s == DEVDOTDOT){ q.path = QID(0, Qprotodir); q.type = QTDIR; devdir(c, q, "ssl", 0, eve, 0555, dp); return 1; } ds = dstate[CONV(c->qid)]; if(ds != 0) nm = ds->user; else nm = eve; switch(s) { default: return -1; case 0: q.path = QID(CONV(c->qid), Qctl); p = "ctl"; break; case 1: q.path = QID(CONV(c->qid), Qdata); p = "data"; break; case 2: q.path = QID(CONV(c->qid), Qsecretin); p = "secretin"; break; case 3: q.path = QID(CONV(c->qid), Qsecretout); p = "secretout"; break; case 4: q.path = QID(CONV(c->qid), Qencalgs); p = "encalgs"; break; case 5: q.path = QID(CONV(c->qid), Qhashalgs); p = "hashalgs"; break; } devdir(c, q, p, 0, nm, 0660, dp); return 1; case Qclonus: devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp); return 1; default: ds = dstate[CONV(c->qid)]; if(ds != 0) nm = ds->user; else nm = eve; devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp); return 1; } return -1; } static Chan* sslattach(char *spec) { Chan *c; c = devattach('D', spec); c->qid.path = QID(0, Qtopdir); c->qid.vers = 0; c->qid.type = QTDIR; return c; } static Walkqid* sslwalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, nil, 0, sslgen); } static int sslstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, nil, 0, sslgen); } static Chan* sslopen(Chan *c, int omode) { Dstate *s, **pp; int perm; int ft; perm = 0; omode &= 3; switch(omode) { case OREAD: perm = 4; break; case OWRITE: perm = 2; break; case ORDWR: perm = 6; break; } ft = TYPE(c->qid); switch(ft) { default: panic("sslopen"); case Qtopdir: case Qprotodir: case Qconvdir: if(omode != OREAD) error(Eperm); break; case Qclonus: s = dsclone(c); if(s == 0) error(Enodev); break; case Qctl: case Qdata: case Qsecretin: case Qsecretout: if(waserror()) { unlock(&dslock); nexterror(); } lock(&dslock); pp = &dstate[CONV(c->qid)]; s = *pp; if(s == 0) dsnew(c, pp); else { if((perm & (s->perm>>6)) != perm && (strcmp(up->user, s->user) != 0 || (perm & s->perm) != perm)) error(Eperm); s->ref++; } unlock(&dslock); poperror(); break; case Qencalgs: case Qhashalgs: if(omode != OREAD) error(Eperm); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } static int sslwstat(Chan *c, uchar *db, int n) { Dir *dir; Dstate *s; int m; s = dstate[CONV(c->qid)]; if(s == 0) error(Ebadusefd); if(strcmp(s->user, up->user) != 0) error(Eperm); dir = smalloc(sizeof(Dir)+n); m = convM2D(db, n, &dir[0], (char*)&dir[1]); if(m == 0){ free(dir); error(Eshortstat); } if(!emptystr(dir->uid)) kstrdup(&s->user, dir->uid); if(dir->mode != ~0) s->perm = dir->mode; free(dir); return m; } static void sslclose(Chan *c) { Dstate *s; int ft; ft = TYPE(c->qid); switch(ft) { case Qctl: case Qdata: case Qsecretin: case Qsecretout: if((c->flag & COPEN) == 0) break; s = dstate[CONV(c->qid)]; if(s == 0) break; lock(&dslock); if(--s->ref > 0) { unlock(&dslock); break; } dstate[CONV(c->qid)] = 0; unlock(&dslock); if(s->user != nil) free(s->user); sslhangup(s); if(s->c) cclose(s->c); if(s->in.secret) free(s->in.secret); if(s->out.secret) free(s->out.secret); if(s->in.state) free(s->in.state); if(s->out.state) free(s->out.state); free(s); } } /* * make sure we have at least 'n' bytes in list 'l' */ static void ensure(Dstate *s, Block **l, int n) { int sofar, i; Block *b, *bl; sofar = 0; for(b = *l; b; b = b->next){ sofar += BLEN(b); if(sofar >= n) return; l = &b->next; } while(sofar < n){ bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0); if(bl == 0) nexterror(); *l = bl; i = 0; for(b = bl; b; b = b->next){ i += BLEN(b); l = &b->next; } if(i == 0) error(Ehungup); sofar += i; } } /* * copy 'n' bytes from 'l' into 'p' and free * the bytes in 'l' */ static void consume(Block **l, uchar *p, int n) { Block *b; int i; for(; *l && n > 0; n -= i){ b = *l; i = BLEN(b); if(i > n) i = n; memmove(p, b->rp, i); b->rp += i; p += i; if(BLEN(b) < 0) panic("consume"); if(BLEN(b)) break; *l = b->next; freeb(b); } } /* * give back n bytes static void regurgitate(Dstate *s, uchar *p, int n) { Block *b; if(n <= 0) return; b = s->unprocessed; if(s->unprocessed == nil || b->rp - b->base < n) { b = allocb(n); memmove(b->wp, p, n); b->wp += n; b->next = s->unprocessed; s->unprocessed = b; } else { b->rp -= n; memmove(b->rp, p, n); } } */ /* * remove at most n bytes from the queue, if discard is set * dump the remainder */ static Block* qtake(Block **l, int n, int discard) { Block *nb, *b, *first; int i; first = *l; for(b = first; b; b = b->next){ i = BLEN(b); if(i == n){ if(discard){ freeblist(b->next); *l = 0; } else *l = b->next; b->next = 0; return first; } else if(i > n){ i -= n; if(discard){ freeblist(b->next); b->wp -= i; *l = 0; } else { nb = allocb(i); memmove(nb->wp, b->rp+n, i); nb->wp += i; b->wp -= i; nb->next = b->next; *l = nb; } b->next = 0; if(BLEN(b) < 0) panic("qtake"); return first; } else n -= i; if(BLEN(b) < 0) panic("qtake"); } *l = 0; return first; } /* * We can't let Eintr's lose data since the program * doing the read may be able to handle it. The only * places Eintr is possible is during the read's in consume. * Therefore, we make sure we can always put back the bytes * consumed before the last ensure. */ static Block* sslbread(Chan *c, long n, ulong o) { Dstate * volatile s; Block *b; uchar consumed[3], *p; int toconsume; int len, pad; USED(o); s = dstate[CONV(c->qid)]; if(s == 0) panic("sslbread"); if(s->state == Sincomplete) error(Ebadusefd); qlock(&s->in.q); if(waserror()){ qunlock(&s->in.q); nexterror(); } if(s->processed == 0){ /* * Read in the whole message. Until we've got it all, * it stays on s->unprocessed, so that if we get Eintr, * we'll pick up where we left off. */ ensure(s, &s->unprocessed, 3); s->unprocessed = pullupblock(s->unprocessed, 2); p = s->unprocessed->rp; if(p[0] & 0x80){ len = ((p[0] & 0x7f)<<8) | p[1]; ensure(s, &s->unprocessed, len); pad = 0; toconsume = 2; } else { s->unprocessed = pullupblock(s->unprocessed, 3); len = ((p[0] & 0x3f)<<8) | p[1]; pad = p[2]; if(pad > len){ print("pad %d buf len %d\n", pad, len); error("bad pad in ssl message"); } toconsume = 3; } ensure(s, &s->unprocessed, toconsume+len); /* skip header */ consume(&s->unprocessed, consumed, toconsume); /* grab the next message and decode/decrypt it */ b = qtake(&s->unprocessed, len, 0); if(blocklen(b) != len) print("devssl: sslbread got wrong count %d != %d", blocklen(b), len); if(waserror()){ qunlock(&s->in.ctlq); if(b != nil) freeb(b); nexterror(); } qlock(&s->in.ctlq); switch(s->state){ case Sencrypting: if(b == nil) error("ssl message too short (encrypting)"); b = decryptb(s, b); break; case Sdigesting: b = pullupblock(b, s->diglen); if(b == nil) error("ssl message too short (digesting)"); checkdigestb(s, b); pullblock(&b, s->diglen); len -= s->diglen; break; case Sdigenc: b = decryptb(s, b); b = pullupblock(b, s->diglen); if(b == nil) error("ssl message too short (dig+enc)"); checkdigestb(s, b); pullblock(&b, s->diglen); len -= s->diglen; break; } /* remove pad */ if(pad) s->processed = qtake(&b, len - pad, 1); else s->processed = b; b = nil; s->in.mid++; qunlock(&s->in.ctlq); poperror(); } /* return at most what was asked for */ b = qtake(&s->processed, n, 0); qunlock(&s->in.q); poperror(); return b; } static long sslread(Chan *c, void *a, long n, vlong off) { Block * volatile b; Block *nb; uchar *va; int i; char buf[128]; ulong offset = off; int ft; if(c->qid.type & QTDIR) return devdirread(c, a, n, 0, 0, sslgen); ft = TYPE(c->qid); switch(ft) { default: error(Ebadusefd); case Qctl: ft = CONV(c->qid); sprint(buf, "%d", ft); return readstr(offset, a, n, buf); case Qdata: b = sslbread(c, n, offset); break; case Qencalgs: return readstr(offset, a, n, encalgs); break; case Qhashalgs: return readstr(offset, a, n, hashalgs); break; } if(waserror()){ freeblist(b); nexterror(); } n = 0; va = a; for(nb = b; nb; nb = nb->next){ i = BLEN(nb); memmove(va+n, nb->rp, i); n += i; } freeblist(b); poperror(); return n; } /* * this algorithm doesn't have to be great since we're just * trying to obscure the block fill */ static void randfill(uchar *buf, int len) { while(len-- > 0) *buf++ = fastrand(); } static long sslbwrite(Chan *c, Block *b, ulong o) { Dstate * volatile s; long rv; USED(o); s = dstate[CONV(c->qid)]; if(s == nil) panic("sslbwrite"); if(s->state == Sincomplete){ freeb(b); error(Ebadusefd); } /* lock so split writes won't interleave */ if(waserror()){ qunlock(&s->out.q); nexterror(); } qlock(&s->out.q); rv = sslput(s, b); poperror(); qunlock(&s->out.q); return rv; } /* * use SSL record format, add in count, digest and/or encrypt. * the write is interruptable. if it is interrupted, we'll * get out of sync with the far side. not much we can do about * it since we don't know if any bytes have been written. */ static long sslput(Dstate *s, Block * volatile b) { Block *nb; int h, n, m, pad, rv; uchar *p; int offset; if(waserror()){ iprint("error: %s\n", up->errstr); if(b != nil) free(b); nexterror(); } rv = 0; while(b != nil){ m = n = BLEN(b); h = s->diglen + 2; /* trim to maximum block size */ pad = 0; if(m > s->max){ m = s->max; } else if(s->blocklen != 1){ pad = (m + s->diglen)%s->blocklen; if(pad){ if(m > s->maxpad){ pad = 0; m = s->maxpad; } else { pad = s->blocklen - pad; h++; } } } rv += m; if(m != n){ nb = allocb(m + h + pad); memmove(nb->wp + h, b->rp, m); nb->wp += m + h; b->rp += m; } else { /* add header space */ nb = padblock(b, h); b = 0; } m += s->diglen; /* SSL style count */ if(pad){ nb = padblock(nb, -pad); randfill(nb->wp, pad); nb->wp += pad; m += pad; p = nb->rp; p[0] = (m>>8); p[1] = m; p[2] = pad; offset = 3; } else { p = nb->rp; p[0] = (m>>8) | 0x80; p[1] = m; offset = 2; } switch(s->state){ case Sencrypting: nb = encryptb(s, nb, offset); break; case Sdigesting: nb = digestb(s, nb, offset); break; case Sdigenc: nb = digestb(s, nb, offset); nb = encryptb(s, nb, offset); break; } s->out.mid++; m = BLEN(nb); devtab[s->c->type]->bwrite(s->c, nb, s->c->offset); s->c->offset += m; } poperror(); return rv; } static void setsecret(OneWay *w, uchar *secret, int n) { if(w->secret) free(w->secret); w->secret = smalloc(n); memmove(w->secret, secret, n); w->slen = n; } static void initDESkey(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } w->state = smalloc(sizeof(DESstate)); if(w->slen >= 16) setupDESstate(w->state, w->secret, w->secret+8); else if(w->slen >= 8) setupDESstate(w->state, w->secret, 0); else error("secret too short"); } /* * 40 bit DES is the same as 56 bit DES. However, * 16 bits of the key are masked to zero. */ static void initDESkey_40(OneWay *w) { uchar key[8]; if(w->state){ free(w->state); w->state = 0; } if(w->slen >= 8){ memmove(key, w->secret, 8); key[0] &= 0x0f; key[2] &= 0x0f; key[4] &= 0x0f; key[6] &= 0x0f; } w->state = malloc(sizeof(DESstate)); if(w->slen >= 16) setupDESstate(w->state, key, w->secret+8); else if(w->slen >= 8) setupDESstate(w->state, key, 0); else error("secret too short"); } static void initRC4key(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } w->state = smalloc(sizeof(RC4state)); setupRC4state(w->state, w->secret, w->slen); } /* * 40 bit RC4 is the same as n-bit RC4. However, * we ignore all but the first 40 bits of the key. */ static void initRC4key_40(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } if(w->slen > 5) w->slen = 5; w->state = malloc(sizeof(RC4state)); setupRC4state(w->state, w->secret, w->slen); } /* * 128 bit RC4 is the same as n-bit RC4. However, * we ignore all but the first 128 bits of the key. */ static void initRC4key_128(OneWay *w) { if(w->state){ free(w->state); w->state = 0; } if(w->slen > 16) w->slen = 16; w->state = malloc(sizeof(RC4state)); setupRC4state(w->state, w->secret, w->slen); } typedef struct Hashalg Hashalg; struct Hashalg { char *name; int diglen; DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); }; Hashalg hashtab[] = { { "md4", MD4dlen, md4, }, { "md5", MD5dlen, md5, }, { "sha1", SHA1dlen, sha1, }, { "sha", SHA1dlen, sha1, }, { 0 } }; static int parsehashalg(char *p, Dstate *s) { Hashalg *ha; for(ha = hashtab; ha->name; ha++){ if(strcmp(p, ha->name) == 0){ s->hf = ha->hf; s->diglen = ha->diglen; s->state &= ~Sclear; s->state |= Sdigesting; return 0; } } return -1; } typedef struct Encalg Encalg; struct Encalg { char *name; int blocklen; int alg; void (*keyinit)(OneWay*); }; #ifdef NOSPOOKS Encalg encrypttab[] = { { "descbc", 8, DESCBC, initDESkey, }, /* DEPRECATED -- use des_56_cbc */ { "desecb", 8, DESECB, initDESkey, }, /* DEPRECATED -- use des_56_ecb */ { "des_56_cbc", 8, DESCBC, initDESkey, }, { "des_56_ecb", 8, DESECB, initDESkey, }, { "des_40_cbc", 8, DESCBC, initDESkey_40, }, { "des_40_ecb", 8, DESECB, initDESkey_40, }, { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ { "rc4_256", 1, RC4, initRC4key, }, { "rc4_128", 1, RC4, initRC4key_128, }, { "rc4_40", 1, RC4, initRC4key_40, }, { 0 } }; #else Encalg encrypttab[] = { { "des_40_cbc", 8, DESCBC, initDESkey_40, }, { "des_40_ecb", 8, DESECB, initDESkey_40, }, { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ { "rc4_40", 1, RC4, initRC4key_40, }, { 0 } }; #endif /* NOSPOOKS */ static int parseencryptalg(char *p, Dstate *s) { Encalg *ea; for(ea = encrypttab; ea->name; ea++){ if(strcmp(p, ea->name) == 0){ s->encryptalg = ea->alg; s->blocklen = ea->blocklen; (*ea->keyinit)(&s->in); (*ea->keyinit)(&s->out); s->state &= ~Sclear; s->state |= Sencrypting; return 0; } } return -1; } static long sslwrite(Chan *c, void *a, long n, vlong o) { Dstate * volatile s; Block * volatile b; int m, t; char *p, *np, *e, buf[128]; uchar *x; USED(o); s = dstate[CONV(c->qid)]; if(s == 0) panic("sslwrite"); t = TYPE(c->qid); if(t == Qdata){ if(s->state == Sincomplete) error(Ebadusefd); /* lock should a write gets split over multiple records */ if(waserror()){ qunlock(&s->out.q); nexterror(); } qlock(&s->out.q); p = a; if(0) iprint("write %d %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", n, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); e = p + n; do { m = e - p; if(m > s->max) m = s->max; b = allocb(m); if(waserror()){ freeb(b); nexterror(); } memmove(b->wp, p, m); poperror(); b->wp += m; sslput(s, b); p += m; } while(p < e); p = a; if(0) iprint("wrote %d %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", n, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); poperror(); qunlock(&s->out.q); return n; } /* mutex with operations using what we're about to change */ if(waserror()){ qunlock(&s->in.ctlq); qunlock(&s->out.q); nexterror(); } qlock(&s->in.ctlq); qlock(&s->out.q); switch(t){ default: panic("sslwrite"); case Qsecretin: setsecret(&s->in, a, n); goto out; case Qsecretout: setsecret(&s->out, a, n); goto out; case Qctl: break; } if(n >= sizeof(buf)) error("arg too long"); strncpy(buf, a, n); buf[n] = 0; p = strchr(buf, '\n'); if(p) *p = 0; p = strchr(buf, ' '); if(p) *p++ = 0; if(strcmp(buf, "fd") == 0){ s->c = buftochan(p); /* default is clear (msg delimiters only) */ s->state = Sclear; s->blocklen = 1; s->diglen = 0; s->maxpad = s->max = (1<<15) - s->diglen - 1; s->in.mid = 0; s->out.mid = 0; } else if(strcmp(buf, "alg") == 0 && p != 0){ s->blocklen = 1; s->diglen = 0; if(s->c == 0) error("must set fd before algorithm"); s->state = Sclear; s->maxpad = s->max = (1<<15) - s->diglen - 1; if(strcmp(p, "clear") == 0){ goto out; } if(s->in.secret && s->out.secret == 0) setsecret(&s->out, s->in.secret, s->in.slen); if(s->out.secret && s->in.secret == 0) setsecret(&s->in, s->out.secret, s->out.slen); if(s->in.secret == 0 || s->out.secret == 0) error("algorithm but no secret"); s->hf = 0; s->encryptalg = Noencryption; s->blocklen = 1; for(;;){ np = strchr(p, ' '); if(np) *np++ = 0; if(parsehashalg(p, s) < 0) if(parseencryptalg(p, s) < 0) error("bad algorithm"); if(np == 0) break; p = np; } if(s->hf == 0 && s->encryptalg == Noencryption) error("bad algorithm"); if(s->blocklen != 1){ s->max = (1<<15) - s->diglen - 1; s->max -= s->max % s->blocklen; s->maxpad = (1<<14) - s->diglen - 1; s->maxpad -= s->maxpad % s->blocklen; } else s->maxpad = s->max = (1<<15) - s->diglen - 1; } else if(strcmp(buf, "secretin") == 0 && p != 0) { m = (strlen(p)*3)/2; x = smalloc(m); t = dec64(x, m, p, strlen(p)); setsecret(&s->in, x, t); free(x); } else if(strcmp(buf, "secretout") == 0 && p != 0) { m = (strlen(p)*3)/2 + 1; x = smalloc(m); t = dec64(x, m, p, strlen(p)); setsecret(&s->out, x, t); free(x); } else error(Ebadarg); out: qunlock(&s->in.ctlq); qunlock(&s->out.q); poperror(); return n; } static void sslinit(void) { struct Encalg *e; struct Hashalg *h; int n; char *cp; n = 1; for(e = encrypttab; e->name != nil; e++) n += strlen(e->name) + 1; cp = encalgs = smalloc(n); for(e = encrypttab;;){ strcpy(cp, e->name); cp += strlen(e->name); e++; if(e->name == nil) break; *cp++ = ' '; } *cp = 0; n = 1; for(h = hashtab; h->name != nil; h++) n += strlen(h->name) + 1; cp = hashalgs = smalloc(n); for(h = hashtab;;){ strcpy(cp, h->name); cp += strlen(h->name); h++; if(h->name == nil) break; *cp++ = ' '; } *cp = 0; } Dev ssldevtab = { 'D', "ssl", devreset, sslinit, devshutdown, sslattach, sslwalk, sslstat, sslopen, devcreate, sslclose, sslread, sslbread, sslwrite, sslbwrite, devremove, sslwstat, }; static Block* encryptb(Dstate *s, Block *b, int offset) { uchar *p, *ep, *p2, *ip, *eip; DESstate *ds; switch(s->encryptalg){ case DESECB: ds = s->out.state; ep = b->rp + BLEN(b); for(p = b->rp + offset; p < ep; p += 8) block_cipher(ds->expanded, p, 0); break; case DESCBC: ds = s->out.state; ep = b->rp + BLEN(b); for(p = b->rp + offset; p < ep; p += 8){ p2 = p; ip = ds->ivec; for(eip = ip+8; ip < eip; ) *p2++ ^= *ip++; block_cipher(ds->expanded, p, 0); memmove(ds->ivec, p, 8); } break; case RC4: rc4(s->out.state, b->rp + offset, BLEN(b) - offset); break; } return b; } static Block* decryptb(Dstate *s, Block *bin) { Block *b, **l; uchar *p, *ep, *tp, *ip, *eip; DESstate *ds; uchar tmp[8]; int i; l = &bin; for(b = bin; b; b = b->next){ /* make sure we have a multiple of s->blocklen */ if(s->blocklen > 1){ i = BLEN(b); if(i % s->blocklen){ *l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen)); if(b == 0) error("ssl encrypted message too short"); } } l = &b->next; /* decrypt */ switch(s->encryptalg){ case DESECB: ds = s->in.state; ep = b->rp + BLEN(b); for(p = b->rp; p < ep; p += 8) block_cipher(ds->expanded, p, 1); break; case DESCBC: ds = s->in.state; ep = b->rp + BLEN(b); for(p = b->rp; p < ep;){ memmove(tmp, p, 8); block_cipher(ds->expanded, p, 1); tp = tmp; ip = ds->ivec; for(eip = ip+8; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } break; case RC4: rc4(s->in.state, b->rp, BLEN(b)); break; } } return bin; } static Block* digestb(Dstate *s, Block *b, int offset) { uchar *p; DigestState ss; uchar msgid[4]; ulong n, h; OneWay *w; w = &s->out; memset(&ss, 0, sizeof(ss)); h = s->diglen + offset; n = BLEN(b) - h; /* hash secret + message */ (*s->hf)(w->secret, w->slen, 0, &ss); (*s->hf)(b->rp + h, n, 0, &ss); /* hash message id */ p = msgid; n = w->mid; *p++ = n>>24; *p++ = n>>16; *p++ = n>>8; *p = n; (*s->hf)(msgid, 4, b->rp + offset, &ss); return b; } static void checkdigestb(Dstate *s, Block *bin) { uchar *p; DigestState ss; uchar msgid[4]; int n, h; OneWay *w; uchar digest[128]; Block *b; w = &s->in; memset(&ss, 0, sizeof(ss)); /* hash secret */ (*s->hf)(w->secret, w->slen, 0, &ss); /* hash message */ h = s->diglen; for(b = bin; b; b = b->next){ n = BLEN(b) - h; if(n < 0) panic("checkdigestb"); (*s->hf)(b->rp + h, n, 0, &ss); h = 0; } /* hash message id */ p = msgid; n = w->mid; *p++ = n>>24; *p++ = n>>16; *p++ = n>>8; *p = n; (*s->hf)(msgid, 4, digest, &ss); if(memcmp(digest, bin->rp, s->diglen) != 0) error("bad digest"); } /* get channel associated with an fd */ static Chan* buftochan(char *p) { Chan *c; int fd; if(p == 0) error(Ebadarg); fd = strtoul(p, 0, 0); if(fd < 0) error(Ebadarg); c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ if(devtab[c->type] == &ssldevtab){ cclose(c); error("cannot ssl encrypt devssl files"); } return c; } /* hand up a digest connection */ static void sslhangup(Dstate *s) { Block *b; qlock(&s->in.q); for(b = s->processed; b; b = s->processed){ s->processed = b->next; freeb(b); } if(s->unprocessed){ freeb(s->unprocessed); s->unprocessed = 0; } s->state = Sincomplete; qunlock(&s->in.q); } static Dstate* dsclone(Chan *ch) { int i; Dstate *ret; if(waserror()) { unlock(&dslock); nexterror(); } lock(&dslock); ret = nil; for(i=0; i= dshiwat) dshiwat++; memset(s, 0, sizeof(*s)); s->state = Sincomplete; s->ref = 1; kstrdup(&s->user, up->user); s->perm = 0660; t = TYPE(ch->qid); if(t == Qclonus) t = Qctl; ch->qid.path = QID(pp - dstate, t); ch->qid.vers = 0; } drawterm-20110822.orig/kern/Makefile0000644000175000017500000000114211245145711016467 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libkern.a OFILES=\ allocb.$O\ cache.$O\ chan.$O\ data.$O\ dev.$O\ devaudio.$O\ devaudio-$(AUDIO).$O\ devcons.$O\ devdraw.$O\ devfs-$(OS).$O\ devip.$O\ devip-$(OS).$O\ devlfd.$O\ devmnt.$O\ devmouse.$O\ devpipe.$O\ devroot.$O\ devssl.$O\ devtls.$O\ devtab.$O\ error.$O\ parse.$O\ pgrp.$O\ procinit.$O\ rwlock.$O\ sleep.$O\ smalloc.$O\ stub.$O\ sysfile.$O\ sysproc.$O\ qio.$O\ qlock.$O\ term.$O\ uart.$O\ waserror.$O\ $(OS).$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/kern/devroot.c0000644000175000017500000001122311245145712016657 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" enum { Qdir = 0, Qboot = 0x1000, Qmnt = 0x2000, Qfactotum, Nrootfiles = 32, Nbootfiles = 32, Nmntfiles = 2, }; typedef struct Dirlist Dirlist; struct Dirlist { uint base; Dirtab *dir; uchar **data; int ndir; int mdir; }; static Dirtab rootdir[Nrootfiles] = { "#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555, "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, }; static uchar *rootdata[Nrootfiles]; static Dirlist rootlist = { 0, rootdir, rootdata, 3, Nrootfiles }; static Dirtab bootdir[Nbootfiles] = { "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555, }; static uchar *bootdata[Nbootfiles]; static Dirlist bootlist = { Qboot, bootdir, bootdata, 1, Nbootfiles }; static uchar *mntdata[Nmntfiles]; static Dirtab mntdir[Nmntfiles] = { "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, "factotum", {Qfactotum, 0, QTDIR}, 0, DMDIR|0555, }; static Dirlist mntlist = { Qmnt, mntdir, mntdata, 2, Nmntfiles }; /* * add a file to the list */ static void addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm) { Dirtab *d; if(l->ndir >= l->mdir) panic("too many root files"); l->data[l->ndir] = contents; d = &l->dir[l->ndir]; strcpy(d->name, name); d->length = len; d->perm = perm; d->qid.type = 0; d->qid.vers = 0; d->qid.path = ++l->ndir + l->base; if(perm & DMDIR) d->qid.type |= QTDIR; } /* * add a root file */ void addbootfile(char *name, uchar *contents, ulong len) { addlist(&bootlist, name, contents, len, 0555); } /* * add a root directory */ static void addrootdir(char *name) { addlist(&rootlist, name, nil, 0, DMDIR|0555); } static void rootreset(void) { addrootdir("bin"); addrootdir("dev"); addrootdir("env"); addrootdir("fd"); addrootdir("net"); addrootdir("net.alt"); addrootdir("proc"); addrootdir("root"); addrootdir("srv"); } static Chan* rootattach(char *spec) { return devattach('/', spec); } static int rootgen(Chan *c, char *name, Dirtab *dirt, int ndirt, int s, Dir *dp) { int t; Dirtab *d; Dirlist *l; USED(dirt); USED(ndirt); switch((int)c->qid.path){ case Qdir: if(s == DEVDOTDOT){ Qid tqiddir = {Qdir, 0, QTDIR}; devdir(c, tqiddir, "#/", 0, eve, 0555, dp); return 1; } return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp); case Qmnt: if(s == DEVDOTDOT){ Qid tqiddir = {Qdir, 0, QTDIR}; devdir(c, tqiddir, "#/", 0, eve, 0555, dp); return 1; } return devgen(c, name, mntlist.dir, mntlist.ndir, s, dp); case Qboot: if(s == DEVDOTDOT){ Qid tqiddir = {Qdir, 0, QTDIR}; devdir(c, tqiddir, "#/", 0, eve, 0555, dp); return 1; } return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp); default: if(s == DEVDOTDOT){ Qid tqiddir = {Qdir, 0, QTDIR}; tqiddir.path = c->qid.path&0xF000; devdir(c, tqiddir, "#/", 0, eve, 0555, dp); return 1; } if(s != 0) return -1; switch((int)c->qid.path & 0xF000){ case Qdir: t = c->qid.path-1; l = &rootlist; break; case Qboot: t = c->qid.path - Qboot - 1; l = &bootlist; break; case Qmnt: t = c->qid.path - Qmnt - 1; l = &mntlist; break; default: return -1; } if(t >= l->ndir) return -1; if(t < 0){ print("rootgen %llud %d %d\n", c->qid.path, s, t); panic("whoops"); } d = &l->dir[t]; devdir(c, d->qid, d->name, d->length, eve, d->perm, dp); return 1; } return -1; } static Walkqid* rootwalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, nil, 0, rootgen); } static int rootstat(Chan *c, uchar *dp, int n) { return devstat(c, dp, n, nil, 0, rootgen); } static Chan* rootopen(Chan *c, int omode) { return devopen(c, omode, nil, 0, devgen); } /* * sysremove() knows this is a nop */ static void rootclose(Chan *c) { USED(c); } static long rootread(Chan *c, void *buf, long n, vlong off) { ulong t; Dirtab *d; Dirlist *l; uchar *data; ulong offset = off; t = c->qid.path; switch(t){ case Qdir: case Qboot: case Qmnt: return devdirread(c, buf, n, nil, 0, rootgen); } if(t&Qboot) l = &bootlist; else if(t&Qmnt) l = &mntlist; else l = &bootlist; t &= 0xFFF; t--; if(t >= l->ndir) error(Egreg); d = &l->dir[t]; data = l->data[t]; if(offset >= d->length) return 0; if(offset+n > d->length) n = d->length - offset; memmove(buf, data+offset, n); return n; } static long rootwrite(Chan *c, void *v, long n, vlong o) { USED(c); USED(v); USED(n); USED(o); error(Egreg); return 0; } Dev rootdevtab = { '/', "root", rootreset, devinit, devshutdown, rootattach, rootwalk, rootstat, rootopen, devcreate, rootclose, rootread, devbread, rootwrite, devbwrite, devremove, devwstat, }; drawterm-20110822.orig/kern/devaudio-sun.c0000644000175000017500000001126711245145711017607 0ustar tinchotincho/* * Sun */ #include #include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devaudio.h" enum { Channels = 2, Rate = 44100, Bits = 16, }; static char* afn = 0; static char* cfn = 0; static int afd = -1; static int cfd = -1; static int speed = Rate; static int needswap = -1; static void audiodevinit(void) { uchar *p; ushort leorder; if ((afn = getenv("AUDIODEV")) == nil) afn = "/dev/audio"; cfn = (char*)malloc(strlen(afn) + 3 + 1); if(cfn == nil) panic("out of memory"); strcpy(cfn, afn); strcat(cfn, "ctl"); /* * Plan 9 /dev/audio is always little endian; * solaris /dev/audio seems to expect native byte order, * so on big endian machine (like sparc) we have to swap. */ leorder = (ushort) 0x0100; p = (uchar*)&leorder; if (p[0] == 0 && p[1] == 1) { /* little-endian: nothing to do */ needswap = 0; } else { /* big-endian: translate Plan 9 little-endian */ needswap = 1; } } /* maybe this should return -1 instead of sysfatal */ void audiodevopen(void) { audio_info_t info; struct audio_device ad; if (afn == nil || cfn == nil) audiodevinit(); if((afd = open(afn, O_WRONLY)) < 0) goto err; if(cfd < 0 && (cfd = open(cfn, O_RDWR)) < 0) goto err; AUDIO_INITINFO(&info); info.play.precision = Bits; info.play.channels = Channels; info.play.sample_rate = speed; info.play.encoding = AUDIO_ENCODING_LINEAR; if(ioctl(afd, AUDIO_SETINFO, &info) < 0) goto err; return; err: if(afd >= 0) close(afd); afd = -1; if(cfd >= 0) close(cfd); cfd = -1; oserror(); } void audiodevclose(void) { if(afd >= 0) close(afd); if(cfd >= 0) close(cfd); afd = -1; cfd = -1; } static double fromsun(double val, double min, double max) { return (val-min) / (max-min); } static double tosun(double val, double min, double max) { return val*(max-min) + min; } static void setvolbal(double left, double right) { audio_info_t info; double vol, bal; if (left < 0 || right < 0) { /* should not happen */ return; } else if (left == right) { vol = tosun(left/100.0, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN); bal = AUDIO_MID_BALANCE; } else if (left < right) { vol = tosun(right/100.0, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN); bal = tosun(1.0 - left/right, AUDIO_MID_BALANCE, AUDIO_RIGHT_BALANCE); } else if (right < left) { vol = tosun(left/100.0, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN); bal = tosun(1.0 - right/left, AUDIO_MID_BALANCE, AUDIO_LEFT_BALANCE); } AUDIO_INITINFO(&info); info.play.gain = (long)(vol+0.5); info.play.balance = (long)(bal+0.5); if(ioctl(cfd, AUDIO_SETINFO, &info) < 0) oserror(); } static void getvolbal(int *left, int *right) { audio_info_t info; double gain, bal, vol, l, r; AUDIO_INITINFO(&info); if (ioctl(cfd, AUDIO_GETINFO, &info) < 0) oserror(); gain = info.play.gain; bal = info.play.balance; vol = fromsun(gain, AUDIO_MIN_GAIN, AUDIO_MAX_GAIN) * 100.0; if (bal == AUDIO_MID_BALANCE) { l = r = vol; } else if (bal < AUDIO_MID_BALANCE) { l = vol; r = vol * (1.0 - fromsun(bal, AUDIO_MID_BALANCE, AUDIO_LEFT_BALANCE)); } else { r = vol; l = vol * (1.0 - fromsun(bal, AUDIO_MID_BALANCE, AUDIO_RIGHT_BALANCE)); } *left = (long)(l+0.5); *right = (long)(r+0.5); return; } void audiodevsetvol(int what, int left, int right) { audio_info_t info; ulong x; int l, r; if (afn == nil || cfn == nil) audiodevinit(); if(cfd < 0 && (cfd = open(cfn, O_RDWR)) < 0) { cfd = -1; oserror(); } if(what == Vspeed){ x = left; AUDIO_INITINFO(&info); info.play.sample_rate = x; if(ioctl(cfd, AUDIO_SETINFO, &info) < 0) oserror(); speed = x; return; } if(what == Vaudio){ getvolbal(&l, &r); if (left < 0) setvolbal(l, right); else if (right < 0) setvolbal(left, r); else setvolbal(left, right); return; } } void audiodevgetvol(int what, int *left, int *right) { audio_info_t info; if (afn == nil || cfn == nil) audiodevinit(); if(cfd < 0 && (cfd = open(cfn, O_RDWR)) < 0) { cfd = -1; oserror(); } switch(what) { case Vspeed: *left = *right = speed; break; case Vaudio: getvolbal(left, right); break; case Vtreb: case Vbass: *left = *right = 50; break; default: *left = *right = 0; } } static uchar *buf = 0; static int nbuf = 0; int audiodevwrite(void *v, int n) { int i, m, tot; uchar *p; if (needswap) { if (nbuf < n) { buf = (uchar*)erealloc(buf, n); if(buf == nil) panic("out of memory"); nbuf = n; } p = (uchar*)v; for(i=0; i+1 #include #include #include #include #include #include #include "lib.h" #include "dat.h" #include "fns.h" typedef struct Oproc Oproc; struct Oproc { int nsleep; int nwakeup; pthread_mutex_t mutex; pthread_cond_t cond; }; static pthread_key_t prdakey; Proc* _getproc(void) { void *v; if((v = pthread_getspecific(prdakey)) == nil) panic("cannot getspecific"); return v; } void _setproc(Proc *p) { if(pthread_setspecific(prdakey, p) != 0) panic("cannot setspecific"); } void osinit(void) { if(pthread_key_create(&prdakey, 0)) panic("cannot pthread_key_create"); } #undef pipe void osnewproc(Proc *p) { Oproc *op; pthread_mutexattr_t attr; op = (Oproc*)p->oproc; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); pthread_mutex_init(&op->mutex, &attr); pthread_mutexattr_destroy(&attr); pthread_cond_init(&op->cond, 0); } void osmsleep(int ms) { struct timeval tv; tv.tv_sec = ms / 1000; tv.tv_usec = (ms % 1000) * 1000; /* micro */ if(select(0, NULL, NULL, NULL, &tv) < 0) panic("select"); } void osyield(void) { sched_yield(); } void oserrstr(void) { char *p; if((p = strerror(errno)) != nil) strecpy(up->errstr, up->errstr+ERRMAX, p); else snprint(up->errstr, ERRMAX, "unix error %d", errno); } void oserror(void) { oserrstr(); nexterror(); } static void* tramp(void*); void osproc(Proc *p) { pthread_t pid; if(pthread_create(&pid, nil, tramp, p)){ oserrstr(); panic("osproc: %r"); } sched_yield(); } static void* tramp(void *vp) { Proc *p; p = vp; if(pthread_setspecific(prdakey, p)) panic("cannot setspecific"); (*p->fn)(p->arg); /* BUG: leaks Proc */ pthread_setspecific(prdakey, 0); pthread_exit(0); return 0; } void procsleep(void) { Proc *p; Oproc *op; p = up; op = (Oproc*)p->oproc; pthread_mutex_lock(&op->mutex); op->nsleep++; while(op->nsleep > op->nwakeup) pthread_cond_wait(&op->cond, &op->mutex); pthread_mutex_unlock(&op->mutex); } void procwakeup(Proc *p) { Oproc *op; op = (Oproc*)p->oproc; pthread_mutex_lock(&op->mutex); op->nwakeup++; if(op->nwakeup == op->nsleep) pthread_cond_signal(&op->cond); pthread_mutex_unlock(&op->mutex); } int randfd; #undef open void randominit(void) { #ifdef USE_RANDOM srandom(getpid()+fastticks(nil)+ticks()); #else if((randfd = open("/dev/urandom", OREAD)) < 0) if((randfd = open("/dev/random", OREAD)) < 0) panic("open /dev/random: %r"); #endif } #undef read ulong randomread(void *v, ulong n) { #ifdef USE_RANDOM int i; for(i=0; ilk); lock(&up->rlock); if(r->p){ print("double sleep %lud %lud\n", r->p->pid, up->pid); dumpstack(); } /* * Wakeup only knows there may be something to do by testing * r->p in order to get something to lock on. * Flush that information out to memory in case the sleep is * committed. */ r->p = up; if((*f)(arg) || up->notepending){ /* * if condition happened or a note is pending * never mind */ r->p = nil; unlock(&up->rlock); unlock(&r->lk); } else { /* * now we are committed to * change state and call scheduler */ up->state = Wakeme; up->r = r; /* statistics */ /* m->cs++; */ unlock(&up->rlock); unlock(&r->lk); procsleep(); } if(up->notepending) { up->notepending = 0; splx(s); error(Eintr); } splx(s); } Proc* wakeup(Rendez *r) { Proc *p; int s; s = splhi(); lock(&r->lk); p = r->p; if(p != nil){ lock(&p->rlock); if(p->state != Wakeme || p->r != r) panic("wakeup: state"); r->p = nil; p->r = nil; p->state = Running; procwakeup(p); unlock(&p->rlock); } unlock(&r->lk); splx(s); return p; } drawterm-20110822.orig/kern/sysproc.c0000644000175000017500000000076211245145712016705 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" long sysexits(ulong *arg) { char *status; char *inval = "invalid exit string"; char buf[ERRMAX]; status = (char*)arg[0]; if(status){ if(waserror()) status = inval; else{ validaddr((ulong)status, 1, 0); if(vmemchr(status, 0, ERRMAX) == 0){ memmove(buf, status, ERRMAX); buf[ERRMAX-1] = 0; status = buf; } } poperror(); } pexit(status, 1); return 0; /* not reached */ } drawterm-20110822.orig/kern/syscall.c0000644000175000017500000003111411245145712016650 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" Chan* fdtochan(int fd, int mode, int chkmnt, int iref) { Fgrp *f; Chan *c; c = 0; f = up->fgrp; lock(&f->ref.lk); if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) { unlock(&f->ref.lk); error(Ebadfd); } if(iref) refinc(&c->ref); unlock(&f->ref.lk); if(chkmnt && (c->flag&CMSG)) goto bad; if(mode<0 || c->mode==ORDWR) return c; if((mode&OTRUNC) && c->mode==OREAD) goto bad; if((mode&~OTRUNC) != c->mode) goto bad; return c; bad: if(iref) cclose(c); error(Ebadusefd); return nil; /* shut up compiler */ } static void fdclose(int fd, int flag) { int i; Chan *c; Fgrp *f; f = up->fgrp; lock(&f->ref.lk); c = f->fd[fd]; if(c == 0) { unlock(&f->ref.lk); return; } if(flag) { if(c==0 || !(c->flag&flag)) { unlock(&f->ref.lk); return; } } f->fd[fd] = 0; if(fd == f->maxfd) for(i=fd; --i>=0 && f->fd[i]==0; ) f->maxfd = i; unlock(&f->ref.lk); cclose(c); } static int newfd(Chan *c) { int i; Fgrp *f; f = up->fgrp; lock(&f->ref.lk); for(i=0; ifd[i] == 0){ if(i > f->maxfd) f->maxfd = i; f->fd[i] = c; unlock(&f->ref.lk); return i; } unlock(&f->ref.lk); error("no file descriptors"); return 0; } int sysclose(int fd) { if(waserror()) return -1; fdtochan(fd, -1, 0, 0); fdclose(fd, 0); poperror(); return 0; } int syscreate(char *path, int mode, ulong perm) { int fd; Chan *c = 0; if(waserror()) { cclose(c); return -1; } openmode(mode); /* error check only */ c = namec(path, Acreate, mode, perm); fd = newfd((Chan*)c); poperror(); return fd; } int sysdup(int old, int new) { Chan *oc; Fgrp *f = up->fgrp; Chan *c = 0; if(waserror()) return -1; c = fdtochan(old, -1, 0, 1); if(new != -1) { if(new < 0 || NFD <= new) { cclose(c); error(Ebadfd); } lock(&f->ref.lk); if(new > f->maxfd) f->maxfd = new; oc = f->fd[new]; f->fd[new] = (Chan*)c; unlock(&f->ref.lk); if(oc != 0) cclose(oc); } else { if(waserror()) { cclose(c); nexterror(); } new = newfd((Chan*)c); poperror(); } poperror(); return new; } int sysfstat(int fd, char *buf) { Chan *c = 0; if(waserror()) { cclose(c); return -1; } c = fdtochan(fd, -1, 0, 1); devtab[c->type]->stat((Chan*)c, buf); poperror(); cclose(c); return 0; } int sysfwstat(int fd, char *buf) { Chan *c = 0; if(waserror()) { cclose(c); return -1; } nameok(buf); c = fdtochan(fd, -1, 1, 1); devtab[c->type]->wstat((Chan*)c, buf); poperror(); cclose(c); return 0; } int syschdir(char *dir) { return 0; } long bindmount(Chan *c0, char *old, int flag, char *spec) { int ret; Chan *c1 = 0; if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER)) error(Ebadarg); c1 = namec(old, Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } ret = cmount(c0, c1, flag, spec); poperror(); cclose(c1); return ret; } int sysbind(char *new, char *old, int flags) { long r; Chan *c0 = 0; if(waserror()) { cclose(c0); return -1; } c0 = namec(new, Aaccess, 0, 0); r = bindmount(c0, old, flags, ""); poperror(); cclose(c0); return 0; } int sysmount(int fd, char *old, int flags, char *spec) { long r; Chan *c0 = 0, *bc = 0; struct { Chan* chan; char* spec; int flags; } mntparam; if(waserror()) { cclose(bc); cclose(c0); return -1; } bc = fdtochan(fd, ORDWR, 0, 1); mntparam.chan = (Chan*)bc; mntparam.spec = spec; mntparam.flags = flags; c0 = (*devtab[devno('M', 0)].attach)(&mntparam); cclose(bc); r = bindmount(c0, old, flags, spec); poperror(); cclose(c0); return r; } int sysunmount(char *old, char *new) { Chan *cmount = 0, *cmounted = 0; if(waserror()) { cclose(cmount); cclose(cmounted); return -1; } cmount = namec(new, Amount, OREAD, 0); if(old != 0) cmounted = namec(old, Aopen, OREAD, 0); cunmount(cmount, cmounted); poperror(); cclose(cmount); cclose(cmounted); return 0; } int sysopen(char *path, int mode) { int fd; Chan *c = 0; if(waserror()){ cclose(c); return -1; } openmode(mode); /* error check only */ c = namec(path, Aopen, mode, 0); fd = newfd((Chan*)c); poperror(); return fd; } long unionread(Chan *c, void *va, long n) { long nr; Chan *nc = 0; Pgrp *pg = 0; pg = up->pgrp; rlock(&pg->ns); for(;;) { if(waserror()) { runlock(&pg->ns); nexterror(); } nc = clone(c->mnt->to, 0); poperror(); if(c->mountid != c->mnt->mountid) { runlock(&pg->ns); cclose(nc); return 0; } /* Error causes component of union to be skipped */ if(waserror()) { cclose(nc); goto next; } nc = (*devtab[nc->type].open)((Chan*)nc, OREAD); nc->offset = c->offset; nr = (*devtab[nc->type].read)((Chan*)nc, va, n, nc->offset); /* devdirread e.g. changes it */ c->offset = nc->offset; poperror(); cclose(nc); if(nr > 0) { runlock(&pg->ns); return nr; } /* Advance to next element */ next: c->mnt = c->mnt->next; if(c->mnt == 0) break; c->mountid = c->mnt->mountid; c->offset = 0; } runlock(&pg->ns); return 0; } long sysread(int fd, void *va, long n) { int dir; Lock *cl; Chan *c = 0; if(waserror()) { cclose(c); return -1; } c = fdtochan(fd, OREAD, 1, 1); dir = c->qid.path&CHDIR; if(dir) { n -= n%DIRLEN; if(c->offset%DIRLEN || n==0) error(Etoosmall); } if(dir && c->mnt) n = unionread((Chan*)c, va, n); else n = (*devtab[c->type].read)((Chan*)c, va, n, c->offset); cl = (Lock*)&c->r.l; lock(cl); c->offset += n; unlock(cl); poperror(); cclose(c); return n; } int sysremove(char *path) { Chan *c = 0; if(waserror()) { if(c != 0) c->type = 0; /* see below */ cclose(c); return -1; } c = namec(path, Aaccess, 0, 0); (*devtab[c->type].remove)((Chan*)c); /* * Remove clunks the fid, but we need to recover the Chan * so fake it up. rootclose() is known to be a nop. */ c->type = 0; poperror(); cclose(c); return 0; } long sysseek(int fd, long off, int whence) { Dir dir; Chan *c; char buf[DIRLEN]; if(waserror()) return -1; c = fdtochan(fd, -1, 1, 0); if(c->qid.path & CHDIR) error(Eisdir); switch(whence) { case 0: c->offset = off; break; case 1: lock(&c->r.l); /* lock for read/write update */ c->offset += off; off = c->offset; unlock(&c->r.l); break; case 2: (*devtab[c->type].stat)(c, buf); convM2D(buf, &dir); c->offset = dir.length + off; off = c->offset; break; } poperror(); return off; } int sysstat(char *path, char *buf) { Chan *c = 0; if(waserror()){ cclose(c); return -1; } c = namec(path, Aaccess, 0, 0); (*devtab[c->type].stat)((Chan*)c, buf); poperror(); cclose(c); return 0; } long syswrite(int fd, void *va, long n) { Lock *cl; Chan *c = 0; if(waserror()) { cclose(c); return -1; } c = fdtochan(fd, OWRITE, 1, 1); if(c->qid.path & CHDIR) error(Eisdir); n = (*devtab[c->type].write)((Chan*)c, va, n, c->offset); cl = (Lock*)&c->r.l; lock(cl); c->offset += n; unlock(cl); poperror(); cclose(c); return n; } int syswstat(char *path, char *buf) { Chan *c = 0; if(waserror()) { cclose(c); return -1; } nameok(buf); c = namec(path, Aaccess, 0, 0); (*devtab[c->type].wstat)((Chan*)c, buf); poperror(); cclose(c); return 0; } int sysdirstat(char *name, Dir *dir) { char buf[DIRLEN]; if(sysstat(name, buf) == -1) return -1; convM2D(buf, dir); return 0; } int sysdirfstat(int fd, Dir *dir) { char buf[DIRLEN]; if(sysfstat(fd, buf) == -1) return -1; convM2D(buf, dir); return 0; } int sysdirwstat(char *name, Dir *dir) { char buf[DIRLEN]; convD2M(dir, buf); return syswstat(name, buf); } int sysdirfwstat(int fd, Dir *dir) { char buf[DIRLEN]; convD2M(dir, buf); return sysfwstat(fd, buf); } long sysdirread(int fd, Dir *dbuf, long count) { int c, n, i, r; char buf[DIRLEN*50]; n = 0; count = (count/sizeof(Dir)) * DIRLEN; while(n < count) { c = count - n; if(c > sizeof(buf)) c = sizeof(buf); r = sysread(fd, buf, c); if(r == 0) break; if(r < 0 || r % DIRLEN) return -1; for(i=0; i 0){ net[n] = 0; p = strchr(net, ' '); if(p == 0) continue; *p++ = 0; rv = call(net, p, cfdp, dir, local); if(rv >= 0) break; } sysclose(fd); return rv; } static int identtrans(char *addr, char *naddr, int na, char *file, int nf) { char *p; char reply[4*NAMELEN]; /* parse the network */ strncpy(reply, addr, sizeof(reply)); reply[sizeof(reply)-1] = 0; p = strchr(reply, '!'); if(p) *p++ = 0; sprint(file, "/net/%.*s/clone", na - sizeof("/net//clone"), reply); strncpy(naddr, p, na); naddr[na-1] = 0; return 1; } static int nettrans(char *addr, char *naddr, int na, char *file, int nf) { long n; int fd; char *cp; char reply[4*NAMELEN]; /* * ask the connection server */ fd = sysopen("/net/cs", ORDWR); if(fd < 0) return identtrans(addr, naddr, na, file, nf); if(syswrite(fd, addr, strlen(addr)) < 0){ sysclose(fd); return -1; } sysseek(fd, 0, 0); n = sysread(fd, reply, sizeof(reply)-1); sysclose(fd); if(n <= 0) return -1; reply[n] = '\0'; /* * parse the reply */ cp = strchr(reply, ' '); if(cp == 0) return -1; *cp++ = 0; strncpy(naddr, cp, na); naddr[na-1] = 0; strncpy(file, reply, nf); file[nf-1] = 0; return 0; } int sysannounce(char *addr, char *dir) { char *cp; int ctl, n, m; char buf[3*NAMELEN]; char buf2[3*NAMELEN]; char netdir[2*NAMELEN]; char naddr[3*NAMELEN]; /* * translate the address */ if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0){ werrstr("can't translate address"); return -1; } /* * get a control channel */ ctl = sysopen(netdir, ORDWR); if(ctl<0){ werrstr("can't open control channel"); return -1; } cp = strrchr(netdir, '/'); *cp = 0; /* * find out which line we have */ n = sprint(buf, "%.*s/", 2*NAMELEN+1, netdir); m = sysread(ctl, &buf[n], sizeof(buf)-n-1); if(m <= 0) { sysclose(ctl); werrstr("can't read control file"); return -1; } buf[n+m] = 0; /* * make the call */ n = sprint(buf2, "announce %.*s", 2*NAMELEN, naddr); if(syswrite(ctl, buf2, n) != n) { sysclose(ctl); werrstr("announcement fails"); return -1; } strcpy(dir, buf); return ctl; } int syslisten(char *dir, char *newdir) { char *cp; int ctl, n, m; char buf[3*NAMELEN]; /* * open listen, wait for a call */ sprint(buf, "%.*s/listen", 2*NAMELEN+1, dir); ctl = sysopen(buf, ORDWR); if(ctl < 0) return -1; /* * find out which line we have */ strcpy(buf, dir); cp = strrchr(buf, '/'); *++cp = 0; n = cp-buf; m = sysread(ctl, cp, sizeof(buf) - n - 1); if(n<=0){ sysclose(ctl); return -1; } buf[n+m] = 0; strcpy(newdir, buf); return ctl; } drawterm-20110822.orig/kern/devaudio.c0000644000175000017500000001366611245145711017011 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devaudio.h" enum { Qdir = 0, Qaudio, Qvolume, Aclosed = 0, Aread, Awrite, Speed = 44100, Ncmd = 50, /* max volume command words */ }; Dirtab audiodir[] = { ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "audio", {Qaudio}, 0, 0666, "volume", {Qvolume}, 0, 0666, }; static struct { QLock lk; Rendez vous; int amode; /* Aclosed/Aread/Awrite for /audio */ } audio; #define aqlock(a) qlock(&(a)->lk) #define aqunlock(a) qunlock(&(a)->lk) static struct { char* name; int flag; int ilval; /* initial values */ int irval; } volumes[] = { "audio", Fout, 50, 50, "synth", Fin|Fout, 0, 0, "cd", Fin|Fout, 0, 0, "line", Fin|Fout, 0, 0, "mic", Fin|Fout|Fmono, 0, 0, "speaker", Fout|Fmono, 0, 0, "treb", Fout, 50, 50, "bass", Fout, 50, 50, "speed", Fin|Fout|Fmono, Speed, Speed, 0 }; static char Emode[] = "illegal open mode"; static char Evolume[] = "illegal volume specifier"; static void resetlevel(void) { int i; for(i=0; volumes[i].name; i++) audiodevsetvol(i, volumes[i].ilval, volumes[i].irval); } static void audioinit(void) { } static Chan* audioattach(char *param) { return devattach('A', param); } static Walkqid* audiowalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen); } static int audiostat(Chan *c, uchar *db, int n) { return devstat(c, db, n, audiodir, nelem(audiodir), devgen); } static Chan* audioopen(Chan *c, int omode) { int amode; switch((ulong)c->qid.path) { default: error(Eperm); break; case Qvolume: case Qdir: break; case Qaudio: amode = Awrite; if((omode&7) == OREAD) amode = Aread; aqlock(&audio); if(waserror()){ aqunlock(&audio); nexterror(); } if(audio.amode != Aclosed) error(Einuse); audiodevopen(); audio.amode = amode; poperror(); aqunlock(&audio); break; } c = devopen(c, omode, audiodir, nelem(audiodir), devgen); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } static void audioclose(Chan *c) { switch((ulong)c->qid.path) { default: error(Eperm); break; case Qdir: case Qvolume: break; case Qaudio: if(c->flag & COPEN) { aqlock(&audio); audiodevclose(); audio.amode = Aclosed; aqunlock(&audio); } break; } } static long audioread(Chan *c, void *v, long n, vlong off) { int liv, riv, lov, rov; long m; char buf[300]; int j; ulong offset = off; char *a; a = v; switch((ulong)c->qid.path) { default: error(Eperm); break; case Qdir: return devdirread(c, a, n, audiodir, nelem(audiodir), devgen); case Qaudio: if(audio.amode != Aread) error(Emode); aqlock(&audio); if(waserror()){ aqunlock(&audio); nexterror(); } n = audiodevread(v, n); poperror(); aqunlock(&audio); break; case Qvolume: j = 0; buf[0] = 0; for(m=0; volumes[m].name; m++){ audiodevgetvol(m, &lov, &rov); liv = lov; riv = rov; j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name); if((volumes[m].flag & Fmono) || (liv==riv && lov==rov)){ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov) j += snprint(buf+j, sizeof(buf)-j, " %d", liv); else{ if(volumes[m].flag & Fin) j += snprint(buf+j, sizeof(buf)-j, " in %d", liv); if(volumes[m].flag & Fout) j += snprint(buf+j, sizeof(buf)-j, " out %d", lov); } }else{ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov && riv==rov) j += snprint(buf+j, sizeof(buf)-j, " left %d right %d", liv, riv); else{ if(volumes[m].flag & Fin) j += snprint(buf+j, sizeof(buf)-j, " in left %d right %d", liv, riv); if(volumes[m].flag & Fout) j += snprint(buf+j, sizeof(buf)-j, " out left %d right %d", lov, rov); } } j += snprint(buf+j, sizeof(buf)-j, "\n"); } return readstr(offset, a, n, buf); } return n; } static long audiowrite(Chan *c, void *vp, long n, vlong off) { long m; int i, v, left, right, in, out; Cmdbuf *cb; char *a; USED(off); a = vp; switch((ulong)c->qid.path) { default: error(Eperm); break; case Qvolume: v = Vaudio; left = 1; right = 1; in = 1; out = 1; cb = parsecmd(vp, n); if(waserror()){ free(cb); nexterror(); } for(i = 0; i < cb->nf; i++){ /* * a number is volume */ if(cb->f[i][0] >= '0' && cb->f[i][0] <= '9') { m = strtoul(cb->f[i], 0, 10); if(!out) goto cont0; if(left && right) audiodevsetvol(v, m, m); else if(left) audiodevsetvol(v, m, -1); else if(right) audiodevsetvol(v, -1, m); goto cont0; } for(m=0; volumes[m].name; m++) { if(strcmp(cb->f[i], volumes[m].name) == 0) { v = m; in = 1; out = 1; left = 1; right = 1; goto cont0; } } if(strcmp(cb->f[i], "reset") == 0) { resetlevel(); goto cont0; } if(strcmp(cb->f[i], "in") == 0) { in = 1; out = 0; goto cont0; } if(strcmp(cb->f[i], "out") == 0) { in = 0; out = 1; goto cont0; } if(strcmp(cb->f[i], "left") == 0) { left = 1; right = 0; goto cont0; } if(strcmp(cb->f[i], "right") == 0) { left = 0; right = 1; goto cont0; } error(Evolume); break; cont0:; } free(cb); poperror(); break; case Qaudio: if(audio.amode != Awrite) error(Emode); aqlock(&audio); if(waserror()){ aqunlock(&audio); nexterror(); } n = audiodevwrite(vp, n); poperror(); aqunlock(&audio); break; } return n; } void audioswab(uchar *a, uint n) { ulong *p, *ep, b; p = (ulong*)a; ep = p + (n>>2); while(p < ep) { b = *p; b = (b>>24) | (b<<24) | ((b&0xff0000) >> 8) | ((b&0x00ff00) << 8); *p++ = b; } } Dev audiodevtab = { 'A', "audio", devreset, audioinit, devshutdown, audioattach, audiowalk, audiostat, audioopen, devcreate, audioclose, audioread, devbread, audiowrite, devbwrite, devremove, devwstat, }; drawterm-20110822.orig/kern/devmouse.c0000644000175000017500000000732711245145712017036 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "draw.h" #include "memdraw.h" #include "screen.h" int mousequeue = 1; Mouseinfo mouse; Cursorinfo cursor; static int mousechanged(void*); enum{ Qdir, Qcursor, Qmouse }; Dirtab mousedir[]={ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "cursor", {Qcursor}, 0, 0666, "mouse", {Qmouse}, 0, 0666, }; #define NMOUSE (sizeof(mousedir)/sizeof(Dirtab)) static Chan* mouseattach(char *spec) { return devattach('m', spec); } static Walkqid* mousewalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, mousedir, NMOUSE, devgen); } static int mousestat(Chan *c, uchar *db, int n) { return devstat(c, db, n, mousedir, NMOUSE, devgen); } static Chan* mouseopen(Chan *c, int omode) { switch((long)c->qid.path){ case Qdir: if(omode != OREAD) error(Eperm); break; case Qmouse: lock(&mouse.lk); if(mouse.open){ unlock(&mouse.lk); error(Einuse); } mouse.open = 1; unlock(&mouse.lk); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void mouseclose(Chan *c) { if(!(c->flag&COPEN)) return; switch((long)c->qid.path) { case Qmouse: lock(&mouse.lk); mouse.open = 0; unlock(&mouse.lk); cursorarrow(); } } long mouseread(Chan *c, void *va, long n, vlong offset) { char buf[4*12+1]; uchar *p; int i, nn; ulong msec; /* static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; */ p = va; switch((long)c->qid.path){ case Qdir: return devdirread(c, va, n, mousedir, NMOUSE, devgen); case Qcursor: if(offset != 0) return 0; if(n < 2*4+2*2*16) error(Eshort); n = 2*4+2*2*16; lock(&cursor.lk); BPLONG(p+0, cursor.offset.x); BPLONG(p+4, cursor.offset.y); memmove(p+8, cursor.clr, 2*16); memmove(p+40, cursor.set, 2*16); unlock(&cursor.lk); return n; case Qmouse: while(mousechanged(0) == 0) sleep(&mouse.r, mousechanged, 0); lock(&screen.lk); if(screen.reshaped) { screen.reshaped = 0; sprint(buf, "t%11d %11d", 0, ticks()); if(n > 1+2*12) n = 1+2*12; memmove(va, buf, n); unlock(&screen.lk); return n; } unlock(&screen.lk); lock(&mouse.lk); i = mouse.ri; nn = (mouse.wi + Mousequeue - i) % Mousequeue; if(nn < 1) panic("empty mouse queue"); msec = ticks(); while(nn > 1) { if(mouse.queue[i].msec + Mousewindow > msec) break; i = (i+1)%Mousequeue; nn--; } sprint(buf, "m%11d %11d %11d %11d", mouse.queue[i].xy.x, mouse.queue[i].xy.y, mouse.queue[i].buttons, mouse.queue[i].msec); mouse.ri = (i+1)%Mousequeue; unlock(&mouse.lk); if(n > 1+4*12) n = 1+4*12; memmove(va, buf, n); return n; } return 0; } long mousewrite(Chan *c, void *va, long n, vlong offset) { char *p; Point pt; char buf[64]; USED(offset); p = va; switch((long)c->qid.path){ case Qdir: error(Eisdir); case Qcursor: if(n < 2*4+2*2*16){ cursorarrow(); }else{ n = 2*4+2*2*16; lock(&cursor.lk); cursor.offset.x = BGLONG(p+0); cursor.offset.y = BGLONG(p+4); memmove(cursor.clr, p+8, 2*16); memmove(cursor.set, p+40, 2*16); unlock(&cursor.lk); setcursor(); } return n; case Qmouse: if(n > sizeof buf-1) n = sizeof buf -1; memmove(buf, va, n); buf[n] = 0; p = 0; pt.x = strtoul(buf+1, &p, 0); if(p == 0) error(Eshort); pt.y = strtoul(p, 0, 0); if(ptinrect(pt, gscreen->r)) mouseset(pt); return n; } error(Egreg); return -1; } int mousechanged(void *a) { USED(a); return mouse.ri != mouse.wi || screen.reshaped; } Dev mousedevtab = { 'm', "mouse", devreset, devinit, devshutdown, mouseattach, mousewalk, mousestat, mouseopen, devcreate, mouseclose, mouseread, devbread, mousewrite, devbwrite, devremove, devwstat, }; drawterm-20110822.orig/kern/qlock.c0000644000175000017500000000213711245145712016312 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" static void queue(Proc **first, Proc **last) { Proc *t; t = *last; if(t == 0) *first = up; else t->qnext = up; *last = up; up->qnext = 0; } static Proc* dequeue(Proc **first, Proc **last) { Proc *t; t = *first; if(t == 0) return 0; *first = t->qnext; if(*first == 0) *last = 0; return t; } void qlock(QLock *q) { lock(&q->lk); if(q->hold == 0) { q->hold = up; unlock(&q->lk); return; } /* * Can't assert this because of RWLock assert(q->hold != up); */ queue((Proc**)&q->first, (Proc**)&q->last); unlock(&q->lk); procsleep(); } int canqlock(QLock *q) { lock(&q->lk); if(q->hold == 0) { q->hold = up; unlock(&q->lk); return 1; } unlock(&q->lk); return 0; } void qunlock(QLock *q) { Proc *p; lock(&q->lk); /* * Can't assert this because of RWlock assert(q->hold == CT); */ p = dequeue((Proc**)&q->first, (Proc**)&q->last); if(p) { q->hold = p; unlock(&q->lk); procwakeup(p); } else { q->hold = 0; unlock(&q->lk); } } int holdqlock(QLock *q) { return q->hold == up; } drawterm-20110822.orig/kern/devtls.c0000644000175000017500000013036711245145712016511 0ustar tinchotincho/* * devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0 */ #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "libsec.h" typedef struct OneWay OneWay; typedef struct Secret Secret; typedef struct TlsRec TlsRec; typedef struct TlsErrs TlsErrs; enum { Statlen= 1024, /* max. length of status or stats message */ /* buffer limits */ MaxRecLen = 1<<14, /* max payload length of a record layer message */ MaxCipherRecLen = MaxRecLen + 2048, RecHdrLen = 5, MaxMacLen = SHA1dlen, /* protocol versions we can accept */ TLSVersion = 0x0301, SSL3Version = 0x0300, ProtocolVersion = 0x0301, /* maximum version we speak */ MinProtoVersion = 0x0300, /* limits on version we accept */ MaxProtoVersion = 0x03ff, /* connection states */ SHandshake = 1 << 0, /* doing handshake */ SOpen = 1 << 1, /* application data can be sent */ SRClose = 1 << 2, /* remote side has closed down */ SLClose = 1 << 3, /* sent a close notify alert */ SAlert = 1 << 5, /* sending or sent a fatal alert */ SError = 1 << 6, /* some sort of error has occured */ SClosed = 1 << 7, /* it is all over */ /* record types */ RChangeCipherSpec = 20, RAlert, RHandshake, RApplication, SSL2ClientHello = 1, HSSL2ClientHello = 9, /* local convention; see tlshand.c */ /* alerts */ ECloseNotify = 0, EUnexpectedMessage = 10, EBadRecordMac = 20, EDecryptionFailed = 21, ERecordOverflow = 22, EDecompressionFailure = 30, EHandshakeFailure = 40, ENoCertificate = 41, EBadCertificate = 42, EUnsupportedCertificate = 43, ECertificateRevoked = 44, ECertificateExpired = 45, ECertificateUnknown = 46, EIllegalParameter = 47, EUnknownCa = 48, EAccessDenied = 49, EDecodeError = 50, EDecryptError = 51, EExportRestriction = 60, EProtocolVersion = 70, EInsufficientSecurity = 71, EInternalError = 80, EUserCanceled = 90, ENoRenegotiation = 100, EMAX = 256 }; struct Secret { char *encalg; /* name of encryption alg */ char *hashalg; /* name of hash alg */ int (*enc)(Secret*, uchar*, int); int (*dec)(Secret*, uchar*, int); int (*unpad)(uchar*, int, int); DigestState *(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); int block; /* encryption block len, 0 if none */ int maclen; void *enckey; uchar mackey[MaxMacLen]; }; struct OneWay { QLock io; /* locks io access */ QLock seclock; /* locks secret paramaters */ ulong seq; Secret *sec; /* cipher in use */ Secret *new; /* cipher waiting for enable */ }; struct TlsRec { Chan *c; /* io channel */ int ref; /* serialized by tdlock for atomic destroy */ int version; /* version of the protocol we are speaking */ char verset; /* version has been set */ char opened; /* opened command every issued? */ char err[ERRMAX]; /* error message to return to handshake requests */ vlong handin; /* bytes communicated by the record layer */ vlong handout; vlong datain; vlong dataout; Lock statelk; int state; int debug; /* record layer mac functions for different protocol versions */ void (*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*); /* input side -- protected by in.io */ OneWay in; Block *processed; /* next bunch of application data */ Block *unprocessed; /* data read from c but not parsed into records */ /* handshake queue */ Lock hqlock; /* protects hqref, alloc & free of handq, hprocessed */ int hqref; Queue *handq; /* queue of handshake messages */ Block *hprocessed; /* remainder of last block read from handq */ QLock hqread; /* protects reads for hprocessed, handq */ /* output side */ OneWay out; /* protections */ char *user; int perm; }; struct TlsErrs{ int err; int sslerr; int tlserr; int fatal; char *msg; }; static TlsErrs tlserrs[] = { {ECloseNotify, ECloseNotify, ECloseNotify, 0, "close notify"}, {EUnexpectedMessage, EUnexpectedMessage, EUnexpectedMessage, 1, "unexpected message"}, {EBadRecordMac, EBadRecordMac, EBadRecordMac, 1, "bad record mac"}, {EDecryptionFailed, EIllegalParameter, EDecryptionFailed, 1, "decryption failed"}, {ERecordOverflow, EIllegalParameter, ERecordOverflow, 1, "record too long"}, {EDecompressionFailure, EDecompressionFailure, EDecompressionFailure, 1, "decompression failed"}, {EHandshakeFailure, EHandshakeFailure, EHandshakeFailure, 1, "could not negotiate acceptable security parameters"}, {ENoCertificate, ENoCertificate, ECertificateUnknown, 1, "no appropriate certificate available"}, {EBadCertificate, EBadCertificate, EBadCertificate, 1, "corrupted or invalid certificate"}, {EUnsupportedCertificate, EUnsupportedCertificate, EUnsupportedCertificate, 1, "unsupported certificate type"}, {ECertificateRevoked, ECertificateRevoked, ECertificateRevoked, 1, "revoked certificate"}, {ECertificateExpired, ECertificateExpired, ECertificateExpired, 1, "expired certificate"}, {ECertificateUnknown, ECertificateUnknown, ECertificateUnknown, 1, "unacceptable certificate"}, {EIllegalParameter, EIllegalParameter, EIllegalParameter, 1, "illegal parameter"}, {EUnknownCa, EHandshakeFailure, EUnknownCa, 1, "unknown certificate authority"}, {EAccessDenied, EHandshakeFailure, EAccessDenied, 1, "access denied"}, {EDecodeError, EIllegalParameter, EDecodeError, 1, "error decoding message"}, {EDecryptError, EIllegalParameter, EDecryptError, 1, "error decrypting message"}, {EExportRestriction, EHandshakeFailure, EExportRestriction, 1, "export restriction violated"}, {EProtocolVersion, EIllegalParameter, EProtocolVersion, 1, "protocol version not supported"}, {EInsufficientSecurity, EHandshakeFailure, EInsufficientSecurity, 1, "stronger security routines required"}, {EInternalError, EHandshakeFailure, EInternalError, 1, "internal error"}, {EUserCanceled, ECloseNotify, EUserCanceled, 0, "handshake canceled by user"}, {ENoRenegotiation, EUnexpectedMessage, ENoRenegotiation, 0, "no renegotiation"}, }; enum { /* max. open tls connections */ MaxTlsDevs = 1024 }; static Lock tdlock; static int tdhiwat; static int maxtlsdevs = 128; static TlsRec **tlsdevs; static char **trnames; static char *encalgs; static char *hashalgs; enum{ Qtopdir = 1, /* top level directory */ Qprotodir, Qclonus, Qencalgs, Qhashalgs, Qconvdir, /* directory for a conversation */ Qdata, Qctl, Qhand, Qstatus, Qstats, }; #define TYPE(x) ((x).path & 0xf) #define CONV(x) (((x).path >> 5)&(MaxTlsDevs-1)) #define QID(c, y) (((c)<<5) | (y)) static void checkstate(TlsRec *, int, int); static void ensure(TlsRec*, Block**, int); static void consume(Block**, uchar*, int); static Chan* buftochan(char*); static void tlshangup(TlsRec*); static void tlsError(TlsRec*, char *); static void alertHand(TlsRec*, char *); static TlsRec *newtls(Chan *c); static TlsRec *mktlsrec(void); static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); static void sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac); static void tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac); static void put64(uchar *p, vlong x); static void put32(uchar *p, u32int); static void put24(uchar *p, int); static void put16(uchar *p, int); /* static u32int get32(uchar *p); */ static int get16(uchar *p); static void tlsSetState(TlsRec *tr, int new, int old); static void rcvAlert(TlsRec *tr, int err); static void sendAlert(TlsRec *tr, int err); static void rcvError(TlsRec *tr, int err, char *msg, ...); static int rc4enc(Secret *sec, uchar *buf, int n); static int des3enc(Secret *sec, uchar *buf, int n); static int des3dec(Secret *sec, uchar *buf, int n); static int noenc(Secret *sec, uchar *buf, int n); static int sslunpad(uchar *buf, int n, int block); static int tlsunpad(uchar *buf, int n, int block); static void freeSec(Secret *sec); static char *tlsstate(int s); static void pdump(int, void*, char*); static char *tlsnames[] = { /* unused */ 0, /* topdir */ 0, /* protodir */ 0, "clone", "encalgs", "hashalgs", /* convdir */ 0, "data", "ctl", "hand", "status", "stats", }; static int convdir[] = { Qctl, Qdata, Qhand, Qstatus, Qstats }; static int tlsgen(Chan *c, char*unused1, Dirtab *unused2, int unused3, int s, Dir *dp) { Qid q; TlsRec *tr; char *name, *nm; int perm, t; q.vers = 0; q.type = QTFILE; t = TYPE(c->qid); switch(t) { case Qtopdir: if(s == DEVDOTDOT){ q.path = QID(0, Qtopdir); q.type = QTDIR; devdir(c, q, "#a", 0, eve, 0555, dp); return 1; } if(s > 0) return -1; q.path = QID(0, Qprotodir); q.type = QTDIR; devdir(c, q, "tls", 0, eve, 0555, dp); return 1; case Qprotodir: if(s == DEVDOTDOT){ q.path = QID(0, Qtopdir); q.type = QTDIR; devdir(c, q, ".", 0, eve, 0555, dp); return 1; } if(s < 3){ switch(s) { default: return -1; case 0: q.path = QID(0, Qclonus); break; case 1: q.path = QID(0, Qencalgs); break; case 2: q.path = QID(0, Qhashalgs); break; } perm = 0444; if(TYPE(q) == Qclonus) perm = 0555; devdir(c, q, tlsnames[TYPE(q)], 0, eve, perm, dp); return 1; } s -= 3; if(s >= tdhiwat) return -1; q.path = QID(s, Qconvdir); q.type = QTDIR; lock(&tdlock); tr = tlsdevs[s]; if(tr != nil) nm = tr->user; else nm = eve; if((name = trnames[s]) == nil){ name = trnames[s] = smalloc(16); sprint(name, "%d", s); } devdir(c, q, name, 0, nm, 0555, dp); unlock(&tdlock); return 1; case Qconvdir: if(s == DEVDOTDOT){ q.path = QID(0, Qprotodir); q.type = QTDIR; devdir(c, q, "tls", 0, eve, 0555, dp); return 1; } if(s < 0 || s >= nelem(convdir)) return -1; lock(&tdlock); tr = tlsdevs[CONV(c->qid)]; if(tr != nil){ nm = tr->user; perm = tr->perm; }else{ perm = 0; nm = eve; } t = convdir[s]; if(t == Qstatus || t == Qstats) perm &= 0444; q.path = QID(CONV(c->qid), t); devdir(c, q, tlsnames[t], 0, nm, perm, dp); unlock(&tdlock); return 1; case Qclonus: case Qencalgs: case Qhashalgs: perm = 0444; if(t == Qclonus) perm = 0555; devdir(c, c->qid, tlsnames[t], 0, eve, perm, dp); return 1; default: lock(&tdlock); tr = tlsdevs[CONV(c->qid)]; if(tr != nil){ nm = tr->user; perm = tr->perm; }else{ perm = 0; nm = eve; } if(t == Qstatus || t == Qstats) perm &= 0444; devdir(c, c->qid, tlsnames[t], 0, nm, perm, dp); unlock(&tdlock); return 1; } return -1; } static Chan* tlsattach(char *spec) { Chan *c; c = devattach('a', spec); c->qid.path = QID(0, Qtopdir); c->qid.type = QTDIR; c->qid.vers = 0; return c; } static Walkqid* tlswalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, nil, 0, tlsgen); } static int tlsstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, nil, 0, tlsgen); } static Chan* tlsopen(Chan *c, int omode) { TlsRec *tr, **pp; int t, perm; perm = 0; omode &= 3; switch(omode) { case OREAD: perm = 4; break; case OWRITE: perm = 2; break; case ORDWR: perm = 6; break; } t = TYPE(c->qid); switch(t) { default: panic("tlsopen"); case Qtopdir: case Qprotodir: case Qconvdir: if(omode != OREAD) error(Eperm); break; case Qclonus: tr = newtls(c); if(tr == nil) error(Enodev); break; case Qctl: case Qdata: case Qhand: case Qstatus: case Qstats: if((t == Qstatus || t == Qstats) && omode != OREAD) error(Eperm); if(waserror()) { unlock(&tdlock); nexterror(); } lock(&tdlock); pp = &tlsdevs[CONV(c->qid)]; tr = *pp; if(tr == nil) error("must open connection using clone"); if((perm & (tr->perm>>6)) != perm && (strcmp(up->user, tr->user) != 0 || (perm & tr->perm) != perm)) error(Eperm); if(t == Qhand){ if(waserror()){ unlock(&tr->hqlock); nexterror(); } lock(&tr->hqlock); if(tr->handq != nil) error(Einuse); tr->handq = qopen(2 * MaxCipherRecLen, 0, 0, nil); if(tr->handq == nil) error("cannot allocate handshake queue"); tr->hqref = 1; unlock(&tr->hqlock); poperror(); } tr->ref++; unlock(&tdlock); poperror(); break; case Qencalgs: case Qhashalgs: if(omode != OREAD) error(Eperm); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; c->iounit = qiomaxatomic; return c; } static int tlswstat(Chan *c, uchar *dp, int n) { Dir *d; TlsRec *tr; int rv; d = nil; if(waserror()){ free(d); unlock(&tdlock); nexterror(); } lock(&tdlock); tr = tlsdevs[CONV(c->qid)]; if(tr == nil) error(Ebadusefd); if(strcmp(tr->user, up->user) != 0) error(Eperm); d = smalloc(n + sizeof *d); rv = convM2D(dp, n, &d[0], (char*) &d[1]); if(rv == 0) error(Eshortstat); if(!emptystr(d->uid)) kstrdup(&tr->user, d->uid); if(d->mode != ~0UL) tr->perm = d->mode; free(d); poperror(); unlock(&tdlock); return rv; } static void dechandq(TlsRec *tr) { lock(&tr->hqlock); if(--tr->hqref == 0){ if(tr->handq != nil){ qfree(tr->handq); tr->handq = nil; } if(tr->hprocessed != nil){ freeb(tr->hprocessed); tr->hprocessed = nil; } } unlock(&tr->hqlock); } static void tlsclose(Chan *c) { TlsRec *tr; int t; t = TYPE(c->qid); switch(t) { case Qctl: case Qdata: case Qhand: case Qstatus: case Qstats: if((c->flag & COPEN) == 0) break; tr = tlsdevs[CONV(c->qid)]; if(tr == nil) break; if(t == Qhand) dechandq(tr); lock(&tdlock); if(--tr->ref > 0) { unlock(&tdlock); return; } tlsdevs[CONV(c->qid)] = nil; unlock(&tdlock); if(tr->c != nil && !waserror()){ checkstate(tr, 0, SOpen|SHandshake|SRClose); sendAlert(tr, ECloseNotify); poperror(); } tlshangup(tr); if(tr->c != nil) cclose(tr->c); freeSec(tr->in.sec); freeSec(tr->in.new); freeSec(tr->out.sec); freeSec(tr->out.new); free(tr->user); free(tr); break; } } /* * make sure we have at least 'n' bytes in list 'l' */ static void ensure(TlsRec *s, Block **l, int n) { int sofar, i; Block *b, *bl; sofar = 0; for(b = *l; b; b = b->next){ sofar += BLEN(b); if(sofar >= n) return; l = &b->next; } while(sofar < n){ bl = devtab[s->c->type]->bread(s->c, MaxCipherRecLen + RecHdrLen, 0); if(bl == 0) error(Ehungup); *l = bl; i = 0; for(b = bl; b; b = b->next){ i += BLEN(b); l = &b->next; } if(i == 0) error(Ehungup); sofar += i; } if(s->debug) pprint("ensure read %d\n", sofar); } /* * copy 'n' bytes from 'l' into 'p' and free * the bytes in 'l' */ static void consume(Block **l, uchar *p, int n) { Block *b; int i; for(; *l && n > 0; n -= i){ b = *l; i = BLEN(b); if(i > n) i = n; memmove(p, b->rp, i); b->rp += i; p += i; if(BLEN(b) < 0) panic("consume"); if(BLEN(b)) break; *l = b->next; freeb(b); } } /* * give back n bytes */ static void regurgitate(TlsRec *s, uchar *p, int n) { Block *b; if(n <= 0) return; b = s->unprocessed; if(s->unprocessed == nil || b->rp - b->base < n) { b = allocb(n); memmove(b->wp, p, n); b->wp += n; b->next = s->unprocessed; s->unprocessed = b; } else { b->rp -= n; memmove(b->rp, p, n); } } /* * remove at most n bytes from the queue */ static Block* qgrab(Block **l, int n) { Block *bb, *b; int i; b = *l; if(BLEN(b) == n){ *l = b->next; b->next = nil; return b; } i = 0; for(bb = b; bb != nil && i < n; bb = bb->next) i += BLEN(bb); if(i > n) i = n; bb = allocb(i); consume(l, bb->wp, i); bb->wp += i; return bb; } static void tlsclosed(TlsRec *tr, int new) { lock(&tr->statelk); if(tr->state == SOpen || tr->state == SHandshake) tr->state = new; else if((new | tr->state) == (SRClose|SLClose)) tr->state = SClosed; unlock(&tr->statelk); alertHand(tr, "close notify"); } /* * read and process one tls record layer message * must be called with tr->in.io held * We can't let Eintrs lose data, since doing so will get * us out of sync with the sender and break the reliablity * of the channel. Eintr only happens during the reads in * consume. Therefore we put back any bytes consumed before * the last call to ensure. */ static void tlsrecread(TlsRec *tr) { OneWay *volatile in; Block *volatile b; uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen]; int volatile nconsumed; int len, type, ver, unpad_len; nconsumed = 0; if(waserror()){ if(strcmp(up->errstr, Eintr) == 0 && !waserror()){ regurgitate(tr, header, nconsumed); poperror(); }else tlsError(tr, "channel error"); nexterror(); } ensure(tr, &tr->unprocessed, RecHdrLen); consume(&tr->unprocessed, header, RecHdrLen); if(tr->debug)pprint("consumed %d header\n", RecHdrLen); nconsumed = RecHdrLen; if((tr->handin == 0) && (header[0] & 0x80)){ /* Cope with an SSL3 ClientHello expressed in SSL2 record format. This is sent by some clients that we must interoperate with, such as Java's JSSE and Microsoft's Internet Explorer. */ len = (get16(header) & ~0x8000) - 3; type = header[2]; ver = get16(header + 3); if(type != SSL2ClientHello || len < 22) rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message"); }else{ /* normal SSL3 record format */ type = header[0]; ver = get16(header+1); len = get16(header+3); } if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion)) rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'", tr->version, tr->verset?"/set":"", len, type, ver, (char*)header); if(len > MaxCipherRecLen || len < 0) rcvError(tr, ERecordOverflow, "record message too long %d", len); ensure(tr, &tr->unprocessed, len); nconsumed = 0; poperror(); /* * If an Eintr happens after this, we'll get out of sync. * Make sure nothing we call can sleep. * Errors are ok, as they kill the connection. * Luckily, allocb won't sleep, it'll just error out. */ b = nil; if(waserror()){ if(b != nil) freeb(b); tlsError(tr, "channel error"); nexterror(); } b = qgrab(&tr->unprocessed, len); if(tr->debug) pprint("consumed unprocessed %d\n", len); in = &tr->in; if(waserror()){ qunlock(&in->seclock); nexterror(); } qlock(&in->seclock); p = b->rp; if(in->sec != nil) { /* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here should look alike, including timing of the response. */ unpad_len = (*in->sec->dec)(in->sec, p, len); if(unpad_len >= in->sec->maclen) len = unpad_len - in->sec->maclen; if(tr->debug) pprint("decrypted %d\n", unpad_len); if(tr->debug) pdump(unpad_len, p, "decrypted:"); /* update length */ put16(header+3, len); put64(seq, in->seq); in->seq++; (*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac); if(unpad_len < in->sec->maclen) rcvError(tr, EBadRecordMac, "short record mac"); if(memcmp(hmac, p+len, in->sec->maclen) != 0) rcvError(tr, EBadRecordMac, "record mac mismatch"); b->wp = b->rp + len; } qunlock(&in->seclock); poperror(); if(len < 0) rcvError(tr, EDecodeError, "runt record message"); switch(type) { default: rcvError(tr, EIllegalParameter, "invalid record message 0x%x", type); break; case RChangeCipherSpec: if(len != 1 || p[0] != 1) rcvError(tr, EDecodeError, "invalid change cipher spec"); qlock(&in->seclock); if(in->new == nil){ qunlock(&in->seclock); rcvError(tr, EUnexpectedMessage, "unexpected change cipher spec"); } freeSec(in->sec); in->sec = in->new; in->new = nil; in->seq = 0; qunlock(&in->seclock); break; case RAlert: if(len != 2) rcvError(tr, EDecodeError, "invalid alert"); if(p[0] == 2) rcvAlert(tr, p[1]); if(p[0] != 1) rcvError(tr, EIllegalParameter, "invalid alert fatal code"); /* * propate non-fatal alerts to handshaker */ if(p[1] == ECloseNotify) { tlsclosed(tr, SRClose); if(tr->opened) error("tls hungup"); error("close notify"); } if(p[1] == ENoRenegotiation) alertHand(tr, "no renegotiation"); else if(p[1] == EUserCanceled) alertHand(tr, "handshake canceled by user"); else rcvError(tr, EIllegalParameter, "invalid alert code"); break; case RHandshake: /* * don't worry about dropping the block * qbwrite always queues even if flow controlled and interrupted. * * if there isn't any handshaker, ignore the request, * but notify the other side we are doing so. */ lock(&tr->hqlock); if(tr->handq != nil){ tr->hqref++; unlock(&tr->hqlock); if(waserror()){ dechandq(tr); nexterror(); } b = padblock(b, 1); *b->rp = RHandshake; qbwrite(tr->handq, b); b = nil; poperror(); dechandq(tr); }else{ unlock(&tr->hqlock); if(tr->verset && tr->version != SSL3Version && !waserror()){ sendAlert(tr, ENoRenegotiation); poperror(); } } break; case SSL2ClientHello: lock(&tr->hqlock); if(tr->handq != nil){ tr->hqref++; unlock(&tr->hqlock); if(waserror()){ dechandq(tr); nexterror(); } /* Pass the SSL2 format data, so that the handshake code can compute the correct checksums. HSSL2ClientHello = HandshakeType 9 is unused in RFC2246. */ b = padblock(b, 8); b->rp[0] = RHandshake; b->rp[1] = HSSL2ClientHello; put24(&b->rp[2], len+3); b->rp[5] = SSL2ClientHello; put16(&b->rp[6], ver); qbwrite(tr->handq, b); b = nil; poperror(); dechandq(tr); }else{ unlock(&tr->hqlock); if(tr->verset && tr->version != SSL3Version && !waserror()){ sendAlert(tr, ENoRenegotiation); poperror(); } } break; case RApplication: if(!tr->opened) rcvError(tr, EUnexpectedMessage, "application message received before handshake completed"); if(BLEN(b) > 0){ tr->processed = b; b = nil; } break; } if(b != nil) freeb(b); poperror(); } /* * got a fatal alert message */ static void rcvAlert(TlsRec *tr, int err) { char *s; int i; s = "unknown error"; for(i=0; i < nelem(tlserrs); i++){ if(tlserrs[i].err == err){ s = tlserrs[i].msg; break; } } if(tr->debug) pprint("rcvAlert: %s\n", s); tlsError(tr, s); if(!tr->opened) error(s); error("tls error"); } /* * found an error while decoding the input stream */ static void rcvError(TlsRec *tr, int err, char *fmt, ...) { char msg[ERRMAX]; va_list arg; va_start(arg, fmt); vseprint(msg, msg+sizeof(msg), fmt, arg); va_end(arg); if(tr->debug) pprint("rcvError: %s\n", msg); sendAlert(tr, err); if(!tr->opened) error(msg); error("tls error"); } /* * make sure the next hand operation returns with a 'msg' error */ static void alertHand(TlsRec *tr, char *msg) { Block *b; int n; lock(&tr->hqlock); if(tr->handq == nil){ unlock(&tr->hqlock); return; } tr->hqref++; unlock(&tr->hqlock); n = strlen(msg); if(waserror()){ dechandq(tr); nexterror(); } b = allocb(n + 2); *b->wp++ = RAlert; memmove(b->wp, msg, n + 1); b->wp += n + 1; qbwrite(tr->handq, b); poperror(); dechandq(tr); } static void checkstate(TlsRec *tr, int ishand, int ok) { int state; lock(&tr->statelk); state = tr->state; unlock(&tr->statelk); if(state & ok) return; switch(state){ case SHandshake: case SOpen: break; case SError: case SAlert: if(ishand) error(tr->err); error("tls error"); case SRClose: case SLClose: case SClosed: error("tls hungup"); } error("tls improperly configured"); } static Block* tlsbread(Chan *c, long n, ulong offset) { int ty; Block *b; TlsRec *volatile tr; ty = TYPE(c->qid); switch(ty) { default: return devbread(c, n, offset); case Qhand: case Qdata: break; } tr = tlsdevs[CONV(c->qid)]; if(tr == nil) panic("tlsbread"); if(waserror()){ qunlock(&tr->in.io); nexterror(); } qlock(&tr->in.io); if(ty == Qdata){ checkstate(tr, 0, SOpen); while(tr->processed == nil) tlsrecread(tr); /* return at most what was asked for */ b = qgrab(&tr->processed, n); if(tr->debug) pprint("consumed processed %d\n", BLEN(b)); if(tr->debug) pdump(BLEN(b), b->rp, "consumed:"); qunlock(&tr->in.io); poperror(); tr->datain += BLEN(b); }else{ checkstate(tr, 1, SOpen|SHandshake|SLClose); /* * it's ok to look at state without the lock * since it only protects reading records, * and we have that tr->in.io held. */ while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq)) tlsrecread(tr); qunlock(&tr->in.io); poperror(); if(waserror()){ qunlock(&tr->hqread); nexterror(); } qlock(&tr->hqread); if(tr->hprocessed == nil){ b = qbread(tr->handq, MaxRecLen + 1); if(*b->rp++ == RAlert){ kstrcpy(up->errstr, (char*)b->rp, ERRMAX); freeb(b); nexterror(); } tr->hprocessed = b; } b = qgrab(&tr->hprocessed, n); poperror(); qunlock(&tr->hqread); tr->handin += BLEN(b); } return b; } static long tlsread(Chan *c, void *a, long n, vlong off) { Block *volatile b; Block *nb; uchar *va; int i, ty; char *buf, *s, *e; ulong offset = off; TlsRec * tr; if(c->qid.type & QTDIR) return devdirread(c, a, n, 0, 0, tlsgen); tr = tlsdevs[CONV(c->qid)]; ty = TYPE(c->qid); switch(ty) { default: error(Ebadusefd); case Qstatus: buf = smalloc(Statlen); qlock(&tr->in.seclock); qlock(&tr->out.seclock); s = buf; e = buf + Statlen; s = seprint(s, e, "State: %s\n", tlsstate(tr->state)); s = seprint(s, e, "Version: 0x%x\n", tr->version); if(tr->in.sec != nil) s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg); if(tr->in.new != nil) s = seprint(s, e, "NewEncIn: %s\nNewHashIn: %s\n", tr->in.new->encalg, tr->in.new->hashalg); if(tr->out.sec != nil) s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg); if(tr->out.new != nil) seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); n = readstr(offset, a, n, buf); free(buf); return n; case Qstats: buf = smalloc(Statlen); s = buf; e = buf + Statlen; s = seprint(s, e, "DataIn: %lld\n", tr->datain); s = seprint(s, e, "DataOut: %lld\n", tr->dataout); s = seprint(s, e, "HandIn: %lld\n", tr->handin); seprint(s, e, "HandOut: %lld\n", tr->handout); n = readstr(offset, a, n, buf); free(buf); return n; case Qctl: buf = smalloc(Statlen); snprint(buf, Statlen, "%llud", CONV(c->qid)); n = readstr(offset, a, n, buf); free(buf); return n; case Qdata: case Qhand: b = tlsbread(c, n, offset); break; case Qencalgs: return readstr(offset, a, n, encalgs); case Qhashalgs: return readstr(offset, a, n, hashalgs); } if(waserror()){ freeblist(b); nexterror(); } n = 0; va = a; for(nb = b; nb; nb = nb->next){ i = BLEN(nb); memmove(va+n, nb->rp, i); n += i; } freeblist(b); poperror(); return n; } /* * write a block in tls records */ static void tlsrecwrite(TlsRec *tr, int type, Block *b) { Block *volatile bb; Block *nb; uchar *p, seq[8]; OneWay *volatile out; int n, maclen, pad, ok; out = &tr->out; bb = b; if(waserror()){ qunlock(&out->io); if(bb != nil) freeb(bb); nexterror(); } qlock(&out->io); if(tr->debug)pprint("send %d\n", BLEN(b)); if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); ok = SHandshake|SOpen|SRClose; if(type == RAlert) ok |= SAlert; while(bb != nil){ checkstate(tr, type != RApplication, ok); /* * get at most one maximal record's input, * with padding on the front for header and * back for mac and maximal block padding. */ if(waserror()){ qunlock(&out->seclock); nexterror(); } qlock(&out->seclock); maclen = 0; pad = 0; if(out->sec != nil){ maclen = out->sec->maclen; pad = maclen + out->sec->block; } n = BLEN(bb); if(n > MaxRecLen){ n = MaxRecLen; nb = allocb(n + pad + RecHdrLen); memmove(nb->wp + RecHdrLen, bb->rp, n); bb->rp += n; }else{ /* * carefully reuse bb so it will get freed if we're out of memory */ bb = padblock(bb, RecHdrLen); if(pad) nb = padblock(bb, -pad); else nb = bb; bb = nil; } p = nb->rp; p[0] = type; put16(p+1, tr->version); put16(p+3, n); if(out->sec != nil){ put64(seq, out->seq); out->seq++; (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n); n += maclen; /* encrypt */ n = (*out->sec->enc)(out->sec, p + RecHdrLen, n); nb->wp = p + RecHdrLen + n; /* update length */ put16(p+3, n); } if(type == RChangeCipherSpec){ if(out->new == nil) error("change cipher without a new cipher"); freeSec(out->sec); out->sec = out->new; out->new = nil; out->seq = 0; } qunlock(&out->seclock); poperror(); /* * if bwrite error's, we assume the block is queued. * if not, we're out of sync with the receiver and will not recover. */ if(waserror()){ if(strcmp(up->errstr, "interrupted") != 0) tlsError(tr, "channel error"); nexterror(); } devtab[tr->c->type]->bwrite(tr->c, nb, 0); poperror(); } qunlock(&out->io); poperror(); } static long tlsbwrite(Chan *c, Block *b, ulong offset) { int ty; ulong n; TlsRec *tr; n = BLEN(b); tr = tlsdevs[CONV(c->qid)]; if(tr == nil) panic("tlsbread"); ty = TYPE(c->qid); switch(ty) { default: return devbwrite(c, b, offset); case Qhand: tlsrecwrite(tr, RHandshake, b); tr->handout += n; break; case Qdata: checkstate(tr, 0, SOpen); tlsrecwrite(tr, RApplication, b); tr->dataout += n; break; } return n; } typedef struct Hashalg Hashalg; struct Hashalg { char *name; int maclen; void (*initkey)(Hashalg *, int, Secret *, uchar*); }; static void initmd5key(Hashalg *ha, int version, Secret *s, uchar *p) { s->maclen = ha->maclen; if(version == SSL3Version) s->mac = sslmac_md5; else s->mac = hmac_md5; memmove(s->mackey, p, ha->maclen); } static void initclearmac(Hashalg *unused1, int unused2, Secret *s, uchar *unused3) { s->maclen = 0; s->mac = nomac; } static void initsha1key(Hashalg *ha, int version, Secret *s, uchar *p) { s->maclen = ha->maclen; if(version == SSL3Version) s->mac = sslmac_sha1; else s->mac = hmac_sha1; memmove(s->mackey, p, ha->maclen); } static Hashalg hashtab[] = { { "clear", 0, initclearmac, }, { "md5", MD5dlen, initmd5key, }, { "sha1", SHA1dlen, initsha1key, }, { 0 } }; static Hashalg* parsehashalg(char *p) { Hashalg *ha; for(ha = hashtab; ha->name; ha++) if(strcmp(p, ha->name) == 0) return ha; error("unsupported hash algorithm"); return nil; } typedef struct Encalg Encalg; struct Encalg { char *name; int keylen; int ivlen; void (*initkey)(Encalg *ea, Secret *, uchar*, uchar*); }; static void initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *unused1) { s->enckey = smalloc(sizeof(RC4state)); s->enc = rc4enc; s->dec = rc4enc; s->block = 0; setupRC4state(s->enckey, p, ea->keylen); } static void initDES3key(Encalg *unused1, Secret *s, uchar *p, uchar *iv) { s->enckey = smalloc(sizeof(DES3state)); s->enc = des3enc; s->dec = des3dec; s->block = 8; setupDES3state(s->enckey, (uchar(*)[8])p, iv); } static void initclearenc(Encalg *unused1, Secret *s, uchar *unused2, uchar *unused3) { s->enc = noenc; s->dec = noenc; s->block = 0; } static Encalg encrypttab[] = { { "clear", 0, 0, initclearenc }, { "rc4_128", 128/8, 0, initRC4key }, { "3des_ede_cbc", 3 * 8, 8, initDES3key }, { 0 } }; static Encalg* parseencalg(char *p) { Encalg *ea; for(ea = encrypttab; ea->name; ea++) if(strcmp(p, ea->name) == 0) return ea; error("unsupported encryption algorithm"); return nil; } static long tlswrite(Chan *c, void *a, long n, vlong off) { Encalg *ea; Hashalg *ha; TlsRec *volatile tr; Secret *volatile tos, *volatile toc; Block *volatile b; Cmdbuf *volatile cb; int m, ty; char *p, *e; uchar *volatile x; ulong offset = off; tr = tlsdevs[CONV(c->qid)]; if(tr == nil) panic("tlswrite"); ty = TYPE(c->qid); switch(ty){ case Qdata: case Qhand: p = a; e = p + n; do{ m = e - p; if(m > MaxRecLen) m = MaxRecLen; b = allocb(m); if(waserror()){ freeb(b); nexterror(); } memmove(b->wp, p, m); poperror(); b->wp += m; tlsbwrite(c, b, offset); p += m; }while(p < e); return n; case Qctl: break; default: error(Ebadusefd); return -1; } cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } if(cb->nf < 1) error("short control request"); /* mutex with operations using what we're about to change */ if(waserror()){ qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); nexterror(); } qlock(&tr->in.seclock); qlock(&tr->out.seclock); if(strcmp(cb->f[0], "fd") == 0){ if(cb->nf != 3) error("usage: fd open-fd version"); if(tr->c != nil) error(Einuse); m = strtol(cb->f[2], nil, 0); if(m < MinProtoVersion || m > MaxProtoVersion) error("unsupported version"); tr->c = buftochan(cb->f[1]); tr->version = m; tlsSetState(tr, SHandshake, SClosed); }else if(strcmp(cb->f[0], "version") == 0){ if(cb->nf != 2) error("usage: version vers"); if(tr->c == nil) error("must set fd before version"); if(tr->verset) error("version already set"); m = strtol(cb->f[1], nil, 0); if(m == SSL3Version) tr->packMac = sslPackMac; else if(m == TLSVersion) tr->packMac = tlsPackMac; else error("unsupported version"); tr->verset = 1; tr->version = m; }else if(strcmp(cb->f[0], "secret") == 0){ if(cb->nf != 5) error("usage: secret hashalg encalg isclient secretdata"); if(tr->c == nil || !tr->verset) error("must set fd and version before secrets"); if(tr->in.new != nil){ freeSec(tr->in.new); tr->in.new = nil; } if(tr->out.new != nil){ freeSec(tr->out.new); tr->out.new = nil; } ha = parsehashalg(cb->f[1]); ea = parseencalg(cb->f[2]); p = cb->f[4]; m = (strlen(p)*3)/2; x = smalloc(m); tos = nil; toc = nil; if(waserror()){ freeSec(tos); freeSec(toc); free(x); nexterror(); } m = dec64(x, m, p, strlen(p)); if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen) error("not enough secret data provided"); tos = smalloc(sizeof(Secret)); toc = smalloc(sizeof(Secret)); if(!ha->initkey || !ea->initkey) error("misimplemented secret algorithm"); (*ha->initkey)(ha, tr->version, tos, &x[0]); (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]); (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]); (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]); if(!tos->mac || !tos->enc || !tos->dec || !toc->mac || !toc->enc || !toc->dec) error("missing algorithm implementations"); if(strtol(cb->f[3], nil, 0) == 0){ tr->in.new = tos; tr->out.new = toc; }else{ tr->in.new = toc; tr->out.new = tos; } if(tr->version == SSL3Version){ toc->unpad = sslunpad; tos->unpad = sslunpad; }else{ toc->unpad = tlsunpad; tos->unpad = tlsunpad; } toc->encalg = ea->name; toc->hashalg = ha->name; tos->encalg = ea->name; tos->hashalg = ha->name; free(x); poperror(); }else if(strcmp(cb->f[0], "changecipher") == 0){ if(cb->nf != 1) error("usage: changecipher"); if(tr->out.new == nil) error("cannot change cipher spec without setting secret"); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); poperror(); free(cb); poperror(); /* * the real work is done as the message is written * so the stream is encrypted in sync. */ b = allocb(1); *b->wp++ = 1; tlsrecwrite(tr, RChangeCipherSpec, b); return n; }else if(strcmp(cb->f[0], "opened") == 0){ if(cb->nf != 1) error("usage: opened"); if(tr->in.sec == nil || tr->out.sec == nil) error("cipher must be configured before enabling data messages"); lock(&tr->statelk); if(tr->state != SHandshake && tr->state != SOpen){ unlock(&tr->statelk); error("cannot enable data messages"); } tr->state = SOpen; unlock(&tr->statelk); tr->opened = 1; }else if(strcmp(cb->f[0], "alert") == 0){ if(cb->nf != 2) error("usage: alert n"); if(tr->c == nil) error("must set fd before sending alerts"); m = strtol(cb->f[1], nil, 0); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); poperror(); free(cb); poperror(); sendAlert(tr, m); if(m == ECloseNotify) tlsclosed(tr, SLClose); return n; } else if(strcmp(cb->f[0], "debug") == 0){ if(cb->nf == 2){ if(strcmp(cb->f[1], "on") == 0) tr->debug = 1; else tr->debug = 0; } else tr->debug = 1; } else error(Ebadarg); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); poperror(); free(cb); poperror(); return n; } static void tlsinit(void) { struct Encalg *e; struct Hashalg *h; int n; char *cp; static int already; if(!already){ fmtinstall('H', encodefmt); already = 1; } tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs); trnames = smalloc((sizeof *trnames) * maxtlsdevs); n = 1; for(e = encrypttab; e->name != nil; e++) n += strlen(e->name) + 1; cp = encalgs = smalloc(n); for(e = encrypttab;;){ strcpy(cp, e->name); cp += strlen(e->name); e++; if(e->name == nil) break; *cp++ = ' '; } *cp = 0; n = 1; for(h = hashtab; h->name != nil; h++) n += strlen(h->name) + 1; cp = hashalgs = smalloc(n); for(h = hashtab;;){ strcpy(cp, h->name); cp += strlen(h->name); h++; if(h->name == nil) break; *cp++ = ' '; } *cp = 0; } Dev tlsdevtab = { 'a', "tls", devreset, tlsinit, devshutdown, tlsattach, tlswalk, tlsstat, tlsopen, devcreate, tlsclose, tlsread, tlsbread, tlswrite, tlsbwrite, devremove, tlswstat, }; /* get channel associated with an fd */ static Chan* buftochan(char *p) { Chan *c; int fd; if(p == 0) error(Ebadarg); fd = strtoul(p, 0, 0); if(fd < 0) error(Ebadarg); c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ return c; } static void sendAlert(TlsRec *tr, int err) { Block *b; int i, fatal; char *msg; if(tr->debug)pprint("sendAlert %d\n", err); fatal = 1; msg = "tls unknown alert"; for(i=0; i < nelem(tlserrs); i++) { if(tlserrs[i].err == err) { msg = tlserrs[i].msg; if(tr->version == SSL3Version) err = tlserrs[i].sslerr; else err = tlserrs[i].tlserr; fatal = tlserrs[i].fatal; break; } } if(!waserror()){ b = allocb(2); *b->wp++ = fatal + 1; *b->wp++ = err; if(fatal) tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose); tlsrecwrite(tr, RAlert, b); poperror(); } if(fatal) tlsError(tr, msg); } static void tlsError(TlsRec *tr, char *msg) { int s; if(tr->debug)pprint("tleError %s\n", msg); lock(&tr->statelk); s = tr->state; tr->state = SError; if(s != SError){ strncpy(tr->err, msg, ERRMAX - 1); tr->err[ERRMAX - 1] = '\0'; } unlock(&tr->statelk); if(s != SError) alertHand(tr, msg); } static void tlsSetState(TlsRec *tr, int new, int old) { lock(&tr->statelk); if(tr->state & old) tr->state = new; unlock(&tr->statelk); } /* hand up a digest connection */ static void tlshangup(TlsRec *tr) { Block *b; qlock(&tr->in.io); for(b = tr->processed; b; b = tr->processed){ tr->processed = b->next; freeb(b); } if(tr->unprocessed != nil){ freeb(tr->unprocessed); tr->unprocessed = nil; } qunlock(&tr->in.io); tlsSetState(tr, SClosed, ~0); } static TlsRec* newtls(Chan *ch) { TlsRec **pp, **ep, **np; char **nmp; int t, newmax; if(waserror()) { unlock(&tdlock); nexterror(); } lock(&tdlock); ep = &tlsdevs[maxtlsdevs]; for(pp = tlsdevs; pp < ep; pp++) if(*pp == nil) break; if(pp >= ep) { if(maxtlsdevs >= MaxTlsDevs) { unlock(&tdlock); poperror(); return nil; } newmax = 2 * maxtlsdevs; if(newmax > MaxTlsDevs) newmax = MaxTlsDevs; np = smalloc(sizeof(TlsRec*) * newmax); memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs); tlsdevs = np; pp = &tlsdevs[maxtlsdevs]; memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs)); nmp = smalloc(sizeof *nmp * newmax); memmove(nmp, trnames, sizeof *nmp * maxtlsdevs); trnames = nmp; maxtlsdevs = newmax; } *pp = mktlsrec(); if(pp - tlsdevs >= tdhiwat) tdhiwat++; t = TYPE(ch->qid); if(t == Qclonus) t = Qctl; ch->qid.path = QID(pp - tlsdevs, t); ch->qid.vers = 0; unlock(&tdlock); poperror(); return *pp; } static TlsRec * mktlsrec(void) { TlsRec *tr; tr = mallocz(sizeof(*tr), 1); if(tr == nil) error(Enomem); tr->state = SClosed; tr->ref = 1; kstrdup(&tr->user, up->user); tr->perm = 0660; return tr; } static char* tlsstate(int s) { switch(s){ case SHandshake: return "Handshaking"; case SOpen: return "Established"; case SRClose: return "RemoteClosed"; case SLClose: return "LocalClosed"; case SAlert: return "Alerting"; case SError: return "Errored"; case SClosed: return "Closed"; } return "Unknown"; } static void freeSec(Secret *s) { if(s != nil){ free(s->enckey); free(s); } } static int noenc(Secret *unused1, uchar *unused2, int n) { return n; } static int rc4enc(Secret *sec, uchar *buf, int n) { rc4(sec->enckey, buf, n); return n; } static int tlsunpad(uchar *buf, int n, int block) { int pad, nn; pad = buf[n - 1]; nn = n - 1 - pad; if(nn <= 0 || n % block) return -1; while(--n > nn) if(pad != buf[n - 1]) return -1; return nn; } static int sslunpad(uchar *buf, int n, int block) { int pad, nn; pad = buf[n - 1]; nn = n - 1 - pad; if(nn <= 0 || n % block) return -1; return nn; } static int blockpad(uchar *buf, int n, int block) { int pad, nn; nn = n + block; nn -= nn % block; pad = nn - (n + 1); while(n < nn) buf[n++] = pad; return nn; } static int des3enc(Secret *sec, uchar *buf, int n) { n = blockpad(buf, n, 8); des3CBCencrypt(buf, n, sec->enckey); return n; } static int des3dec(Secret *sec, uchar *buf, int n) { des3CBCdecrypt(buf, n, sec->enckey); return (*sec->unpad)(buf, n, 8); } static DigestState* nomac(uchar *unused1, ulong unused2, uchar *unused3, ulong unused4, uchar *unused5, DigestState *unused6) { return nil; } /* * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac. */ static DigestState* sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s, DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen) { int i; uchar pad[48], innerdigest[20]; if(xlen > sizeof(innerdigest) || padlen > sizeof(pad)) return nil; if(klen>64) return nil; /* first time through */ if(s == nil){ for(i=0; imac)(buf, 11, mackey, sec->maclen, 0, 0); (*sec->mac)(body, len, mackey, sec->maclen, mac, s); } static void tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac) { DigestState *s; uchar buf[13]; memmove(buf, seq, 8); memmove(&buf[8], header, 5); s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0); (*sec->mac)(body, len, mackey, sec->maclen, mac, s); } static void put32(uchar *p, u32int x) { p[0] = x>>24; p[1] = x>>16; p[2] = x>>8; p[3] = x; } static void put64(uchar *p, vlong x) { put32(p, (u32int)(x >> 32)); put32(p+4, (u32int)x); } static void put24(uchar *p, int x) { p[0] = x>>16; p[1] = x>>8; p[2] = x; } static void put16(uchar *p, int x) { p[0] = x>>8; p[1] = x; } /* static u32int get32(uchar *p) { return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; } */ static int get16(uchar *p) { return (p[0]<<8)|p[1]; } static char *charmap = "0123456789abcdef"; static void pdump(int len, void *a, char *tag) { uchar *p; int i; char buf[65+32]; char *q; p = a; strcpy(buf, tag); while(len > 0){ q = buf + strlen(tag); for(i = 0; len > 0 && i < 32; i++){ if(*p >= ' ' && *p < 0x7f){ *q++ = ' '; *q++ = *p; } else { *q++ = charmap[*p>>4]; *q++ = charmap[*p & 0xf]; } len--; p++; } *q = 0; if(len > 0) pprint("%s...\n", buf); else pprint("%s\n", buf); } } drawterm-20110822.orig/kern/sysfile.c0000644000175000017500000004321311245145712016657 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "user.h" #undef open #undef mount #undef read #undef write #undef seek #undef stat #undef wstat #undef remove #undef close #undef fstat #undef fwstat /* * The sys*() routines needn't poperror() as they return directly to syscall(). */ static void unlockfgrp(Fgrp *f) { int ex; ex = f->exceed; f->exceed = 0; unlock(&f->ref.lk); if(ex) pprint("warning: process exceeds %d file descriptors\n", ex); } int growfd(Fgrp *f, int fd) /* fd is always >= 0 */ { Chan **newfd, **oldfd; if(fd < f->nfd) return 0; if(fd >= f->nfd+DELTAFD) return -1; /* out of range */ /* * Unbounded allocation is unwise; besides, there are only 16 bits * of fid in 9P */ if(f->nfd >= 5000){ Exhausted: print("no free file descriptors\n"); return -1; } newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*)); if(newfd == 0) goto Exhausted; oldfd = f->fd; memmove(newfd, oldfd, f->nfd*sizeof(Chan*)); f->fd = newfd; free(oldfd); f->nfd += DELTAFD; if(fd > f->maxfd){ if(fd/100 > f->maxfd/100) f->exceed = (fd/100)*100; f->maxfd = fd; } return 1; } /* * this assumes that the fgrp is locked */ int findfreefd(Fgrp *f, int start) { int fd; for(fd=start; fdnfd; fd++) if(f->fd[fd] == 0) break; if(fd >= f->nfd && growfd(f, fd) < 0) return -1; return fd; } int newfd(Chan *c) { int fd; Fgrp *f; f = up->fgrp; lock(&f->ref.lk); fd = findfreefd(f, 0); if(fd < 0){ unlockfgrp(f); return -1; } if(fd > f->maxfd) f->maxfd = fd; f->fd[fd] = c; unlockfgrp(f); return fd; } int newfd2(int fd[2], Chan *c[2]) { Fgrp *f; f = up->fgrp; lock(&f->ref.lk); fd[0] = findfreefd(f, 0); if(fd[0] < 0){ unlockfgrp(f); return -1; } fd[1] = findfreefd(f, fd[0]+1); if(fd[1] < 0){ unlockfgrp(f); return -1; } if(fd[1] > f->maxfd) f->maxfd = fd[1]; f->fd[fd[0]] = c[0]; f->fd[fd[1]] = c[1]; unlockfgrp(f); return 0; } Chan* fdtochan(int fd, int mode, int chkmnt, int iref) { Chan *c; Fgrp *f; c = 0; f = up->fgrp; lock(&f->ref.lk); if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) { unlock(&f->ref.lk); error(Ebadfd); } if(iref) incref(&c->ref); unlock(&f->ref.lk); if(chkmnt && (c->flag&CMSG)) { if(iref) cclose(c); error(Ebadusefd); } if(mode<0 || c->mode==ORDWR) return c; if((mode&OTRUNC) && c->mode==OREAD) { if(iref) cclose(c); error(Ebadusefd); } if((mode&~OTRUNC) != c->mode) { if(iref) cclose(c); error(Ebadusefd); } return c; } int openmode(ulong o) { o &= ~(OTRUNC|OCEXEC|ORCLOSE); if(o > OEXEC) error(Ebadarg); if(o == OEXEC) return OREAD; return o; } long _sysfd2path(int fd, char *buf, uint nbuf) { Chan *c; c = fdtochan(fd, -1, 0, 1); if(c->name == nil) snprint(buf, nbuf, ""); else snprint(buf, nbuf, "%s", c->name->s); cclose(c); return 0; } long _syspipe(int fd[2]) { Chan *c[2]; Dev *d; static char *datastr[] = {"data", "data1"}; d = devtab[devno('|', 0)]; c[0] = namec("#|", Atodir, 0, 0); c[1] = 0; fd[0] = -1; fd[1] = -1; if(waserror()){ cclose(c[0]); if(c[1]) cclose(c[1]); nexterror(); } c[1] = cclone(c[0]); if(walk(&c[0], datastr+0, 1, 1, nil) < 0) error(Egreg); if(walk(&c[1], datastr+1, 1, 1, nil) < 0) error(Egreg); c[0] = d->open(c[0], ORDWR); c[1] = d->open(c[1], ORDWR); if(newfd2(fd, c) < 0) error(Enofd); poperror(); return 0; } long _sysdup(int fd0, int fd1) { int fd; Chan *c, *oc; Fgrp *f = up->fgrp; /* * Close after dup'ing, so date > #d/1 works */ c = fdtochan(fd0, -1, 0, 1); fd = fd1; if(fd != -1){ lock(&f->ref.lk); if(fd<0 || growfd(f, fd)<0) { unlockfgrp(f); cclose(c); error(Ebadfd); } if(fd > f->maxfd) f->maxfd = fd; oc = f->fd[fd]; f->fd[fd] = c; unlockfgrp(f); if(oc) cclose(oc); }else{ if(waserror()) { cclose(c); nexterror(); } fd = newfd(c); if(fd < 0) error(Enofd); poperror(); } return fd; } long _sysopen(char *name, int mode) { int fd; Chan *c = 0; openmode(mode); /* error check only */ if(waserror()){ if(c) cclose(c); nexterror(); } c = namec(name, Aopen, mode, 0); fd = newfd(c); if(fd < 0) error(Enofd); poperror(); return fd; } void fdclose(int fd, int flag) { int i; Chan *c; Fgrp *f = up->fgrp; lock(&f->ref.lk); c = f->fd[fd]; if(c == 0){ /* can happen for users with shared fd tables */ unlock(&f->ref.lk); return; } if(flag){ if(c==0 || !(c->flag&flag)){ unlock(&f->ref.lk); return; } } f->fd[fd] = 0; if(fd == f->maxfd) for(i=fd; --i>=0 && f->fd[i]==0; ) f->maxfd = i; unlock(&f->ref.lk); cclose(c); } long _sysclose(int fd) { fdtochan(fd, -1, 0, 0); fdclose(fd, 0); return 0; } long unionread(Chan *c, void *va, long n) { int i; long nr; Mhead *m; Mount *mount; qlock(&c->umqlock); m = c->umh; rlock(&m->lock); mount = m->mount; /* bring mount in sync with c->uri and c->umc */ for(i = 0; mount != nil && i < c->uri; i++) mount = mount->next; nr = 0; while(mount != nil) { /* Error causes component of union to be skipped */ if(mount->to && !waserror()) { if(c->umc == nil){ c->umc = cclone(mount->to); c->umc = devtab[c->umc->type]->open(c->umc, OREAD); } nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset); c->umc->offset += nr; poperror(); } if(nr > 0) break; /* Advance to next element */ c->uri++; if(c->umc) { cclose(c->umc); c->umc = nil; } mount = mount->next; } runlock(&m->lock); qunlock(&c->umqlock); return nr; } static long kread(int fd, void *buf, long n, vlong *offp) { int dir; Chan *c; vlong off; c = fdtochan(fd, OREAD, 1, 1); if(waserror()) { cclose(c); nexterror(); } dir = c->qid.type&QTDIR; /* * The offset is passed through on directories, normally. sysseek complains but * pread is used by servers and e.g. exportfs that shouldn't need to worry about this issue. */ if(offp == nil) /* use and maintain channel's offset */ off = c->offset; else off = *offp; if(off < 0) error(Enegoff); if(dir && c->umh) n = unionread(c, buf, n); else n = devtab[c->type]->read(c, buf, n, off); if(offp == nil){ lock(&c->ref.lk); c->offset += n; unlock(&c->ref.lk); } poperror(); cclose(c); return n; } /* name conflicts with netbsd long _sys_read(int fd, void *buf, long n) { return kread(fd, buf, n, nil); } */ long _syspread(int fd, void *buf, long n, vlong off) { if(off == ((uvlong) ~0)) return kread(fd, buf, n, nil); return kread(fd, buf, n, &off); } static long kwrite(int fd, void *buf, long nn, vlong *offp) { Chan *c; long m, n; vlong off; n = 0; c = fdtochan(fd, OWRITE, 1, 1); if(waserror()) { if(offp == nil){ lock(&c->ref.lk); c->offset -= n; unlock(&c->ref.lk); } cclose(c); nexterror(); } if(c->qid.type & QTDIR) error(Eisdir); n = nn; if(offp == nil){ /* use and maintain channel's offset */ lock(&c->ref.lk); off = c->offset; c->offset += n; unlock(&c->ref.lk); }else off = *offp; if(off < 0) error(Enegoff); m = devtab[c->type]->write(c, buf, n, off); if(offp == nil && m < n){ lock(&c->ref.lk); c->offset -= n - m; unlock(&c->ref.lk); } poperror(); cclose(c); return m; } long sys_write(int fd, void *buf, long n) { return kwrite(fd, buf, n, nil); } long _syspwrite(int fd, void *buf, long n, vlong off) { if(off == ((uvlong) ~0)) return kwrite(fd, buf, n, nil); return kwrite(fd, buf, n, &off); } static vlong _sysseek(int fd, vlong off, int whence) { Chan *c; uchar buf[sizeof(Dir)+100]; Dir dir; int n; c = fdtochan(fd, -1, 1, 1); if(waserror()){ cclose(c); nexterror(); } if(devtab[c->type]->dc == '|') error(Eisstream); switch(whence){ case 0: if((c->qid.type & QTDIR) && off != 0) error(Eisdir); if(off < 0) error(Enegoff); c->offset = off; break; case 1: if(c->qid.type & QTDIR) error(Eisdir); lock(&c->ref.lk); /* lock for read/write update */ off = off + c->offset; if(off < 0) error(Enegoff); c->offset = off; unlock(&c->ref.lk); break; case 2: if(c->qid.type & QTDIR) error(Eisdir); n = devtab[c->type]->stat(c, buf, sizeof buf); if(convM2D(buf, n, &dir, nil) == 0) error("internal error: stat error in seek"); off = dir.length + off; if(off < 0) error(Enegoff); c->offset = off; break; default: error(Ebadarg); } c->uri = 0; c->dri = 0; cclose(c); poperror(); return off; } void validstat(uchar *s, int n) { int m; char buf[64]; if(statcheck(s, n) < 0) error(Ebadstat); /* verify that name entry is acceptable */ s += STATFIXLEN - 4*BIT16SZ; /* location of first string */ /* * s now points at count for first string. * if it's too long, let the server decide; this is * only for his protection anyway. otherwise * we'd have to allocate and waserror. */ m = GBIT16(s); s += BIT16SZ; if(m+1 > sizeof buf) return; memmove(buf, s, m); buf[m] = '\0'; /* name could be '/' */ if(strcmp(buf, "/") != 0) validname(buf, 0); } long _sysfstat(int fd, void *buf, long n) { Chan *c; uint l; l = n; validaddr(buf, l, 1); c = fdtochan(fd, -1, 0, 1); if(waserror()) { cclose(c); nexterror(); } l = devtab[c->type]->stat(c, buf, l); poperror(); cclose(c); return l; } long _sysstat(char *name, void *buf, long n) { Chan *c; uint l; l = n; validaddr(buf, l, 1); validaddr(name, 1, 0); c = namec(name, Aaccess, 0, 0); if(waserror()){ cclose(c); nexterror(); } l = devtab[c->type]->stat(c, buf, l); poperror(); cclose(c); return l; } long _syschdir(char *name) { Chan *c; validaddr(name, 1, 0); c = namec(name, Atodir, 0, 0); cclose(up->dot); up->dot = c; return 0; } long bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec) { int ret; Chan *c0, *c1, *ac, *bc; struct{ Chan *chan; Chan *authchan; char *spec; int flags; }bogus; if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER)) error(Ebadarg); bogus.flags = flag & MCACHE; if(ismount){ if(up->pgrp->noattach) error(Enoattach); ac = nil; bc = fdtochan(fd, ORDWR, 0, 1); if(waserror()) { if(ac) cclose(ac); cclose(bc); nexterror(); } if(afd >= 0) ac = fdtochan(afd, ORDWR, 0, 1); bogus.chan = bc; bogus.authchan = ac; validaddr((ulong)spec, 1, 0); bogus.spec = spec; if(waserror()) error(Ebadspec); validname(spec, 1); poperror(); ret = devno('M', 0); c0 = devtab[ret]->attach((char*)&bogus); poperror(); if(ac) cclose(ac); cclose(bc); }else{ bogus.spec = 0; validaddr((ulong)arg0, 1, 0); c0 = namec(arg0, Abind, 0, 0); } if(waserror()){ cclose(c0); nexterror(); } validaddr((ulong)arg1, 1, 0); c1 = namec(arg1, Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } ret = cmount(&c0, c1, flag, bogus.spec); poperror(); cclose(c1); poperror(); cclose(c0); if(ismount) fdclose(fd, 0); return ret; } long _sysbind(char *old, char *new, int flag) { return bindmount(0, -1, -1, old, new, flag, nil); } long _sysmount(int fd, int afd, char *new, int flag, char *spec) { return bindmount(1, fd, afd, nil, new, flag, spec); } long _sysunmount(char *old, char *new) { Chan *cmount, *cmounted; cmounted = 0; cmount = namec(new, Amount, 0, 0); if(old) { if(waserror()) { cclose(cmount); nexterror(); } validaddr(old, 1, 0); /* * This has to be namec(..., Aopen, ...) because * if arg[0] is something like /srv/cs or /fd/0, * opening it is the only way to get at the real * Chan underneath. */ cmounted = namec(old, Aopen, OREAD, 0); poperror(); } if(waserror()) { cclose(cmount); if(cmounted) cclose(cmounted); nexterror(); } cunmount(cmount, cmounted); cclose(cmount); if(cmounted) cclose(cmounted); poperror(); return 0; } long _syscreate(char *name, int mode, ulong perm) { int fd; Chan *c = 0; openmode(mode&~OEXCL); /* error check only; OEXCL okay here */ if(waserror()) { if(c) cclose(c); nexterror(); } validaddr(name, 1, 0); c = namec(name, Acreate, mode, perm); fd = newfd(c); if(fd < 0) error(Enofd); poperror(); return fd; } long _sysremove(char *name) { Chan *c; c = namec(name, Aremove, 0, 0); if(waserror()){ c->type = 0; /* see below */ cclose(c); nexterror(); } devtab[c->type]->remove(c); /* * Remove clunks the fid, but we need to recover the Chan * so fake it up. rootclose() is known to be a nop. */ c->type = 0; poperror(); cclose(c); return 0; } long _syswstat(char *name, void *buf, long n) { Chan *c; uint l; l = n; validstat(buf, l); validaddr(name, 1, 0); c = namec(name, Aaccess, 0, 0); if(waserror()){ cclose(c); nexterror(); } l = devtab[c->type]->wstat(c, buf, l); poperror(); cclose(c); return l; } long _sysfwstat(int fd, void *buf, long n) { Chan *c; uint l; l = n; validaddr(buf, l, 0); validstat(buf, l); c = fdtochan(fd, -1, 1, 1); if(waserror()) { cclose(c); nexterror(); } l = devtab[c->type]->wstat(c, buf, l); poperror(); cclose(c); return l; } static void starterror(void) { assert(up->nerrlab == 0); } static void _syserror(void) { char *p; p = up->syserrstr; up->syserrstr = up->errstr; up->errstr = p; } static void enderror(void) { assert(up->nerrlab == 1); poperror(); } int sysbind(char *old, char *new, int flag) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _sysbind(old, new, flag); enderror(); return n; } int syschdir(char *path) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _syschdir(path); enderror(); return n; } int sysclose(int fd) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _sysclose(fd); enderror(); return n; } int syscreate(char *name, int mode, ulong perm) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _syscreate(name, mode, perm); enderror(); return n; } int sysdup(int fd0, int fd1) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _sysdup(fd0, fd1); enderror(); return n; } int sysfstat(int fd, uchar *buf, int n) { starterror(); if(waserror()){ _syserror(); return -1; } n = _sysfstat(fd, buf, n); enderror(); return n; } int sysfwstat(int fd, uchar *buf, int n) { starterror(); if(waserror()){ _syserror(); return -1; } n = _sysfwstat(fd, buf, n); enderror(); return n; } int sysmount(int fd, int afd, char *new, int flag, char *spec) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _sysmount(fd, afd, new, flag, spec); enderror(); return n; } int sysunmount(char *old, char *new) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _sysunmount(old, new); enderror(); return n; } int sysopen(char *name, int mode) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _sysopen(name, mode); enderror(); return n; } int syspipe(int *fd) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _syspipe(fd); enderror(); return n; } long syspread(int fd, void *buf, long n, vlong off) { starterror(); if(waserror()){ _syserror(); return -1; } n = _syspread(fd, buf, n, off); enderror(); return n; } long syspwrite(int fd, void *buf, long n, vlong off) { starterror(); if(waserror()){ _syserror(); return -1; } n = _syspwrite(fd, buf, n, off); enderror(); return n; } long sysread(int fd, void *buf, long n) { starterror(); if(waserror()){ _syserror(); return -1; } n = _syspread(fd, buf, n, (uvlong) ~0); enderror(); return n; } int sysremove(char *path) { int n; starterror(); if(waserror()){ _syserror(); return -1; } n = _sysremove(path); enderror(); return n; } vlong sysseek(int fd, vlong off, int whence) { starterror(); if(waserror()){ _syserror(); return -1; } off = _sysseek(fd, off, whence); enderror(); return off; } int sysstat(char *name, uchar *buf, int n) { starterror(); if(waserror()){ _syserror(); return -1; } n = _sysstat(name, buf, n); enderror(); return n; } long syswrite(int fd, void *buf, long n) { starterror(); if(waserror()){ _syserror(); return -1; } n = _syspwrite(fd, buf, n, (uvlong) ~0); enderror(); return n; } int syswstat(char *name, uchar *buf, int n) { starterror(); if(waserror()){ _syserror(); return -1; } n = _syswstat(name, buf, n); enderror(); return n; } void werrstr(char *f, ...) { char buf[ERRMAX]; va_list arg; va_start(arg, f); vsnprint(buf, sizeof buf, f, arg); va_end(arg); if(up->nerrlab) strecpy(up->errstr, up->errstr+ERRMAX, buf); else strecpy(up->syserrstr, up->syserrstr+ERRMAX, buf); } int __errfmt(Fmt *fmt) { if(up->nerrlab) return fmtstrcpy(fmt, up->errstr); else return fmtstrcpy(fmt, up->syserrstr); } int errstr(char *buf, uint n) { char tmp[ERRMAX]; char *p; p = up->nerrlab ? up->errstr : up->syserrstr; memmove(tmp, p, ERRMAX); utfecpy(p, p+ERRMAX, buf); utfecpy(buf, buf+n, tmp); return strlen(buf); } int rerrstr(char *buf, uint n) { char *p; p = up->nerrlab ? up->errstr : up->syserrstr; utfecpy(buf, buf+n, p); return strlen(buf); } void* _sysrendezvous(void* arg0, void* arg1) { void *tag, *val; Proc *p, **l; tag = arg0; l = &REND(up->rgrp, (uintptr)tag); up->rendval = (void*)~0; lock(&up->rgrp->ref.lk); for(p = *l; p; p = p->rendhash) { if(p->rendtag == tag) { *l = p->rendhash; val = p->rendval; p->rendval = arg1; while(p->mach != 0) ; procwakeup(p); unlock(&up->rgrp->ref.lk); return val; } l = &p->rendhash; } /* Going to sleep here */ up->rendtag = tag; up->rendval = arg1; up->rendhash = *l; *l = up; up->state = Rendezvous; unlock(&up->rgrp->ref.lk); procsleep(); return up->rendval; } void* sysrendezvous(void *tag, void *val) { void *n; starterror(); if(waserror()){ _syserror(); return (void*)~0; } n = _sysrendezvous(tag, val); enderror(); return n; } drawterm-20110822.orig/kern/parse.c0000644000175000017500000000371111245145712016312 0ustar tinchotincho#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" /* * Generous estimate of number of fields, including terminal nil pointer */ static int ncmdfield(char *p, int n) { int white, nwhite; char *ep; int nf; if(p == nil) return 1; nf = 0; ep = p+n; white = 1; /* first text will start field */ while(p < ep){ nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */ if(white && !nwhite) /* beginning of field */ nf++; white = nwhite; } return nf+1; /* +1 for nil */ } /* * parse a command written to a device */ Cmdbuf* parsecmd(char *p, int n) { Cmdbuf *volatile cb; int nf; char *sp; nf = ncmdfield(p, n); /* allocate Cmdbuf plus string pointers plus copy of string including \0 */ sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1); cb = (Cmdbuf*)sp; cb->f = (char**)(&cb[1]); cb->buf = (char*)(&cb->f[nf]); if(up!=nil && waserror()){ free(cb); nexterror(); } memmove(cb->buf, p, n); if(up != nil) poperror(); /* dump new line and null terminate */ if(n > 0 && cb->buf[n-1] == '\n') n--; cb->buf[n] = '\0'; cb->nf = tokenize(cb->buf, cb->f, nf-1); cb->f[cb->nf] = nil; return cb; } /* * Reconstruct original message, for error diagnostic */ void cmderror(Cmdbuf *cb, char *s) { int i; char *p, *e; p = up->genbuf; e = p+ERRMAX-10; p = seprint(p, e, "%s \"", s); for(i=0; inf; i++){ if(i > 0) p = seprint(p, e, " "); p = seprint(p, e, "%q", cb->f[i]); } strcpy(p, "\""); error(up->genbuf); } /* * Look up entry in table */ Cmdtab* lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) { int i; Cmdtab *ct; if(cb->nf == 0) error("empty control message"); for(ct = ctab, i=0; icmd, "*") !=0) /* wildcard always matches */ if(strcmp(ct->cmd, cb->f[0]) != 0) continue; if(ct->narg != 0 && ct->narg != cb->nf) cmderror(cb, Ecmdargs); return ct; } cmderror(cb, "unknown control message"); return nil; } drawterm-20110822.orig/kern/fns.h0000644000175000017500000002501611245145712015775 0ustar tinchotincho#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) void accounttime(void); void addclock0link(void (*)(void), int); int addphysseg(Physseg*); void addbootfile(char*, uchar*, ulong); Block* adjustblock(Block*, int); void alarmkproc(void*); Block* allocb(int); int anyhigher(void); int anyready(void); Page* auxpage(void); Block* bl2mem(uchar*, Block*, int); int blocklen(Block*); void callwithureg(void(*)(Ureg*)); char* c2name(Chan*); int cangetc(void*); int canlock(Lock*); int canpage(Proc*); int canputc(void*); int canqlock(QLock*); int canrlock(RWlock*); void chandevinit(void); void chandevreset(void); void chandevshutdown(void); void chanfree(Chan*); void chanrec(Mnt*); void checkalarms(void); void checkb(Block*, char*); void cinit(void); Chan* cclone(Chan*); void cclose(Chan*); char* clipread(void); int clipwrite(char*); void closeegrp(Egrp*); void closefgrp(Fgrp*); void closemount(Mount*); void closepgrp(Pgrp*); void closergrp(Rgrp*); long clrfpintr(void); void cmderror(Cmdbuf*, char*); int cmount(Chan**, Chan*, int, char*); void cnameclose(Cname*); void confinit(void); void confinit1(int); int consactive(void); extern void (*consdebug)(void); void copen(Chan*); Block* concatblock(Block*); Block* copyblock(Block*, int); void copypage(Page*, Page*); int cread(Chan*, uchar*, int, vlong); void cunmount(Chan*, Chan*); void cupdate(Chan*, uchar*, int, vlong); void cwrite(Chan*, uchar*, int, vlong); ulong dbgpc(Proc*); int decref(Ref*); int decrypt(void*, void*, int); void delay(int); Chan* devattach(int, char*); Block* devbread(Chan*, long, ulong); long devbwrite(Chan*, Block*, ulong); Chan* devclone(Chan*); int devconfig(int, char *, DevConf *); void devcreate(Chan*, char*, int, ulong); void devdir(Chan*, Qid, char*, vlong, char*, long, Dir*); long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*); Devgen devgen; void devinit(void); int devno(int, int); Chan* devopen(Chan*, int, Dirtab*, int, Devgen*); void devpermcheck(char*, ulong, int); void devpower(int); void devremove(Chan*); void devreset(void); void devshutdown(void); int devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*); Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*); int devwstat(Chan*, uchar*, int); void drawactive(int); void drawcmap(void); int drawcanqlock(void); void drawqlock(void); void drawqunlock(void); void dumpaproc(Proc*); void dumpqueues(void); void dumpregs(Ureg*); void dumpstack(void); Fgrp* dupfgrp(Fgrp*); void duppage(Page*); void dupswap(Page*); int emptystr(char*); int encrypt(void*, void*, int); void envcpy(Egrp*, Egrp*); int eqchan(Chan*, Chan*, int); int eqqid(Qid, Qid); void error(char*); long execregs(ulong, ulong, ulong); void exhausted(char*); void exit(int); uvlong fastticks(uvlong*); int fault(ulong, int); void fdclose(int, int); Chan* fdtochan(int, int, int, int); int fixfault(Segment*, ulong, int, int); void flushmmu(void); void forkchild(Proc*, Ureg*); void forkret(void); void free(void*); void freeb(Block*); void freeblist(Block*); int freebroken(void); void freepte(Segment*, Pte*); void freesegs(int); void freesession(Session*); ulong getmalloctag(void*); ulong getrealloctag(void*); void gotolabel(Label*); char* getconfenv(void); int haswaitq(void*); long hostdomainwrite(char*, int); long hostownerwrite(char*, int); void hzsched(void); void iallocinit(void); Block* iallocb(int); void iallocsummary(void); long ibrk(ulong, int); void ilock(Lock*); void iunlock(Lock*); int incref(Ref*); void initseg(void); int iprint(char*, ...); void isdir(Chan*); int iseve(void); #define islo() (0) Segment* isoverlap(Proc*, ulong, int); int ispages(void*); int isphysseg(char*); void ixsummary(void); void kbdclock(void); int kbdcr2nl(Queue*, int); int kbdputc(Queue*, int); void kbdrepeat(int); long keyread(char*, int, long); void kickpager(void); void killbig(void); int kproc(char*, void(*)(void*), void*); void kprocchild(Proc*, void (*)(void*), void*); extern void (*kproftimer)(ulong); void ksetenv(char*, char*, int); void kstrcpy(char*, char*, int); void kstrdup(char**, char*); long latin1(Rune*, int); void lock(Lock*); void lockinit(void); void logopen(Log*); void logclose(Log*); char* logctl(Log*, int, char**, Logflag*); void logn(Log*, int, void*, int); long logread(Log*, void*, ulong, long); void log(Log*, int, char*, ...); Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int); void machinit(void); void* mallocz(ulong, int); #define malloc kmalloc void* malloc(ulong); void mallocsummary(void); Block* mem2bl(uchar*, int); void mfreeseg(Segment*, ulong, int); void microdelay(int); void mkqid(Qid*, vlong, ulong, int); void mmurelease(Proc*); void mmuswitch(Proc*); Chan* mntauth(Chan*, char*); void mntdump(void); long mntversion(Chan*, char*, int, int); void mountfree(Mount*); ulong ms2tk(ulong); ulong msize(void*); ulong ms2tk(ulong); uvlong ms2fastticks(ulong); void muxclose(Mnt*); Chan* namec(char*, int, int, ulong); Chan* newchan(void); int newfd(Chan*); Mhead* newmhead(Chan*); Mount* newmount(Mhead*, Chan*, int, char*); Page* newpage(int, Segment **, ulong); Pgrp* newpgrp(void); Rgrp* newrgrp(void); Proc* newproc(void); char* nextelem(char*, char*); void nexterror(void); Cname* newcname(char*); int notify(Ureg*); int nrand(int); int okaddr(ulong, ulong, int); int openmode(ulong); void oserrstr(void); void oserror(void); Block* packblock(Block*); Block* padblock(Block*, int); void pagechainhead(Page*); void pageinit(void); void pagersummary(void); void panic(char*, ...); Cmdbuf* parsecmd(char *a, int n); ulong perfticks(void); void pexit(char*, int); int preempted(void); void printinit(void); int procindex(ulong); void pgrpcpy(Pgrp*, Pgrp*); void pgrpnote(ulong, char*, long, int); Pgrp* pgrptab(int); void pio(Segment *, ulong, ulong, Page **); #define poperror() up->nerrlab-- void portclock(Ureg*); int postnote(Proc*, int, char*, int); int pprint(char*, ...); void prflush(void); ulong procalarm(ulong); int proccounter(char *name); void procctl(Proc*); void procdump(void); int procfdprint(Chan*, int, int, char*, int); void procinit0(void); void procflushseg(Segment*); void procpriority(Proc*, int, int); Proc* proctab(int); void procwired(Proc*, int); Pte* ptealloc(void); Pte* ptecpy(Pte*); int pullblock(Block**, int); Block* pullupblock(Block*, int); Block* pullupqueue(Queue*, int); void putmhead(Mhead*); void putmmu(ulong, ulong, Page*); void putpage(Page*); void putseg(Segment*); void putstr(char*); void putstrn(char*, int); void putswap(Page*); ulong pwait(Waitmsg*); Label* pwaserror(void); void qaddlist(Queue*, Block*); Block* qbread(Queue*, int); long qbwrite(Queue*, Block*); Queue* qbypass(void (*)(void*, Block*), void*); int qcanread(Queue*); void qclose(Queue*); int qconsume(Queue*, void*, int); Block* qcopy(Queue*, int, ulong); int qdiscard(Queue*, int); void qflush(Queue*); void qfree(Queue*); int qfull(Queue*); Block* qget(Queue*); void qhangup(Queue*, char*); int qisclosed(Queue*); void qinit(void); int qiwrite(Queue*, void*, int); int qlen(Queue*); void qlock(QLock*); Queue* qopen(int, int, void (*)(void*), void*); int qpass(Queue*, Block*); int qpassnolim(Queue*, Block*); int qproduce(Queue*, void*, int); void qputback(Queue*, Block*); long qread(Queue*, void*, int); Block* qremove(Queue*); void qreopen(Queue*); void qsetlimit(Queue*, int); void qunlock(QLock*); int qwindow(Queue*); int qwrite(Queue*, void*, int); void qnoblock(Queue*, int); int rand(void); void randominit(void); ulong randomread(void*, ulong); void rdb(void); int readnum(ulong, char*, ulong, ulong, int); int readstr(ulong, char*, ulong, char*); void ready(Proc*); void rebootcmd(int, char**); void reboot(void*, void*, ulong); void relocateseg(Segment*, ulong); void renameuser(char*, char*); void resched(char*); void resrcwait(char*); int return0(void*); void rlock(RWlock*); long rtctime(void); void runlock(RWlock*); Proc* runproc(void); void savefpregs(FPsave*); extern void (*saveintrts)(void); void sched(void); void scheddump(void); void schedinit(void); extern void (*screenputs)(char*, int); long seconds(void); ulong segattach(Proc*, ulong, char *, ulong, ulong); void segclock(ulong); void segpage(Segment*, Page*); void setkernur(Ureg*, Proc*); int setlabel(Label*); void setmalloctag(void*, uintptr); void setrealloctag(void*, ulong); void setregisters(Ureg*, char*, char*, int); void setswapchan(Chan*); long showfilewrite(char*, int); char* skipslash(char*); void sleep(Rendez*, int(*)(void*), void*); void* smalloc(ulong); int splhi(void); int spllo(void); void splx(int); void splxpc(int); char* srvname(Chan*); int swapcount(ulong); int swapfull(void); void swapinit(void); void timeradd(Timer*); void timerdel(Timer*); void timersinit(void); void timerintr(Ureg*, uvlong); void timerset(uvlong); ulong tk2ms(ulong); #define TK2MS(x) ((x)*(1000/HZ)) vlong todget(vlong*); void todfix(void); void todsetfreq(vlong); void todinit(void); void todset(vlong, vlong, int); Block* trimblock(Block*, int, int); void tsleep(Rendez*, int (*)(void*), void*, int); int uartctl(Uart*, char*); int uartgetc(void); void uartkick(void*); void uartmouse(Uart*, int (*)(Queue*, int), int); void uartputc(int); void uartputs(char*, int); void uartrecv(Uart*, char); Uart* uartsetup(Uart*); int uartstageoutput(Uart*); void unbreak(Proc*); void uncachepage(Page*); long unionread(Chan*, void*, long); void unlock(Lock*); Proc** uploc(void); void userinit(void); ulong userpc(void); long userwrite(char*, int); #define validaddr(a, b, c) void validname(char*, int); void validstat(uchar*, int); void vcacheinval(Page*, ulong); void* vmemchr(void*, int, int); Proc* wakeup(Rendez*); int walk(Chan**, char**, int, int, int*); #define waserror() (setjmp(pwaserror()->buf)) void wlock(RWlock*); void wunlock(RWlock*); void* xalloc(ulong); void* xallocz(ulong, int); void xfree(void*); void xhole(ulong, ulong); void xinit(void); int xmerge(void*, void*); void* xspanalloc(ulong, int, ulong); void xsummary(void); void yield(void); Segment* data2txt(Segment*); Segment* dupseg(Segment**, int, int); Segment* newseg(int, ulong, ulong); Segment* seg(Proc*, ulong, int); void hnputv(void*, vlong); void hnputl(void*, ulong); void hnputs(void*, ushort); vlong nhgetv(void*); ulong nhgetl(void*); ushort nhgets(void*); ulong ticks(void); void osproc(Proc*); void osnewproc(Proc*); void procsleep(void); void procwakeup(Proc*); void osinit(void); void screeninit(void); extern void terminit(void); drawterm-20110822.orig/9ball.rc0000644000175000017500000000004711245145711015424 0ustar tinchotinchoIDI_ICON1 ICON DISCARDABLE "9ball.ico" drawterm-20110822.orig/Make.osx-x110000644000175000017500000000065211245145711016114 0ustar tinchotincho# Mac OS X PTHREAD= # for Mac AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib -lX11 -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \ (cd posix-$$arch && make) drawterm-20110822.orig/args.h0000644000175000017500000000130511245145711015176 0ustar tinchotinchoextern char *argv0; #define ARGBEGIN for((argv0? 0: (argv0=*argv)),argv++,argc--;\ argv[0] && argv[0][0]=='-' && argv[0][1];\ argc--, argv++) {\ char *_args, *_argt;\ Rune _argc;\ _args = &argv[0][1];\ if(_args[0]=='-' && _args[1]==0){\ argc--; argv++; break;\ }\ _argc = 0;\ while(*_args && (_args += chartorune(&_argc, _args)))\ switch(_argc) #define ARGEND SET(_argt);USED(_argt); USED(_argc); USED(_args);}USED(argv); USED(argc); #define ARGF() (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) #define ARGC() _argc #define EARGF(x) (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0))) drawterm-20110822.orig/posix-sun4u/0000755000175000017500000000000011245145712016311 5ustar tinchotinchodrawterm-20110822.orig/posix-sun4u/md5block.c0000644000175000017500000001165011245145712020160 0ustar tinchotincho#include #include #include /* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ /* * Rotate ammounts used in the algorithm */ enum { S11= 7, S12= 12, S13= 17, S14= 22, S21= 5, S22= 9, S23= 14, S24= 20, S31= 4, S32= 11, S33= 16, S34= 23, S41= 6, S42= 10, S43= 15, S44= 21, }; static u32int md5tab[] = { /* round 1 */ /*[0]*/ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, /* round 2 */ /*[16]*/0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, /* round 3 */ /*[32]*/0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, /* round 4 */ /*[48]*/0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static void decode(u32int*, uchar*, ulong); extern void _md5block(uchar *p, ulong len, u32int *s); void _md5block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, sh; u32int *t; uchar *end; u32int x[16]; for(end = p+len; p < end; p += 64){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; decode(x, p, 64); t = md5tab; sh = 0; for(; sh != 16; t += 4){ a += ((c ^ d) & b) ^ d; a += x[sh] + t[0]; a = (a << S11) | (a >> (32 - S11)); a += b; d += ((b ^ c) & a) ^ c; d += x[sh + 1] + t[1]; d = (d << S12) | (d >> (32 - S12)); d += a; c += ((a ^ b) & d) ^ b; c += x[sh + 2] + t[2]; c = (c << S13) | (c >> (32 - S13)); c += d; b += ((d ^ a) & c) ^ a; b += x[sh + 3] + t[3]; b = (b << S14) | (b >> (32 - S14)); b += c; sh += 4; } sh = 1; for(; sh != 1+20*4; t += 4){ a += ((b ^ c) & d) ^ c; a += x[sh & 0xf] + t[0]; a = (a << S21) | (a >> (32 - S21)); a += b; d += ((a ^ b) & c) ^ b; d += x[(sh + 5) & 0xf] + t[1]; d = (d << S22) | (d >> (32 - S22)); d += a; c += ((d ^ a) & b) ^ a; c += x[(sh + 10) & 0xf] + t[2]; c = (c << S23) | (c >> (32 - S23)); c += d; b += ((c ^ d) & a) ^ d; b += x[(sh + 15) & 0xf] + t[3]; b = (b << S24) | (b >> (32 - S24)); b += c; sh += 20; } sh = 5; for(; sh != 5+12*4; t += 4){ a += b ^ c ^ d; a += x[sh & 0xf] + t[0]; a = (a << S31) | (a >> (32 - S31)); a += b; d += a ^ b ^ c; d += x[(sh + 3) & 0xf] + t[1]; d = (d << S32) | (d >> (32 - S32)); d += a; c += d ^ a ^ b; c += x[(sh + 6) & 0xf] + t[2]; c = (c << S33) | (c >> (32 - S33)); c += d; b += c ^ d ^ a; b += x[(sh + 9) & 0xf] + t[3]; b = (b << S34) | (b >> (32 - S34)); b += c; sh += 12; } sh = 0; for(; sh != 28*4; t += 4){ a += c ^ (b | ~d); a += x[sh & 0xf] + t[0]; a = (a << S41) | (a >> (32 - S41)); a += b; d += b ^ (a | ~c); d += x[(sh + 7) & 0xf] + t[1]; d = (d << S42) | (d >> (32 - S42)); d += a; c += a ^ (d | ~b); c += x[(sh + 14) & 0xf] + t[2]; c = (c << S43) | (c >> (32 - S43)); c += d; b += d ^ (c | ~a); b += x[(sh + 21) & 0xf] + t[3]; b = (b << S44) | (b >> (32 - S44)); b += c; sh += 28; } s[0] += a; s[1] += b; s[2] += c; s[3] += d; } } /* * decodes input (uchar) into output (u32int). Assumes len is * a multiple of 4. */ static void decode(u32int *output, uchar *input, ulong len) { uchar *e; for(e = input+len; input < e; input += 4) *output++ = input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24); } drawterm-20110822.orig/posix-sun4u/tas.s0000644000175000017500000000005211245145712017261 0ustar tinchotincho.globl tas tas: retl ldstub [%o0], %o0 drawterm-20110822.orig/posix-sun4u/Makefile0000644000175000017500000000044411245145712017753 0ustar tinchotinchoROOT=.. include ../Make.config LIB=../libmachdep.a OFILES=\ getcallerpc.$O\ md5block.$O\ sha1block.$O\ tas.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c %.$O: %.s $(AS) -o $*.$O $*.s %.s: %.spp cpp $*.spp >$*.s drawterm-20110822.orig/posix-sun4u/sha1block.c0000644000175000017500000001114611245145712020327 0ustar tinchotincho#include #include #include void _sha1block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, e, x; uchar *end; u32int *wp, *wend; u32int w[80]; /* at this point, we have a multiple of 64 bytes */ for(end = p+len; p < end;){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; e = s[4]; wend = w + 15; for(wp = w; wp < wend; wp += 5){ wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); wp[1] = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7]; d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); wp[2] = (p[8]<<24) | (p[9]<<16) | (p[10]<<8) | p[11]; c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); wp[3] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); wp[4] = (p[16]<<24) | (p[17]<<16) | (p[18]<<8) | p[19]; a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); p += 20; } wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); wp += 5; p += 4; wend = w + 40; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x6ed9eba1 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x6ed9eba1 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x6ed9eba1 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x6ed9eba1 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x6ed9eba1 + (c^d^e); c = (c<<30)|(c>>2); } wend = w + 60; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x8f1bbcdc + ((b&c)|((b|c)&d)); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x8f1bbcdc + ((a&b)|((a|b)&c)); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x8f1bbcdc + ((e&a)|((e|a)&b)); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x8f1bbcdc + ((d&e)|((d|e)&a)); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x8f1bbcdc + ((c&d)|((c|d)&e)); c = (c<<30)|(c>>2); } wend = w + 80; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0xca62c1d6 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0xca62c1d6 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0xca62c1d6 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0xca62c1d6 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0xca62c1d6 + (c^d^e); c = (c<<30)|(c>>2); } /* save state */ s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; } } drawterm-20110822.orig/posix-sun4u/getcallerpc.c0000644000175000017500000000013311245145712020737 0ustar tinchotincho#include "u.h" #include "libc.h" ulong getcallerpc(void *a) { return ((ulong*)a)[-1]; } drawterm-20110822.orig/Make.sun0000644000175000017500000000057111245145711015501 0ustar tinchotincho# Sun-specific PTHREAD= AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CC=cc CFLAGS=-xCC -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -g -D_THREAD_SAFE O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib -lX11 -lrt -lpthread -lsocket -lnsl LDFLAGS= TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \ (cd posix-$$arch && make) drawterm-20110822.orig/drawterm.rc0000644000175000017500000000326111245145711016247 0ustar tinchotincho//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON DISCARDABLE "drawterm.ico" #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED drawterm-20110822.orig/latin1.c0000644000175000017500000001717611245145712015443 0ustar tinchotincho#include "u.h" #include "libc.h" /* * The code makes two assumptions: strlen(ld) is 1 or 2; latintab[i].ld can be a * prefix of latintab[j].ld only when j", { 0x21D2, 0x2255, 0x2261, 0x229C, 0x22DC, 0x22DD, }, "V", "=", { 0x21D0, }, "7", "8", { 0x215E, }, "5", "68", { 0x215A, 0x215D, }, "4", "5", { 0x2158, }, "R", "R", { 0x211D, }, "Q", "Q", { 0x211A, }, "P", "P", { 0x2119, }, "C", "CAU", { 0x2102, 0x22C2, 0x22C3, }, "e", "nmsl", { 0x2013, 0x2014, 0x2205, 0x22EF, }, "b", "u0123456789+-=()kqrbnp", { 0x2022, 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x265A, 0x265B, 0x265C, 0x265D, 0x265E, 0x265F, }, "@e", "h", { 0x44D, }, "@\'", "\'", { 0x44A, }, "@s", "hc", { 0x448, 0x449, }, "@c", "h", { 0x447, }, "@t", "s", { 0x446, }, "@k", "h", { 0x445, }, "@z", "h", { 0x436, }, "@y", "euao", { 0x435, 0x44E, 0x44F, 0x451, }, "@E", "Hh", { 0x42D, 0x42D, }, "@S", "HhCc", { 0x428, 0x428, 0x429, 0x429, }, "@C", "Hh", { 0x427, 0x427, }, "@T", "Ss", { 0x426, 0x426, }, "@K", "Hh", { 0x425, 0x425, }, "@Z", "Hh", { 0x416, 0x416, }, "@@", "EZKSTYezksty\'", { 0x415, 0x417, 0x41A, 0x421, 0x422, 0x42B, 0x435, 0x437, 0x43A, 0x441, 0x442, 0x44B, 0x44C, }, "@Y", "OoEeUuAa", { 0x401, 0x401, 0x415, 0x415, 0x42E, 0x42E, 0x42F, 0x42F, }, "@", "ABVGDIJLMNOPRUFXabvgdijlmnoprufx", { 0x410, 0x411, 0x412, 0x413, 0x414, 0x418, 0x419, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x423, 0x424, 0x425, 0x430, 0x431, 0x432, 0x433, 0x434, 0x438, 0x439, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x443, 0x444, 0x445, }, "*", "ABGDEZYHIKLMNCOPRSTUFXQWabgdezyhiklmncoprstufxqw*", { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x2217, }, "G", "-", { 0x1E4, }, "N", "JjN", { 0x1CA, 0x1CB, 0x2115, }, "2", "-35", { 0x1BB, 0x2154, 0x2156, }, "z", "-", { 0x1B6, }, "Z", "-Z", { 0x1B5, 0x2124, }, "Y", "R", { 0x1A6, }, "h", "v-", { 0x195, 0x210F, }, "$*", "hfk", { 0x3D1, 0x3D5, 0x3F0, }, "$", "fVavgHILlpRBeEFMo", { 0x192, 0x1B2, 0x251, 0x28B, 0x210A, 0x210B, 0x2110, 0x2112, 0x2113, 0x2118, 0x211B, 0x212C, 0x212F, 0x2130, 0x2131, 0x2133, 0x2134, }, "t", "-smefu", { 0x167, 0x3C2, 0x2122, 0x2203, 0x2234, 0x22A2, }, "T", "-u", { 0x166, 0x22A8, }, "L", "-Jj&|", { 0x141, 0x1C7, 0x1C8, 0x22C0, 0x22C1, }, "i", "j-fsbp", { 0x133, 0x268, 0x221E, 0x222B, 0x2286, 0x2287, }, "I", "J-", { 0x132, 0x197, }, "H", "-H", { 0x126, 0x210D, }, "v\"", "Uu", { 0x1D9, 0x1DA, }, "v", "CcDdEeLlNnRrSsTtZzAaIiOoUuGgKkj", { 0x10C, 0x10D, 0x10E, 0x10F, 0x11A, 0x11B, 0x13D, 0x13E, 0x147, 0x148, 0x158, 0x159, 0x160, 0x161, 0x164, 0x165, 0x17D, 0x17E, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1F0, }, "u", "AEeGgIiOoUu-a", { 0x102, 0x114, 0x115, 0x11E, 0x11F, 0x12C, 0x12D, 0x14E, 0x14F, 0x16C, 0x16D, 0x289, 0x2191, }, ":", "-=()", { 0xF7, 0x2254, 0x2639, 0x263A, }, "a", "ebn", { 0xE6, 0x2194, 0x2220, }, "/", "Oo", { 0xD8, 0xF8, }, "Dv", "Zz", { 0x1C4, 0x1C5, }, "D", "-e", { 0xD0, 0x2206, }, "A", "E", { 0xC6, }, "o", "AaeUuiO", { 0xC5, 0xE5, 0x153, 0x16E, 0x16F, 0x1A3, 0x229A, }, "~!", "=", { 0x2246, }, "~", "ANOanoIiUu-=~", { 0xC3, 0xD1, 0xD5, 0xE3, 0xF1, 0xF5, 0x128, 0x129, 0x168, 0x169, 0x2243, 0x2245, 0x2248, }, "^", "AEIOUaeiouCcGgHhJjSsWwYy", { 0xC2, 0xCA, 0xCE, 0xD4, 0xDB, 0xE2, 0xEA, 0xEE, 0xF4, 0xFB, 0x108, 0x109, 0x11C, 0x11D, 0x124, 0x125, 0x134, 0x135, 0x15C, 0x15D, 0x174, 0x175, 0x176, 0x177, }, "`\"", "Uu", { 0x1DB, 0x1DC, }, "`", "AEIOUaeiou", { 0xC0, 0xC8, 0xCC, 0xD2, 0xD9, 0xE0, 0xE8, 0xEC, 0xF2, 0xF9, }, "?", "?!", { 0xBF, 0x203D, }, "3", "458", { 0xBE, 0x2157, 0x215C, }, "1", "423568", { 0xBC, 0xBD, 0x2153, 0x2155, 0x2159, 0x215B, }, ">!", "=~", { 0x2269, 0x22E7, }, ">", ">=~<", { 0xBB, 0x2265, 0x2273, 0x2277, }, ",", ",CcAaEeGgIiKkLlNnRrSsTtUuOo", { 0xB8, 0xC7, 0xE7, 0x104, 0x105, 0x118, 0x119, 0x122, 0x123, 0x12E, 0x12F, 0x136, 0x137, 0x13B, 0x13C, 0x145, 0x146, 0x156, 0x157, 0x15E, 0x15F, 0x162, 0x163, 0x172, 0x173, 0x1EA, 0x1EB, }, ".", ".CcEeGgILlZzO", { 0xB7, 0x10A, 0x10B, 0x116, 0x117, 0x120, 0x121, 0x130, 0x13F, 0x140, 0x17B, 0x17C, 0x2299, }, "p", "gOdrt", { 0xB6, 0x2117, 0x2202, 0x220F, 0x221D, }, "m", "iuo", { 0xB5, 0xD7, 0x2208, }, "\'\"", "Uu", { 0x1D7, 0x1D8, }, "\'", "\'AEIOUYaeiouyCcgLlNnRrSsZz", { 0xB4, 0xC1, 0xC9, 0xCD, 0xD3, 0xDA, 0xDD, 0xE1, 0xE9, 0xED, 0xF3, 0xFA, 0xFD, 0x106, 0x107, 0x123, 0x139, 0x13A, 0x143, 0x144, 0x154, 0x155, 0x15A, 0x15B, 0x179, 0x17A, }, "+", "-O", { 0xB1, 0x2295, }, "dv", "z", { 0x1C6, }, "d", "e-zgda", { 0xB0, 0xF0, 0x2A3, 0x2020, 0x2021, 0x2193, }, "_,", "Oo", { 0x1EC, 0x1ED, }, "_.", "Aa", { 0x1E0, 0x1E1, }, "_\"", "UuAa", { 0x1D5, 0x1D6, 0x1DE, 0x1DF, }, "_", "_AaEeIiOoUu", { 0xAF, 0x100, 0x101, 0x112, 0x113, 0x12A, 0x12B, 0x14C, 0x14D, 0x16A, 0x16B, }, "r", "O\'\"", { 0xAE, 0x2019, 0x201D, }, "-*", "l", { 0x19B, }, "-", "-Dd:HLlTtbIZz2Ggiuh>+~O", { 0xAD, 0xD0, 0xF0, 0xF7, 0x126, 0x141, 0x142, 0x166, 0x167, 0x180, 0x197, 0x1B5, 0x1B6, 0x1BB, 0x1E4, 0x1E5, 0x268, 0x289, 0x210F, 0x2192, 0x2213, 0x2242, 0x2296, }, "n", "oj", { 0xAC, 0x1CC, }, "", { 0xAB, 0x2190, 0x2264, 0x2272, 0x2276, }, "s", "a231os0456789+-=()nturbp", { 0xAA, 0xB2, 0xB3, 0xB9, 0xBA, 0xDF, 0x2070, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, 0x220D, 0x2211, 0x221A, 0x2282, 0x2283, }, "O", "crEIp+-x/.o*=", { 0xA9, 0xAE, 0x152, 0x1A2, 0x2117, 0x2295, 0x2296, 0x2297, 0x2298, 0x2299, 0x229A, 0x229B, 0x229C, }, "\"*", "IUiu", { 0x3AA, 0x3AB, 0x3CA, 0x3CB, }, "\"", "\"AEIOUaeiouyY", { 0xA8, 0xC4, 0xCB, 0xCF, 0xD6, 0xDC, 0xE4, 0xEB, 0xEF, 0xF6, 0xFC, 0xFF, 0x178, }, "S", "S", { 0xA7, }, "|", "|Pp", { 0xA6, 0xDE, 0xFE, }, "y", "$", { 0xA5, }, "g", "$-r", { 0xA4, 0x1E5, 0x2207, }, "l", "$-j\'\"&|z", { 0xA3, 0x142, 0x1C9, 0x2018, 0x201C, 0x2227, 0x2228, 0x22C4, }, "c", "$Oaug", { 0xA2, 0xA9, 0x2229, 0x222A, 0x2245, }, "!~", "-=~", { 0x2244, 0x2247, 0x2249, }, "!", "!?m=<>bp", { 0xA1, 0x203D, 0x2209, 0x2260, 0x226E, 0x226F, 0x2284, 0x2285, }, 0, 0, { 0, } }; /* * Given 5 characters k[0]..k[4], find the rune or return -1 for failure. */ long unicode(Rune *k) { long i, c; k++; /* skip 'X' */ c = 0; for(i=0; i<4; i++,k++){ c <<= 4; if('0'<=*k && *k<='9') c += *k-'0'; else if('a'<=*k && *k<='f') c += 10 + *k-'a'; else if('A'<=*k && *k<='F') c += 10 + *k-'A'; else return -1; } return c; } /* * Given n characters k[0]..k[n-1], find the corresponding rune or return -1 for * failure, or something < -1 if n is too small. In the latter case, the result * is minus the required n. */ long latin1(Rune *k, int n) { struct cvlist *l; int c; char* p; if(k[0] == 'X'){ if(n>=5) return unicode(k); else return -5; } for(l=latintab; l->ld!=0; l++) if(k[0] == l->ld[0]){ if(n == 1) return -2; if(l->ld[1] == 0) c = k[1]; else if(l->ld[1] != k[1]) continue; else if(n == 2) return -3; else c = k[2]; for(p=l->si; *p!=0; p++) if(*p == c) return l->so[p - l->si]; return -1; } return -1; } drawterm-20110822.orig/posix-port/0000755000175000017500000000000011245145712016217 5ustar tinchotinchodrawterm-20110822.orig/posix-port/md5block.c0000644000175000017500000001165011245145712020066 0ustar tinchotincho#include #include #include /* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ /* * Rotate ammounts used in the algorithm */ enum { S11= 7, S12= 12, S13= 17, S14= 22, S21= 5, S22= 9, S23= 14, S24= 20, S31= 4, S32= 11, S33= 16, S34= 23, S41= 6, S42= 10, S43= 15, S44= 21, }; static u32int md5tab[] = { /* round 1 */ /*[0]*/ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, /* round 2 */ /*[16]*/0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, /* round 3 */ /*[32]*/0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, /* round 4 */ /*[48]*/0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static void decode(u32int*, uchar*, ulong); extern void _md5block(uchar *p, ulong len, u32int *s); void _md5block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, sh; u32int *t; uchar *end; u32int x[16]; for(end = p+len; p < end; p += 64){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; decode(x, p, 64); t = md5tab; sh = 0; for(; sh != 16; t += 4){ a += ((c ^ d) & b) ^ d; a += x[sh] + t[0]; a = (a << S11) | (a >> (32 - S11)); a += b; d += ((b ^ c) & a) ^ c; d += x[sh + 1] + t[1]; d = (d << S12) | (d >> (32 - S12)); d += a; c += ((a ^ b) & d) ^ b; c += x[sh + 2] + t[2]; c = (c << S13) | (c >> (32 - S13)); c += d; b += ((d ^ a) & c) ^ a; b += x[sh + 3] + t[3]; b = (b << S14) | (b >> (32 - S14)); b += c; sh += 4; } sh = 1; for(; sh != 1+20*4; t += 4){ a += ((b ^ c) & d) ^ c; a += x[sh & 0xf] + t[0]; a = (a << S21) | (a >> (32 - S21)); a += b; d += ((a ^ b) & c) ^ b; d += x[(sh + 5) & 0xf] + t[1]; d = (d << S22) | (d >> (32 - S22)); d += a; c += ((d ^ a) & b) ^ a; c += x[(sh + 10) & 0xf] + t[2]; c = (c << S23) | (c >> (32 - S23)); c += d; b += ((c ^ d) & a) ^ d; b += x[(sh + 15) & 0xf] + t[3]; b = (b << S24) | (b >> (32 - S24)); b += c; sh += 20; } sh = 5; for(; sh != 5+12*4; t += 4){ a += b ^ c ^ d; a += x[sh & 0xf] + t[0]; a = (a << S31) | (a >> (32 - S31)); a += b; d += a ^ b ^ c; d += x[(sh + 3) & 0xf] + t[1]; d = (d << S32) | (d >> (32 - S32)); d += a; c += d ^ a ^ b; c += x[(sh + 6) & 0xf] + t[2]; c = (c << S33) | (c >> (32 - S33)); c += d; b += c ^ d ^ a; b += x[(sh + 9) & 0xf] + t[3]; b = (b << S34) | (b >> (32 - S34)); b += c; sh += 12; } sh = 0; for(; sh != 28*4; t += 4){ a += c ^ (b | ~d); a += x[sh & 0xf] + t[0]; a = (a << S41) | (a >> (32 - S41)); a += b; d += b ^ (a | ~c); d += x[(sh + 7) & 0xf] + t[1]; d = (d << S42) | (d >> (32 - S42)); d += a; c += a ^ (d | ~b); c += x[(sh + 14) & 0xf] + t[2]; c = (c << S43) | (c >> (32 - S43)); c += d; b += d ^ (c | ~a); b += x[(sh + 21) & 0xf] + t[3]; b = (b << S44) | (b >> (32 - S44)); b += c; sh += 28; } s[0] += a; s[1] += b; s[2] += c; s[3] += d; } } /* * decodes input (uchar) into output (u32int). Assumes len is * a multiple of 4. */ static void decode(u32int *output, uchar *input, ulong len) { uchar *e; for(e = input+len; input < e; input += 4) *output++ = input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24); } drawterm-20110822.orig/posix-port/Makefile0000644000175000017500000000043311245145712017657 0ustar tinchotinchoROOT=.. include ../Make.config LIB=../libmachdep.a OFILES=\ getcallerpc.$O\ md5block.$O\ sha1block.$O\ default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c %.$O: %.s $(AS) -o $*.$O $*.s %.s: %.spp cpp $*.spp >$*.s drawterm-20110822.orig/posix-port/sha1block.c0000644000175000017500000001114611245145712020235 0ustar tinchotincho#include #include #include void _sha1block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, e, x; uchar *end; u32int *wp, *wend; u32int w[80]; /* at this point, we have a multiple of 64 bytes */ for(end = p+len; p < end;){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; e = s[4]; wend = w + 15; for(wp = w; wp < wend; wp += 5){ wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); wp[1] = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7]; d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); wp[2] = (p[8]<<24) | (p[9]<<16) | (p[10]<<8) | p[11]; c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); wp[3] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); wp[4] = (p[16]<<24) | (p[17]<<16) | (p[18]<<8) | p[19]; a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); p += 20; } wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); wp += 5; p += 4; wend = w + 40; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x6ed9eba1 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x6ed9eba1 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x6ed9eba1 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x6ed9eba1 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x6ed9eba1 + (c^d^e); c = (c<<30)|(c>>2); } wend = w + 60; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x8f1bbcdc + ((b&c)|((b|c)&d)); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x8f1bbcdc + ((a&b)|((a|b)&c)); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x8f1bbcdc + ((e&a)|((e|a)&b)); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x8f1bbcdc + ((d&e)|((d|e)&a)); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x8f1bbcdc + ((c&d)|((c|d)&e)); c = (c<<30)|(c>>2); } wend = w + 80; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0xca62c1d6 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0xca62c1d6 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0xca62c1d6 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0xca62c1d6 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0xca62c1d6 + (c^d^e); c = (c<<30)|(c>>2); } /* save state */ s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; } } drawterm-20110822.orig/posix-port/getcallerpc.c0000644000175000017500000000011611245145712020646 0ustar tinchotincho#include "u.h" #include "libc.h" uintptr getcallerpc(void *a) { return 0; } drawterm-20110822.orig/libmemdraw/0000755000175000017500000000000011506541252016215 5ustar tinchotinchodrawterm-20110822.orig/libmemdraw/hwdraw.c0000644000175000017500000000023711245145712017660 0ustar tinchotincho#include #include #include #include int hwdraw(Memdrawparam *p) { USED(p); return 0; /* could not satisfy request */ } drawterm-20110822.orig/libmemdraw/alpha.hoc0000644000175000017500000000033411245145712017776 0ustar tinchotinchofunc f(x) { return x-x%1 } func pixel(dr, dg, db, da, sr, sg, sb, sa, m) { M = 255-f((sa*m)/255) print f((sr*m+dr*M)/255), " ", f((sg*m+dg*M)/255), " ", f((sb*m+db*M)/255), " ", f((sa*m+da*M)/255), "\n" return 0 } drawterm-20110822.orig/libmemdraw/mkcmap.c0000644000175000017500000000256211245145712017637 0ustar tinchotincho#include #include #include #include /* struct Memcmap { uchar cmap2rgb[3*256]; uchar rgb2cmap[16*16*16]; }; */ static Memcmap* mkcmap(void) { static Memcmap def; int i, rgb, r, g, b; for(i=0; i<256; i++){ rgb = cmap2rgb(i); r = (rgb>>16)&0xff; g = (rgb>>8)&0xff; b = rgb&0xff; def.cmap2rgb[3*i] = r; def.cmap2rgb[3*i+1] = g; def.cmap2rgb[3*i+2] = b; } for(r=0; r<16; r++) for(g=0; g<16; g++) for(b=0; b<16; b++) def.rgb2cmap[r*16*16+g*16+b] = rgb2cmap(r*0x11, g*0x11, b*0x11); return &def; } void main(int argc, char **argv) { Memcmap *c; int i, j, inferno; inferno = 0; ARGBEGIN{ case 'i': inferno = 1; }ARGEND memimageinit(); c = mkcmap(); if(!inferno) print("#include \n#include \n"); else print("#include \"lib9.h\"\n"); print("#include \n"); print("#include \n\n"); print("static Memcmap def = {\n"); print("/* cmap2rgb */ {\n"); for(i=0; icmap2rgb); ){ print("\t"); for(j=0; j<16; j++, i++) print("0x%2.2ux,", c->cmap2rgb[i]); print("\n"); } print("},\n"); print("/* rgb2cmap */ {\n"); for(i=0; irgb2cmap);){ print("\t"); for(j=0; j<16; j++, i++) print("0x%2.2ux,", c->rgb2cmap[i]); print("\n"); } print("}\n"); print("};\n"); print("Memcmap *memdefcmap = &def;\n"); print("void _memmkcmap(void){}\n"); exits(0); } drawterm-20110822.orig/libmemdraw/write.c0000644000175000017500000001042711245145712017520 0ustar tinchotincho#include #include #include #include #define CHUNK 8000 #define HSHIFT 3 /* HSHIFT==5 runs slightly faster, but hash table is 64x bigger */ #define NHASH (1<<(HSHIFT*NMATCH)) #define HMASK (NHASH-1) #define hupdate(h, c) ((((h)<r; bpl = bytesperline(r, i->depth); n = Dy(r)*bpl; data = malloc(n); ncblock = _compblocksize(r, i->depth); outbuf = malloc(ncblock); hash = malloc(NHASH*sizeof(Hlist)); chain = malloc(NMEM*sizeof(Hlist)); if(data == 0 || outbuf == 0 || hash == 0 || chain == 0){ ErrOut: free(data); free(outbuf); free(hash); free(chain); return -1; } for(miny = r.min.y; miny != r.max.y; miny += dy){ dy = r.max.y-miny; if(dy*bpl > CHUNK) dy = CHUNK/bpl; nb = unloadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy), data+(miny-r.min.y)*bpl, dy*bpl); if(nb != dy*bpl) goto ErrOut; } sprint(hdr, "compressed\n%11s %11d %11d %11d %11d ", chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y); if(write(fd, hdr, 11+5*12) != 11+5*12) goto ErrOut; edata = data+n; eout = outbuf+ncblock; line = data; r.max.y = r.min.y; while(line != edata){ memset(hash, 0, NHASH*sizeof(Hlist)); memset(chain, 0, NMEM*sizeof(Hlist)); cp = chain; h = 0; outp = outbuf; for(n = 0; n != NMATCH; n++) h = hupdate(h, line[n]); loutp = outbuf; while(line != edata){ ndump = 0; eline = line+bpl; for(p = line; p != eline; ){ if(eline-p < NRUN) es = eline; else es = p+NRUN; q = 0; runlen = 0; for(hp = hash[h].next; hp; hp = hp->next){ s = p + runlen; if(s >= es) continue; t = hp->s + runlen; for(; s >= p; s--) if(*s != *t--) goto matchloop; t += runlen+2; s += runlen+2; for(; s < es; s++) if(*s != *t++) break; n = s-p; if(n > runlen){ runlen = n; q = hp->s; if(n == NRUN) break; } matchloop: ; } if(runlen < NMATCH){ if(ndump == NDUMP){ if(eout-outp < ndump+1) goto Bfull; *outp++ = ndump-1+128; memmove(outp, dumpbuf, ndump); outp += ndump; ndump = 0; } dumpbuf[ndump++] = *p; runlen = 1; } else{ if(ndump != 0){ if(eout-outp < ndump+1) goto Bfull; *outp++ = ndump-1+128; memmove(outp, dumpbuf, ndump); outp += ndump; ndump = 0; } offs = p-q-1; if(eout-outp < 2) goto Bfull; *outp++ = ((runlen-NMATCH)<<2) + (offs>>8); *outp++ = offs&255; } for(q = p+runlen; p != q; p++){ if(cp->prev) cp->prev->next = 0; cp->next = hash[h].next; cp->prev = &hash[h]; if(cp->next) cp->next->prev = cp; cp->prev->next = cp; cp->s = p; if(++cp == &chain[NMEM]) cp = chain; if(edata-p > NMATCH) h = hupdate(h, p[NMATCH]); } } if(ndump != 0){ if(eout-outp < ndump+1) goto Bfull; *outp++ = ndump-1+128; memmove(outp, dumpbuf, ndump); outp += ndump; } line = eline; loutp = outp; r.max.y++; } Bfull: if(loutp == outbuf) goto ErrOut; n = loutp-outbuf; sprint(hdr, "%11d %11ld ", r.max.y, n); write(fd, hdr, 2*12); write(fd, outbuf, n); r.min.y = r.max.y; } free(data); free(outbuf); free(hash); free(chain); return 0; } drawterm-20110822.orig/libmemdraw/arctest.c0000644000175000017500000000154111245145712020030 0ustar tinchotincho#include #include #include #include #include extern int drawdebug; void main(int argc, char **argv) { char cc; Memimage *x; Point c = {208,871}; int a = 441; int b = 441; int thick = 0; Point sp = {0,0}; int alpha = 51; int phi = 3; vlong t0, t1; int i, n; vlong del; memimageinit(); x = allocmemimage(Rect(0,0,1000,1000), CMAP8); n = atoi(argv[1]); t0 = nsec(); t0 = nsec(); t0 = nsec(); t1 = nsec(); del = t1-t0; t0 = nsec(); for(i=0; i #include #include #include Memsubfont* allocmemsubfont(char *name, int n, int height, int ascent, Fontchar *info, Memimage *i) { Memsubfont *f; f = malloc(sizeof(Memsubfont)); if(f == 0) return 0; f->n = n; f->height = height; f->ascent = ascent; f->info = info; f->bits = i; if(name) f->name = strdup(name); else f->name = 0; return f; } void freememsubfont(Memsubfont *f) { if(f == 0) return; free(f->info); /* note: f->info must have been malloc'ed! */ freememimage(f->bits); free(f); } drawterm-20110822.orig/libmemdraw/openmemsubfont.c0000644000175000017500000000160411245145712021424 0ustar tinchotincho#include #include #include #include Memsubfont* openmemsubfont(char *name) { Memsubfont *sf; Memimage *i; Fontchar *fc; int fd, n; char hdr[3*12+4+1]; uchar *p; fd = open(name, OREAD); if(fd < 0) return nil; p = nil; i = readmemimage(fd); if(i == nil) goto Err; if(read(fd, hdr, 3*12) != 3*12){ werrstr("openmemsubfont: header read error: %r"); goto Err; } n = atoi(hdr); p = malloc(6*(n+1)); if(p == nil) goto Err; if(read(fd, p, 6*(n+1)) != 6*(n+1)){ werrstr("openmemsubfont: fontchar read error: %r"); goto Err; } fc = malloc(sizeof(Fontchar)*(n+1)); if(fc == nil) goto Err; _unpackinfo(fc, p, n); sf = allocmemsubfont(name, n, atoi(hdr+12), atoi(hdr+24), fc, i); if(sf == nil){ free(fc); goto Err; } free(p); return sf; Err: close(fd); if (i != nil) freememimage(i); if (p != nil) free(p); return nil; } drawterm-20110822.orig/libmemdraw/cmap.c0000644000175000017500000006107611245145712017314 0ustar tinchotincho/* * generated by mkcmap.c */ #include #include #include #include static Memcmap def = { /* cmap2rgb */ { 0x00,0x00,0x00,0x00,0x00,0x44,0x00,0x00,0x88,0x00,0x00,0xcc,0x00,0x44,0x00,0x00, 0x44,0x44,0x00,0x44,0x88,0x00,0x44,0xcc,0x00,0x88,0x00,0x00,0x88,0x44,0x00,0x88, 0x88,0x00,0x88,0xcc,0x00,0xcc,0x00,0x00,0xcc,0x44,0x00,0xcc,0x88,0x00,0xcc,0xcc, 0x00,0xdd,0xdd,0x11,0x11,0x11,0x00,0x00,0x55,0x00,0x00,0x99,0x00,0x00,0xdd,0x00, 0x55,0x00,0x00,0x55,0x55,0x00,0x4c,0x99,0x00,0x49,0xdd,0x00,0x99,0x00,0x00,0x99, 0x4c,0x00,0x99,0x99,0x00,0x93,0xdd,0x00,0xdd,0x00,0x00,0xdd,0x49,0x00,0xdd,0x93, 0x00,0xee,0x9e,0x00,0xee,0xee,0x22,0x22,0x22,0x00,0x00,0x66,0x00,0x00,0xaa,0x00, 0x00,0xee,0x00,0x66,0x00,0x00,0x66,0x66,0x00,0x55,0xaa,0x00,0x4f,0xee,0x00,0xaa, 0x00,0x00,0xaa,0x55,0x00,0xaa,0xaa,0x00,0x9e,0xee,0x00,0xee,0x00,0x00,0xee,0x4f, 0x00,0xff,0x55,0x00,0xff,0xaa,0x00,0xff,0xff,0x33,0x33,0x33,0x00,0x00,0x77,0x00, 0x00,0xbb,0x00,0x00,0xff,0x00,0x77,0x00,0x00,0x77,0x77,0x00,0x5d,0xbb,0x00,0x55, 0xff,0x00,0xbb,0x00,0x00,0xbb,0x5d,0x00,0xbb,0xbb,0x00,0xaa,0xff,0x00,0xff,0x00, 0x44,0x00,0x44,0x44,0x00,0x88,0x44,0x00,0xcc,0x44,0x44,0x00,0x44,0x44,0x44,0x44, 0x44,0x88,0x44,0x44,0xcc,0x44,0x88,0x00,0x44,0x88,0x44,0x44,0x88,0x88,0x44,0x88, 0xcc,0x44,0xcc,0x00,0x44,0xcc,0x44,0x44,0xcc,0x88,0x44,0xcc,0xcc,0x44,0x00,0x00, 0x55,0x00,0x00,0x55,0x00,0x55,0x4c,0x00,0x99,0x49,0x00,0xdd,0x55,0x55,0x00,0x55, 0x55,0x55,0x4c,0x4c,0x99,0x49,0x49,0xdd,0x4c,0x99,0x00,0x4c,0x99,0x4c,0x4c,0x99, 0x99,0x49,0x93,0xdd,0x49,0xdd,0x00,0x49,0xdd,0x49,0x49,0xdd,0x93,0x49,0xdd,0xdd, 0x4f,0xee,0xee,0x66,0x00,0x00,0x66,0x00,0x66,0x55,0x00,0xaa,0x4f,0x00,0xee,0x66, 0x66,0x00,0x66,0x66,0x66,0x55,0x55,0xaa,0x4f,0x4f,0xee,0x55,0xaa,0x00,0x55,0xaa, 0x55,0x55,0xaa,0xaa,0x4f,0x9e,0xee,0x4f,0xee,0x00,0x4f,0xee,0x4f,0x4f,0xee,0x9e, 0x55,0xff,0xaa,0x55,0xff,0xff,0x77,0x00,0x00,0x77,0x00,0x77,0x5d,0x00,0xbb,0x55, 0x00,0xff,0x77,0x77,0x00,0x77,0x77,0x77,0x5d,0x5d,0xbb,0x55,0x55,0xff,0x5d,0xbb, 0x00,0x5d,0xbb,0x5d,0x5d,0xbb,0xbb,0x55,0xaa,0xff,0x55,0xff,0x00,0x55,0xff,0x55, 0x88,0x00,0x88,0x88,0x00,0xcc,0x88,0x44,0x00,0x88,0x44,0x44,0x88,0x44,0x88,0x88, 0x44,0xcc,0x88,0x88,0x00,0x88,0x88,0x44,0x88,0x88,0x88,0x88,0x88,0xcc,0x88,0xcc, 0x00,0x88,0xcc,0x44,0x88,0xcc,0x88,0x88,0xcc,0xcc,0x88,0x00,0x00,0x88,0x00,0x44, 0x99,0x00,0x4c,0x99,0x00,0x99,0x93,0x00,0xdd,0x99,0x4c,0x00,0x99,0x4c,0x4c,0x99, 0x4c,0x99,0x93,0x49,0xdd,0x99,0x99,0x00,0x99,0x99,0x4c,0x99,0x99,0x99,0x93,0x93, 0xdd,0x93,0xdd,0x00,0x93,0xdd,0x49,0x93,0xdd,0x93,0x93,0xdd,0xdd,0x99,0x00,0x00, 0xaa,0x00,0x00,0xaa,0x00,0x55,0xaa,0x00,0xaa,0x9e,0x00,0xee,0xaa,0x55,0x00,0xaa, 0x55,0x55,0xaa,0x55,0xaa,0x9e,0x4f,0xee,0xaa,0xaa,0x00,0xaa,0xaa,0x55,0xaa,0xaa, 0xaa,0x9e,0x9e,0xee,0x9e,0xee,0x00,0x9e,0xee,0x4f,0x9e,0xee,0x9e,0x9e,0xee,0xee, 0xaa,0xff,0xff,0xbb,0x00,0x00,0xbb,0x00,0x5d,0xbb,0x00,0xbb,0xaa,0x00,0xff,0xbb, 0x5d,0x00,0xbb,0x5d,0x5d,0xbb,0x5d,0xbb,0xaa,0x55,0xff,0xbb,0xbb,0x00,0xbb,0xbb, 0x5d,0xbb,0xbb,0xbb,0xaa,0xaa,0xff,0xaa,0xff,0x00,0xaa,0xff,0x55,0xaa,0xff,0xaa, 0xcc,0x00,0xcc,0xcc,0x44,0x00,0xcc,0x44,0x44,0xcc,0x44,0x88,0xcc,0x44,0xcc,0xcc, 0x88,0x00,0xcc,0x88,0x44,0xcc,0x88,0x88,0xcc,0x88,0xcc,0xcc,0xcc,0x00,0xcc,0xcc, 0x44,0xcc,0xcc,0x88,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0xcc,0x00,0x44,0xcc,0x00,0x88, 0xdd,0x00,0x93,0xdd,0x00,0xdd,0xdd,0x49,0x00,0xdd,0x49,0x49,0xdd,0x49,0x93,0xdd, 0x49,0xdd,0xdd,0x93,0x00,0xdd,0x93,0x49,0xdd,0x93,0x93,0xdd,0x93,0xdd,0xdd,0xdd, 0x00,0xdd,0xdd,0x49,0xdd,0xdd,0x93,0xdd,0xdd,0xdd,0xdd,0x00,0x00,0xdd,0x00,0x49, 0xee,0x00,0x4f,0xee,0x00,0x9e,0xee,0x00,0xee,0xee,0x4f,0x00,0xee,0x4f,0x4f,0xee, 0x4f,0x9e,0xee,0x4f,0xee,0xee,0x9e,0x00,0xee,0x9e,0x4f,0xee,0x9e,0x9e,0xee,0x9e, 0xee,0xee,0xee,0x00,0xee,0xee,0x4f,0xee,0xee,0x9e,0xee,0xee,0xee,0xee,0x00,0x00, 0xff,0x00,0x00,0xff,0x00,0x55,0xff,0x00,0xaa,0xff,0x00,0xff,0xff,0x55,0x00,0xff, 0x55,0x55,0xff,0x55,0xaa,0xff,0x55,0xff,0xff,0xaa,0x00,0xff,0xaa,0x55,0xff,0xaa, 0xaa,0xff,0xaa,0xff,0xff,0xff,0x00,0xff,0xff,0x55,0xff,0xff,0xaa,0xff,0xff,0xff, }, /* rgb2cmap */ { 0x00,0x00,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x00,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x11,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x17,0x07,0x07,0x18,0x18,0x29, 0x04,0x04,0x04,0x05,0x05,0x05,0x16,0x06,0x06,0x17,0x28,0x07,0x07,0x18,0x29,0x3a, 0x15,0x15,0x15,0x05,0x05,0x16,0x16,0x06,0x06,0x17,0x28,0x39,0x07,0x18,0x29,0x3a, 0x26,0x26,0x26,0x05,0x16,0x16,0x27,0x27,0x38,0x28,0x28,0x39,0x39,0x29,0x29,0x3a, 0x37,0x37,0x37,0x09,0x09,0x09,0x27,0x38,0x0a,0x0a,0x39,0x0b,0x0b,0x0b,0x1c,0x3a, 0x08,0x08,0x08,0x09,0x09,0x09,0x38,0x0a,0x0a,0x0a,0x1b,0x0b,0x0b,0x1c,0x1c,0x2d, 0x19,0x19,0x19,0x09,0x1a,0x1a,0x2b,0x0a,0x0a,0x1b,0x1b,0x0b,0x0b,0x1c,0x2d,0x3e, 0x2a,0x2a,0x2a,0x1a,0x2b,0x2b,0x2b,0x3c,0x1b,0x1b,0x2c,0x2c,0x3d,0x2d,0x2d,0x3e, 0x3b,0x3b,0x3b,0x0d,0x0d,0x3c,0x3c,0x0e,0x0e,0x0e,0x2c,0x3d,0x0f,0x0f,0x3e,0x3e, 0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x3c,0x0e,0x0e,0x0e,0x3d,0x0f,0x0f,0x0f,0x10,0x3e, 0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x2f,0x0e,0x1f,0x1f,0x20,0x0f,0x0f,0x10,0x10,0x21, 0x2e,0x2e,0x2e,0x1e,0x2f,0x2f,0x2f,0x1f,0x1f,0x20,0x20,0x31,0x10,0x10,0x21,0x21, 0x3f,0x3f,0x3f,0x2f,0x30,0x30,0x30,0x30,0x20,0x31,0x31,0x31,0x31,0x21,0x21,0x32, 0x00,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x11,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x11,0x11,0x22,0x22,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x04,0x04,0x22,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x17,0x07,0x07,0x18,0x18,0x29, 0x04,0x04,0x04,0x05,0x05,0x05,0x16,0x06,0x06,0x17,0x28,0x07,0x07,0x18,0x29,0x3a, 0x15,0x15,0x15,0x05,0x05,0x16,0x16,0x06,0x06,0x17,0x28,0x39,0x07,0x18,0x29,0x3a, 0x26,0x26,0x26,0x05,0x16,0x16,0x27,0x27,0x38,0x28,0x28,0x39,0x39,0x29,0x29,0x3a, 0x37,0x37,0x37,0x09,0x09,0x09,0x27,0x38,0x0a,0x0a,0x39,0x0b,0x0b,0x0b,0x1c,0x3a, 0x08,0x08,0x08,0x09,0x09,0x09,0x38,0x0a,0x0a,0x0a,0x1b,0x0b,0x0b,0x1c,0x1c,0x2d, 0x19,0x19,0x19,0x09,0x1a,0x1a,0x2b,0x0a,0x0a,0x1b,0x1b,0x0b,0x0b,0x1c,0x2d,0x3e, 0x2a,0x2a,0x2a,0x1a,0x2b,0x2b,0x2b,0x3c,0x1b,0x1b,0x2c,0x2c,0x3d,0x2d,0x2d,0x3e, 0x3b,0x3b,0x3b,0x0d,0x0d,0x3c,0x3c,0x0e,0x0e,0x0e,0x2c,0x3d,0x0f,0x0f,0x3e,0x3e, 0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x3c,0x0e,0x0e,0x0e,0x3d,0x0f,0x0f,0x0f,0x10,0x3e, 0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x2f,0x0e,0x1f,0x1f,0x20,0x0f,0x0f,0x10,0x10,0x21, 0x2e,0x2e,0x2e,0x1e,0x2f,0x2f,0x2f,0x1f,0x1f,0x20,0x20,0x31,0x10,0x10,0x21,0x21, 0x3f,0x3f,0x3f,0x2f,0x30,0x30,0x30,0x30,0x20,0x31,0x31,0x31,0x31,0x21,0x21,0x32, 0x11,0x11,0x11,0x01,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x11,0x11,0x22,0x22,0x01,0x12,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x11,0x22,0x22,0x22,0x33,0x33,0x23,0x34,0x02,0x13,0x24,0x35,0x03,0x14,0x25,0x36, 0x04,0x22,0x22,0x33,0x33,0x33,0x05,0x06,0x06,0x06,0x17,0x07,0x07,0x18,0x18,0x29, 0x04,0x04,0x33,0x33,0x33,0x05,0x16,0x06,0x06,0x17,0x28,0x07,0x07,0x18,0x29,0x3a, 0x15,0x15,0x33,0x33,0x05,0x16,0x16,0x06,0x06,0x17,0x28,0x39,0x07,0x18,0x29,0x3a, 0x26,0x26,0x26,0x05,0x16,0x16,0x27,0x27,0x38,0x28,0x28,0x39,0x39,0x29,0x29,0x3a, 0x37,0x37,0x37,0x09,0x09,0x09,0x27,0x38,0x0a,0x0a,0x39,0x0b,0x0b,0x0b,0x1c,0x3a, 0x08,0x08,0x08,0x09,0x09,0x09,0x38,0x0a,0x0a,0x0a,0x1b,0x0b,0x0b,0x1c,0x1c,0x2d, 0x19,0x19,0x19,0x09,0x1a,0x1a,0x2b,0x0a,0x0a,0x1b,0x1b,0x0b,0x0b,0x1c,0x2d,0x3e, 0x2a,0x2a,0x2a,0x1a,0x2b,0x2b,0x2b,0x3c,0x1b,0x1b,0x2c,0x2c,0x3d,0x2d,0x2d,0x3e, 0x3b,0x3b,0x3b,0x0d,0x0d,0x3c,0x3c,0x0e,0x0e,0x0e,0x2c,0x3d,0x0f,0x0f,0x3e,0x3e, 0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x3c,0x0e,0x0e,0x0e,0x3d,0x0f,0x0f,0x0f,0x10,0x3e, 0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x2f,0x0e,0x1f,0x1f,0x20,0x0f,0x0f,0x10,0x10,0x21, 0x2e,0x2e,0x2e,0x1e,0x2f,0x2f,0x2f,0x1f,0x1f,0x20,0x20,0x31,0x10,0x10,0x21,0x21, 0x3f,0x3f,0x3f,0x2f,0x30,0x30,0x30,0x30,0x20,0x31,0x31,0x31,0x31,0x21,0x21,0x32, 0x4f,0x4f,0x22,0x40,0x40,0x40,0x40,0x41,0x41,0x41,0x52,0x42,0x42,0x53,0x53,0x64, 0x4f,0x22,0x22,0x22,0x40,0x40,0x40,0x41,0x41,0x41,0x52,0x42,0x42,0x53,0x53,0x64, 0x22,0x22,0x22,0x33,0x33,0x33,0x40,0x41,0x41,0x41,0x52,0x42,0x42,0x53,0x53,0x64, 0x43,0x22,0x33,0x33,0x33,0x44,0x44,0x45,0x45,0x45,0x56,0x46,0x46,0x46,0x57,0x68, 0x43,0x43,0x33,0x33,0x44,0x44,0x44,0x45,0x45,0x45,0x56,0x46,0x46,0x57,0x57,0x68, 0x43,0x43,0x33,0x44,0x44,0x44,0x55,0x45,0x45,0x56,0x56,0x46,0x46,0x57,0x68,0x68, 0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79, 0x47,0x47,0x47,0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x5b,0x79, 0x47,0x47,0x47,0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x5a,0x4a,0x4a,0x4a,0x5b,0x6c, 0x47,0x47,0x47,0x48,0x48,0x59,0x59,0x49,0x49,0x5a,0x5a,0x4a,0x4a,0x5b,0x5b,0x6c, 0x58,0x58,0x58,0x59,0x59,0x59,0x6a,0x49,0x5a,0x5a,0x6b,0x6b,0x5b,0x5b,0x6c,0x7d, 0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x6b,0x4e,0x4e,0x4e,0x6c,0x7d, 0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x5e,0x4e,0x4e,0x4e,0x5f,0x5f, 0x5c,0x5c,0x5c,0x4c,0x5d,0x5d,0x5d,0x4d,0x4d,0x5e,0x5e,0x4e,0x4e,0x5f,0x5f,0x60, 0x5c,0x5c,0x5c,0x5d,0x5d,0x6e,0x6e,0x5e,0x5e,0x5e,0x6f,0x6f,0x5f,0x5f,0x60,0x60, 0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x7f,0x7f,0x6f,0x6f,0x70,0x70,0x5f,0x60,0x60,0x71, 0x4f,0x4f,0x40,0x40,0x40,0x40,0x51,0x41,0x41,0x52,0x63,0x42,0x42,0x53,0x64,0x75, 0x4f,0x4f,0x22,0x40,0x40,0x40,0x51,0x41,0x41,0x52,0x63,0x42,0x42,0x53,0x64,0x75, 0x43,0x22,0x33,0x33,0x33,0x40,0x51,0x41,0x41,0x52,0x63,0x42,0x42,0x53,0x64,0x75, 0x43,0x43,0x33,0x33,0x44,0x44,0x44,0x45,0x45,0x45,0x56,0x46,0x46,0x57,0x57,0x68, 0x43,0x43,0x33,0x44,0x44,0x44,0x55,0x45,0x45,0x56,0x56,0x46,0x46,0x57,0x68,0x68, 0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79, 0x54,0x54,0x54,0x44,0x55,0x55,0x55,0x45,0x56,0x56,0x67,0x78,0x78,0x57,0x68,0x79, 0x47,0x47,0x47,0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x5b,0x79, 0x47,0x47,0x47,0x48,0x48,0x48,0x59,0x49,0x49,0x49,0x5a,0x4a,0x4a,0x5b,0x5b,0x6c, 0x58,0x58,0x58,0x48,0x59,0x59,0x59,0x49,0x49,0x5a,0x5a,0x4a,0x4a,0x5b,0x6c,0x6c, 0x69,0x69,0x69,0x59,0x59,0x6a,0x6a,0x49,0x5a,0x5a,0x6b,0x6b,0x5b,0x5b,0x6c,0x7d, 0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x7b,0x4d,0x4d,0x4d,0x6b,0x4e,0x4e,0x4e,0x7d,0x7d, 0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x7b,0x4d,0x4d,0x4d,0x5e,0x4e,0x4e,0x4e,0x5f,0x7d, 0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5d,0x4d,0x5e,0x5e,0x5e,0x4e,0x4e,0x5f,0x5f,0x60, 0x6d,0x6d,0x6d,0x5d,0x6e,0x6e,0x6e,0x5e,0x5e,0x6f,0x6f,0x70,0x5f,0x5f,0x60,0x60, 0x7e,0x7e,0x7e,0x6e,0x6e,0x7f,0x7f,0x7f,0x6f,0x6f,0x70,0x70,0x70,0x60,0x60,0x71, 0x50,0x50,0x50,0x40,0x40,0x51,0x51,0x41,0x41,0x52,0x63,0x74,0x42,0x53,0x64,0x75, 0x50,0x50,0x50,0x40,0x40,0x51,0x51,0x41,0x41,0x52,0x63,0x74,0x42,0x53,0x64,0x75, 0x50,0x50,0x33,0x33,0x40,0x51,0x51,0x41,0x41,0x52,0x63,0x74,0x42,0x53,0x64,0x75, 0x43,0x43,0x33,0x44,0x44,0x44,0x55,0x45,0x45,0x56,0x56,0x46,0x46,0x57,0x68,0x68, 0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79, 0x54,0x54,0x54,0x44,0x55,0x55,0x55,0x45,0x56,0x56,0x67,0x78,0x78,0x57,0x68,0x79, 0x54,0x54,0x54,0x55,0x55,0x55,0x66,0x66,0x56,0x67,0x67,0x78,0x78,0x68,0x68,0x79, 0x47,0x47,0x47,0x48,0x48,0x48,0x66,0x49,0x49,0x49,0x78,0x78,0x4a,0x4a,0x5b,0x79, 0x47,0x47,0x47,0x48,0x48,0x59,0x59,0x49,0x49,0x5a,0x5a,0x4a,0x4a,0x5b,0x6c,0x6c, 0x58,0x58,0x58,0x59,0x59,0x59,0x6a,0x49,0x5a,0x5a,0x6b,0x6b,0x5b,0x5b,0x6c,0x7d, 0x69,0x69,0x69,0x59,0x6a,0x6a,0x6a,0x7b,0x5a,0x6b,0x6b,0x6b,0x7c,0x6c,0x6c,0x7d, 0x7a,0x7a,0x7a,0x4c,0x4c,0x7b,0x7b,0x7b,0x4d,0x6b,0x6b,0x7c,0x7c,0x4e,0x7d,0x7d, 0x4b,0x4b,0x4b,0x4c,0x4c,0x7b,0x7b,0x4d,0x4d,0x5e,0x7c,0x7c,0x4e,0x5f,0x5f,0x7d, 0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x6e,0x4d,0x5e,0x5e,0x6f,0x4e,0x5f,0x5f,0x60,0x60, 0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6e,0x5e,0x6f,0x6f,0x6f,0x70,0x5f,0x60,0x60,0x71, 0x7e,0x7e,0x7e,0x6e,0x7f,0x7f,0x7f,0x7f,0x6f,0x70,0x70,0x70,0x70,0x60,0x71,0x71, 0x61,0x61,0x61,0x40,0x51,0x51,0x62,0x62,0x73,0x63,0x63,0x74,0x74,0x64,0x64,0x75, 0x61,0x61,0x61,0x40,0x51,0x51,0x62,0x62,0x73,0x63,0x63,0x74,0x74,0x64,0x64,0x75, 0x61,0x61,0x61,0x40,0x51,0x51,0x62,0x62,0x73,0x63,0x63,0x74,0x74,0x64,0x64,0x75, 0x43,0x43,0x43,0x44,0x44,0x55,0x55,0x45,0x45,0x56,0x67,0x46,0x46,0x57,0x68,0x79, 0x54,0x54,0x54,0x44,0x55,0x55,0x55,0x45,0x56,0x56,0x67,0x78,0x78,0x57,0x68,0x79, 0x54,0x54,0x54,0x55,0x55,0x55,0x66,0x66,0x56,0x67,0x67,0x78,0x78,0x68,0x68,0x79, 0x65,0x65,0x65,0x55,0x55,0x66,0x66,0x66,0x77,0x67,0x78,0x78,0x78,0x78,0x79,0x79, 0x65,0x65,0x65,0x48,0x48,0x66,0x66,0x77,0x77,0x77,0x78,0x78,0x78,0x5b,0x79,0x79, 0x76,0x76,0x76,0x48,0x59,0x59,0x77,0x77,0x77,0x5a,0x5a,0x4a,0x4a,0x5b,0x6c,0x6c, 0x69,0x69,0x69,0x59,0x59,0x6a,0x6a,0x77,0x5a,0x5a,0x6b,0x6b,0x5b,0x6c,0x6c,0x7d, 0x69,0x69,0x69,0x6a,0x6a,0x6a,0x7b,0x7b,0x5a,0x6b,0x6b,0x7c,0x7c,0x6c,0x7d,0x7d, 0x7a,0x7a,0x7a,0x4c,0x7b,0x7b,0x7b,0x7b,0x4d,0x6b,0x7c,0x7c,0x7c,0x7c,0x7d,0x7d, 0x7a,0x7a,0x7a,0x4c,0x7b,0x7b,0x7b,0x7b,0x4d,0x5e,0x7c,0x7c,0x7c,0x5f,0x5f,0x7d, 0x6d,0x6d,0x6d,0x5d,0x5d,0x6e,0x7b,0x5e,0x5e,0x6f,0x6f,0x7c,0x5f,0x5f,0x60,0x60, 0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x7f,0x7f,0x6f,0x6f,0x70,0x70,0x5f,0x60,0x60,0x71, 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x6f,0x70,0x70,0x70,0x70,0x60,0x71,0x71, 0x72,0x72,0x72,0x8f,0x8f,0x62,0x62,0x73,0x73,0x80,0x74,0x81,0x81,0x81,0x92,0x75, 0x72,0x72,0x72,0x8f,0x8f,0x62,0x62,0x73,0x73,0x80,0x74,0x81,0x81,0x81,0x92,0x75, 0x72,0x72,0x72,0x83,0x83,0x62,0x62,0x73,0x73,0x80,0x74,0x81,0x81,0x81,0x92,0x75, 0x82,0x82,0x82,0x83,0x83,0x83,0x83,0x84,0x84,0x84,0x84,0x85,0x85,0x85,0x96,0x79, 0x82,0x82,0x82,0x83,0x83,0x83,0x66,0x84,0x84,0x84,0x67,0x85,0x85,0x85,0x96,0x79, 0x65,0x65,0x65,0x83,0x83,0x66,0x66,0x66,0x84,0x84,0x78,0x78,0x85,0x85,0x96,0x79, 0x65,0x65,0x65,0x83,0x66,0x66,0x66,0x77,0x77,0x77,0x78,0x78,0x78,0x96,0x79,0x79, 0x76,0x76,0x76,0x87,0x87,0x66,0x77,0x77,0x77,0x88,0x78,0x89,0x89,0x89,0x89,0x79, 0x76,0x76,0x76,0x87,0x87,0x87,0x77,0x77,0x88,0x88,0x88,0x89,0x89,0x89,0x9a,0x9a, 0x86,0x86,0x86,0x87,0x87,0x87,0x77,0x88,0x88,0x88,0x6b,0x89,0x89,0x9a,0x9a,0x7d, 0x7a,0x7a,0x7a,0x87,0x6a,0x7b,0x7b,0x7b,0x88,0x6b,0x6b,0x7c,0x7c,0x9a,0x7d,0x7d, 0x8a,0x8a,0x8a,0x8b,0x8b,0x7b,0x7b,0x8c,0x8c,0x8c,0x7c,0x7c,0x8d,0x8d,0x7d,0x7d, 0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x7b,0x8c,0x8c,0x8c,0x7c,0x8d,0x8d,0x8d,0x9e,0x9e, 0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x9c,0x8c,0x8c,0x9d,0x9d,0x8d,0x8d,0x9e,0x9e,0x9e, 0x9b,0x9b,0x9b,0x9c,0x9c,0x9c,0x7f,0x8c,0x9d,0x9d,0x70,0x70,0x9e,0x9e,0x9e,0x71, 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x9d,0x70,0x70,0x70,0x9e,0x9e,0x71,0x71, 0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x73,0x73,0x80,0x80,0x91,0x81,0x81,0x92,0x92,0xa3, 0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x73,0x73,0x80,0x80,0x91,0x81,0x81,0x92,0x92,0xa3, 0x82,0x82,0x82,0x83,0x83,0x83,0x73,0x73,0x80,0x80,0x91,0x81,0x81,0x92,0x92,0xa3, 0x82,0x82,0x82,0x83,0x83,0x83,0x83,0x84,0x84,0x84,0x95,0x85,0x85,0x85,0x96,0xa7, 0x82,0x82,0x82,0x83,0x83,0x83,0x94,0x84,0x84,0x84,0x95,0x85,0x85,0x96,0x96,0xa7, 0x82,0x82,0x82,0x83,0x83,0x94,0x94,0x84,0x84,0x95,0x95,0x85,0x85,0x96,0xa7,0xa7, 0x76,0x76,0x76,0x83,0x94,0x94,0x77,0x77,0x77,0x95,0x95,0x85,0x85,0x96,0xa7,0xa7, 0x76,0x76,0x76,0x87,0x87,0x87,0x77,0x77,0x88,0x88,0x88,0x89,0x89,0x89,0x9a,0x9a, 0x86,0x86,0x86,0x87,0x87,0x87,0x77,0x88,0x88,0x88,0x99,0x89,0x89,0x9a,0x9a,0xab, 0x86,0x86,0x86,0x87,0x87,0x98,0x98,0x88,0x88,0x99,0x99,0x89,0x89,0x9a,0x9a,0xab, 0x97,0x97,0x97,0x98,0x98,0x98,0x98,0x88,0x99,0x99,0x99,0x89,0x9a,0x9a,0xab,0xab, 0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x8c,0x8d,0x8d,0x8d,0xab,0xbc, 0x8a,0x8a,0x8a,0x8b,0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x9d,0x8d,0x8d,0x8d,0x9e,0x9e, 0x9b,0x9b,0x9b,0x8b,0x9c,0x9c,0x9c,0x8c,0x9d,0x9d,0x9d,0x8d,0x8d,0x9e,0x9e,0xaf, 0x9b,0x9b,0x9b,0x9c,0x9c,0xad,0xad,0x9d,0x9d,0x9d,0xae,0xae,0x9e,0x9e,0xaf,0xaf, 0xac,0xac,0xac,0xad,0xad,0xad,0xad,0x9d,0xae,0xae,0xae,0xbf,0x9e,0xaf,0xaf,0xaf, 0x9f,0x9f,0x9f,0x8f,0x90,0x90,0xa1,0x80,0x80,0x91,0x91,0x81,0x81,0x92,0xa3,0xb4, 0x9f,0x9f,0x9f,0x8f,0x90,0x90,0xa1,0x80,0x80,0x91,0x91,0x81,0x81,0x92,0xa3,0xb4, 0x9f,0x9f,0x9f,0x83,0x90,0x90,0xa1,0x80,0x80,0x91,0x91,0x81,0x81,0x92,0xa3,0xb4, 0x82,0x82,0x82,0x83,0x83,0x94,0x94,0x84,0x84,0x95,0x95,0x85,0x85,0x96,0x96,0xa7, 0x93,0x93,0x93,0x83,0x94,0x94,0x94,0x84,0x84,0x95,0x95,0x85,0x85,0x96,0xa7,0xa7, 0x93,0x93,0x93,0x94,0x94,0x94,0xa5,0x84,0x95,0x95,0xa6,0xa6,0x96,0x96,0xa7,0xb8, 0xa4,0xa4,0xa4,0x94,0x94,0xa5,0xa5,0x77,0x95,0x95,0xa6,0xa6,0x96,0xa7,0xa7,0xb8, 0x86,0x86,0x86,0x87,0x87,0x87,0x77,0x88,0x88,0x88,0x99,0x89,0x89,0x9a,0x9a,0xb8, 0x86,0x86,0x86,0x87,0x87,0x98,0x98,0x88,0x88,0x99,0x99,0x89,0x89,0x9a,0x9a,0xab, 0x97,0x97,0x97,0x98,0x98,0x98,0x98,0x88,0x99,0x99,0x99,0x89,0x9a,0x9a,0xab,0xab, 0x97,0x97,0x97,0x98,0x98,0xa9,0xa9,0x99,0x99,0x99,0xaa,0xaa,0x9a,0xab,0xab,0xbc, 0x8a,0x8a,0x8a,0x8b,0x8b,0xa9,0xa9,0x8c,0x8c,0x8c,0xaa,0x8d,0x8d,0x8d,0xab,0xbc, 0x8a,0x8a,0x8a,0x8b,0x8b,0x9c,0x9c,0x8c,0x8c,0x9d,0x9d,0x8d,0x8d,0x9e,0x9e,0xbc, 0x9b,0x9b,0x9b,0x9c,0x9c,0x9c,0xad,0x9d,0x9d,0x9d,0xae,0x8d,0x9e,0x9e,0xaf,0xaf, 0xac,0xac,0xac,0x9c,0xad,0xad,0xad,0x9d,0x9d,0xae,0xae,0xae,0x9e,0xaf,0xaf,0xaf, 0xbd,0xbd,0xbd,0xad,0xad,0xbe,0xbe,0xbe,0xae,0xae,0xbf,0xbf,0xbf,0xaf,0xaf,0xb0, 0xa0,0xa0,0xa0,0x90,0xa1,0xa1,0xa1,0xb2,0x91,0x91,0xa2,0xa2,0xb3,0xa3,0xa3,0xb4, 0xa0,0xa0,0xa0,0x90,0xa1,0xa1,0xa1,0xb2,0x91,0x91,0xa2,0xa2,0xb3,0xa3,0xa3,0xb4, 0xa0,0xa0,0xa0,0x90,0xa1,0xa1,0xa1,0xb2,0x91,0x91,0xa2,0xa2,0xb3,0xa3,0xa3,0xb4, 0x93,0x93,0x93,0x94,0x94,0x94,0xa5,0x84,0x95,0x95,0xa6,0xa6,0x96,0x96,0xa7,0xb8, 0xa4,0xa4,0xa4,0x94,0x94,0xa5,0xa5,0x84,0x95,0x95,0xa6,0xa6,0x96,0x96,0xa7,0xb8, 0xa4,0xa4,0xa4,0x94,0xa5,0xa5,0xa5,0xb6,0x95,0xa6,0xa6,0xa6,0xb7,0xa7,0xa7,0xb8, 0xa4,0xa4,0xa4,0xa5,0xa5,0xa5,0xb6,0xb6,0x95,0xa6,0xa6,0xb7,0xb7,0xa7,0xb8,0xb8, 0xb5,0xb5,0xb5,0x87,0x87,0xb6,0xb6,0xb6,0x88,0x99,0xa6,0xb7,0xb7,0x9a,0xb8,0xb8, 0x97,0x97,0x97,0x98,0x98,0x98,0x98,0x88,0x99,0x99,0x99,0x89,0x9a,0x9a,0xab,0xab, 0x97,0x97,0x97,0x98,0x98,0xa9,0xa9,0x99,0x99,0x99,0xaa,0xaa,0x9a,0xab,0xab,0xbc, 0xa8,0xa8,0xa8,0xa9,0xa9,0xa9,0xa9,0xa9,0x99,0xaa,0xaa,0xaa,0xbb,0xab,0xab,0xbc, 0xa8,0xa8,0xa8,0xa9,0xa9,0xa9,0xba,0xba,0x8c,0xaa,0xaa,0xbb,0xbb,0xab,0xbc,0xbc, 0xb9,0xb9,0xb9,0x9c,0x9c,0xba,0xba,0xba,0x9d,0x9d,0xbb,0xbb,0xbb,0x9e,0x9e,0xbc, 0xac,0xac,0xac,0x9c,0x9c,0xad,0xad,0x9d,0x9d,0xae,0xae,0xae,0x9e,0x9e,0xaf,0xaf, 0xac,0xac,0xac,0xad,0xad,0xad,0xbe,0xbe,0xae,0xae,0xae,0xbf,0x9e,0xaf,0xaf,0xb0, 0xbd,0xbd,0xbd,0xbe,0xbe,0xbe,0xbe,0xbe,0xae,0xbf,0xbf,0xbf,0xbf,0xaf,0xb0,0xb0, 0xb1,0xb1,0xb1,0xce,0xce,0xb2,0xb2,0xcf,0xcf,0xa2,0xa2,0xb3,0xb3,0xc0,0xb4,0xb4, 0xb1,0xb1,0xb1,0xce,0xce,0xb2,0xb2,0xcf,0xcf,0xa2,0xa2,0xb3,0xb3,0xc0,0xb4,0xb4, 0xb1,0xb1,0xb1,0xc2,0xc2,0xb2,0xb2,0xc3,0xc3,0xa2,0xa2,0xb3,0xb3,0xc0,0xb4,0xb4, 0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xa5,0xc3,0xc3,0xc3,0xa6,0xc4,0xc4,0xc4,0xa7,0xb8, 0xc1,0xc1,0xc1,0xc2,0xc2,0xa5,0xb6,0xc3,0xc3,0xc3,0xa6,0xc4,0xc4,0xc4,0xb8,0xb8, 0xb5,0xb5,0xb5,0xc2,0xa5,0xb6,0xb6,0xb6,0xc3,0xa6,0xa6,0xb7,0xb7,0xc4,0xb8,0xb8, 0xb5,0xb5,0xb5,0xa5,0xb6,0xb6,0xb6,0xb6,0xc3,0xa6,0xb7,0xb7,0xb7,0xb7,0xb8,0xb8, 0xc5,0xc5,0xc5,0xc6,0xc6,0xb6,0xb6,0xc7,0xc7,0xc7,0xb7,0xb7,0xc8,0xc8,0xb8,0xb8, 0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xc6,0xc7,0xc7,0xc7,0xaa,0xc8,0xc8,0xc8,0xab,0xbc, 0xa8,0xa8,0xa8,0xc6,0xc6,0xa9,0xa9,0xc7,0xc7,0xaa,0xaa,0xaa,0xc8,0xc8,0xab,0xbc, 0xa8,0xa8,0xa8,0xa9,0xa9,0xa9,0xba,0xba,0xaa,0xaa,0xaa,0xbb,0xbb,0xab,0xbc,0xbc, 0xb9,0xb9,0xb9,0xca,0xca,0xba,0xba,0xba,0xcb,0xaa,0xbb,0xbb,0xbb,0xcc,0xbc,0xbc, 0xb9,0xb9,0xb9,0xca,0xca,0xba,0xba,0xcb,0xcb,0xcb,0xbb,0xbb,0xcc,0xcc,0xcc,0xbc, 0xc9,0xc9,0xc9,0xca,0xca,0xca,0xba,0xcb,0xcb,0xcb,0xae,0xcc,0xcc,0xcc,0xaf,0xaf, 0xbd,0xbd,0xbd,0xad,0xbe,0xbe,0xbe,0xbe,0xae,0xae,0xbf,0xbf,0xcc,0xaf,0xaf,0xb0, 0xbd,0xbd,0xbd,0xbe,0xbe,0xbe,0xbe,0xbe,0xbf,0xbf,0xbf,0xbf,0xbf,0xaf,0xb0,0xb0, 0xcd,0xcd,0xcd,0xce,0xce,0xce,0xb2,0xcf,0xcf,0xcf,0xb3,0xb3,0xc0,0xc0,0xd1,0xb4, 0xcd,0xcd,0xcd,0xce,0xce,0xce,0xb2,0xcf,0xcf,0xcf,0xb3,0xb3,0xc0,0xc0,0xd1,0xb4, 0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xb2,0xc3,0xc3,0xc3,0xb3,0xb3,0xc0,0xc0,0xd1,0xb4, 0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xc2,0xc3,0xc3,0xc3,0xd4,0xc4,0xc4,0xc4,0xd5,0xd5, 0xc1,0xc1,0xc1,0xc2,0xc2,0xc2,0xb6,0xc3,0xc3,0xc3,0xd4,0xc4,0xc4,0xc4,0xd5,0xb8, 0xc1,0xc1,0xc1,0xc2,0xc2,0xb6,0xb6,0xc3,0xc3,0xd4,0xb7,0xb7,0xc4,0xd5,0xd5,0xb8, 0xb5,0xb5,0xb5,0xc2,0xb6,0xb6,0xb6,0xb6,0xc3,0xd4,0xb7,0xb7,0xb7,0xd5,0xd5,0xb8, 0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xb6,0xc7,0xc7,0xc7,0xb7,0xc8,0xc8,0xc8,0xd9,0xd9, 0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xc6,0xc7,0xc7,0xc7,0xd8,0xc8,0xc8,0xc8,0xd9,0xd9, 0xc5,0xc5,0xc5,0xc6,0xc6,0xd7,0xd7,0xc7,0xc7,0xd8,0xd8,0xc8,0xc8,0xd9,0xd9,0xbc, 0xb9,0xb9,0xb9,0xd7,0xd7,0xba,0xba,0xba,0xd8,0xd8,0xbb,0xbb,0xbb,0xd9,0xd9,0xbc, 0xb9,0xb9,0xb9,0xca,0xca,0xba,0xba,0xcb,0xcb,0xcb,0xbb,0xbb,0xcc,0xcc,0xcc,0xbc, 0xc9,0xc9,0xc9,0xca,0xca,0xca,0xba,0xcb,0xcb,0xcb,0xbb,0xcc,0xcc,0xcc,0xdd,0xdd, 0xc9,0xc9,0xc9,0xca,0xca,0xdb,0xdb,0xcb,0xcb,0xdc,0xdc,0xcc,0xcc,0xdd,0xdd,0xdd, 0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdb,0xdc,0xdc,0xdc,0xdc,0xcc,0xdd,0xdd,0xdd,0xb0, 0xbd,0xbd,0xbd,0xdb,0xbe,0xbe,0xbe,0xdc,0xdc,0xbf,0xbf,0xbf,0xdd,0xdd,0xb0,0xb0, 0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xcf,0xd0,0xd0,0xe1,0xc0,0xc0,0xd1,0xd1,0xe2, 0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xcf,0xd0,0xd0,0xe1,0xc0,0xc0,0xd1,0xd1,0xe2, 0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xc3,0xd0,0xd0,0xe1,0xc0,0xc0,0xd1,0xd1,0xe2, 0xd2,0xd2,0xd2,0xc2,0xd3,0xd3,0xd3,0xc3,0xc3,0xd4,0xd4,0xc4,0xc4,0xd5,0xd5,0xe6, 0xd2,0xd2,0xd2,0xd3,0xd3,0xd3,0xd3,0xc3,0xd4,0xd4,0xd4,0xc4,0xc4,0xd5,0xd5,0xe6, 0xd2,0xd2,0xd2,0xd3,0xd3,0xd3,0xe4,0xc3,0xd4,0xd4,0xe5,0xc4,0xd5,0xd5,0xe6,0xe6, 0xe3,0xe3,0xe3,0xd3,0xd3,0xe4,0xb6,0xd4,0xd4,0xe5,0xe5,0xb7,0xd5,0xd5,0xe6,0xe6, 0xc5,0xc5,0xc5,0xc6,0xc6,0xc6,0xd7,0xc7,0xc7,0xd8,0xd8,0xc8,0xc8,0xd9,0xd9,0xd9, 0xd6,0xd6,0xd6,0xc6,0xd7,0xd7,0xd7,0xc7,0xd8,0xd8,0xd8,0xc8,0xc8,0xd9,0xd9,0xea, 0xd6,0xd6,0xd6,0xd7,0xd7,0xd7,0xe8,0xd8,0xd8,0xd8,0xe9,0xc8,0xd9,0xd9,0xea,0xea, 0xe7,0xe7,0xe7,0xd7,0xd7,0xe8,0xe8,0xd8,0xd8,0xe9,0xe9,0xe9,0xd9,0xd9,0xea,0xea, 0xc9,0xc9,0xc9,0xca,0xca,0xca,0xba,0xcb,0xcb,0xcb,0xe9,0xcc,0xcc,0xcc,0xea,0xea, 0xc9,0xc9,0xc9,0xca,0xca,0xdb,0xdb,0xcb,0xcb,0xdc,0xdc,0xcc,0xcc,0xdd,0xdd,0xdd, 0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdb,0xdc,0xdc,0xdc,0xdc,0xcc,0xdd,0xdd,0xdd,0xee, 0xda,0xda,0xda,0xdb,0xdb,0xec,0xec,0xdc,0xdc,0xed,0xed,0xed,0xdd,0xdd,0xee,0xee, 0xeb,0xeb,0xeb,0xec,0xec,0xec,0xec,0xdc,0xed,0xed,0xed,0xed,0xdd,0xee,0xee,0xee, 0xef,0xef,0xef,0xdf,0xe0,0xe0,0xe0,0xd0,0xd0,0xe1,0xe1,0xf2,0xd1,0xd1,0xe2,0xe2, 0xef,0xef,0xef,0xdf,0xe0,0xe0,0xe0,0xd0,0xd0,0xe1,0xe1,0xf2,0xd1,0xd1,0xe2,0xe2, 0xef,0xef,0xef,0xdf,0xe0,0xe0,0xe0,0xd0,0xd0,0xe1,0xe1,0xf2,0xd1,0xd1,0xe2,0xe2, 0xd2,0xd2,0xd2,0xd3,0xd3,0xe4,0xe4,0xd4,0xd4,0xd4,0xe5,0xe5,0xd5,0xd5,0xe6,0xe6, 0xe3,0xe3,0xe3,0xd3,0xe4,0xe4,0xe4,0xd4,0xd4,0xe5,0xe5,0xf6,0xd5,0xd5,0xe6,0xe6, 0xe3,0xe3,0xe3,0xe4,0xe4,0xe4,0xe4,0xd4,0xe5,0xe5,0xe5,0xf6,0xd5,0xe6,0xe6,0xf7, 0xe3,0xe3,0xe3,0xe4,0xe4,0xe4,0xf5,0xf5,0xe5,0xe5,0xf6,0xf6,0xd5,0xe6,0xe6,0xf7, 0xd6,0xd6,0xd6,0xd7,0xd7,0xd7,0xf5,0xc7,0xd8,0xd8,0xf6,0xc8,0xd9,0xd9,0xd9,0xf7, 0xd6,0xd6,0xd6,0xd7,0xd7,0xe8,0xe8,0xd8,0xd8,0xd8,0xe9,0xe9,0xd9,0xd9,0xea,0xea, 0xe7,0xe7,0xe7,0xd7,0xe8,0xe8,0xe8,0xd8,0xd8,0xe9,0xe9,0xe9,0xd9,0xea,0xea,0xea, 0xe7,0xe7,0xe7,0xe8,0xe8,0xe8,0xf9,0xf9,0xe9,0xe9,0xe9,0xfa,0xd9,0xea,0xea,0xfb, 0xf8,0xf8,0xf8,0xe8,0xf9,0xf9,0xf9,0xcb,0xe9,0xe9,0xfa,0xfa,0xcc,0xea,0xea,0xfb, 0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdb,0xdc,0xdc,0xdc,0xdc,0xcc,0xdd,0xdd,0xdd,0xee, 0xda,0xda,0xda,0xdb,0xdb,0xec,0xec,0xdc,0xdc,0xed,0xed,0xed,0xdd,0xdd,0xee,0xee, 0xeb,0xeb,0xeb,0xec,0xec,0xec,0xec,0xdc,0xed,0xed,0xed,0xed,0xdd,0xee,0xee,0xee, 0xeb,0xeb,0xeb,0xec,0xec,0xfd,0xfd,0xfd,0xed,0xed,0xfe,0xfe,0xee,0xee,0xee,0xff, 0xf0,0xf0,0xf0,0xe0,0xf1,0xf1,0xf1,0xf1,0xe1,0xf2,0xf2,0xf2,0xf2,0xe2,0xe2,0xf3, 0xf0,0xf0,0xf0,0xe0,0xf1,0xf1,0xf1,0xf1,0xe1,0xf2,0xf2,0xf2,0xf2,0xe2,0xe2,0xf3, 0xf0,0xf0,0xf0,0xe0,0xf1,0xf1,0xf1,0xf1,0xe1,0xf2,0xf2,0xf2,0xf2,0xe2,0xe2,0xf3, 0xe3,0xe3,0xe3,0xe4,0xe4,0xe4,0xf5,0xf5,0xe5,0xe5,0xf6,0xf6,0xd5,0xe6,0xe6,0xf7, 0xf4,0xf4,0xf4,0xe4,0xe4,0xf5,0xf5,0xf5,0xe5,0xe5,0xf6,0xf6,0xf6,0xe6,0xe6,0xf7, 0xf4,0xf4,0xf4,0xe4,0xf5,0xf5,0xf5,0xf5,0xe5,0xf6,0xf6,0xf6,0xf6,0xe6,0xf7,0xf7, 0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf5,0xf5,0xe5,0xf6,0xf6,0xf6,0xf6,0xe6,0xf7,0xf7, 0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf5,0xf5,0xd8,0xf6,0xf6,0xf6,0xd9,0xd9,0xf7,0xf7, 0xe7,0xe7,0xe7,0xe8,0xe8,0xe8,0xe8,0xd8,0xe9,0xe9,0xe9,0xfa,0xd9,0xea,0xea,0xea, 0xf8,0xf8,0xf8,0xe8,0xe8,0xf9,0xf9,0xf9,0xe9,0xe9,0xfa,0xfa,0xfa,0xea,0xea,0xfb, 0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xe9,0xfa,0xfa,0xfa,0xfa,0xea,0xfb,0xfb, 0xf8,0xf8,0xf8,0xf9,0xf9,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfa,0xfa,0xea,0xfb,0xfb, 0xf8,0xf8,0xf8,0xdb,0xf9,0xf9,0xf9,0xdc,0xdc,0xfa,0xfa,0xfa,0xdd,0xdd,0xee,0xfb, 0xeb,0xeb,0xeb,0xec,0xec,0xec,0xec,0xdc,0xed,0xed,0xed,0xed,0xdd,0xee,0xee,0xee, 0xeb,0xeb,0xeb,0xec,0xec,0xfd,0xfd,0xfd,0xed,0xed,0xfe,0xfe,0xee,0xee,0xee,0xff, 0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfd,0xed,0xfe,0xfe,0xfe,0xfe,0xee,0xff,0xff, } }; Memcmap *memdefcmap = &def; void _memmkcmap(void){} drawterm-20110822.orig/libmemdraw/cload.c0000644000175000017500000000247211245145712017451 0ustar tinchotincho#include #include #include #include int _cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int y, bpl, c, cnt, offs; uchar mem[NMEM], *memp, *omemp, *emem, *linep, *elinep, *u, *eu; if(!rectinrect(r, i->r)) return -1; bpl = bytesperline(r, i->depth); u = data; eu = data+ndata; memp = mem; emem = mem+NMEM; y = r.min.y; linep = byteaddr(i, Pt(r.min.x, y)); elinep = linep+bpl; for(;;){ if(linep == elinep){ if(++y == r.max.y) break; linep = byteaddr(i, Pt(r.min.x, y)); elinep = linep+bpl; } if(u == eu){ /* buffer too small */ return -1; } c = *u++; if(c >= 128){ for(cnt=c-128+1; cnt!=0 ;--cnt){ if(u == eu){ /* buffer too small */ return -1; } if(linep == elinep){ /* phase error */ return -1; } *linep++ = *u; *memp++ = *u++; if(memp == emem) memp = mem; } } else{ if(u == eu) /* short buffer */ return -1; offs = *u++ + ((c&3)<<8)+1; if(memp-mem < offs) omemp = memp+(NMEM-offs); else omemp = memp-offs; for(cnt=(c>>2)+NMATCH; cnt!=0; --cnt){ if(linep == elinep) /* phase error */ return -1; *linep++ = *omemp; *memp++ = *omemp++; if(omemp == emem) omemp = mem; if(memp == emem) memp = mem; } } } return u-data; } drawterm-20110822.orig/libmemdraw/unload.c0000644000175000017500000000066311245145712017651 0ustar tinchotincho#include #include #include #include int unloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int y, l; uchar *q; if(!rectinrect(r, i->r)) return -1; l = bytesperline(r, i->depth); if(ndata < l*Dy(r)) return -1; ndata = l*Dy(r); q = byteaddr(i, r.min); for(y=r.min.y; ywidth*sizeof(ulong); data += l; } return ndata; } drawterm-20110822.orig/libmemdraw/defont.c0000644000175000017500000000241711245145712017645 0ustar tinchotincho#include #include #include #include Memsubfont* getmemdefont(void) { char *hdr, *p; int n; Fontchar *fc; Memsubfont *f; int ld; Rectangle r; Memdata *md; Memimage *i; /* * make sure data is word-aligned. this is true with Plan 9 compilers * but not in general. the byte order is right because the data is * declared as char*, not ulong*. */ p = (char*)defontdata; n = (uintptr)p & 3; if(n != 0){ memmove(p+(4-n), p, sizeofdefont-n); p += 4-n; } ld = atoi(p+0*12); r.min.x = atoi(p+1*12); r.min.y = atoi(p+2*12); r.max.x = atoi(p+3*12); r.max.y = atoi(p+4*12); md = mallocz(sizeof(Memdata), 1); if(md == nil) return nil; p += 5*12; md->base = nil; /* so freememimage doesn't free p */ md->bdata = (uchar*)p; /* ick */ md->ref = 1; md->allocd = 1; /* so freememimage does free md */ i = allocmemimaged(r, drawld2chan[ld], md, nil); if(i == nil){ free(md); return nil; } hdr = p+Dy(r)*i->width*sizeof(ulong); n = atoi(hdr); p = hdr+3*12; fc = malloc(sizeof(Fontchar)*(n+1)); if(fc == 0){ freememimage(i); return 0; } _unpackinfo(fc, (uchar*)p, n); f = allocmemsubfont("*default*", n, atoi(hdr+12), atoi(hdr+24), fc, i); if(f == 0){ freememimage(i); free(fc); return 0; } return f; } drawterm-20110822.orig/libmemdraw/drawtest.c0000644000175000017500000005562111245145712020230 0ustar tinchotincho#include #include #include #include #include #define DBG if(0) #define RGB2K(r,g,b) ((299*((ulong)(r))+587*((ulong)(g))+114*((ulong)(b)))/1000) /* * This program tests the 'memimagedraw' primitive stochastically. * It tests the combination aspects of it thoroughly, but since the * three images it uses are disjoint, it makes no check of the * correct behavior when images overlap. That is, however, much * easier to get right and to test. */ void drawonepixel(Memimage*, Point, Memimage*, Point, Memimage*, Point); void verifyone(void); void verifyline(void); void verifyrect(void); void verifyrectrepl(int, int); void putpixel(Memimage *img, Point pt, ulong nv); ulong rgbatopix(uchar, uchar, uchar, uchar); char *dchan, *schan, *mchan; int dbpp, sbpp, mbpp; int drawdebug=0; int seed; int niters = 100; int dbpp; /* bits per pixel in destination */ int sbpp; /* bits per pixel in src */ int mbpp; /* bits per pixel in mask */ int dpm; /* pixel mask at high part of byte, in destination */ int nbytes; /* in destination */ int Xrange = 64; int Yrange = 8; Memimage *dst; Memimage *src; Memimage *mask; Memimage *stmp; Memimage *mtmp; Memimage *ones; uchar *dstbits; uchar *srcbits; uchar *maskbits; ulong *savedstbits; void rdb(void) { } int iprint(char *fmt, ...) { int n; va_list va; char buf[1024]; va_start(va, fmt); n = doprint(buf, buf+sizeof buf, fmt, va) - buf; va_end(va); write(1,buf,n); return 1; } void main(int argc, char *argv[]) { memimageinit(); seed = time(0); ARGBEGIN{ case 'x': Xrange = atoi(ARGF()); break; case 'y': Yrange = atoi(ARGF()); break; case 'n': niters = atoi(ARGF()); break; case 's': seed = atoi(ARGF()); break; }ARGEND dchan = "r8g8b8"; schan = "r8g8b8"; mchan = "r8g8b8"; switch(argc){ case 3: mchan = argv[2]; case 2: schan = argv[1]; case 1: dchan = argv[0]; case 0: break; default: goto Usage; Usage: fprint(2, "usage: dtest [dchan [schan [mchan]]]\n"); exits("usage"); } fmtinstall('b', numbconv); /* binary! */ fprint(2, "%s -x %d -y %d -s 0x%x %s %s %s\n", argv0, Xrange, Yrange, seed, dchan, schan, mchan); srand(seed); dst = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(dchan)); src = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan)); mask = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan)); stmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan)); mtmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan)); ones = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan)); // print("chan %lux %lux %lux %lux %lux %lux\n", dst->chan, src->chan, mask->chan, stmp->chan, mtmp->chan, ones->chan); if(dst==0 || src==0 || mask==0 || mtmp==0 || ones==0) { Alloc: fprint(2, "dtest: allocation failed: %r\n"); exits("alloc"); } nbytes = (4*Xrange+4)*Yrange; srcbits = malloc(nbytes); dstbits = malloc(nbytes); maskbits = malloc(nbytes); savedstbits = malloc(nbytes); if(dstbits==0 || srcbits==0 || maskbits==0 || savedstbits==0) goto Alloc; dbpp = dst->depth; sbpp = src->depth; mbpp = mask->depth; dpm = 0xFF ^ (0xFF>>dbpp); memset(ones->data->bdata, 0xFF, ones->width*sizeof(ulong)*Yrange); fprint(2, "dtest: verify single pixel operation\n"); verifyone(); fprint(2, "dtest: verify full line non-replicated\n"); verifyline(); fprint(2, "dtest: verify full rectangle non-replicated\n"); verifyrect(); fprint(2, "dtest: verify full rectangle source replicated\n"); verifyrectrepl(1, 0); fprint(2, "dtest: verify full rectangle mask replicated\n"); verifyrectrepl(0, 1); fprint(2, "dtest: verify full rectangle source and mask replicated\n"); verifyrectrepl(1, 1); exits(0); } /* * Dump out an ASCII representation of an image. The label specifies * a list of characters to put at various points in the picture. */ static void Bprintr5g6b5(Biobuf *bio, char*, ulong v) { int r,g,b; r = (v>>11)&31; g = (v>>5)&63; b = v&31; Bprint(bio, "%.2x%.2x%.2x", r,g,b); } static void Bprintr5g5b5a1(Biobuf *bio, char*, ulong v) { int r,g,b,a; r = (v>>11)&31; g = (v>>6)&31; b = (v>>1)&31; a = v&1; Bprint(bio, "%.2x%.2x%.2x%.2x", r,g,b,a); } void dumpimage(char *name, Memimage *img, void *vdata, Point labelpt) { Biobuf b; uchar *data; uchar *p; char *arg; void (*fmt)(Biobuf*, char*, ulong); int npr, x, y, nb, bpp; ulong v, mask; Rectangle r; fmt = nil; arg = nil; switch(img->depth){ case 1: case 2: case 4: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.1ux"; break; case 8: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.2ux"; break; case 16: arg = nil; if(img->chan == RGB16) fmt = Bprintr5g6b5; else{ fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.4ux"; } break; case 24: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.6lux"; break; case 32: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.8lux"; break; } if(fmt == nil){ fprint(2, "bad format\n"); abort(); } r = img->r; Binit(&b, 2, OWRITE); data = vdata; bpp = img->depth; Bprint(&b, "%s\t%d\tr %R clipr %R repl %d data %p *%P\n", name, r.min.x, r, img->clipr, (img->flags&Frepl) ? 1 : 0, vdata, labelpt); mask = (1ULL<data->bdata); Bprint(&b, "%-4d\t", y); // for(x=r.min.x; x>nb)&mask); } Bprint(&b, "\n"); } Bterm(&b); } /* * Verify that the destination pixel has the specified value. * The value is in the high bits of v, suitably masked, but must * be extracted from the destination Memimage. */ void checkone(Point p, Point sp, Point mp) { int delta; uchar *dp, *sdp; delta = (uchar*)byteaddr(dst, p)-(uchar*)dst->data->bdata; dp = (uchar*)dst->data->bdata+delta; sdp = (uchar*)savedstbits+delta; if(memcmp(dp, sdp, (dst->depth+7)/8) != 0) { fprint(2, "dtest: one bad pixel drawing at dst %P from source %P mask %P\n", p, sp, mp); fprint(2, " %.2ux %.2ux %.2ux %.2ux should be %.2ux %.2ux %.2ux %.2ux\n", dp[0], dp[1], dp[2], dp[3], sdp[0], sdp[1], sdp[2], sdp[3]); fprint(2, "addresses dst %p src %p mask %p\n", dp, byteaddr(src, sp), byteaddr(mask, mp)); dumpimage("src", src, src->data->bdata, sp); dumpimage("mask", mask, mask->data->bdata, mp); dumpimage("origdst", dst, dstbits, p); dumpimage("dst", dst, dst->data->bdata, p); dumpimage("gooddst", dst, savedstbits, p); abort(); } } /* * Verify that the destination line has the same value as the saved line. */ #define RECTPTS(r) (r).min.x, (r).min.y, (r).max.x, (r).max.y void checkline(Rectangle r, Point sp, Point mp, int y, Memimage *stmp, Memimage *mtmp) { ulong *dp; int nb; ulong *saved; dp = wordaddr(dst, Pt(0, y)); saved = savedstbits + y*dst->width; if(dst->depth < 8) nb = Xrange/(8/dst->depth); else nb = Xrange*(dst->depth/8); if(memcmp(dp, saved, nb) != 0){ fprint(2, "dtest: bad line at y=%d; saved %p dp %p\n", y, saved, dp); fprint(2, "draw dst %R src %P mask %P\n", r, sp, mp); dumpimage("src", src, src->data->bdata, sp); if(stmp) dumpimage("stmp", stmp, stmp->data->bdata, sp); dumpimage("mask", mask, mask->data->bdata, mp); if(mtmp) dumpimage("mtmp", mtmp, mtmp->data->bdata, mp); dumpimage("origdst", dst, dstbits, r.min); dumpimage("dst", dst, dst->data->bdata, r.min); dumpimage("gooddst", dst, savedstbits, r.min); abort(); } } /* * Fill the bits of an image with random data. * The Memimage parameter is used only to make sure * the data is well formatted: only ucbits is written. */ void fill(Memimage *img, uchar *ucbits) { int i, x, y; ushort *up; uchar alpha, r, g, b; void *data; if((img->flags&Falpha) == 0){ up = (ushort*)ucbits; for(i=0; i> 7; if(i+i != nbytes) *(uchar*)up = lrand() >> 7; }else{ data = img->data->bdata; img->data->bdata = ucbits; for(x=img->r.min.x; xr.max.x; x++) for(y=img->r.min.y; yr.max.y; y++){ alpha = rand() >> 4; r = rand()%(alpha+1); g = rand()%(alpha+1); b = rand()%(alpha+1); putpixel(img, Pt(x,y), rgbatopix(r,g,b,alpha)); } img->data->bdata = data; } } /* * Mask is preset; do the rest */ void verifyonemask(void) { Point dp, sp, mp; fill(dst, dstbits); fill(src, srcbits); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); dp.x = nrand(Xrange); dp.y = nrand(Yrange); sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange); drawonepixel(dst, dp, src, sp, mask, mp); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); memmove(savedstbits, dst->data->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memimagedraw(dst, Rect(dp.x, dp.y, dp.x+1, dp.y+1), src, sp, mask, mp, SoverD); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); checkone(dp, sp, mp); } void verifyone(void) { int i; /* mask all zeros */ memset(maskbits, 0, nbytes); for(i=0; idata->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); dr.min.x = nrand(Xrange-1); dr.min.y = nrand(Yrange-1); dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x); dr.max.y = dr.min.y + 1; sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange); tp = sp; up = mp; for(x=dr.min.x; xdata->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memimagedraw(dst, dr, src, sp, mask, mp, SoverD); checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), dr.min.y, nil, nil); } void verifyline(void) { int i; /* mask all ones */ memset(maskbits, 0xFF, nbytes); for(i=0; idata->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); dr.min.x = nrand(Xrange-1); dr.min.y = nrand(Yrange-1); dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x); dr.max.y = dr.min.y + 1 + nrand(Yrange-1-dr.min.y); sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange); tp = sp; up = mp; for(y=dr.min.y; ydata->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memimagedraw(dst, dr, src, sp, mask, mp, SoverD); for(y=0; yr, sp), drawrepl(mask->r, mp), y, nil, nil); } void verifyrect(void) { int i; /* mask all zeros */ memset(maskbits, 0, nbytes); for(i=0; ir) */ r.min.x = nrand(Xrange-1); r.min.y = nrand(Yrange-1); /* make it trivial more often than pure chance allows */ switch(lrand()&0){ case 1: r.max.x = r.min.x + 2; r.max.y = r.min.y + 2; if(r.max.x < Xrange && r.max.y < Yrange) break; /* fall through */ case 0: r.max.x = r.min.x + 1; r.max.y = r.min.y + 1; break; default: if(r.min.x+3 >= Xrange) r.max.x = Xrange; else r.max.x = r.min.x+3 + nrand(Xrange-(r.min.x+3)); if(r.min.y+3 >= Yrange) r.max.y = Yrange; else r.max.y = r.min.y+3 + nrand(Yrange-(r.min.y+3)); } assert(r.min.x >= 0); assert(r.max.x <= Xrange); assert(r.min.y >= 0); assert(r.max.y <= Yrange); /* copy from i to tmp so we have just the replicated bits */ nb = tmp->width*sizeof(ulong)*Yrange; memset(tmp->data->bdata, 0, nb); memimagedraw(tmp, r, i, r.min, ones, r.min, SoverD); memmove(i->data->bdata, tmp->data->bdata, nb); /* i is now a non-replicated instance of the replication */ /* replicate it by hand through tmp */ memset(tmp->data->bdata, 0, nb); x = -(tilexy(r.min.x, r.max.x, 0)-r.min.x); for(; xflags |= Frepl; i->r = r; i->clipr = randrect(); // fprint(2, "replicate [[%d %d] [%d %d]] [[%d %d][%d %d]]\n", r.min.x, r.min.y, r.max.x, r.max.y, // i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y); tmp->clipr = i->clipr; } /* * Mask is preset; do the rest */ void verifyrectmaskrepl(int srcrepl, int maskrepl) { Point sp, mp, tp, up; Rectangle dr; int x, y; Memimage *s, *m; // print("verfrect %d %d\n", srcrepl, maskrepl); src->flags &= ~Frepl; src->r = Rect(0, 0, Xrange, Yrange); src->clipr = src->r; stmp->flags &= ~Frepl; stmp->r = Rect(0, 0, Xrange, Yrange); stmp->clipr = src->r; mask->flags &= ~Frepl; mask->r = Rect(0, 0, Xrange, Yrange); mask->clipr = mask->r; mtmp->flags &= ~Frepl; mtmp->r = Rect(0, 0, Xrange, Yrange); mtmp->clipr = mask->r; fill(dst, dstbits); fill(src, srcbits); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); if(srcrepl){ replicate(src, stmp); s = stmp; }else s = src; if(maskrepl){ replicate(mask, mtmp); m = mtmp; }else m = mask; dr = randrect(); sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange); DBG print("smalldraws\n"); for(tp.y=sp.y,up.y=mp.y,y=dr.min.y; ydata->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); DBG print("bigdraw\n"); memimagedraw(dst, dr, src, sp, mask, mp, SoverD); for(y=0; yr, sp), drawrepl(mask->r, mp), y, srcrepl?stmp:nil, maskrepl?mtmp:nil); } void verifyrectrepl(int srcrepl, int maskrepl) { int i; /* mask all ones */ memset(maskbits, 0xFF, nbytes); for(i=0; i>= (nhave-nwant); return v & ((1<>24; *r = v>>16; *g = v>>8; *b = v; } /* * Convert uchar channels into ulong pixel. */ ulong rgbatopix(uchar r, uchar g, uchar b, uchar a) { return (a<<24)|(r<<16)|(g<<8)|b; } /* * Retrieve the pixel value at pt in the image. */ ulong getpixel(Memimage *img, Point pt) { uchar r, g, b, a, *p; int nbits, npack, bpp; ulong v, c, rbits, bits; r = g = b = 0; a = ~0; /* default alpha is full */ p = byteaddr(img, pt); v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24); bpp = img->depth; if(bpp<8){ /* * Sub-byte greyscale pixels. * * We want to throw away the top pt.x%npack pixels and then use the next bpp bits * in the bottom byte of v. This madness is due to having big endian bits * but little endian bytes. */ npack = 8/bpp; v >>= 8 - bpp*(pt.x%npack+1); v &= (1<chan; c; c>>=8){ nbits = NBITS(c); bits = v & ((1<>= nbits; switch(TYPE(c)){ case CRed: r = rbits; break; case CGreen: g = rbits; break; case CBlue: b = rbits; break; case CGrey: r = g = b = rbits; break; case CAlpha: a = rbits; break; case CMap: p = img->cmap->cmap2rgb + 3*bits; r = p[0]; g = p[1]; b = p[2]; break; case CIgnore: break; default: fprint(2, "unknown channel type %lud\n", TYPE(c)); abort(); } } } return rgbatopix(r, g, b, a); } /* * Return the greyscale equivalent of a pixel. */ uchar getgrey(Memimage *img, Point pt) { uchar r, g, b, a; pixtorgba(getpixel(img, pt), &r, &g, &b, &a); return RGB2K(r, g, b); } /* * Return the value at pt in image, if image is interpreted * as a mask. This means the alpha channel if present, else * the greyscale or its computed equivalent. */ uchar getmask(Memimage *img, Point pt) { if(img->flags&Falpha) return getpixel(img, pt)>>24; else return getgrey(img, pt); } #undef DBG #define DBG if(0) /* * Write a pixel to img at point pt. * * We do this by reading a 32-bit little endian * value from p and then writing it back * after tweaking the appropriate bits. Because * the data is little endian, we don't have to worry * about what the actual depth is, as long as it is * less than 32 bits. */ void putpixel(Memimage *img, Point pt, ulong nv) { uchar r, g, b, a, *p, *q; ulong c, mask, bits, v; int bpp, sh, npack, nbits; pixtorgba(nv, &r, &g, &b, &a); p = byteaddr(img, pt); v = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24); bpp = img->depth; DBG print("v %.8lux...", v); if(bpp < 8){ /* * Sub-byte greyscale pixels. We need to skip the leftmost pt.x%npack pixels, * which is equivalent to skipping the rightmost npack - pt.x%npack - 1 pixels. */ npack = 8/bpp; sh = bpp*(npack - pt.x%npack - 1); bits = RGB2K(r,g,b); DBG print("repl %lux 8 %d = %lux...", bits, bpp, replbits(bits, 8, bpp)); bits = replbits(bits, 8, bpp); mask = (1<chan; c; c>>=8){ nbits = NBITS(c); switch(TYPE(c)){ case CRed: bits = r; break; case CGreen: bits = g; break; case CBlue: bits = b; break; case CGrey: bits = RGB2K(r, g, b); break; case CAlpha: bits = a; break; case CIgnore: bits = 0; break; case CMap: q = img->cmap->rgb2cmap; bits = q[(r>>4)*16*16+(g>>4)*16+(b>>4)]; break; default: SET(bits); fprint(2, "unknown channel type %lud\n", TYPE(c)); abort(); } DBG print("repl %lux 8 %d = %lux...", bits, nbits, replbits(bits, 8, nbits)); if(TYPE(c) != CMap) bits = replbits(bits, 8, nbits); mask = (1<>8; p[2] = v>>16; p[3] = v>>24; } #undef DBG #define DBG if(0) void drawonepixel(Memimage *dst, Point dp, Memimage *src, Point sp, Memimage *mask, Point mp) { uchar m, M, sr, sg, sb, sa, sk, dr, dg, db, da, dk; pixtorgba(getpixel(dst, dp), &dr, &dg, &db, &da); pixtorgba(getpixel(src, sp), &sr, &sg, &sb, &sa); m = getmask(mask, mp); M = 255-(sa*m)/255; DBG print("dst %x %x %x %x src %x %x %x %x m %x = ", dr,dg,db,da, sr,sg,sb,sa, m); if(dst->flags&Fgrey){ /* * We need to do the conversion to grey before the alpha calculation * because the draw operator does this, and we need to be operating * at the same precision so we get exactly the same answers. */ sk = RGB2K(sr, sg, sb); dk = RGB2K(dr, dg, db); dk = (sk*m + dk*M)/255; dr = dg = db = dk; da = (sa*m + da*M)/255; }else{ /* * True color alpha calculation treats all channels (including alpha) * the same. It might have been nice to use an array, but oh well. */ dr = (sr*m + dr*M)/255; dg = (sg*m + dg*M)/255; db = (sb*m + db*M)/255; da = (sa*m + da*M)/255; } DBG print("%x %x %x %x\n", dr,dg,db,da); putpixel(dst, dp, rgbatopix(dr, dg, db, da)); } drawterm-20110822.orig/libmemdraw/cread.c0000644000175000017500000000367611245145712017454 0ustar tinchotincho#include #include #include #include Memimage* creadmemimage(int fd) { char hdr[5*12+1]; Rectangle r; int m, nb, miny, maxy, new, ldepth, ncblock; uchar *buf; Memimage *i; ulong chan; if(readn(fd, hdr, 5*12) != 5*12){ werrstr("readmemimage: short header (2)"); return nil; } /* * distinguish new channel descriptor from old ldepth. * channel descriptors have letters as well as numbers, * while ldepths are a single digit formatted as %-11d. */ new = 0; for(m=0; m<10; m++){ if(hdr[m] != ' '){ new = 1; break; } } if(hdr[11] != ' '){ werrstr("creadimage: bad format"); return nil; } if(new){ hdr[11] = '\0'; if((chan = strtochan(hdr)) == 0){ werrstr("creadimage: bad channel string %s", hdr); return nil; } }else{ ldepth = ((int)hdr[10])-'0'; if(ldepth<0 || ldepth>3){ werrstr("creadimage: bad ldepth %d", ldepth); return nil; } chan = drawld2chan[ldepth]; } r.min.x=atoi(hdr+1*12); r.min.y=atoi(hdr+2*12); r.max.x=atoi(hdr+3*12); r.max.y=atoi(hdr+4*12); if(r.min.x>r.max.x || r.min.y>r.max.y){ werrstr("creadimage: bad rectangle"); return nil; } i = allocmemimage(r, chan); if(i == nil) return nil; ncblock = _compblocksize(r, i->depth); buf = malloc(ncblock); if(buf == nil) goto Errout; miny = r.min.y; while(miny != r.max.y){ if(readn(fd, hdr, 2*12) != 2*12){ Shortread: werrstr("readmemimage: short read"); Errout: freememimage(i); free(buf); return nil; } maxy = atoi(hdr+0*12); nb = atoi(hdr+1*12); if(maxy<=miny || r.max.y #include #include #include #include /* * ellipse(dst, c, a, b, t, src, sp) * draws an ellipse centered at c with semiaxes a,b>=0 * and semithickness t>=0, or filled if t<0. point sp * in src maps to c in dst * * very thick skinny ellipses are brushed with circles (slow) * others are approximated by filling between 2 ellipses * criterion for very thick when b 0.5*x/(1-x) * where x = b/a */ typedef struct Param Param; typedef struct State State; static void bellipse(int, State*, Param*); static void erect(int, int, int, int, Param*); static void eline(int, int, int, int, Param*); struct Param { Memimage *dst; Memimage *src; Point c; int t; Point sp; Memimage *disc; int op; }; /* * denote residual error by e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 * e(x,y) = 0 on ellipse, e(x,y) < 0 inside, e(x,y) > 0 outside */ struct State { int a; int x; vlong a2; /* a^2 */ vlong b2; /* b^2 */ vlong b2x; /* b^2 * x */ vlong a2y; /* a^2 * y */ vlong c1; vlong c2; /* test criteria */ vlong ee; /* ee = e(x+1/2,y-1/2) - (a^2+b^2)/4 */ vlong dxe; vlong dye; vlong d2xe; vlong d2ye; }; static State* newstate(State *s, int a, int b) { s->x = 0; s->a = a; s->a2 = (vlong)(a*a); s->b2 = (vlong)(b*b); s->b2x = (vlong)0; s->a2y = s->a2*(vlong)b; s->c1 = -((s->a2>>2) + (vlong)(a&1) + s->b2); s->c2 = -((s->b2>>2) + (vlong)(b&1)); s->ee = -s->a2y; s->dxe = (vlong)0; s->dye = s->ee<<1; s->d2xe = s->b2<<1; s->d2ye = s->a2<<1; return s; } /* * return x coord of rightmost pixel on next scan line */ static int step(State *s) { while(s->x < s->a) { if(s->ee+s->b2x <= s->c1 || /* e(x+1,y-1/2) <= 0 */ s->ee+s->a2y <= s->c2) { /* e(x+1/2,y) <= 0 (rare) */ s->dxe += s->d2xe; s->ee += s->dxe; s->b2x += s->b2; s->x++; continue; } s->dye += s->d2ye; s->ee += s->dye; s->a2y -= s->a2; if(s->ee-s->a2y <= s->c2) { /* e(x+1/2,y-1) <= 0 */ s->dxe += s->d2xe; s->ee += s->dxe; s->b2x += s->b2; return s->x++; } break; } return s->x; } void memellipse(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int op) { State in, out; int y, inb, inx, outx, u; Param p; if(a < 0) a = -a; if(b < 0) b = -b; p.dst = dst; p.src = src; p.c = c; p.t = t; p.sp = subpt(sp, c); p.disc = nil; p.op = op; u = (t<<1)*(a-b); if((bb*b) || (aa*a)) { /* if(bb*b/a || aa*a/b) # very thick */ bellipse(b, newstate(&in, a, b), &p); return; } if(t < 0) { inb = -1; newstate(&out, a, y = b); } else { inb = b - t; newstate(&out, a+t, y = b+t); } if(t > 0) newstate(&in, a-t, inb); inx = 0; for( ; y>=0; y--) { outx = step(&out); if(y > inb) { erect(-outx, y, outx, y, &p); if(y != 0) erect(-outx, -y, outx, -y, &p); continue; } if(t > 0) { inx = step(&in); if(y == inb) inx = 0; } else if(inx > outx) inx = outx; erect(inx, y, outx, y, &p); if(y != 0) erect(inx, -y, outx, -y, &p); erect(-outx, y, -inx, y, &p); if(y != 0) erect(-outx, -y, -inx, -y, &p); inx = outx + 1; } } static Point p00 = {0, 0}; /* * a brushed ellipse */ static void bellipse(int y, State *s, Param *p) { int t, ox, oy, x, nx; t = p->t; p->disc = allocmemimage(Rect(-t,-t,t+1,t+1), GREY1); if(p->disc == nil) return; memfillcolor(p->disc, DTransparent); memellipse(p->disc, p00, t, t, -1, memopaque, p00, p->op); oy = y; ox = 0; nx = x = step(s); do { while(nx==x && y-->0) nx = step(s); y++; eline(-x,-oy,-ox, -y, p); eline(ox,-oy, x, -y, p); eline(-x, y,-ox, oy, p); eline(ox, y, x, oy, p); ox = x+1; x = nx; y--; oy = y; } while(oy > 0); } /* * a rectangle with closed (not half-open) coordinates expressed * relative to the center of the ellipse */ static void erect(int x0, int y0, int x1, int y1, Param *p) { Rectangle r; /* print("R %d,%d %d,%d\n", x0, y0, x1, y1); */ r = Rect(p->c.x+x0, p->c.y+y0, p->c.x+x1+1, p->c.y+y1+1); memdraw(p->dst, r, p->src, addpt(p->sp, r.min), memopaque, p00, p->op); } /* * a brushed point similarly specified */ static void epoint(int x, int y, Param *p) { Point p0; Rectangle r; /* print("P%d %d,%d\n", p->t, x, y); */ p0 = Pt(p->c.x+x, p->c.y+y); r = Rpt(addpt(p0, p->disc->r.min), addpt(p0, p->disc->r.max)); memdraw(p->dst, r, p->src, addpt(p->sp, r.min), p->disc, p->disc->r.min, p->op); } /* * a brushed horizontal or vertical line similarly specified */ static void eline(int x0, int y0, int x1, int y1, Param *p) { /* print("L%d %d,%d %d,%d\n", p->t, x0, y0, x1, y1); */ if(x1 > x0+1) erect(x0+1, y0-p->t, x1-1, y1+p->t, p); else if(y1 > y0+1) erect(x0-p->t, y0+1, x1+p->t, y1-1, p); epoint(x0, y0, p); if(x1-x0 || y1-y0) epoint(x1, y1, p); } drawterm-20110822.orig/libmemdraw/read.c0000644000175000017500000000415711245145712017304 0ustar tinchotincho#include #include #include #include Memimage* readmemimage(int fd) { char hdr[5*12+1]; int dy; ulong chan; uint l, n; int m, j; int new, miny, maxy; Rectangle r; uchar *tmp; int ldepth, chunk; Memimage *i; if(readn(fd, hdr, 11) != 11){ werrstr("readimage: short header"); return nil; } if(memcmp(hdr, "compressed\n", 11) == 0) return creadmemimage(fd); if(readn(fd, hdr+11, 5*12-11) != 5*12-11){ werrstr("readimage: short header (2)"); return nil; } /* * distinguish new channel descriptor from old ldepth. * channel descriptors have letters as well as numbers, * while ldepths are a single digit formatted as %-11d. */ new = 0; for(m=0; m<10; m++){ if(hdr[m] != ' '){ new = 1; break; } } if(hdr[11] != ' '){ werrstr("readimage: bad format"); return nil; } if(new){ hdr[11] = '\0'; if((chan = strtochan(hdr)) == 0){ werrstr("readimage: bad channel string %s", hdr); return nil; } }else{ ldepth = ((int)hdr[10])-'0'; if(ldepth<0 || ldepth>3){ werrstr("readimage: bad ldepth %d", ldepth); return nil; } chan = drawld2chan[ldepth]; } r.min.x = atoi(hdr+1*12); r.min.y = atoi(hdr+2*12); r.max.x = atoi(hdr+3*12); r.max.y = atoi(hdr+4*12); if(r.min.x>r.max.x || r.min.y>r.max.y){ werrstr("readimage: bad rectangle"); return nil; } miny = r.min.y; maxy = r.max.y; l = bytesperline(r, chantodepth(chan)); i = allocmemimage(r, chan); if(i == nil) return nil; chunk = 32*1024; if(chunk < l) chunk = l; tmp = malloc(chunk); if(tmp == nil) goto Err; while(maxy > miny){ dy = maxy - miny; if(dy*l > chunk) dy = chunk/l; if(dy <= 0){ werrstr("readmemimage: image too wide for buffer"); goto Err; } n = dy*l; m = readn(fd, tmp, n); if(m != n){ werrstr("readmemimage: read count %d not %d: %r", m, n); Err: freememimage(i); free(tmp); return nil; } if(!new) /* an old image: must flip all the bits */ for(j=0; j #include #include #include #include void mempoly(Memimage *dst, Point *vert, int nvert, int end0, int end1, int radius, Memimage *src, Point sp, int op) { int i, e0, e1; Point d; if(nvert < 2) return; d = subpt(sp, vert[0]); for(i=1; i #include #include #include #include Point memimagestring(Memimage *b, Point p, Memimage *color, Point cp, Memsubfont *f, char *cs) { int w, width; uchar *s; Rune c; Fontchar *i; s = (uchar*)cs; for(; (c=*s); p.x+=width, cp.x+=width){ width = 0; if(c < Runeself) s++; else{ w = chartorune(&c, (char*)s); if(w == 0){ s++; continue; } s += w; } if(c >= f->n) continue; // i = f->info+c; i = &(f->info[c]); width = i->width; memdraw(b, Rect(p.x+i->left, p.y+i->top, p.x+i->left+(i[1].x-i[0].x), p.y+i->bottom), color, cp, f->bits, Pt(i->x, i->top), SoverD); } return p; } Point memsubfontwidth(Memsubfont *f, char *cs) { Rune c; Point p; uchar *s; Fontchar *i; int w, width; p = Pt(0, f->height); s = (uchar*)cs; for(; (c=*s); p.x+=width){ width = 0; if(c < Runeself) s++; else{ w = chartorune(&c, (char*)s); if(w == 0){ s++; continue; } s += w; } if(c >= f->n) continue; i = f->info+c; width = i->width; } return p; } drawterm-20110822.orig/libmemdraw/times0000644000175000017500000000111211245145712017255 0ustar tinchotinchodraw1: 6M for draw 0,0,100,100 no repl draw3: 4M for draw 0,0,100,100 no repl just read src, dst - 250k mask reading - 650k write dst - 100k alpha calculation - 3000k olddraw: 10M for draw 0, 0, 1000, 1000 no repl all ldepth 3 44M for draw 0, 0, 1000, 1000 src, mask ldepth 2 dst ldepth 3 draw4: 160M for draw 0, 0, 1000, 1000 no repl all r8g8b8 null loop: 10k src, dst reading: 13-15M each mask reading: 30M alpha calculation loop: 90M null alpha loop: 2M minimal loop control +20M alpha calculation with divides +190M alpha calculation wtih shifts +70M writeback: 11M drawterm-20110822.orig/libmemdraw/arc.c0000644000175000017500000000506011245145712017130 0ustar tinchotincho#include #include #include #include #include /* * elarc(dst,c,a,b,t,src,sp,alpha,phi) * draws the part of an ellipse between rays at angles alpha and alpha+phi * measured counterclockwise from the positive x axis. other * arguments are as for ellipse(dst,c,a,b,t,src,sp) */ enum { R, T, L, B /* right, top, left, bottom */ }; static Point corners[] = { {1,1}, {-1,1}, {-1,-1}, {1,-1} }; static Point p00; /* * make a "wedge" mask covering the desired angle and contained in * a surrounding square; draw a full ellipse; intersect that with the * wedge to make a mask through which to copy src to dst. */ void memarc(Memimage *dst, Point c, int a, int b, int t, Memimage *src, Point sp, int alpha, int phi, int op) { int i, w, beta, tmp, c1, c2, m, m1; Rectangle rect; Point p, bnd[8]; Memimage *wedge, *figure, *mask; if(a < 0) a = -a; if(b < 0) b = -b; w = t; if(w < 0) w = 0; alpha = -alpha; /* compensate for upside-down coords */ phi = -phi; beta = alpha + phi; if(phi < 0){ tmp = alpha; alpha = beta; beta = tmp; phi = -phi; } if(phi >= 360){ memellipse(dst, c, a, b, t, src, sp, op); return; } while(alpha < 0) alpha += 360; while(beta < 0) beta += 360; c1 = alpha/90 & 3; /* number of nearest corner */ c2 = beta/90 & 3; /* * icossin returns point at radius ICOSSCALE. * multiplying by m1 moves it outside the ellipse */ rect = Rect(-a-w, -b-w, a+w+1, b+w+1); m = rect.max.x; /* inradius of bounding square */ if(m < rect.max.y) m = rect.max.y; m1 = (m+ICOSSCALE-1) >> 10; m = m1 << 10; /* assure m1*cossin is inside */ i = 0; bnd[i++] = Pt(0,0); icossin(alpha, &p.x, &p.y); bnd[i++] = mulpt(p, m1); for(;;) { bnd[i++] = mulpt(corners[c1], m); if(c1==c2 && phi<180) break; c1 = (c1+1) & 3; phi -= 90; } icossin(beta, &p.x, &p.y); bnd[i++] = mulpt(p, m1); figure = nil; mask = nil; wedge = allocmemimage(rect, GREY1); if(wedge == nil) goto Return; memfillcolor(wedge, DTransparent); memfillpoly(wedge, bnd, i, ~0, memopaque, p00, S); figure = allocmemimage(rect, GREY1); if(figure == nil) goto Return; memfillcolor(figure, DTransparent); memellipse(figure, p00, a, b, t, memopaque, p00, S); mask = allocmemimage(rect, GREY1); if(mask == nil) goto Return; memfillcolor(mask, DTransparent); memimagedraw(mask, rect, figure, rect.min, wedge, rect.min, S); c = subpt(c, dst->r.min); memdraw(dst, dst->r, src, subpt(sp, c), mask, subpt(p00, c), op); Return: freememimage(wedge); freememimage(figure); freememimage(mask); } drawterm-20110822.orig/libmemdraw/line.c0000644000175000017500000002546311245145712017323 0ustar tinchotincho#include #include #include #include #include enum { Arrow1 = 8, Arrow2 = 10, Arrow3 = 3, }; #ifdef NOT static int lmin(int a, int b) { if(a < b) return a; return b; } #endif static int lmax(int a, int b) { if(a > b) return a; return b; } #ifdef NOTUSED /* * Rather than line clip, we run the Bresenham loop over the full line, * and clip on each pixel. This is more expensive but means that * lines look the same regardless of how the windowing has tiled them. * For speed, we check for clipping outside the loop and make the * test easy when possible. */ static void horline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr) { int x, y, dy, deltay, deltax, maxx; int dd, easy, e, bpp, m, m0; uchar *d; deltax = p1.x - p0.x; deltay = p1.y - p0.y; dd = dst->width*sizeof(ulong); dy = 1; if(deltay < 0){ dd = -dd; deltay = -deltay; dy = -1; } maxx = lmin(p1.x, clipr.max.x-1); bpp = dst->depth; m0 = 0xFF^(0xFF>>bpp); m = m0 >> (p0.x&(7/dst->depth))*bpp; easy = ptinrect(p0, clipr) && ptinrect(p1, clipr); e = 2*deltay - deltax; y = p0.y; d = byteaddr(dst, p0); deltay *= 2; deltax = deltay - 2*deltax; for(x=p0.x; x<=maxx; x++){ if(easy || (clipr.min.x<=x && clipr.min.y<=y && y 0){ y += dy; d += dd; e += deltax; }else e += deltay; d++; m >>= bpp; if(m == 0) m = m0; } } static void verline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr) { int x, y, deltay, deltax, maxy; int easy, e, bpp, m, m0, dd; uchar *d; deltax = p1.x - p0.x; deltay = p1.y - p0.y; dd = 1; if(deltax < 0){ dd = -1; deltax = -deltax; } maxy = lmin(p1.y, clipr.max.y-1); bpp = dst->depth; m0 = 0xFF^(0xFF>>bpp); m = m0 >> (p0.x&(7/dst->depth))*bpp; easy = ptinrect(p0, clipr) && ptinrect(p1, clipr); e = 2*deltax - deltay; x = p0.x; d = byteaddr(dst, p0); deltax *= 2; deltay = deltax - 2*deltay; for(y=p0.y; y<=maxy; y++){ if(easy || (clipr.min.y<=y && clipr.min.x<=x && x 0){ x += dd; d += dd; e += deltay; }else e += deltax; d += dst->width*sizeof(ulong); m >>= bpp; if(m == 0) m = m0; } } static void horliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) { int x, y, sx, sy, deltay, deltax, minx, maxx; int bpp, m, m0; uchar *d, *s; deltax = p1.x - p0.x; deltay = p1.y - p0.y; sx = drawreplxy(src->r.min.x, src->r.max.x, p0.x+dsrc.x); minx = lmax(p0.x, clipr.min.x); maxx = lmin(p1.x, clipr.max.x-1); bpp = dst->depth; m0 = 0xFF^(0xFF>>bpp); m = m0 >> (minx&(7/dst->depth))*bpp; for(x=minx; x<=maxx; x++){ y = p0.y + (deltay*(x-p0.x)+deltax/2)/deltax; if(clipr.min.y<=y && yr.min.y, src->r.max.y, y+dsrc.y); s = byteaddr(src, Pt(sx, sy)); *d ^= (*d^*s) & m; } if(++sx >= src->r.max.x) sx = src->r.min.x; m >>= bpp; if(m == 0) m = m0; } } static void verliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) { int x, y, sx, sy, deltay, deltax, miny, maxy; int bpp, m, m0; uchar *d, *s; deltax = p1.x - p0.x; deltay = p1.y - p0.y; sy = drawreplxy(src->r.min.y, src->r.max.y, p0.y+dsrc.y); miny = lmax(p0.y, clipr.min.y); maxy = lmin(p1.y, clipr.max.y-1); bpp = dst->depth; m0 = 0xFF^(0xFF>>bpp); for(y=miny; y<=maxy; y++){ if(deltay == 0) /* degenerate line */ x = p0.x; else x = p0.x + (deltax*(y-p0.y)+deltay/2)/deltay; if(clipr.min.x<=x && x> (x&(7/dst->depth))*bpp; d = byteaddr(dst, Pt(x, y)); sx = drawreplxy(src->r.min.x, src->r.max.x, x+dsrc.x); s = byteaddr(src, Pt(sx, sy)); *d ^= (*d^*s) & m; } if(++sy >= src->r.max.y) sy = src->r.min.y; } } static void horline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) { int x, y, deltay, deltax, minx, maxx; int bpp, m, m0; uchar *d, *s; deltax = p1.x - p0.x; deltay = p1.y - p0.y; minx = lmax(p0.x, clipr.min.x); maxx = lmin(p1.x, clipr.max.x-1); bpp = dst->depth; m0 = 0xFF^(0xFF>>bpp); m = m0 >> (minx&(7/dst->depth))*bpp; for(x=minx; x<=maxx; x++){ y = p0.y + (deltay*(x-p0.x)+deltay/2)/deltax; if(clipr.min.y<=y && y>= bpp; if(m == 0) m = m0; } } static void verline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr) { int x, y, deltay, deltax, miny, maxy; int bpp, m, m0; uchar *d, *s; deltax = p1.x - p0.x; deltay = p1.y - p0.y; miny = lmax(p0.y, clipr.min.y); maxy = lmin(p1.y, clipr.max.y-1); bpp = dst->depth; m0 = 0xFF^(0xFF>>bpp); for(y=miny; y<=maxy; y++){ if(deltay == 0) /* degenerate line */ x = p0.x; else x = p0.x + deltax*(y-p0.y)/deltay; if(clipr.min.x<=x && x> (x&(7/dst->depth))*bpp; d = byteaddr(dst, Pt(x, y)); s = byteaddr(src, addpt(dsrc, Pt(x, y))); *d ^= (*d^*s) & m; } } } #endif /* NOTUSED */ static Memimage* membrush(int radius) { static Memimage *brush; static int brushradius; if(brush==nil || brushradius!=radius){ freememimage(brush); brush = allocmemimage(Rect(0, 0, 2*radius+1, 2*radius+1), memopaque->chan); if(brush != nil){ memfillcolor(brush, DTransparent); /* zeros */ memellipse(brush, Pt(radius, radius), radius, radius, -1, memopaque, Pt(radius, radius), S); } brushradius = radius; } return brush; } static void discend(Point p, int radius, Memimage *dst, Memimage *src, Point dsrc, int op) { Memimage *disc; Rectangle r; disc = membrush(radius); if(disc != nil){ r.min.x = p.x - radius; r.min.y = p.y - radius; r.max.x = p.x + radius+1; r.max.y = p.y + radius+1; memdraw(dst, r, src, addpt(r.min, dsrc), disc, Pt(0,0), op); } } static void arrowend(Point tip, Point *pp, int end, int sin, int cos, int radius) { int x1, x2, x3; /* before rotation */ if(end == Endarrow){ x1 = Arrow1; x2 = Arrow2; x3 = Arrow3; }else{ x1 = (end>>5) & 0x1FF; /* distance along line from end of line to tip */ x2 = (end>>14) & 0x1FF; /* distance along line from barb to tip */ x3 = (end>>23) & 0x1FF; /* distance perpendicular from edge of line to barb */ } /* comments follow track of right-facing arrowhead */ pp->x = tip.x+((2*radius+1)*sin/2-x1*cos); /* upper side of shaft */ pp->y = tip.y-((2*radius+1)*cos/2+x1*sin); pp++; pp->x = tip.x+((2*radius+2*x3+1)*sin/2-x2*cos); /* upper barb */ pp->y = tip.y-((2*radius+2*x3+1)*cos/2+x2*sin); pp++; pp->x = tip.x; pp->y = tip.y; pp++; pp->x = tip.x+(-(2*radius+2*x3+1)*sin/2-x2*cos); /* lower barb */ pp->y = tip.y-(-(2*radius+2*x3+1)*cos/2+x2*sin); pp++; pp->x = tip.x+(-(2*radius+1)*sin/2-x1*cos); /* lower side of shaft */ pp->y = tip.y+((2*radius+1)*cos/2-x1*sin); } void _memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op) { /* * BUG: We should really really pick off purely horizontal and purely * vertical lines and handle them separately with calls to memimagedraw * on rectangles. */ int hor; int sin, cos, dx, dy, t; Rectangle oclipr, r; Point q, pts[10], *pp, d; if(radius < 0) return; if(rectclip(&clipr, dst->r) == 0) return; if(rectclip(&clipr, dst->clipr) == 0) return; d = subpt(sp, p0); if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0) return; if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0) return; /* this means that only verline() handles degenerate lines (p0==p1) */ hor = (abs(p1.x-p0.x) > abs(p1.y-p0.y)); /* * Clipping is a little peculiar. We can't use Sutherland-Cohen * clipping because lines are wide. But this is probably just fine: * we do all math with the original p0 and p1, but clip when deciding * what pixels to draw. This means the layer code can call this routine, * using clipr to define the region being written, and get the same set * of pixels regardless of the dicing. */ if((hor && p0.x>p1.x) || (!hor && p0.y>p1.y)){ q = p0; p0 = p1; p1 = q; t = end0; end0 = end1; end1 = t; } if((p0.x == p1.x || p0.y == p1.y) && (end0&0x1F) == Endsquare && (end1&0x1F) == Endsquare){ r.min = p0; r.max = p1; if(p0.x == p1.x){ r.min.x -= radius; r.max.x += radius+1; } else{ r.min.y -= radius; r.max.y += radius+1; } oclipr = dst->clipr; dst->clipr = clipr; memimagedraw(dst, r, src, sp, memopaque, sp, op); dst->clipr = oclipr; return; } /* Hard: */ /* draw thick line using polygon fill */ icossin2(p1.x-p0.x, p1.y-p0.y, &cos, &sin); dx = (sin*(2*radius+1))/2; dy = (cos*(2*radius+1))/2; pp = pts; oclipr = dst->clipr; dst->clipr = clipr; q.x = ICOSSCALE*p0.x+ICOSSCALE/2-cos/2; q.y = ICOSSCALE*p0.y+ICOSSCALE/2-sin/2; switch(end0 & 0x1F){ case Enddisc: discend(p0, radius, dst, src, d, op); /* fall through */ case Endsquare: default: pp->x = q.x-dx; pp->y = q.y+dy; pp++; pp->x = q.x+dx; pp->y = q.y-dy; pp++; break; case Endarrow: arrowend(q, pp, end0, -sin, -cos, radius); _memfillpolysc(dst, pts, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op); pp[1] = pp[4]; pp += 2; } q.x = ICOSSCALE*p1.x+ICOSSCALE/2+cos/2; q.y = ICOSSCALE*p1.y+ICOSSCALE/2+sin/2; switch(end1 & 0x1F){ case Enddisc: discend(p1, radius, dst, src, d, op); /* fall through */ case Endsquare: default: pp->x = q.x+dx; pp->y = q.y-dy; pp++; pp->x = q.x-dx; pp->y = q.y+dy; pp++; break; case Endarrow: arrowend(q, pp, end1, sin, cos, radius); _memfillpolysc(dst, pp, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op); pp[1] = pp[4]; pp += 2; } _memfillpolysc(dst, pts, pp-pts, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 0, 10, 1, op); dst->clipr = oclipr; return; } void memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op) { _memimageline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op); } /* * Simple-minded conservative code to compute bounding box of line. * Result is probably a little larger than it needs to be. */ static void addbbox(Rectangle *r, Point p) { if(r->min.x > p.x) r->min.x = p.x; if(r->min.y > p.y) r->min.y = p.y; if(r->max.x < p.x+1) r->max.x = p.x+1; if(r->max.y < p.y+1) r->max.y = p.y+1; } int memlineendsize(int end) { int x3; if((end&0x3F) != Endarrow) return 0; if(end == Endarrow) x3 = Arrow3; else x3 = (end>>23) & 0x1FF; return x3; } Rectangle memlinebbox(Point p0, Point p1, int end0, int end1, int radius) { Rectangle r, r1; int extra; r.min.x = 10000000; r.min.y = 10000000; r.max.x = -10000000; r.max.y = -10000000; extra = lmax(memlineendsize(end0), memlineendsize(end1)); r1 = insetrect(canonrect(Rpt(p0, p1)), -(radius+extra)); addbbox(&r, r1.min); addbbox(&r, r1.max); return r; } drawterm-20110822.orig/libmemdraw/iprint.c0000644000175000017500000000020011245145712017657 0ustar tinchotincho#include #include #include #include int iprint(char *fmt,...) { USED(fmt); return -1; } drawterm-20110822.orig/libmemdraw/load.c0000644000175000017500000000273011245145712017303 0ustar tinchotincho#include #include #include #include int _loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int y, l, lpart, rpart, mx, m, mr; uchar *q; if(!rectinrect(r, i->r)) return -1; l = bytesperline(r, i->depth); if(ndata < l*Dy(r)) return -1; ndata = l*Dy(r); q = byteaddr(i, r.min); mx = 7/i->depth; lpart = (r.min.x & mx) * i->depth; rpart = (r.max.x & mx) * i->depth; m = 0xFF >> lpart; /* may need to do bit insertion on edges */ if(l == 1){ /* all in one byte */ if(rpart) m ^= 0xFF >> rpart; for(y=r.min.y; ywidth*sizeof(ulong); data++; } return ndata; } if(lpart==0 && rpart==0){ /* easy case */ for(y=r.min.y; ywidth*sizeof(ulong); data += l; } return ndata; } mr = 0xFF ^ (0xFF >> rpart); if(lpart!=0 && rpart==0){ for(y=r.min.y; y 1) memmove(q+1, data+1, l-1); q += i->width*sizeof(ulong); data += l; } return ndata; } if(lpart==0 && rpart!=0){ for(y=r.min.y; y 1) memmove(q, data, l-1); q[l-1] ^= (data[l-1]^q[l-1]) & mr; q += i->width*sizeof(ulong); data += l; } return ndata; } for(y=r.min.y; y 2) memmove(q+1, data+1, l-2); q[l-1] ^= (data[l-1]^q[l-1]) & mr; q += i->width*sizeof(ulong); data += l; } return ndata; } drawterm-20110822.orig/libmemdraw/draw.c0000644000175000017500000015560711506541252017334 0ustar tinchotincho#include #include #include #include int drawdebug; static int tablesbuilt; /* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */ #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) /* * For 16-bit values, x / 255 == (t = x+1, (t+(t>>8)) >> 8). * We add another 127 to round to the nearest value rather * than truncate. * * CALCxy does x bytewise calculations on y input images (x=1,4; y=1,2). * CALC2x does two parallel 16-bit calculations on y input images (y=1,2). */ #define CALC11(a, v, tmp) \ (tmp=(a)*(v)+128, (tmp+(tmp>>8))>>8) #define CALC12(a1, v1, a2, v2, tmp) \ (tmp=(a1)*(v1)+(a2)*(v2)+128, (tmp+(tmp>>8))>>8) #define MASK 0xFF00FF #define CALC21(a, vvuu, tmp) \ (tmp=(a)*(vvuu)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) #define CALC41(a, rgba, tmp1, tmp2) \ (CALC21(a, rgba & MASK, tmp1) | \ (CALC21(a, (rgba>>8)&MASK, tmp2)<<8)) #define CALC22(a1, vvuu1, a2, vvuu2, tmp) \ (tmp=(a1)*(vvuu1)+(a2)*(vvuu2)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) #define CALC42(a1, rgba1, a2, rgba2, tmp1, tmp2) \ (CALC22(a1, rgba1 & MASK, a2, rgba2 & MASK, tmp1) | \ (CALC22(a1, (rgba1>>8) & MASK, a2, (rgba2>>8) & MASK, tmp2)<<8)) static void mktables(void); typedef int Subdraw(Memdrawparam*); static Subdraw chardraw, alphadraw, memoptdraw; static Memimage* memones; static Memimage* memzeros; Memimage *memwhite; Memimage *memblack; Memimage *memtransparent; Memimage *memopaque; int _ifmt(Fmt*); void _memimageinit(void) { static int didinit = 0; if(didinit) return; didinit = 1; mktables(); _memmkcmap(); fmtinstall('R', Rfmt); fmtinstall('P', Pfmt); memones = allocmemimage(Rect(0,0,1,1), GREY1); memones->flags |= Frepl; memones->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); *byteaddr(memones, ZP) = ~0; memzeros = allocmemimage(Rect(0,0,1,1), GREY1); memzeros->flags |= Frepl; memzeros->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); *byteaddr(memzeros, ZP) = 0; if(memones == nil || memzeros == nil) assert(0 /*cannot initialize memimage library */); /* RSC BUG */ memwhite = memones; memblack = memzeros; memopaque = memones; memtransparent = memzeros; } ulong _imgtorgba(Memimage*, ulong); ulong _rgbatoimg(Memimage*, ulong); ulong _pixelbits(Memimage*, Point); #define DBG if(0) static Memdrawparam par; Memdrawparam* _memimagedrawsetup(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op) { if(mask == nil) mask = memopaque; DBG print("memimagedraw %p/%luX %R @ %p %p/%luX %P %p/%luX %P... ", dst, dst->chan, r, dst->data->bdata, src, src->chan, p0, mask, mask->chan, p1); if(drawclip(dst, &r, src, &p0, mask, &p1, &par.sr, &par.mr) == 0){ // if(drawdebug) // iprint("empty clipped rectangle\n"); return nil; } if(op < Clear || op > SoverD){ // if(drawdebug) // iprint("op out of range: %d\n", op); return nil; } par.op = op; par.dst = dst; par.r = r; par.src = src; /* par.sr set by drawclip */ par.mask = mask; /* par.mr set by drawclip */ par.state = 0; if(src->flags&Frepl){ par.state |= Replsrc; if(Dx(src->r)==1 && Dy(src->r)==1){ par.sval = _pixelbits(src, src->r.min); par.state |= Simplesrc; par.srgba = _imgtorgba(src, par.sval); par.sdval = _rgbatoimg(dst, par.srgba); if((par.srgba&0xFF) == 0 && (op&DoutS)){ // if (drawdebug) iprint("fill with transparent source\n"); return nil; /* no-op successfully handled */ } } } if(mask->flags & Frepl){ par.state |= Replmask; if(Dx(mask->r)==1 && Dy(mask->r)==1){ par.mval = _pixelbits(mask, mask->r.min); if(par.mval == 0 && (op&DoutS)){ // if(drawdebug) iprint("fill with zero mask\n"); return nil; /* no-op successfully handled */ } par.state |= Simplemask; if(par.mval == ~0) par.state |= Fullmask; par.mrgba = _imgtorgba(mask, par.mval); } } // if(drawdebug) // iprint("dr %R sr %R mr %R...", r, par.sr, par.mr); DBG print("draw dr %R sr %R mr %R %lux\n", r, par.sr, par.mr, par.state); return ∥ } void _memimagedraw(Memdrawparam *par) { if (par == nil) return; /* * Now that we've clipped the parameters down to be consistent, we * simply try sub-drawing routines in order until we find one that was able * to handle us. If the sub-drawing routine returns zero, it means it was * unable to satisfy the request, so we do not return. */ /* * Hardware support. Each video driver provides this function, * which checks to see if there is anything it can help with. * There could be an if around this checking to see if dst is in video memory. */ DBG print("test hwdraw\n"); if(hwdraw(par)){ //if(drawdebug) iprint("hw handled\n"); DBG print("hwdraw handled\n"); return; } /* * Optimizations using memmove and memset. */ DBG print("test memoptdraw\n"); if(memoptdraw(par)){ //if(drawdebug) iprint("memopt handled\n"); DBG print("memopt handled\n"); return; } /* * Character drawing. * Solid source color being painted through a boolean mask onto a high res image. */ DBG print("test chardraw\n"); if(chardraw(par)){ //if(drawdebug) iprint("chardraw handled\n"); DBG print("chardraw handled\n"); return; } /* * General calculation-laden case that does alpha for each pixel. */ DBG print("do alphadraw\n"); alphadraw(par); //if(drawdebug) iprint("alphadraw handled\n"); DBG print("alphadraw handled\n"); } #undef DBG /* * Clip the destination rectangle further based on the properties of the * source and mask rectangles. Once the destination rectangle is properly * clipped, adjust the source and mask rectangles to be the same size. * Then if source or mask is replicated, move its clipped rectangle * so that its minimum point falls within the repl rectangle. * * Return zero if the final rectangle is null. */ int drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr) { Point rmin, delta; int splitcoords; Rectangle omr; if(r->min.x>=r->max.x || r->min.y>=r->max.y) return 0; splitcoords = (p0->x!=p1->x) || (p0->y!=p1->y); /* clip to destination */ rmin = r->min; if(!rectclip(r, dst->r) || !rectclip(r, dst->clipr)) return 0; /* move mask point */ p1->x += r->min.x-rmin.x; p1->y += r->min.y-rmin.y; /* move source point */ p0->x += r->min.x-rmin.x; p0->y += r->min.y-rmin.y; /* map destination rectangle into source */ sr->min = *p0; sr->max.x = p0->x+Dx(*r); sr->max.y = p0->y+Dy(*r); /* sr is r in source coordinates; clip to source */ if(!(src->flags&Frepl) && !rectclip(sr, src->r)) return 0; if(!rectclip(sr, src->clipr)) return 0; /* compute and clip rectangle in mask */ if(splitcoords){ /* move mask point with source */ p1->x += sr->min.x-p0->x; p1->y += sr->min.y-p0->y; mr->min = *p1; mr->max.x = p1->x+Dx(*sr); mr->max.y = p1->y+Dy(*sr); omr = *mr; /* mr is now rectangle in mask; clip it */ if(!(mask->flags&Frepl) && !rectclip(mr, mask->r)) return 0; if(!rectclip(mr, mask->clipr)) return 0; /* reflect any clips back to source */ sr->min.x += mr->min.x-omr.min.x; sr->min.y += mr->min.y-omr.min.y; sr->max.x += mr->max.x-omr.max.x; sr->max.y += mr->max.y-omr.max.y; *p1 = mr->min; }else{ if(!(mask->flags&Frepl) && !rectclip(sr, mask->r)) return 0; if(!rectclip(sr, mask->clipr)) return 0; *p1 = sr->min; } /* move source clipping back to destination */ delta.x = r->min.x - p0->x; delta.y = r->min.y - p0->y; r->min.x = sr->min.x + delta.x; r->min.y = sr->min.y + delta.y; r->max.x = sr->max.x + delta.x; r->max.y = sr->max.y + delta.y; /* move source rectangle so sr->min is in src->r */ if(src->flags&Frepl) { delta.x = drawreplxy(src->r.min.x, src->r.max.x, sr->min.x) - sr->min.x; delta.y = drawreplxy(src->r.min.y, src->r.max.y, sr->min.y) - sr->min.y; sr->min.x += delta.x; sr->min.y += delta.y; sr->max.x += delta.x; sr->max.y += delta.y; } *p0 = sr->min; /* move mask point so it is in mask->r */ *p1 = drawrepl(mask->r, *p1); mr->min = *p1; mr->max.x = p1->x+Dx(*sr); mr->max.y = p1->y+Dy(*sr); assert(Dx(*sr) == Dx(*mr) && Dx(*mr) == Dx(*r)); assert(Dy(*sr) == Dy(*mr) && Dy(*mr) == Dy(*r)); assert(ptinrect(*p0, src->r)); assert(ptinrect(*p1, mask->r)); assert(ptinrect(r->min, dst->r)); return 1; } /* * Conversion tables. */ static uchar replbit[1+8][256]; /* replbit[x][y] is the replication of the x-bit quantity y to 8-bit depth */ static uchar conv18[256][8]; /* conv18[x][y] is the yth pixel in the depth-1 pixel x */ static uchar conv28[256][4]; /* ... */ static uchar conv48[256][2]; /* * bitmap of how to replicate n bits to fill 8, for 1 ≤ n ≤ 8. * the X's are where to put the bottom (ones) bit of the n-bit pattern. * only the top 8 bits of the result are actually used. * (the lower 8 bits are needed to get bits in the right place * when n is not a divisor of 8.) * * Should check to see if its easier to just refer to replmul than * use the precomputed values in replbit. On PCs it may well * be; on machines with slow multiply instructions it probably isn't. */ #define a ((((((((((((((((0 #define X *2+1) #define _ *2) static int replmul[1+8] = { 0, a X X X X X X X X X X X X X X X X, a _ X _ X _ X _ X _ X _ X _ X _ X, a _ _ X _ _ X _ _ X _ _ X _ _ X _, a _ _ _ X _ _ _ X _ _ _ X _ _ _ X, a _ _ _ _ X _ _ _ _ X _ _ _ _ X _, a _ _ _ _ _ X _ _ _ _ _ X _ _ _ _, a _ _ _ _ _ _ X _ _ _ _ _ _ X _ _, a _ _ _ _ _ _ _ X _ _ _ _ _ _ _ X, }; #undef a #undef X #undef _ static void mktables(void) { int i, j, mask, sh, small; if(tablesbuilt) return; fmtinstall('R', Rfmt); fmtinstall('P', Pfmt); tablesbuilt = 1; /* bit replication up to 8 bits */ for(i=0; i<256; i++){ for(j=0; j<=8; j++){ /* j <= 8 [sic] */ small = i & ((1<>8; } } /* bit unpacking up to 8 bits, only powers of 2 */ for(i=0; i<256; i++){ for(j=0, sh=7, mask=1; j<8; j++, sh--) conv18[i][j] = replbit[1][(i>>sh)&mask]; for(j=0, sh=6, mask=3; j<4; j++, sh-=2) conv28[i][j] = replbit[2][(i>>sh)&mask]; for(j=0, sh=4, mask=15; j<2; j++, sh-=4) conv48[i][j] = replbit[4][(i>>sh)&mask]; } } static uchar ones = 0xff; /* * General alpha drawing case. Can handle anything. */ typedef struct Buffer Buffer; struct Buffer { /* used by most routines */ uchar *red; uchar *grn; uchar *blu; uchar *alpha; uchar *grey; ulong *rgba; int delta; /* number of bytes to add to pointer to get next pixel to the right */ /* used by boolcalc* for mask data */ uchar *m; /* ptr to mask data r.min byte; like p->bytermin */ int mskip; /* no. of left bits to skip in *m */ uchar *bm; /* ptr to mask data img->r.min byte; like p->bytey0s */ int bmskip; /* no. of left bits to skip in *bm */ uchar *em; /* ptr to mask data img->r.max.x byte; like p->bytey0e */ int emskip; /* no. of right bits to skip in *em */ }; typedef struct Param Param; typedef Buffer Readfn(Param*, uchar*, int); typedef void Writefn(Param*, uchar*, Buffer); typedef Buffer Calcfn(Buffer, Buffer, Buffer, int, int, int); enum { MAXBCACHE = 16 }; /* giant rathole to customize functions with */ struct Param { Readfn *replcall; Readfn *greymaskcall; Readfn *convreadcall; Writefn *convwritecall; Memimage *img; Rectangle r; int dx; /* of r */ int needbuf; int convgrey; int alphaonly; uchar *bytey0s; /* byteaddr(Pt(img->r.min.x, img->r.min.y)) */ uchar *bytermin; /* byteaddr(Pt(r.min.x, img->r.min.y)) */ uchar *bytey0e; /* byteaddr(Pt(img->r.max.x, img->r.min.y)) */ int bwidth; int replcache; /* if set, cache buffers */ Buffer bcache[MAXBCACHE]; ulong bfilled; uchar *bufbase; int bufoff; int bufdelta; int dir; int convbufoff; uchar *convbuf; Param *convdpar; int convdx; }; static uchar *drawbuf; static int ndrawbuf; static int mdrawbuf; static Param spar, mpar, dpar; /* easier on the stacks */ static Readfn greymaskread, replread, readptr; static Writefn nullwrite; static Calcfn alphacalc0, alphacalc14, alphacalc2810, alphacalc3679, alphacalc5, alphacalc11, alphacalcS; static Calcfn boolcalc14, boolcalc236789, boolcalc1011; static Readfn* readfn(Memimage*); static Readfn* readalphafn(Memimage*); static Writefn* writefn(Memimage*); static Calcfn* boolcopyfn(Memimage*, Memimage*); static Readfn* convfn(Memimage*, Param*, Memimage*, Param*); static Calcfn *alphacalc[Ncomp] = { alphacalc0, /* Clear */ alphacalc14, /* DoutS */ alphacalc2810, /* SoutD */ alphacalc3679, /* DxorS */ alphacalc14, /* DinS */ alphacalc5, /* D */ alphacalc3679, /* DatopS */ alphacalc3679, /* DoverS */ alphacalc2810, /* SinD */ alphacalc3679, /* SatopD */ alphacalc2810, /* S */ alphacalc11, /* SoverD */ }; static Calcfn *boolcalc[Ncomp] = { alphacalc0, /* Clear */ boolcalc14, /* DoutS */ boolcalc236789, /* SoutD */ boolcalc236789, /* DxorS */ boolcalc14, /* DinS */ alphacalc5, /* D */ boolcalc236789, /* DatopS */ boolcalc236789, /* DoverS */ boolcalc236789, /* SinD */ boolcalc236789, /* SatopD */ boolcalc1011, /* S */ boolcalc1011, /* SoverD */ }; static int allocdrawbuf(void) { uchar *p; if(ndrawbuf > mdrawbuf){ p = realloc(drawbuf, ndrawbuf); if(p == nil){ werrstr("memimagedraw out of memory"); return -1; } drawbuf = p; mdrawbuf = ndrawbuf; } return 0; } static Param getparam(Memimage *img, Rectangle r, int convgrey, int needbuf) { Param p; int nbuf; memset(&p, 0, sizeof p); p.img = img; p.r = r; p.dx = Dx(r); p.needbuf = needbuf; p.convgrey = convgrey; assert(img->r.min.x <= r.min.x && r.min.x < img->r.max.x); p.bytey0s = byteaddr(img, Pt(img->r.min.x, img->r.min.y)); p.bytermin = byteaddr(img, Pt(r.min.x, img->r.min.y)); p.bytey0e = byteaddr(img, Pt(img->r.max.x, img->r.min.y)); p.bwidth = sizeof(ulong)*img->width; assert(p.bytey0s <= p.bytermin && p.bytermin <= p.bytey0e); if(p.r.min.x == p.img->r.min.x) assert(p.bytermin == p.bytey0s); nbuf = 1; if((img->flags&Frepl) && Dy(img->r) <= MAXBCACHE && Dy(img->r) < Dy(r)){ p.replcache = 1; nbuf = Dy(img->r); } p.bufdelta = 4*p.dx; p.bufoff = ndrawbuf; ndrawbuf += p.bufdelta*nbuf; return p; } static void clipy(Memimage *img, int *y) { int dy; dy = Dy(img->r); if(*y == dy) *y = 0; else if(*y == -1) *y = dy-1; assert(0 <= *y && *y < dy); } static void dumpbuf(char *s, Buffer b, int n) { int i; uchar *p; print("%s", s); for(i=0; ir; dx = Dx(r); dy = Dy(r); ndrawbuf = 0; src = par->src; mask = par->mask; dst = par->dst; sr = par->sr; mr = par->mr; op = par->op; isgrey = dst->flags&Fgrey; /* * Buffering when src and dst are the same bitmap is sufficient but not * necessary. There are stronger conditions we could use. We could * check to see if the rectangles intersect, and if simply moving in the * correct y direction can avoid the need to buffer. */ needbuf = (src->data == dst->data); spar = getparam(src, sr, isgrey, needbuf); dpar = getparam(dst, r, isgrey, needbuf); mpar = getparam(mask, mr, 0, needbuf); dir = (needbuf && byteaddr(dst, r.min) > byteaddr(src, sr.min)) ? -1 : 1; spar.dir = mpar.dir = dpar.dir = dir; /* * If the mask is purely boolean, we can convert from src to dst format * when we read src, and then just copy it to dst where the mask tells us to. * This requires a boolean (1-bit grey) mask and lack of a source alpha channel. * * The computation is accomplished by assigning the function pointers as follows: * rdsrc - read and convert source into dst format in a buffer * rdmask - convert mask to bytes, set pointer to it * rddst - fill with pointer to real dst data, but do no reads * calc - copy src onto dst when mask says to. * wrdst - do nothing * This is slightly sleazy, since things aren't doing exactly what their names say, * but it avoids a fair amount of code duplication to make this a case here * rather than have a separate booldraw. */ //if(drawdebug) iprint("flag %lud mchan %lux=?%x dd %d\n", src->flags&Falpha, mask->chan, GREY1, dst->depth); if(!(src->flags&Falpha) && mask->chan == GREY1 && dst->depth >= 8 && op == SoverD){ //if(drawdebug) iprint("boolcopy..."); rdsrc = convfn(dst, &dpar, src, &spar); rddst = readptr; rdmask = readfn(mask); calc = boolcopyfn(dst, mask); wrdst = nullwrite; }else{ /* usual alphadraw parameter fetching */ rdsrc = readfn(src); rddst = readfn(dst); wrdst = writefn(dst); calc = alphacalc[op]; /* * If there is no alpha channel, we'll ask for a grey channel * and pretend it is the alpha. */ if(mask->flags&Falpha){ rdmask = readalphafn(mask); mpar.alphaonly = 1; }else{ mpar.greymaskcall = readfn(mask); mpar.convgrey = 1; rdmask = greymaskread; /* * Should really be above, but then boolcopyfns would have * to deal with bit alignment, and I haven't written that. * * This is a common case for things like ellipse drawing. * When there's no alpha involved and the mask is boolean, * we can avoid all the division and multiplication. */ if(mask->chan == GREY1 && !(src->flags&Falpha)) calc = boolcalc[op]; else if(op == SoverD && !(src->flags&Falpha)) calc = alphacalcS; } } /* * If the image has a small enough repl rectangle, * we can just read each line once and cache them. */ if(spar.replcache){ spar.replcall = rdsrc; rdsrc = replread; } if(mpar.replcache){ mpar.replcall = rdmask; rdmask = replread; } if(allocdrawbuf() < 0) return 0; /* * Before we were saving only offsets from drawbuf in the parameter * structures; now that drawbuf has been grown to accomodate us, * we can fill in the pointers. */ spar.bufbase = drawbuf+spar.bufoff; mpar.bufbase = drawbuf+mpar.bufoff; dpar.bufbase = drawbuf+dpar.bufoff; spar.convbuf = drawbuf+spar.convbufoff; if(dir == 1){ starty = 0; endy = dy; }else{ starty = dy-1; endy = -1; } /* * srcy, masky, and dsty are offsets from the top of their * respective Rectangles. they need to be contained within * the rectangles, so clipy can keep them there without division. */ srcy = (starty + sr.min.y - src->r.min.y)%Dy(src->r); masky = (starty + mr.min.y - mask->r.min.y)%Dy(mask->r); dsty = starty + r.min.y - dst->r.min.y; assert(0 <= srcy && srcy < Dy(src->r)); assert(0 <= masky && masky < Dy(mask->r)); assert(0 <= dsty && dsty < Dy(dst->r)); for(y=starty; y!=endy; y+=dir, srcy+=dir, masky+=dir, dsty+=dir){ clipy(src, &srcy); clipy(dst, &dsty); clipy(mask, &masky); bsrc = rdsrc(&spar, spar.bufbase, srcy); DBG print("["); bmask = rdmask(&mpar, mpar.bufbase, masky); DBG print("]\n"); bdst = rddst(&dpar, dpar.bufbase, dsty); DBG dumpbuf("src", bsrc, dx); DBG dumpbuf("mask", bmask, dx); DBG dumpbuf("dst", bdst, dx); bdst = calc(bdst, bsrc, bmask, dx, isgrey, op); wrdst(&dpar, dpar.bytermin+dsty*dpar.bwidth, bdst); } return 1; } #undef DBG static Buffer alphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op) { USED(grey); USED(op); memset(bdst.rgba, 0, dx*bdst.delta); return bdst; } /* * Do the channels in the buffers match enough * that we can do word-at-a-time operations * on the pixels? */ static int chanmatch(Buffer *bdst, Buffer *bsrc) { uchar *drgb, *srgb; /* * first, r, g, b must be in the same place * in the rgba word. */ drgb = (uchar*)bdst->rgba; srgb = (uchar*)bsrc->rgba; if(bdst->red - drgb != bsrc->red - srgb || bdst->blu - drgb != bsrc->blu - srgb || bdst->grn - drgb != bsrc->grn - srgb) return 0; /* * that implies alpha is in the same place, * if it is there at all (it might be == &ones). * if the destination is &ones, we can scribble * over the rgba slot just fine. */ if(bdst->alpha == &ones) return 1; /* * if the destination is not ones but the src is, * then the simultaneous calculation will use * bogus bytes from the src's rgba. no good. */ if(bsrc->alpha == &ones) return 0; /* * otherwise, alphas are in the same place. */ return 1; } static Buffer alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) { Buffer obdst; int fd, sadelta; int i, sa, ma, q; ulong t, t1; obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc); for(i=0; ibcache[y]; if((p->bfilled & (1<bfilled |= 1<replcall(p, p->bufbase+y*p->bufdelta, y); } return *b; } /* * Alpha reading function that simply relabels the grey pointer. */ static Buffer greymaskread(Param *p, uchar *buf, int y) { Buffer b; b = p->greymaskcall(p, buf, y); b.alpha = b.grey; return b; } #define DBG if(0) static Buffer readnbit(Param *p, uchar *buf, int y) { Buffer b; Memimage *img; uchar *repl, *r, *w, *ow, bits; int i, n, sh, depth, x, dx, npack, nbits; b.rgba = (ulong*)buf; b.grey = w = buf; b.red = b.blu = b.grn = w; b.alpha = &ones; b.delta = 1; dx = p->dx; img = p->img; depth = img->depth; repl = &replbit[depth][0]; npack = 8/depth; sh = 8-depth; /* copy from p->r.min.x until end of repl rectangle */ x = p->r.min.x; n = dx; if(n > p->img->r.max.x - x) n = p->img->r.max.x - x; r = p->bytermin + y*p->bwidth; DBG print("readnbit dx %d %p=%p+%d*%d, *r=%d fetch %d ", dx, r, p->bytermin, y, p->bwidth, *r, n); bits = *r++; nbits = 8; if((i=x&(npack-1))){ DBG print("throwaway %d...", i); bits <<= depth*i; nbits -= depth*i; } for(i=0; i>sh]; DBG print("bit %x...", repl[bits>>sh]); bits <<= depth; nbits -= depth; } dx -= n; if(dx == 0) return b; assert(x+i == p->img->r.max.x); /* copy from beginning of repl rectangle until where we were before. */ x = p->img->r.min.x; n = dx; if(n > p->r.min.x - x) n = p->r.min.x - x; r = p->bytey0s + y*p->bwidth; DBG print("x=%d r=%p...", x, r); bits = *r++; nbits = 8; if((i=x&(npack-1))){ bits <<= depth*i; nbits -= depth*i; } DBG print("nbits=%d...", nbits); for(i=0; i>sh]; DBG print("bit %x...", repl[bits>>sh]); bits <<= depth; nbits -= depth; DBG print("bits %x nbits %d...", bits, nbits); } dx -= n; if(dx == 0) return b; assert(dx > 0); /* now we have exactly one full scan line: just replicate the buffer itself until we are done */ ow = buf; while(dx--) *w++ = *ow++; return b; } #undef DBG #define DBG if(0) static void writenbit(Param *p, uchar *w, Buffer src) { uchar *r; ulong bits; int i, sh, depth, npack, nbits, x, ex; assert(src.grey != nil && src.delta == 1); x = p->r.min.x; ex = x+p->dx; depth = p->img->depth; npack = 8/depth; i=x&(npack-1); bits = i ? (*w >> (8-depth*i)) : 0; nbits = depth*i; sh = 8-depth; r = src.grey; for(; x> sh); nbits += depth; if(nbits == 8){ *w++ = bits; nbits = 0; } } if(nbits){ sh = 8-nbits; bits <<= sh; bits |= *w & ((1<bytey0s + y*p->bwidth; r = p->bytermin + y*p->bwidth; end = p->bytey0e + y*p->bwidth; cmap = p->img->cmap->cmap2rgb; convgrey = p->convgrey; copyalpha = (p->img->flags&Falpha) ? 1 : 0; w = buf; dx = p->dx; if(copyalpha){ b.alpha = buf++; a = p->img->shift[CAlpha]/8; m = p->img->shift[CMap]/8; for(i=0; iimg->cmap->rgb2cmap; delta = src.delta; red= src.red; grn = src.grn; blu = src.blu; dx = p->dx; for(i=0; i>4)*256+(*grn>>4)*16+(*blu>>4)]; } #define DBG if(0) static Buffer readbyte(Param *p, uchar *buf, int y) { Buffer b; Memimage *img; int dx, isgrey, convgrey, alphaonly, copyalpha, i, nb; uchar *begin, *end, *r, *w, *rrepl, *grepl, *brepl, *arepl, *krepl; uchar ured, ugrn, ublu; ulong u; img = p->img; begin = p->bytey0s + y*p->bwidth; r = p->bytermin + y*p->bwidth; end = p->bytey0e + y*p->bwidth; w = buf; dx = p->dx; nb = img->depth/8; convgrey = p->convgrey; /* convert rgb to grey */ isgrey = img->flags&Fgrey; alphaonly = p->alphaonly; copyalpha = (img->flags&Falpha) ? 1 : 0; DBG print("copyalpha %d alphaonly %d convgrey %d isgrey %d\n", copyalpha, alphaonly, convgrey, isgrey); /* if we can, avoid processing everything */ if(!(img->flags&Frepl) && !convgrey && (img->flags&Fbytes)){ memset(&b, 0, sizeof b); if(p->needbuf){ memmove(buf, r, dx*nb); r = buf; } b.rgba = (ulong*)r; if(copyalpha) b.alpha = r+img->shift[CAlpha]/8; else b.alpha = &ones; if(isgrey){ b.grey = r+img->shift[CGrey]/8; b.red = b.grn = b.blu = b.grey; }else{ b.red = r+img->shift[CRed]/8; b.grn = r+img->shift[CGreen]/8; b.blu = r+img->shift[CBlue]/8; } b.delta = nb; return b; } DBG print("2\n"); rrepl = replbit[img->nbits[CRed]]; grepl = replbit[img->nbits[CGreen]]; brepl = replbit[img->nbits[CBlue]]; arepl = replbit[img->nbits[CAlpha]]; krepl = replbit[img->nbits[CGrey]]; for(i=0; i>img->shift[CAlpha]) & img->mask[CAlpha]]; DBG print("a %x\n", w[-1]); } if(isgrey) *w++ = krepl[(u >> img->shift[CGrey]) & img->mask[CGrey]]; else if(!alphaonly){ ured = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]]; ugrn = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]]; ublu = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]]; if(convgrey){ DBG print("g %x %x %x\n", ured, ugrn, ublu); *w++ = RGB2K(ured, ugrn, ublu); DBG print("%x\n", w[-1]); }else{ *w++ = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]]; *w++ = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]]; *w++ = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]]; } } r += nb; if(r == end) r = begin; } b.alpha = copyalpha ? buf : &ones; b.rgba = (ulong*)buf; if(alphaonly){ b.red = b.grn = b.blu = b.grey = nil; if(!copyalpha) b.rgba = nil; b.delta = 1; }else if(isgrey || convgrey){ b.grey = buf+copyalpha; b.red = b.grn = b.blu = buf+copyalpha; b.delta = copyalpha+1; DBG print("alpha %x grey %x\n", b.alpha ? *b.alpha : 0xFF, *b.grey); }else{ b.blu = buf+copyalpha; b.grn = buf+copyalpha+1; b.grey = nil; b.red = buf+copyalpha+2; b.delta = copyalpha+3; } return b; } #undef DBG #define DBG if(0) static void writebyte(Param *p, uchar *w, Buffer src) { Memimage *img; int i, isalpha, isgrey, nb, delta, dx, adelta; uchar ff, *red, *grn, *blu, *grey, *alpha; ulong u, mask; img = p->img; red = src.red; grn = src.grn; blu = src.blu; alpha = src.alpha; delta = src.delta; grey = src.grey; dx = p->dx; nb = img->depth/8; mask = (nb==4) ? 0 : ~((1<depth)-1); isalpha = img->flags&Falpha; isgrey = img->flags&Fgrey; adelta = src.delta; if(isalpha && (alpha == nil || alpha == &ones)){ ff = 0xFF; alpha = &ff; adelta = 0; } for(i=0; i> (8-img->nbits[CGrey])) & img->mask[CGrey]) << img->shift[CGrey]; DBG print("|grey %.8lux...", u); grey += delta; }else{ u |= ((*red >> (8-img->nbits[CRed])) & img->mask[CRed]) << img->shift[CRed]; u |= ((*grn >> (8-img->nbits[CGreen])) & img->mask[CGreen]) << img->shift[CGreen]; u |= ((*blu >> (8-img->nbits[CBlue])) & img->mask[CBlue]) << img->shift[CBlue]; red += delta; grn += delta; blu += delta; DBG print("|rgb %.8lux...", u); } if(isalpha){ u |= ((*alpha >> (8-img->nbits[CAlpha])) & img->mask[CAlpha]) << img->shift[CAlpha]; alpha += adelta; DBG print("|alpha %.8lux...", u); } w[0] = u; w[1] = u>>8; w[2] = u>>16; w[3] = u>>24; w += nb; } } #undef DBG static Readfn* readfn(Memimage *img) { if(img->depth < 8) return readnbit; if(img->nbits[CMap] == 8) return readcmap; return readbyte; } static Readfn* readalphafn(Memimage *m) { USED(m); return readbyte; } static Writefn* writefn(Memimage *img) { if(img->depth < 8) return writenbit; if(img->chan == CMAP8) return writecmap; return writebyte; } static void nullwrite(Param *p, uchar *s, Buffer b) { USED(p); USED(s); } static Buffer readptr(Param *p, uchar *s, int y) { Buffer b; uchar *q; USED(s); q = p->bytermin + y*p->bwidth; b.red = q; /* ptr to data */ b.grn = b.blu = b.grey = b.alpha = nil; b.rgba = (ulong*)q; b.delta = p->img->depth/8; return b; } static Buffer boolmemmove(Buffer bdst, Buffer bsrc, Buffer b1, int dx, int i, int o) { USED(i); USED(o); memmove(bdst.red, bsrc.red, dx*bdst.delta); return bdst; } static Buffer boolcopy8(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) { uchar *m, *r, *w, *ew; USED(i); USED(o); m = bmask.grey; w = bdst.red; r = bsrc.red; ew = w+dx; for(; w < ew; w++,r++) if(*m++) *w = *r; return bdst; /* not used */ } static Buffer boolcopy16(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) { uchar *m; ushort *r, *w, *ew; USED(i); USED(o); m = bmask.grey; w = (ushort*)bdst.red; r = (ushort*)bsrc.red; ew = w+dx; for(; w < ew; w++,r++) if(*m++) *w = *r; return bdst; /* not used */ } static Buffer boolcopy24(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) { uchar *m; uchar *r, *w, *ew; USED(i); USED(o); m = bmask.grey; w = bdst.red; r = bsrc.red; ew = w+dx*3; while(w < ew){ if(*m++){ *w++ = *r++; *w++ = *r++; *w++ = *r++; }else{ w += 3; r += 3; } } return bdst; /* not used */ } static Buffer boolcopy32(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) { uchar *m; ulong *r, *w, *ew; USED(i); USED(o); m = bmask.grey; w = (ulong*)bdst.red; r = (ulong*)bsrc.red; ew = w+dx; for(; w < ew; w++,r++) if(*m++) *w = *r; return bdst; /* not used */ } static Buffer genconv(Param *p, uchar *buf, int y) { Buffer b; int nb; uchar *r, *w, *ew; /* read from source into RGB format in convbuf */ b = p->convreadcall(p, p->convbuf, y); /* write RGB format into dst format in buf */ p->convwritecall(p->convdpar, buf, b); if(p->convdx){ nb = p->convdpar->img->depth/8; r = buf; w = buf+nb*p->dx; ew = buf+nb*p->convdx; while(wchan == src->chan && !(src->flags&Frepl)){ //if(drawdebug) iprint("readptr..."); return readptr; } if(dst->chan==CMAP8 && (src->chan==GREY1||src->chan==GREY2||src->chan==GREY4)){ /* cheat because we know the replicated value is exactly the color map entry. */ //if(drawdebug) iprint("Readnbit..."); return readnbit; } spar->convreadcall = readfn(src); spar->convwritecall = writefn(dst); spar->convdpar = dpar; /* allocate a conversion buffer */ spar->convbufoff = ndrawbuf; ndrawbuf += spar->dx*4; if(spar->dx > Dx(spar->img->r)){ spar->convdx = spar->dx; spar->dx = Dx(spar->img->r); } //if(drawdebug) iprint("genconv..."); return genconv; } ulong _pixelbits(Memimage *i, Point pt) { uchar *p; ulong val; int off, bpp, npack; val = 0; p = byteaddr(i, pt); switch(bpp=i->depth){ case 1: case 2: case 4: npack = 8/bpp; off = pt.x%npack; val = p[0] >> bpp*(npack-1-off); val &= (1<flags&Frepl && Dx(mask->r)==1 && Dy(mask->r)==1 && pixelbits(mask, mask->r.min)==~0) return boolmemmove; switch(img->depth){ case 8: return boolcopy8; case 16: return boolcopy16; case 24: return boolcopy24; case 32: return boolcopy32; default: assert(0 /* boolcopyfn */); } return nil; } /* * Optimized draw for filling and scrolling; uses memset and memmove. * static void memsetb(void *vp, uchar val, int n) { uchar *p, *ep; p = vp; ep = p+n; while(p>8; c = val>>16; while(pchan; chan; chan>>=8){ nb = NBITS(chan); ov = v = val&((1<>= nb; while(nb < 8){ v |= v<>= (nb-8); switch(TYPE(chan)){ case CRed: r = v; break; case CGreen: g = v; break; case CBlue: b = v; break; case CAlpha: a = v; break; case CGrey: r = g = b = v; break; case CMap: p = img->cmap->cmap2rgb+3*ov; r = *p++; g = *p++; b = *p; break; } } return (r<<24)|(g<<16)|(b<<8)|a; } ulong _rgbatoimg(Memimage *img, ulong rgba) { ulong chan; int d, nb; ulong v; uchar *p, r, g, b, a, m; v = 0; r = rgba>>24; g = rgba>>16; b = rgba>>8; a = rgba; d = 0; for(chan=img->chan; chan; chan>>=8){ nb = NBITS(chan); switch(TYPE(chan)){ case CRed: v |= (r>>(8-nb))<>(8-nb))<>(8-nb))<>(8-nb))<cmap->rgb2cmap; m = p[(r>>4)*256+(g>>4)*16+(b>>4)]; v |= (m>>(8-nb))<>(8-nb))<r); dy = Dy(par->r); src = par->src; dst = par->dst; op = par->op; DBG print("state %lux mval %lux dd %d\n", par->state, par->mval, dst->depth); /* * If we have an opaque mask and source is one opaque pixel we can convert to the * destination format and just replicate with memset. */ m = Simplesrc|Simplemask|Fullmask; if((par->state&m)==m && (par->srgba&0xFF) == 0xFF && (op ==S || op == SoverD)){ uchar *dp, p[4]; int d, dwid, ppb, np, nb; uchar lm, rm; DBG print("memopt, dst %p, dst->data->bdata %p\n", dst, dst->data->bdata); dwid = dst->width*sizeof(ulong); dp = byteaddr(dst, par->r.min); v = par->sdval; DBG print("sdval %lud, depth %d\n", v, dst->depth); switch(dst->depth){ case 1: case 2: case 4: for(d=dst->depth; d<8; d*=2) v |= (v<depth; /* pixels per byte */ m = ppb-1; /* left edge */ np = par->r.min.x&m; /* no. pixels unused on left side of word */ dx -= (ppb-np); nb = 8 - np * dst->depth; /* no. bits used on right side of word */ lm = (1<r.min.x, nb, lm, ppb, m); /* right edge */ np = par->r.max.x&m; /* no. pixels used on left side of word */ dx -= np; nb = 8 - np * dst->depth; /* no. bits unused on right side of word */ rm = ~((1<r.max.x, nb, rm, ppb, m); DBG print("dx %d Dx %d\n", dx, Dx(par->r)); /* lm, rm are masks that are 1 where we should touch the bits */ if(dx < 0){ /* just one byte */ lm &= rm; for(y=0; y>8; v = *(ushort*)p; DBG print("dp=%p; dx=%d; for(y=0; y<%d; y++, dp+=%d)\nmemsets(dp, v, dx);\n", dp, dx, dy, dwid); for(y=0; y>8; p[2] = v>>16; p[3] = v>>24; v = *(ulong*)p; for(y=0; ystate&(m|Replsrc))==m && src->depth >= 8 && src->chan == dst->chan && !(src->flags&Falpha) && (op == S || op == SoverD)){ uchar *sp, *dp; long swid, dwid, nb; int dir; if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)) dir = -1; else dir = 1; swid = src->width*sizeof(ulong); dwid = dst->width*sizeof(ulong); sp = byteaddr(src, par->sr.min); dp = byteaddr(dst, par->r.min); if(dir == -1){ sp += (dy-1)*swid; dp += (dy-1)*dwid; swid = -swid; dwid = -dwid; } nb = (dx*src->depth)/8; for(y=0; ystate&(Simplemask|Simplesrc|Replmask|Replsrc))==0 && dst->chan==GREY1 && src->chan==GREY1 && par->mask->chan==GREY1 && (par->r.min.x&7)==(par->sr.min.x&7) && (par->r.min.x&7)==(par->mr.min.x&7)){ uchar *sp, *dp, *mp; uchar lm, rm; long swid, dwid, mwid; int i, x, dir; sp = byteaddr(src, par->sr.min); dp = byteaddr(dst, par->r.min); mp = byteaddr(par->mask, par->mr.min); swid = src->width*sizeof(ulong); dwid = dst->width*sizeof(ulong); mwid = par->mask->width*sizeof(ulong); if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)){ dir = -1; }else dir = 1; lm = 0xFF>>(par->r.min.x&7); rm = 0xFF<<(8-(par->r.max.x&7)); dx -= (8-(par->r.min.x&7)) + (par->r.max.x&7); if(dx < 0){ /* one byte wide */ lm &= rm; if(dir == -1){ dp += dwid*(dy-1); sp += swid*(dy-1); mp += mwid*(dy-1); dwid = -dwid; swid = -swid; mwid = -mwid; } for(y=0; ymask->flags, par->mask->depth, par->src->flags, Dx(par->src->r), Dy(par->src->r), par->dst->depth, par->dst->data, par->src->data); mask = par->mask; src = par->src; dst = par->dst; r = par->r; mr = par->mr; op = par->op; if((par->state&(Replsrc|Simplesrc|Replmask)) != (Replsrc|Simplesrc) || mask->depth != 1 || src->flags&Falpha || dst->depth<8 || dst->data==src->data || op != SoverD) return 0; //if(drawdebug) iprint("chardraw..."); depth = mask->depth; maskwid = mask->width*sizeof(ulong); rp = byteaddr(mask, mr.min); npack = 8/depth; bsh = (mr.min.x % npack) * depth; wp = byteaddr(dst, r.min); dstwid = dst->width*sizeof(ulong); DBG print("bsh %d\n", bsh); dy = Dy(r); dx = Dx(r); ddepth = dst->depth; /* * for loop counts from bsh to bsh+dx * * we want the bottom bits to be the amount * to shift the pixels down, so for n≡0 (mod 8) we want * bottom bits 7. for n≡1, 6, etc. * the bits come from -n-1. */ bx = -bsh-1; ex = -bsh-1-dx; SET(bits); v = par->sdval; /* make little endian */ sp[0] = v; sp[1] = v>>8; sp[2] = v>>16; sp[3] = v>>24; //print("sp %x %x %x %x\n", sp[0], sp[1], sp[2], sp[3]); for(y=0; yex; x--, wc++){ i = x&7; if(i == 8-1) bits = *q++; DBG print("bits %lux sh %d...", bits, i); if((bits>>i)&1) *wc = v; } break; case 16: ws = (ushort*)wp; v = *(ushort*)sp; for(x=bx; x>ex; x--, ws++){ i = x&7; if(i == 8-1) bits = *q++; DBG print("bits %lux sh %d...", bits, i); if((bits>>i)&1) *ws = v; } break; case 24: wc = wp; for(x=bx; x>ex; x--, wc+=3){ i = x&7; if(i == 8-1) bits = *q++; DBG print("bits %lux sh %d...", bits, i); if((bits>>i)&1){ wc[0] = sp[0]; wc[1] = sp[1]; wc[2] = sp[2]; } } break; case 32: wl = (ulong*)wp; v = *(ulong*)sp; for(x=bx; x>ex; x--, wl++){ i = x&7; if(i == 8-1) bits = *q++; DBG iprint("bits %lux sh %d...", bits, i); if((bits>>i)&1) *wl = v; } break; } } DBG print("\n"); return 1; } #undef DBG /* * Fill entire byte with replicated (if necessary) copy of source pixel, * assuming destination ldepth is >= source ldepth. * * This code is just plain wrong for >8bpp. * ulong membyteval(Memimage *src) { int i, val, bpp; uchar uc; unloadmemimage(src, src->r, &uc, 1); bpp = src->depth; uc <<= (src->r.min.x&(7/src->depth))*src->depth; uc &= ~(0xFF>>bpp); // pixel value is now in high part of byte. repeat throughout byte val = uc; for(i=bpp; i<8; i<<=1) val |= val>>i; return val; } * */ void _memfillcolor(Memimage *i, ulong val) { ulong bits; int d, y; if(val == DNofill) return; bits = _rgbatoimg(i, val); switch(i->depth){ case 24: /* 24-bit images suck */ for(y=i->r.min.y; yr.max.y; y++) memset24(byteaddr(i, Pt(i->r.min.x, y)), bits, Dx(i->r)); break; default: /* 1, 2, 4, 8, 16, 32 */ for(d=i->depth; d<32; d*=2) bits = (bits << d) | bits; memsetl(wordaddr(i, i->r.min), bits, i->width*Dy(i->r)); break; } } drawterm-20110822.orig/libmemdraw/alloc.c0000644000175000017500000000652211245145712017461 0ustar tinchotincho#include #include #include #include #define poolalloc(a, b) malloc(b) #define poolfree(a, b) free(b) void memimagemove(void *from, void *to) { Memdata *md; md = *(Memdata**)to; if(md->base != from){ print("compacted data not right: #%p\n", md->base); abort(); } md->base = to; /* if allocmemimage changes this must change too */ md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong); } Memimage* allocmemimaged(Rectangle r, ulong chan, Memdata *md, void *X) { int d; ulong l; Memimage *i; if(Dx(r) <= 0 || Dy(r) <= 0){ werrstr("bad rectangle %R", r); return nil; } if((d = chantodepth(chan)) == 0) { werrstr("bad channel descriptor %.8lux", chan); return nil; } l = wordsperline(r, d); i = mallocz(sizeof(Memimage), 1); if(i == nil) return nil; i->X = X; i->data = md; i->zero = sizeof(ulong)*l*r.min.y; if(r.min.x >= 0) i->zero += (r.min.x*d)/8; else i->zero -= (-r.min.x*d+7)/8; i->zero = -i->zero; i->width = l; i->r = r; i->clipr = r; i->flags = 0; i->layer = nil; i->cmap = memdefcmap; if(memsetchan(i, chan) < 0){ free(i); return nil; } return i; } Memimage* _allocmemimage(Rectangle r, ulong chan) { int d; u32int l, nw; uchar *p; Memdata *md; Memimage *i; if((d = chantodepth(chan)) == 0) { werrstr("bad channel descriptor %.8lux", chan); return nil; } l = wordsperline(r, d); nw = l*Dy(r); md = malloc(sizeof(Memdata)); if(md == nil) return nil; md->ref = 1; md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong)); if(md->base == nil){ free(md); return nil; } p = (uchar*)md->base; *(Memdata**)p = md; p += sizeof(Memdata*); *(ulong*)p = getcallerpc(&r); p += sizeof(ulong); /* if this changes, memimagemove must change too */ md->bdata = p; md->allocd = 1; i = allocmemimaged(r, chan, md, nil); if(i == nil){ poolfree(imagmem, md->base); free(md); return nil; } md->imref = i; return i; } void _freememimage(Memimage *i) { if(i == nil) return; if(i->data->ref-- == 1 && i->data->allocd){ if(i->data->base) poolfree(imagmem, i->data->base); free(i->data); } free(i); } /* * Wordaddr is deprecated. */ ulong* wordaddr(Memimage *i, Point p) { return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1)); } uchar* byteaddr(Memimage *i, Point p) { uchar *a; a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width; if(i->depth < 8){ /* * We need to always round down, * but C rounds toward zero. */ int np; np = 8/i->depth; if(p.x < 0) return a+(p.x-np+1)/np; else return a+p.x/np; } else return a+p.x*(i->depth/8); } int memsetchan(Memimage *i, ulong chan) { int d; int t, j, k; ulong cc; int bytes; if((d = chantodepth(chan)) == 0) { werrstr("bad channel descriptor"); return -1; } i->depth = d; i->chan = chan; i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes); bytes = 1; for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){ t=TYPE(cc); if(t < 0 || t >= NChan){ werrstr("bad channel string"); return -1; } if(t == CGrey) i->flags |= Fgrey; if(t == CAlpha) i->flags |= Falpha; if(t == CMap && i->cmap == nil){ i->cmap = memdefcmap; i->flags |= Fcmap; } i->shift[t] = j; i->mask[t] = (1<nbits[t] = NBITS(cc); if(NBITS(cc) != 8) bytes = 0; } i->nchan = k; if(bytes) i->flags |= Fbytes; return 0; } drawterm-20110822.orig/libmemdraw/fillpoly.c0000644000175000017500000002336511245145712020225 0ustar tinchotincho#include #include #include #include #include typedef struct Seg Seg; struct Seg { Point p0; Point p1; long num; long den; long dz; long dzrem; long z; long zerr; long d; }; static void zsort(Seg **seg, Seg **ep); static int ycompare(const void*, const void*); static int xcompare(const void*, const void*); static int zcompare(const void*, const void*); static void xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int, int, int); static void yscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int, int); #ifdef NOT static void fillcolor(Memimage *dst, int left, int right, int y, Memimage *src, Point p) { int srcval; USED(src); srcval = p.x; p.x = left; p.y = y; memset(byteaddr(dst, p), srcval, right-left); } #endif static void fillline(Memimage *dst, int left, int right, int y, Memimage *src, Point p, int op) { Rectangle r; r.min.x = left; r.min.y = y; r.max.x = right; r.max.y = y+1; p.x += left; p.y += y; memdraw(dst, r, src, p, memopaque, p, op); } static void fillpoint(Memimage *dst, int x, int y, Memimage *src, Point p, int op) { Rectangle r; r.min.x = x; r.min.y = y; r.max.x = x+1; r.max.y = y+1; p.x += x; p.y += y; memdraw(dst, r, src, p, memopaque, p, op); } void memfillpoly(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp, int op) { _memfillpolysc(dst, vert, nvert, w, src, sp, 0, 0, 0, op); } void _memfillpolysc(Memimage *dst, Point *vert, int nvert, int w, Memimage *src, Point sp, int detail, int fixshift, int clipped, int op) { Seg **seg, *segtab; Point p0; int i; if(nvert == 0) return; seg = malloc((nvert+2)*sizeof(Seg*)); if(seg == nil) return; segtab = malloc((nvert+1)*sizeof(Seg)); if(segtab == nil) { free(seg); return; } sp.x = (sp.x - vert[0].x) >> fixshift; sp.y = (sp.y - vert[0].y) >> fixshift; p0 = vert[nvert-1]; if(!fixshift) { p0.x <<= 1; p0.y <<= 1; } for(i = 0; i < nvert; i++) { segtab[i].p0 = p0; p0 = vert[i]; if(!fixshift) { p0.x <<= 1; p0.y <<= 1; } segtab[i].p1 = p0; segtab[i].d = 1; } if(!fixshift) fixshift = 1; xscan(dst, seg, segtab, nvert, w, src, sp, detail, fixshift, clipped, op); if(detail) yscan(dst, seg, segtab, nvert, w, src, sp, fixshift, op); free(seg); free(segtab); } static long mod(long x, long y) { long z; z = x%y; if((long)(((ulong)z)^((ulong)y)) > 0 || z == 0) return z; return z + y; } static long sdiv(long x, long y) { if((long)(((ulong)x)^((ulong)y)) >= 0 || x == 0) return x/y; return (x+((y>>30)|1))/y-1; } static long smuldivmod(long x, long y, long z, long *mod) { vlong vx; if(x == 0 || y == 0){ *mod = 0; return 0; } vx = x; vx *= y; *mod = vx % z; if(*mod < 0) *mod += z; /* z is always >0 */ if((vx < 0) == (z < 0)) return vx/z; return -((-vx)/z); } static void xscan(Memimage *dst, Seg **seg, Seg *segtab, int nseg, int wind, Memimage *src, Point sp, int detail, int fixshift, int clipped, int op) { long y, maxy, x, x2, xerr, xden, onehalf; Seg **ep, **next, **p, **q, *s; long n, i, iy, cnt, ix, ix2, minx, maxx; Point pt; void (*fill)(Memimage*, int, int, int, Memimage*, Point, int); fill = fillline; /* * This can only work on 8-bit destinations, since fillcolor is * just using memset on sp.x. * * I'd rather not even enable it then, since then if the general * code is too slow, someone will come up with a better improvement * than this sleazy hack. -rsc * if(clipped && (src->flags&Frepl) && src->depth==8 && Dx(src->r)==1 && Dy(src->r)==1) { fill = fillcolor; sp.x = membyteval(src); } * */ USED(clipped); for(i=0, s=segtab, p=seg; ip0.y == s->p1.y) continue; if(s->p0.y > s->p1.y) { pt = s->p0; s->p0 = s->p1; s->p1 = pt; s->d = -s->d; } s->num = s->p1.x - s->p0.x; s->den = s->p1.y - s->p0.y; s->dz = sdiv(s->num, s->den) << fixshift; s->dzrem = mod(s->num, s->den) << fixshift; s->dz += sdiv(s->dzrem, s->den); s->dzrem = mod(s->dzrem, s->den); p++; } n = p-seg; if(n == 0) return; *p = 0; qsort(seg, p-seg , sizeof(Seg*), ycompare); onehalf = 0; if(fixshift) onehalf = 1 << (fixshift-1); minx = dst->clipr.min.x; maxx = dst->clipr.max.x; y = seg[0]->p0.y; if(y < (dst->clipr.min.y << fixshift)) y = dst->clipr.min.y << fixshift; iy = (y + onehalf) >> fixshift; y = (iy << fixshift) + onehalf; maxy = dst->clipr.max.y << fixshift; ep = next = seg; while(yp1.y < y) continue; s->z += s->dz; s->zerr += s->dzrem; if(s->zerr >= s->den) { s->z++; s->zerr -= s->den; if(s->zerr < 0 || s->zerr >= s->den) print("bad ratzerr1: %ld den %ld dzrem %ld\n", s->zerr, s->den, s->dzrem); } *q++ = s; } for(p = next; *p; p++) { s = *p; if(s->p0.y >= y) break; if(s->p1.y < y) continue; s->z = s->p0.x; s->z += smuldivmod(y - s->p0.y, s->num, s->den, &s->zerr); if(s->zerr < 0 || s->zerr >= s->den) print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem); *q++ = s; } ep = q; next = p; if(ep == seg) { if(*next == 0) break; iy = (next[0]->p0.y + onehalf) >> fixshift; y = (iy << fixshift) + onehalf; continue; } zsort(seg, ep); for(p = seg; p < ep; p++) { cnt = 0; x = p[0]->z; xerr = p[0]->zerr; xden = p[0]->den; ix = (x + onehalf) >> fixshift; if(ix >= maxx) break; if(ix < minx) ix = minx; cnt += p[0]->d; p++; for(;;) { if(p == ep) { print("xscan: fill to infinity"); return; } cnt += p[0]->d; if((cnt&wind) == 0) break; p++; } x2 = p[0]->z; ix2 = (x2 + onehalf) >> fixshift; if(ix2 <= minx) continue; if(ix2 > maxx) ix2 = maxx; if(ix == ix2 && detail) { if(xerr*p[0]->den + p[0]->zerr*xden > p[0]->den*xden) x++; ix = (x + x2) >> (fixshift+1); ix2 = ix+1; } (*fill)(dst, ix, ix2, iy, src, sp, op); } y += (1<p0.x == s->p1.x) continue; if(s->p0.x > s->p1.x) { pt = s->p0; s->p0 = s->p1; s->p1 = pt; s->d = -s->d; } s->num = s->p1.y - s->p0.y; s->den = s->p1.x - s->p0.x; s->dz = sdiv(s->num, s->den) << fixshift; s->dzrem = mod(s->num, s->den) << fixshift; s->dz += sdiv(s->dzrem, s->den); s->dzrem = mod(s->dzrem, s->den); p++; } n = p-seg; if(n == 0) return; *p = 0; qsort(seg, n , sizeof(Seg*), xcompare); onehalf = 0; if(fixshift) onehalf = 1 << (fixshift-1); miny = dst->clipr.min.y; maxy = dst->clipr.max.y; x = seg[0]->p0.x; if(x < (dst->clipr.min.x << fixshift)) x = dst->clipr.min.x << fixshift; ix = (x + onehalf) >> fixshift; x = (ix << fixshift) + onehalf; maxx = dst->clipr.max.x << fixshift; ep = next = seg; while(xp1.x < x) continue; s->z += s->dz; s->zerr += s->dzrem; if(s->zerr >= s->den) { s->z++; s->zerr -= s->den; if(s->zerr < 0 || s->zerr >= s->den) print("bad ratzerr1: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem); } *q++ = s; } for(p = next; *p; p++) { s = *p; if(s->p0.x >= x) break; if(s->p1.x < x) continue; s->z = s->p0.y; s->z += smuldivmod(x - s->p0.x, s->num, s->den, &s->zerr); if(s->zerr < 0 || s->zerr >= s->den) print("bad ratzerr2: %ld den %ld ratdzrem %ld\n", s->zerr, s->den, s->dzrem); *q++ = s; } ep = q; next = p; if(ep == seg) { if(*next == 0) break; ix = (next[0]->p0.x + onehalf) >> fixshift; x = (ix << fixshift) + onehalf; continue; } zsort(seg, ep); for(p = seg; p < ep; p++) { cnt = 0; y = p[0]->z; yerr = p[0]->zerr; yden = p[0]->den; iy = (y + onehalf) >> fixshift; if(iy >= maxy) break; if(iy < miny) iy = miny; cnt += p[0]->d; p++; for(;;) { if(p == ep) { print("yscan: fill to infinity"); return; } cnt += p[0]->d; if((cnt&wind) == 0) break; p++; } y2 = p[0]->z; iy2 = (y2 + onehalf) >> fixshift; if(iy2 <= miny) continue; if(iy2 > maxy) iy2 = maxy; if(iy == iy2) { if(yerr*p[0]->den + p[0]->zerr*yden > p[0]->den*yden) y++; iy = (y + y2) >> (fixshift+1); fillpoint(dst, ix, iy, src, sp, op); } } x += (1<z > p[1]->z) { s = p[0]; p[0] = p[1]; p[1] = s; done = 0; } } } while(!done); } else { q = ep-1; for(p = seg; p < q; p++) { if(p[0]->z > p[1]->z) { qsort(seg, ep-seg, sizeof(Seg*), zcompare); break; } } } } static int ycompare(const void *a, const void *b) { Seg **s0, **s1; long y0, y1; s0 = (Seg**)a; s1 = (Seg**)b; y0 = (*s0)->p0.y; y1 = (*s1)->p0.y; if(y0 < y1) return -1; if(y0 == y1) return 0; return 1; } static int xcompare(const void *a, const void *b) { Seg **s0, **s1; long x0, x1; s0 = (Seg**)a; s1 = (Seg**)b; x0 = (*s0)->p0.x; x1 = (*s1)->p0.x; if(x0 < x1) return -1; if(x0 == x1) return 0; return 1; } static int zcompare(const void *a, const void *b) { Seg **s0, **s1; long z0, z1; s0 = (Seg**)a; s1 = (Seg**)b; z0 = (*s0)->z; z1 = (*s1)->z; if(z0 < z1) return -1; if(z0 == z1) return 0; return 1; } drawterm-20110822.orig/win32-386/0000755000175000017500000000000011245145712015353 5ustar tinchotinchodrawterm-20110822.orig/win32-386/md5block.spp0000644000175000017500000001467711245145712017616 0ustar tinchotincho/* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 #define PAYME(x) $ ## x /* * SI is data * a += FN(B,C,D); * a += x[sh] + t[sh]; * a = (a << S11) | (a >> (32 - S11)); * a += b; */ #define BODY1(off,V,FN,SH,A,B,C,D)\ FN(B,C,D)\ leal V(A, %edi, 1), A;\ addl off(%ebp), A;\ roll PAYME(SH), A;\ addl B, A;\ #define BODY(off,V,FN,SH,A,B,C,D)\ FN(B,C,D)\ leal V(A, %edi, 1), A;\ addl (off)(%ebp), A;\ roll PAYME(SH), A;\ addl B,A;\ /* * fn1 = ((c ^ d) & b) ^ d */ #define FN1(B,C,D)\ movl C, %edi;\ xorl D, %edi;\ andl B, %edi;\ xorl D, %edi;\ /* * fn2 = ((b ^ c) & d) ^ c; */ #define FN2(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ andl D, %edi;\ xorl C, %edi;\ /* * fn3 = b ^ c ^ d; */ #define FN3(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ xorl D, %edi;\ /* * fn4 = c ^ (b | ~d); */ #define FN4(B,C,D)\ movl D, %edi;\ xorl $-1, %edi;\ orl B, %edi;\ xorl C, %edi;\ #define STACKSIZE 20 #define DATA (STACKSIZE+8) #define LEN (STACKSIZE+12) #define STATE (STACKSIZE+16) #define EDATA (STACKSIZE-4) #define OLDEBX (STACKSIZE-8) #define OLDESI (STACKSIZE-12) #define OLDEDI (STACKSIZE-16) .text .p2align 2,0x90 .globl ___md5block ___md5block: .p2align 2,0x90 .globl __md5block __md5block: .p2align 2,0x90 .globl _md5block _md5block: .p2align 2,0x90 .globl md5block md5block: /* Prelude */ pushl %ebp subl $(STACKSIZE), %esp movl %ebx, OLDEBX(%esp) movl %esi, OLDESI(%esp) movl %edi, OLDEDI(%esp) movl DATA(%esp), %eax addl LEN(%esp), %eax movl %eax, EDATA(%esp) movl DATA(%esp), %ebp 0: movl STATE(%esp), %esi movl (%esi), %eax movl 4(%esi), %ebx movl 8(%esi), %ecx movl 12(%esi), %edx BODY1( 0*4,0xd76aa478,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1( 1*4,0xe8c7b756,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1( 2*4,0x242070db,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1( 3*4,0xc1bdceee,FN1,S14,%ebx,%ecx,%edx,%eax) BODY1( 4*4,0xf57c0faf,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1( 5*4,0x4787c62a,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1( 6*4,0xa8304613,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1( 7*4,0xfd469501,FN1,S14,%ebx,%ecx,%edx,%eax) BODY1( 8*4,0x698098d8,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1( 9*4,0x8b44f7af,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1(10*4,0xffff5bb1,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1(11*4,0x895cd7be,FN1,S14,%ebx,%ecx,%edx,%eax) BODY1(12*4,0x6b901122,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1(13*4,0xfd987193,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1(14*4,0xa679438e,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1(15*4,0x49b40821,FN1,S14,%ebx,%ecx,%edx,%eax) BODY( 1*4,0xf61e2562,FN2,S21,%eax,%ebx,%ecx,%edx) BODY( 6*4,0xc040b340,FN2,S22,%edx,%eax,%ebx,%ecx) BODY(11*4,0x265e5a51,FN2,S23,%ecx,%edx,%eax,%ebx) BODY( 0*4,0xe9b6c7aa,FN2,S24,%ebx,%ecx,%edx,%eax) BODY( 5*4,0xd62f105d,FN2,S21,%eax,%ebx,%ecx,%edx) BODY(10*4,0x02441453,FN2,S22,%edx,%eax,%ebx,%ecx) BODY(15*4,0xd8a1e681,FN2,S23,%ecx,%edx,%eax,%ebx) BODY( 4*4,0xe7d3fbc8,FN2,S24,%ebx,%ecx,%edx,%eax) BODY( 9*4,0x21e1cde6,FN2,S21,%eax,%ebx,%ecx,%edx) BODY(14*4,0xc33707d6,FN2,S22,%edx,%eax,%ebx,%ecx) BODY( 3*4,0xf4d50d87,FN2,S23,%ecx,%edx,%eax,%ebx) BODY( 8*4,0x455a14ed,FN2,S24,%ebx,%ecx,%edx,%eax) BODY(13*4,0xa9e3e905,FN2,S21,%eax,%ebx,%ecx,%edx) BODY( 2*4,0xfcefa3f8,FN2,S22,%edx,%eax,%ebx,%ecx) BODY( 7*4,0x676f02d9,FN2,S23,%ecx,%edx,%eax,%ebx) BODY(12*4,0x8d2a4c8a,FN2,S24,%ebx,%ecx,%edx,%eax) BODY( 5*4,0xfffa3942,FN3,S31,%eax,%ebx,%ecx,%edx) BODY( 8*4,0x8771f681,FN3,S32,%edx,%eax,%ebx,%ecx) BODY(11*4,0x6d9d6122,FN3,S33,%ecx,%edx,%eax,%ebx) BODY(14*4,0xfde5380c,FN3,S34,%ebx,%ecx,%edx,%eax) BODY( 1*4,0xa4beea44,FN3,S31,%eax,%ebx,%ecx,%edx) BODY( 4*4,0x4bdecfa9,FN3,S32,%edx,%eax,%ebx,%ecx) BODY( 7*4,0xf6bb4b60,FN3,S33,%ecx,%edx,%eax,%ebx) BODY(10*4,0xbebfbc70,FN3,S34,%ebx,%ecx,%edx,%eax) BODY(13*4,0x289b7ec6,FN3,S31,%eax,%ebx,%ecx,%edx) BODY( 0*4,0xeaa127fa,FN3,S32,%edx,%eax,%ebx,%ecx) BODY( 3*4,0xd4ef3085,FN3,S33,%ecx,%edx,%eax,%ebx) BODY( 6*4,0x04881d05,FN3,S34,%ebx,%ecx,%edx,%eax) BODY( 9*4,0xd9d4d039,FN3,S31,%eax,%ebx,%ecx,%edx) BODY(12*4,0xe6db99e5,FN3,S32,%edx,%eax,%ebx,%ecx) BODY(15*4,0x1fa27cf8,FN3,S33,%ecx,%edx,%eax,%ebx) BODY( 2*4,0xc4ac5665,FN3,S34,%ebx,%ecx,%edx,%eax) BODY( 0*4,0xf4292244,FN4,S41,%eax,%ebx,%ecx,%edx) BODY( 7*4,0x432aff97,FN4,S42,%edx,%eax,%ebx,%ecx) BODY(14*4,0xab9423a7,FN4,S43,%ecx,%edx,%eax,%ebx) BODY( 5*4,0xfc93a039,FN4,S44,%ebx,%ecx,%edx,%eax) BODY(12*4,0x655b59c3,FN4,S41,%eax,%ebx,%ecx,%edx) BODY( 3*4,0x8f0ccc92,FN4,S42,%edx,%eax,%ebx,%ecx) BODY(10*4,0xffeff47d,FN4,S43,%ecx,%edx,%eax,%ebx) BODY( 1*4,0x85845dd1,FN4,S44,%ebx,%ecx,%edx,%eax) BODY( 8*4,0x6fa87e4f,FN4,S41,%eax,%ebx,%ecx,%edx) BODY(15*4,0xfe2ce6e0,FN4,S42,%edx,%eax,%ebx,%ecx) BODY( 6*4,0xa3014314,FN4,S43,%ecx,%edx,%eax,%ebx) BODY(13*4,0x4e0811a1,FN4,S44,%ebx,%ecx,%edx,%eax) BODY( 4*4,0xf7537e82,FN4,S41,%eax,%ebx,%ecx,%edx) BODY(11*4,0xbd3af235,FN4,S42,%edx,%eax,%ebx,%ecx) BODY( 2*4,0x2ad7d2bb,FN4,S43,%ecx,%edx,%eax,%ebx) BODY( 9*4,0xeb86d391,FN4,S44,%ebx,%ecx,%edx,%eax) addl $(16*4), %ebp movl STATE(%esp), %edi addl %eax,0(%edi) addl %ebx,4(%edi) addl %ecx,8(%edi) addl %edx,12(%edi) movl EDATA(%esp), %edi cmpl %edi, %ebp jb 0b /* Postlude */ movl OLDEBX(%esp), %ebx movl OLDESI(%esp), %esi movl OLDEDI(%esp), %edi addl $(STACKSIZE), %esp popl %ebp ret drawterm-20110822.orig/win32-386/tas.c0000644000175000017500000000041611245145712016307 0ustar tinchotincho#include "u.h" #include "libc.h" int tas(long *x) { int v; __asm__( "movl $1, %%eax\n\t" "xchgl %%eax,(%%ecx)" : "=a" (v) : "c" (x) ); switch(v) { case 0: case 1: return v; default: print("canlock: corrupted 0x%lux\n", v); return 1; } } drawterm-20110822.orig/win32-386/sha1block.spp0000644000175000017500000001146011245145712017750 0ustar tinchotincho.text .p2align 2,0x90 .globl ___sha1block ___sha1block: jmp sha1block .p2align 2,0x90 .globl __sha1block __sha1block: jmp sha1block .p2align 2,0x90 .globl _sha1block _sha1block: jmp sha1block .p2align 2,0x90 .globl sha1block sha1block: /* x = (wp[off-f] ^ wp[off-8] ^ wp[off-14] ^ wp[off-16]) <<< 1; * wp[off] = x; * x += A <<< 5; * E += 0xca62c1d6 + x; * x = FN(B,C,D); * E += x; * B >>> 2 */ #define BSWAPDI BYTE $0x0f; BYTE $0xcf; #define BODY(off,FN,V,A,B,C,D,E)\ movl (off-64)(%ebp), %edi;\ xorl (off-56)(%ebp), %edi;\ xorl (off-32)(%ebp), %edi;\ xorl (off-12)(%ebp), %edi;\ roll $1, %edi;\ movl %edi, off(%ebp);\ leal V(%edi, E, 1), E;\ movl A, %edi;\ roll $5, %edi;\ addl %edi, E;\ FN(B,C,D)\ addl %edi, E;\ rorl $2, B;\ #define BODY0(off,FN,V,A,B,C,D,E)\ movl off(%ebx), %edi;\ bswap %edi;\ movl %edi, off(%ebp);\ leal V(%edi,E,1), E;\ movl A, %edi;\ roll $5,%edi;\ addl %edi,E;\ FN(B,C,D)\ addl %edi,E;\ rorl $2,B;\ /* * fn1 = (((C^D)&B)^D); */ #define FN1(B,C,D)\ movl C, %edi;\ xorl D, %edi;\ andl B, %edi;\ xorl D, %edi;\ /* * fn24 = B ^ C ^ D */ #define FN24(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ xorl D, %edi;\ /* * fn3 = ((B ^ C) & (D ^= B)) ^ B * D ^= B to restore D */ #define FN3(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ xorl B, D;\ andl D, %edi;\ xorl B, %edi;\ xorl B, D;\ /* * stack offsets * void sha1block(uchar *DATA, int LEN, ulong *STATE) */ #define STACKSIZE (48+80*4) #define DATA (STACKSIZE+8) #define LEN (STACKSIZE+12) #define STATE (STACKSIZE+16) /* * stack offsets for locals * ulong w[80]; * uchar *edata; * ulong *w15, *w40, *w60, *w80; * register local * ulong *wp = %ebp * ulong a = eax, b = ebx, c = ecx, d = edx, e = esi * ulong tmp = edi */ #define WARRAY (STACKSIZE-4-(80*4)) #define TMP1 (STACKSIZE-8-(80*4)) #define TMP2 (STACKSIZE-12-(80*4)) #define W15 (STACKSIZE-16-(80*4)) #define W40 (STACKSIZE-20-(80*4)) #define W60 (STACKSIZE-24-(80*4)) #define W80 (STACKSIZE-28-(80*4)) #define EDATA (STACKSIZE-32-(80*4)) #define OLDEBX (STACKSIZE-36-(80*4)) #define OLDESI (STACKSIZE-40-(80*4)) #define OLDEDI (STACKSIZE-44-(80*4)) /* Prelude */ pushl %ebp subl $(STACKSIZE), %esp mov %ebx, OLDEBX(%esp) mov %esi, OLDESI(%esp) mov %edi, OLDEDI(%esp) movl DATA(%esp), %eax addl LEN(%esp), %eax movl %eax, EDATA(%esp) leal (WARRAY+15*4)(%esp), %edi /* aw15 */ movl %edi, W15(%esp) leal (WARRAY+40*4)(%esp), %edx /* aw40 */ movl %edx, W40(%esp) leal (WARRAY+60*4)(%esp), %ecx /* aw60 */ movl %ecx, W60(%esp) leal (WARRAY+80*4)(%esp), %edi /* aw80 */ movl %edi, W80(%esp) 0: leal WARRAY(%esp), %ebp /* warray */ movl STATE(%esp), %edi /* state */ movl (%edi),%eax movl 4(%edi),%ebx movl %ebx, TMP1(%esp) /* tmp1 */ movl 8(%edi), %ecx movl 12(%edi), %edx movl 16(%edi), %esi movl DATA(%esp), %ebx /* data */ 1: BODY0(0,FN1,0x5a827999,%eax,TMP1(%esp),%ecx,%edx,%esi) movl %esi,TMP2(%esp) BODY0(4,FN1,0x5a827999,%esi,%eax,TMP1(%esp),%ecx,%edx) movl TMP1(%esp),%esi BODY0(8,FN1,0x5a827999,%edx,TMP2(%esp),%eax,%esi,%ecx) BODY0(12,FN1,0x5a827999,%ecx,%edx,TMP2(%esp),%eax,%esi) movl %esi,TMP1(%esp) BODY0(16,FN1,0x5a827999,%esi,%ecx,%edx,TMP2(%esp),%eax) movl TMP2(%esp),%esi addl $20, %ebx addl $20, %ebp cmpl W15(%esp), %ebp /* w15 */ jb 1b BODY0(0,FN1,0x5a827999,%eax,TMP1(%esp),%ecx,%edx,%esi) addl $4, %ebx MOVL %ebx, DATA(%esp) /* data */ MOVL TMP1(%esp),%ebx BODY(4,FN1,0x5a827999,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN1,0x5a827999,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN1,0x5a827999,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN1,0x5a827999,%ebx,%ecx,%edx,%esi,%eax) addl $20, %ebp 2: BODY(0,FN24,0x6ed9eba1,%eax,%ebx,%ecx,%edx,%esi) BODY(4,FN24,0x6ed9eba1,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN24,0x6ed9eba1,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN24,0x6ed9eba1,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN24,0x6ed9eba1,%ebx,%ecx,%edx,%esi,%eax) addl $20,%ebp cmpl W40(%esp), %ebp jb 2b 3: BODY(0,FN3,0x8f1bbcdc,%eax,%ebx,%ecx,%edx,%esi) BODY(4,FN3,0x8f1bbcdc,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN3,0x8f1bbcdc,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN3,0x8f1bbcdc,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN3,0x8f1bbcdc,%ebx,%ecx,%edx,%esi,%eax) addl $20, %ebp cmpl W60(%esp), %ebp /* w60 */ jb 3b 4: BODY(0,FN24,0xca62c1d6,%eax,%ebx,%ecx,%edx,%esi) BODY(4,FN24,0xca62c1d6,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN24,0xca62c1d6,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN24,0xca62c1d6,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN24,0xca62c1d6,%ebx,%ecx,%edx,%esi,%eax) addl $20, %ebp cmpl W80(%esp), %ebp /* w80 */ jb 4b movl STATE(%esp), %edi /* state */ addl %eax, 0(%edi) addl %ebx, 4(%edi) addl %ecx, 8(%edi) addl %edx, 12(%edi) addl %esi, 16(%edi) movl EDATA(%esp), %edi /* edata */ cmpl %edi, DATA(%esp) /* data */ jb 0b /* Postlude */ mov OLDEBX(%esp), %ebx mov OLDESI(%esp), %esi mov OLDEDI(%esp), %edi addl $(STACKSIZE), %esp popl %ebp ret drawterm-20110822.orig/win32-386/Makefile0000644000175000017500000000044311245145712017014 0ustar tinchotinchoROOT=.. include ../Make.config LIB=../libmachdep.a OFILES=\ getcallerpc.$O\ md5block.$O\ sha1block.$O\ tas.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c %.$O: %.s $(AS) -o $*.$O $*.s %.s: %.spp cpp $*.spp >$*.s drawterm-20110822.orig/win32-386/getcallerpc.c0000644000175000017500000000013611245145712020004 0ustar tinchotincho#include "u.h" #include "libc.h" uintptr getcallerpc(void *a) { return ((uintptr*)a)[-1]; } drawterm-20110822.orig/Make.irix0000644000175000017500000000075511245145711015653 0ustar tinchotincho# Unix PTHREAD= # for Mac #PTHREAD=-pthread AR=ar AS=as ASFLAGS=-c -mips3 RANLIB=true X11=/usr/X11R6 #CC=gcc #CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 CC=cc CFLAGS=-g -O2 -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -DIRIX O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib -lX11 -g -lpthread LDFLAGS=$(PTHREAD) TARG=drawterm MAKE=gmake all: default libmachdep.a: (cd posix-mips && $(MAKE)) drawterm-20110822.orig/gui-osx/0000755000175000017500000000000011245145711015465 5ustar tinchotinchodrawterm-20110822.orig/gui-osx/cload.c0000644000175000017500000000027411245145711016716 0ustar tinchotincho#include #include #include #include int cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { return _cloadmemimage(i, r, data, ndata); } drawterm-20110822.orig/gui-osx/keycodes.h0000644000175000017500000001113011245145711017440 0ustar tinchotincho/* These are the Macintosh key scancode constants -- from Inside Macintosh */ #define QZ_ESCAPE 0x35 #define QZ_F1 0x7A #define QZ_F2 0x78 #define QZ_F3 0x63 #define QZ_F4 0x76 #define QZ_F5 0x60 #define QZ_F6 0x61 #define QZ_F7 0x62 #define QZ_F8 0x64 #define QZ_F9 0x65 #define QZ_F10 0x6D #define QZ_F11 0x67 #define QZ_F12 0x6F #define QZ_PRINT 0x69 #define QZ_SCROLLOCK 0x6B #define QZ_PAUSE 0x71 #define QZ_POWER 0x7F #define QZ_BACKQUOTE 0x32 #define QZ_1 0x12 #define QZ_2 0x13 #define QZ_3 0x14 #define QZ_4 0x15 #define QZ_5 0x17 #define QZ_6 0x16 #define QZ_7 0x1A #define QZ_8 0x1C #define QZ_9 0x19 #define QZ_0 0x1D #define QZ_MINUS 0x1B #define QZ_EQUALS 0x18 #define QZ_BACKSPACE 0x33 #define QZ_INSERT 0x72 #define QZ_HOME 0x73 #define QZ_PAGEUP 0x74 #define QZ_NUMLOCK 0x47 #define QZ_KP_EQUALS 0x51 #define QZ_KP_DIVIDE 0x4B #define QZ_KP_MULTIPLY 0x43 #define QZ_TAB 0x30 #define QZ_q 0x0C #define QZ_w 0x0D #define QZ_e 0x0E #define QZ_r 0x0F #define QZ_t 0x11 #define QZ_y 0x10 #define QZ_u 0x20 #define QZ_i 0x22 #define QZ_o 0x1F #define QZ_p 0x23 #define QZ_LEFTBRACKET 0x21 #define QZ_RIGHTBRACKET 0x1E #define QZ_BACKSLASH 0x2A #define QZ_DELETE 0x75 #define QZ_END 0x77 #define QZ_PAGEDOWN 0x79 #define QZ_KP7 0x59 #define QZ_KP8 0x5B #define QZ_KP9 0x5C #define QZ_KP_MINUS 0x4E #define QZ_CAPSLOCK 0x39 #define QZ_a 0x00 #define QZ_s 0x01 #define QZ_d 0x02 #define QZ_f 0x03 #define QZ_g 0x05 #define QZ_h 0x04 #define QZ_j 0x26 #define QZ_k 0x28 #define QZ_l 0x25 #define QZ_SEMICOLON 0x29 #define QZ_QUOTE 0x27 #define QZ_RETURN 0x24 #define QZ_KP4 0x56 #define QZ_KP5 0x57 #define QZ_KP6 0x58 #define QZ_KP_PLUS 0x45 #define QZ_LSHIFT 0x38 #define QZ_z 0x06 #define QZ_x 0x07 #define QZ_c 0x08 #define QZ_v 0x09 #define QZ_b 0x0B #define QZ_n 0x2D #define QZ_m 0x2E #define QZ_COMMA 0x2B #define QZ_PERIOD 0x2F #define QZ_SLASH 0x2C /* These are the same as the left versions - use left by default */ #if 0 #define QZ_RSHIFT 0x38 #endif #define QZ_UP 0x7E #define QZ_KP1 0x53 #define QZ_KP2 0x54 #define QZ_KP3 0x55 #define QZ_KP_ENTER 0x4C #define QZ_LCTRL 0x3B #define QZ_LALT 0x3A #define QZ_LMETA 0x37 #define QZ_SPACE 0x31 /* These are the same as the left versions - use left by default */ #if 0 #define QZ_RMETA 0x37 #define QZ_RALT 0x3A #define QZ_RCTRL 0x3B #endif #define QZ_LEFT 0x7B #define QZ_DOWN 0x7D #define QZ_RIGHT 0x7C #define QZ_KP0 0x52 #define QZ_KP_PERIOD 0x41 /* Wierd, these keys are on my iBook under MacOS X */ #define QZ_IBOOK_ENTER 0x34 #define QZ_IBOOK_LEFT 0x3B #define QZ_IBOOK_RIGHT 0x3C #define QZ_IBOOK_DOWN 0x3D #define QZ_IBOOK_UP 0x3E #define KEY_ENTER 13 #define KEY_TAB 9 #define KEY_BASE 0x100 /* Function keys */ #define KEY_F (KEY_BASE+64) /* Control keys */ #define KEY_CTRL (KEY_BASE) #define KEY_BACKSPACE (KEY_CTRL+0) #define KEY_DELETE (KEY_CTRL+1) #define KEY_INSERT (KEY_CTRL+2) #define KEY_HOME (KEY_CTRL+3) #define KEY_END (KEY_CTRL+4) #define KEY_PAGE_UP (KEY_CTRL+5) #define KEY_PAGE_DOWN (KEY_CTRL+6) #define KEY_ESC (KEY_CTRL+7) /* Control keys short name */ #define KEY_BS KEY_BACKSPACE #define KEY_DEL KEY_DELETE #define KEY_INS KEY_INSERT #define KEY_PGUP KEY_PAGE_UP #define KEY_PGDOWN KEY_PAGE_DOWN #define KEY_PGDWN KEY_PAGE_DOWN /* Cursor movement */ #define KEY_CRSR (KEY_BASE+16) #define KEY_RIGHT (KEY_CRSR+0) #define KEY_LEFT (KEY_CRSR+1) #define KEY_DOWN (KEY_CRSR+2) #define KEY_UP (KEY_CRSR+3) /* Multimedia keyboard/remote keys */ #define KEY_MM_BASE (0x100+384) #define KEY_POWER (KEY_MM_BASE+0) #define KEY_MENU (KEY_MM_BASE+1) #define KEY_PLAY (KEY_MM_BASE+2) #define KEY_PAUSE (KEY_MM_BASE+3) #define KEY_PLAYPAUSE (KEY_MM_BASE+4) #define KEY_STOP (KEY_MM_BASE+5) #define KEY_FORWARD (KEY_MM_BASE+6) #define KEY_REWIND (KEY_MM_BASE+7) #define KEY_NEXT (KEY_MM_BASE+8) #define KEY_PREV (KEY_MM_BASE+9) #define KEY_VOLUME_UP (KEY_MM_BASE+10) #define KEY_VOLUME_DOWN (KEY_MM_BASE+11) #define KEY_MUTE (KEY_MM_BASE+12) /* Keypad keys */ #define KEY_KEYPAD (KEY_BASE+32) #define KEY_KP0 (KEY_KEYPAD+0) #define KEY_KP1 (KEY_KEYPAD+1) #define KEY_KP2 (KEY_KEYPAD+2) #define KEY_KP3 (KEY_KEYPAD+3) #define KEY_KP4 (KEY_KEYPAD+4) #define KEY_KP5 (KEY_KEYPAD+5) #define KEY_KP6 (KEY_KEYPAD+6) #define KEY_KP7 (KEY_KEYPAD+7) #define KEY_KP8 (KEY_KEYPAD+8) #define KEY_KP9 (KEY_KEYPAD+9) #define KEY_KPDEC (KEY_KEYPAD+10) #define KEY_KPINS (KEY_KEYPAD+11) #define KEY_KPDEL (KEY_KEYPAD+12) #define KEY_KPENTER (KEY_KEYPAD+13) /* Special keys */ #define KEY_INTERN (0x1000) #define KEY_CLOSE_WIN (KEY_INTERN+0) drawterm-20110822.orig/gui-osx/wstrtoutf.c0000644000175000017500000000063011245145711017711 0ustar tinchotincho#include #include int wstrutflen(Rune *s) { int n; for(n=0; *s; n+=runelen(*s),s++) ; return n; } int wstrtoutf(char *s, Rune *t, int n) { int i; char *s0; s0 = s; if(n <= 0) return wstrutflen(t)+1; while(*t) { if(n < UTFmax+1 && n < runelen(*t)+1) { *s = 0; return i+wstrutflen(t)+1; } i = runetochar(s, t); s += i; n -= i; t++; } *s = 0; return s-s0; } drawterm-20110822.orig/gui-osx/Makefile0000644000175000017500000000033411245145711017125 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libgui.a OFILES=\ alloc.$O\ cload.$O\ draw.$O\ load.$O\ screen.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/gui-osx/screen.c0000644000175000017500000004527411245145711017124 0ustar tinchotincho// in this file, _Rect is os x Rect, // _Point is os x Point #undef Point #define Point _Point #undef Rect #define Rect _Rect #include #include // for full screen #undef Rect #undef Point #undef nil #include "u.h" #include "lib.h" #include "kern/dat.h" #include "kern/fns.h" #include "error.h" #include "user.h" #include #include #include "screen.h" #include "keyboard.h" #include "keycodes.h" #define rWindowResource 128 #define topLeft(r) (((Point *) &(r))[0]) #define botRight(r) (((Point *) &(r))[1]) extern int mousequeue; static int depth; Boolean gDone; RgnHandle gCursorRegionHdl; Memimage *gscreen; Screeninfo screen; static int readybit; static Rendez rend; /// // menu // static MenuRef windMenu; static MenuRef viewMenu; enum { kQuitCmd = 1, kFullScreenCmd = 2, }; static WindowGroupRef winGroup = NULL; static WindowRef theWindow = NULL; static CGContextRef context; static CGDataProviderRef dataProviderRef; static CGImageRef fullScreenImage; static CGRect devRect; static CGRect bounds; static PasteboardRef appleclip; static _Rect winRect; Boolean altPressed = false; Boolean button2 = false; Boolean button3 = false; static int isready(void*a) { return readybit; } CGContextRef QuartzContext; void winproc(void *a); void screeninit(void) { int fmt; int dx, dy; ProcessSerialNumber psn = { 0, kCurrentProcess }; TransformProcessType(&psn, kProcessTransformToForegroundApplication); SetFrontProcess(&psn); memimageinit(); depth = 32; // That's all this code deals with for now screen.depth = 32; fmt = XBGR32; //XRGB32; devRect = CGDisplayBounds(CGMainDisplayID()); // devRect.origin.x = 0; // devRect.origin.y = 0; // devRect.size.width = 1024; // devRect.size.height = 768; dx = devRect.size.width; dy = devRect.size.height; gscreen = allocmemimage(Rect(0,0,dx,dy), fmt); dataProviderRef = CGDataProviderCreateWithData(0, gscreen->data->bdata, dx * dy * 4, 0); fullScreenImage = CGImageCreate(dx, dy, 8, 32, dx * 4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipLast, dataProviderRef, 0, 0, kCGRenderingIntentDefault); kproc("osxscreen", winproc, 0); ksleep(&rend, isready, 0); } // No wonder Apple sells so many wide displays! static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData); static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData); static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData); void window_resized() { GetWindowBounds(theWindow, kWindowContentRgn, &winRect ); bounds = CGRectMake(0, 0, winRect.right-winRect.left, winRect.bottom - winRect.top); } void winproc(void *a) { winRect.left = 30; winRect.top = 60; winRect.bottom = (devRect.size.height * 0.75) + winRect.top; winRect.right = (devRect.size.width * 0.75) + winRect.left; ClearMenuBar(); InitCursor(); CreateStandardWindowMenu(0, &windMenu); InsertMenu(windMenu, 0); MenuItemIndex index; CreateNewMenu(1004, 0, &viewMenu); SetMenuTitleWithCFString(viewMenu, CFSTR("View")); AppendMenuItemTextWithCFString(viewMenu, CFSTR("Full Screen"), 0, kFullScreenCmd, &index); SetMenuItemCommandKey(viewMenu, index, 0, 'F'); InsertMenu(viewMenu, GetMenuID(windMenu)); DrawMenuBar(); uint32_t windowAttrs = 0 | kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowResizableAttribute | kWindowStandardHandlerAttribute | kWindowFullZoomAttribute ; CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow); CreateWindowGroup(0, &winGroup); SetWindowGroup(theWindow, winGroup); SetWindowTitleWithCFString(theWindow, CFSTR("Drawterm")); if(PasteboardCreate(kPasteboardClipboard, &appleclip) != noErr) sysfatal("pasteboard create failed"); const EventTypeSpec quit_events[] = { { kEventClassApplication, kEventAppQuit } }; const EventTypeSpec commands[] = { { kEventClassWindow, kEventWindowClosed }, { kEventClassWindow, kEventWindowBoundsChanged }, { kEventClassCommand, kEventCommandProcess } }; const EventTypeSpec events[] = { { kEventClassKeyboard, kEventRawKeyDown }, { kEventClassKeyboard, kEventRawKeyModifiersChanged }, { kEventClassKeyboard, kEventRawKeyRepeat }, { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseUp }, { kEventClassMouse, kEventMouseMoved }, { kEventClassMouse, kEventMouseDragged }, { kEventClassMouse, kEventMouseWheelMoved }, }; InstallApplicationEventHandler ( NewEventHandlerUPP (ApplicationQuitEventHandler), GetEventTypeCount(quit_events), quit_events, NULL, NULL); InstallApplicationEventHandler ( NewEventHandlerUPP (MainWindowEventHandler), GetEventTypeCount(events), events, NULL, NULL); InstallWindowEventHandler ( theWindow, NewEventHandlerUPP (MainWindowCommandHandler), GetEventTypeCount(commands), commands, theWindow, NULL); ShowWindow(theWindow); ShowMenuBar(); window_resized(); SelectWindow(theWindow); terminit(); // Run the event loop readybit = 1; wakeup(&rend); RunApplicationEventLoop(); } static inline int convert_key(UInt32 key, UInt32 charcode) { switch(key) { case QZ_IBOOK_ENTER: case QZ_RETURN: return '\n'; case QZ_ESCAPE: return 27; case QZ_BACKSPACE: return '\b'; case QZ_LALT: return Kalt; case QZ_LCTRL: return Kctl; case QZ_LSHIFT: return Kshift; case QZ_F1: return KF+1; case QZ_F2: return KF+2; case QZ_F3: return KF+3; case QZ_F4: return KF+4; case QZ_F5: return KF+5; case QZ_F6: return KF+6; case QZ_F7: return KF+7; case QZ_F8: return KF+8; case QZ_F9: return KF+9; case QZ_F10: return KF+10; case QZ_F11: return KF+11; case QZ_F12: return KF+12; case QZ_INSERT: return Kins; case QZ_DELETE: return 0x7F; case QZ_HOME: return Khome; case QZ_END: return Kend; case QZ_KP_PLUS: return '+'; case QZ_KP_MINUS: return '-'; case QZ_TAB: return '\t'; case QZ_PAGEUP: return Kpgup; case QZ_PAGEDOWN: return Kpgdown; case QZ_UP: return Kup; case QZ_DOWN: return Kdown; case QZ_LEFT: return Kleft; case QZ_RIGHT: return Kright; case QZ_KP_MULTIPLY: return '*'; case QZ_KP_DIVIDE: return '/'; case QZ_KP_ENTER: return '\n'; case QZ_KP_PERIOD: return '.'; case QZ_KP0: return '0'; case QZ_KP1: return '1'; case QZ_KP2: return '2'; case QZ_KP3: return '3'; case QZ_KP4: return '4'; case QZ_KP5: return '5'; case QZ_KP6: return '6'; case QZ_KP7: return '7'; case QZ_KP8: return '8'; case QZ_KP9: return '9'; default: return charcode; } } void sendbuttons(int b, int x, int y) { int i; lock(&mouse.lk); i = mouse.wi; if(mousequeue) { if(i == mouse.ri || mouse.lastb != b || mouse.trans) { mouse.wi = (i+1)%Mousequeue; if(mouse.wi == mouse.ri) mouse.ri = (mouse.ri+1)%Mousequeue; mouse.trans = mouse.lastb != b; } else { i = (i-1+Mousequeue)%Mousequeue; } } else { mouse.wi = (i+1)%Mousequeue; mouse.ri = i; } mouse.queue[i].xy.x = x; mouse.queue[i].xy.y = y; mouse.queue[i].buttons = b; mouse.queue[i].msec = ticks(); mouse.lastb = b; unlock(&mouse.lk); wakeup(&mouse.r); } static Ptr fullScreenRestore; static int amFullScreen = 0; static WindowRef oldWindow = NULL; static void leave_full_screen() { if (amFullScreen) { EndFullScreen(fullScreenRestore, 0); theWindow = oldWindow; ShowWindow(theWindow); amFullScreen = 0; window_resized(); Rectangle rect = { { 0, 0 }, { bounds.size.width, bounds.size.height} }; drawqlock(); flushmemscreen(rect); drawqunlock(); } } static void full_screen() { if (!amFullScreen) { oldWindow = theWindow; HideWindow(theWindow); BeginFullScreen(&fullScreenRestore, 0, 0, 0, &theWindow, 0, 0); amFullScreen = 1; window_resized(); Rectangle rect = { { 0, 0 }, { bounds.size.width, bounds.size.height} }; drawqlock(); flushmemscreen(rect); drawqunlock(); } } // catch quit events to handle quits from menu, Cmd+Q, applescript, and task switcher static OSStatus ApplicationQuitEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData) { exit(0); // QuitApplicationEventLoop(); return noErr; } static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData) { OSStatus result = noErr; result = CallNextEventHandler(nextHandler, event); UInt32 class = GetEventClass (event); UInt32 kind = GetEventKind (event); static uint32_t mousebuttons = 0; // bitmask of buttons currently down static uint32_t mouseX = 0; static uint32_t mouseY = 0; if(class == kEventClassKeyboard) { char macCharCodes; UInt32 macKeyCode; UInt32 macKeyModifiers; GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(macCharCodes), NULL, &macCharCodes); GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(macKeyCode), NULL, &macKeyCode); GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(macKeyModifiers), NULL, &macKeyModifiers); switch(kind) { case kEventRawKeyModifiersChanged: if (macKeyModifiers == (controlKey | optionKey)) leave_full_screen(); switch(macKeyModifiers & (optionKey | cmdKey)) { case (optionKey | cmdKey): /* due to chording we need to handle the case when both * modifier keys are pressed at the same time. * currently it's only 2-3 snarf and the 3-2 noop */ altPressed = true; if(mousebuttons & 1 || mousebuttons & 2 || mousebuttons & 4) { mousebuttons |= 2; /* set button 2 */ mousebuttons |= 4; /* set button 3 */ button2 = true; button3 = true; sendbuttons(mousebuttons, mouseX, mouseY); } break; case optionKey: altPressed = true; if(mousebuttons & 1 || mousebuttons & 4) { mousebuttons |= 2; /* set button 2 */ button2 = true; sendbuttons(mousebuttons, mouseX, mouseY); } break; case cmdKey: if(mousebuttons & 1 || mousebuttons & 2) { mousebuttons |= 4; /* set button 3 */ button3 = true; sendbuttons(mousebuttons, mouseX, mouseY); } break; case 0: default: if(button2 || button3) { if(button2) { mousebuttons &= ~2; /* clear button 2 */ button2 = false; altPressed = false; } if(button3) { mousebuttons &= ~4; /* clear button 3 */ button3 = false; } sendbuttons(mousebuttons, mouseX, mouseY); } if(altPressed) { kbdputc(kbdq, Kalt); altPressed = false; } break; } break; case kEventRawKeyDown: case kEventRawKeyRepeat: if(macKeyModifiers != cmdKey) { int key = convert_key(macKeyCode, macCharCodes); if (key != -1) kbdputc(kbdq, key); } else result = eventNotHandledErr; break; default: break; } } else if(class == kEventClassMouse) { _Point mousePos; GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof mousePos, 0, &mousePos); switch (kind) { case kEventMouseWheelMoved: { int32_t wheeldelta; GetEventParameter(event,kEventParamMouseWheelDelta,typeSInt32, 0,sizeof(wheeldelta), 0, &wheeldelta); mouseX = mousePos.h - winRect.left; mouseY = mousePos.v - winRect.top; sendbuttons(wheeldelta>0 ? 8 : 16, mouseX, mouseY); break; } case kEventMouseUp: case kEventMouseDown: { uint32_t buttons; uint32_t modifiers; GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0, sizeof(modifiers), 0, &modifiers); GetEventParameter(event, kEventParamMouseChord, typeUInt32, 0, sizeof buttons, 0, &buttons); /* simulate other buttons via alt/apple key. like x11 */ if(modifiers & optionKey) { mousebuttons = ((buttons & 1) ? 2 : 0); altPressed = false; } else if(modifiers & cmdKey) mousebuttons = ((buttons & 1) ? 4 : 0); else mousebuttons = (buttons & 1); mousebuttons |= ((buttons & 2)<<1); mousebuttons |= ((buttons & 4)>>1); } /* Fallthrough */ case kEventMouseMoved: case kEventMouseDragged: mouseX = mousePos.h - winRect.left; mouseY = mousePos.v - winRect.top; sendbuttons(mousebuttons, mouseX, mouseY); break; default: result = eventNotHandledErr; break; } } return result; } //default window command handler (from menus) static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData) { OSStatus result = noErr; UInt32 class = GetEventClass (event); UInt32 kind = GetEventKind (event); result = CallNextEventHandler(nextHandler, event); if(class == kEventClassCommand) { HICommand theHICommand; GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( HICommand ), NULL, &theHICommand ); switch ( theHICommand.commandID ) { case kHICommandQuit: exit(0); break; case kFullScreenCmd: full_screen(); break; default: result = eventNotHandledErr; break; } } else if(class == kEventClassWindow) { WindowRef window; _Rect rectPort = {0,0,0,0}; GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window); if(window) { GetPortBounds(GetWindowPort(window), &rectPort); } switch (kind) { case kEventWindowClosed: // send a quit carbon event instead of directly calling cleanexit // so that all quits are done in ApplicationQuitEventHandler { EventRef quitEvent; CreateEvent(NULL, kEventClassApplication, kEventAppQuit, 0, kEventAttributeNone, &quitEvent); EventTargetRef target; target = GetApplicationEventTarget(); SendEventToEventTarget(quitEvent, target); } break; //resize window case kEventWindowBoundsChanged: window_resized(); Rectangle rect = { { 0, 0 }, { bounds.size.width, bounds.size.height} }; drawqlock(); flushmemscreen(rect); drawqunlock(); break; default: result = eventNotHandledErr; break; } } return result; } void flushmemscreen(Rectangle r) { // sanity check. Trips from the initial "terminal" if (r.max.x < r.min.x || r.max.y < r.min.y) return; screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP, gscreen->width*sizeof(ulong)); } uchar* attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X) { *r = gscreen->r; *chan = gscreen->chan; *depth = gscreen->depth; *width = gscreen->width; *softscreen = 1; return gscreen->data->bdata; } // PAL - no palette handling. Don't intend to either. void getcolor(ulong i, ulong *r, ulong *g, ulong *b) { // PAL: Certainly wrong to return a grayscale. *r = i; *g = i; *b = i; } void setcolor(ulong index, ulong red, ulong green, ulong blue) { assert(0); } static char snarf[3*SnarfSize+1]; static Rune rsnarf[SnarfSize+1]; char* clipread(void) { CFDataRef cfdata; OSStatus err = noErr; ItemCount nItems; // Wow. This is ridiculously complicated. PasteboardSynchronize(appleclip); if((err = PasteboardGetItemCount(appleclip, &nItems)) != noErr) { fprint(2, "apple pasteboard GetItemCount failed - Error %d\n", err); return 0; } uint32_t i; // Yes, based at 1. Silly API. for(i = 1; i <= nItems; ++i) { PasteboardItemID itemID; CFArrayRef flavorTypeArray; CFIndex flavorCount; if((err = PasteboardGetItemIdentifier(appleclip, i, &itemID)) != noErr){ fprint(2, "Can't get pasteboard item identifier: %d\n", err); return 0; } if((err = PasteboardCopyItemFlavors(appleclip, itemID, &flavorTypeArray))!=noErr){ fprint(2, "Can't copy pasteboard item flavors: %d\n", err); return 0; } flavorCount = CFArrayGetCount(flavorTypeArray); CFIndex flavorIndex; for(flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex){ CFStringRef flavorType; flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex); if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))){ if((err = PasteboardCopyItemFlavorData(appleclip, itemID, CFSTR("public.utf16-plain-text"), &cfdata)) != noErr){ fprint(2, "apple pasteboard CopyItem failed - Error %d\n", err); return 0; } CFIndex length = CFDataGetLength(cfdata); if (length > sizeof rsnarf) length = sizeof rsnarf; CFDataGetBytes(cfdata, CFRangeMake(0, length), (uint8_t *)rsnarf); snprint(snarf, sizeof snarf, "%.*S", length/sizeof(Rune), rsnarf); char *s = snarf; while (*s) { if (*s == '\r') *s = '\n'; s++; } CFRelease(cfdata); return strdup(snarf); } } } return 0; } int clipwrite(char *snarf) { CFDataRef cfdata; PasteboardSyncFlags flags; runesnprint(rsnarf, nelem(rsnarf), "%s", snarf); if(PasteboardClear(appleclip) != noErr){ fprint(2, "apple pasteboard clear failed\n"); return 0; } flags = PasteboardSynchronize(appleclip); if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){ fprint(2, "apple pasteboard cannot assert ownership\n"); return 0; } cfdata = CFDataCreate(kCFAllocatorDefault, (uchar*)rsnarf, runestrlen(rsnarf)*2); if(cfdata == nil){ fprint(2, "apple pasteboard cfdatacreate failed\n"); return 0; } if(PasteboardPutItemFlavor(appleclip, (PasteboardItemID)1, CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){ fprint(2, "apple pasteboard putitem failed\n"); CFRelease(cfdata); return 0; } CFRelease(cfdata); return 1; } void mouseset(Point xy) { CGPoint pnt; pnt.x = xy.x + winRect.left; pnt.y = xy.y + winRect.top; CGWarpMouseCursorPosition(pnt); } void screenload(Rectangle r, int depth, uchar *p, Point pt, int step) { CGRect rbounds; rbounds.size.width = r.max.x - r.min.x; rbounds.size.height = r.max.y - r.min.y; rbounds.origin.x = r.min.x; rbounds.origin.y = r.min.y; if(depth != gscreen->depth) panic("screenload: bad ldepth"); QDBeginCGContext( GetWindowPort(theWindow), &context); // The sub-image is relative to our whole screen image. CGImageRef subimg = CGImageCreateWithImageInRect(fullScreenImage, rbounds); // Drawing the sub-image is relative to the window. rbounds.origin.y = winRect.bottom - winRect.top - r.min.y - rbounds.size.height; CGContextDrawImage(context, rbounds, subimg); CGContextFlush(context); CGImageRelease(subimg); QDEndCGContext( GetWindowPort(theWindow), &context); } // PAL: these don't work. // SetCursor and InitCursor are marked as deprecated in 10.4, and I can't for the // life of me find out what has replaced them. void setcursor(void) { Cursor crsr; int i; for(i=0; i<16; i++){ crsr.data[i] = ((ushort*)cursor.set)[i]; crsr.mask[i] = crsr.data[i] | ((ushort*)cursor.clr)[i]; } crsr.hotSpot.h = -cursor.offset.x; crsr.hotSpot.v = -cursor.offset.y; SetCursor(&crsr); } void cursorarrow(void) { InitCursor(); } drawterm-20110822.orig/gui-osx/load.c0000644000175000017500000000027211245145711016551 0ustar tinchotincho#include #include #include #include int loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { return _loadmemimage(i, r, data, ndata); } drawterm-20110822.orig/gui-osx/draw.c0000644000175000017500000000055511245145711016573 0ustar tinchotincho#include #include #include #include void memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op) { _memimagedraw(_memimagedrawsetup(dst, r, src, sp, mask, mp, op)); } ulong pixelbits(Memimage *m, Point p) { return _pixelbits(m, p); } void memimageinit(void) { _memimageinit(); } drawterm-20110822.orig/gui-osx/alloc.c0000644000175000017500000000043611245145711016726 0ustar tinchotincho#include #include #include #include Memimage* allocmemimage(Rectangle r, ulong chan) { return _allocmemimage(r, chan); } void freememimage(Memimage *i) { _freememimage(i); } void memfillcolor(Memimage *i, ulong val) { _memfillcolor(i, val); } drawterm-20110822.orig/9ball.ico0000644000175000017500000002215611245145711015577 0ustar tinchotinchoh6 @@(F( @AAA aaa000QQQ(((888IIIXXXhhh$$$444<<<MMM---DDDTTT[[[^^^ddd&&&***222666:::>>>FFFKKKOOOVVV!!!###%%%''')))...///111333555777;;;===???BBBCCCGGGHHHLLLNNNPPPRRRSSSWWWZZZ___```bbbeee F'HE''FFF'34 4IH'FF'MP7M6JH'F'7;XWW )P!KI'FIhD0eZ<;:)O''aU9@d\j.g,$? Cc??( @@@@ ```000PPPppp(((888HHHXXXhhhwww$$$,,,444<<<DDDLLLTTT\\\ddd{{{sss"""&&&***...222666:::>>>BBBFFFJJJNNNRRRVVVZZZ^^^bbbfffnnnyyy!!!###%%%''')))+++---///111333555777999;;;===???AAACCCEEEGGGIIIKKKMMMOOOQQQSSSUUUWWWYYY[[[]]]___aaaccceeegggoootttvvvzzz kk""m k"""""kk""@ """k"""""""kk"ok"""""kkkk"""""kkm>mnn@m""kk"""""k"iBsCuuuC$qonm"kk""""kkCE%zGGGz%EvusBm"kk"""k"{}&&&}G%EsBnm"k"""km$HL &Hzxso@"k"""kB NNN(L&H{zECqn"k""k"u:[QO&}Gxuqn"k""k$9Y\*Q J{%$n"k"k@,^`72SQ)OL&%$n"k"kvU;`PPP7N &%q@"kkE.65RK')N &%uBmkkm 7~wwybVSO &{Esn"k"|RprF X,VTOHGvqmk"~<d6# TONLJ}%Cnkm,'PtehjjY-Z X,T &GBkE!g=7]X,TJ}x$mF9/XQO zsD3U=pb V)L&GCC P403p+]Z,SJ{uIlKFf?2-XO(J{% MgA8/]Z,*JcW+b11a_[ J_a11a_/]-OS1111a_/]-*_1a_/]- ,S aZXT,]_/][Z,--Z(@@@@ ```000PPPppp(((888HHHXXXhhhxxx $$$,,,444<<<DDDLLLTTT\\\dddlllttt|||"""&&&***...222666:::>>>BBBFFFJJJNNNRRRVVVZZZ^^^bbbfffjjjnnnrrrvvvzzz~~~ !!!###%%%''')))+++---///111333555777999;;;===???AAACCCEEEGGGIIIKKKMMMOOOQQQSSSUUUWWWYYY[[[]]]___aaaccceeegggiiikkkoooqqqsssuuuwww}}}~B""~""""""" ~"""""""""""""""DzB""""""""""""""""""""""J """""""""""""""""""""""""""B~"""""""""""""""""""""""""""""z""""""""""""""""""""""""B|""""""""""""""""""""""""""""""$~"""DDDDDDDD""""""""""""""""""""""~"FFFFFFFDD""""""""""""""""""""~DF$HHHHH$$FFD""""""""""""""""""BHHH$F"""""""""""""""" FJ&&&&&&&&JH$FD"""""""""""""""$z$LLLL&JHF""""""""""""""&NNNNNNNL&&JHF""""""""""""BLN(PP((NNL&JHFD""""""""""""@PP PP((NLJH$""""""""""""HP RRR P(NLJFD""""""""""~(P R**T**R P(NL&H$FD""""""""""B&**TTTT**R P(&J"""""""""""@ R*\\VVVVVT**RP(NL&"""""""""BP$ \qi9¬,,,,VVT*R PNH$F"""""""" ig3 5\XXXX,VVT* (N&JH$F""""""""3c1aaX,VT*RPL&JH$F"""""""BF.3e_///au\ZZX,VT* P(NL&JH$F"""""L3ceo...ZX,VT*R P(NL&JH$"""""""P1/1fGy{{?}}fd2b `0^\.,VT(N&"_#>{yُxxyyx!6hf2b`0^\.ZR JHFDtIEkxxx In<2b`^.ZX,VTP(LDBO;{)܋1cpjf2b`^*RN$"a_s)sG'cvm2b `0\.ZX,V N&$FsEt9}KIxAqfd2 0^T*PDP\x)x5j[!_d2b `^\.ZX,R($%xyQ+ӽdb`0^VR (qCx#o<Yxٖ $(D 尞W^M@i ===/ŵ' mڵ !SHf$h2dϞ,A6u֢B.ž=KH~haZ|Hf%hW)I)PH0!!īH0&&o AOСC;RZ|fgEI)PU$8iҤL'RE;FN}'K-//pIP+ v%(5+yH EGGW4#vwxD2PϪR^#e|RD+Kɓ'+0a#0`K:u&uu,4;e<V)ĉ) lhh۷'{QӒVg4Jvl*ս@9R)"I 8zh6j(`=0-?g LN>VL),22ݻ7 p.HГ3nq'@y`JTL$85CK Y>@+g-@uP#""Hlȑ/i`Ϟ8B ƕ_灝%@ He0#F i4ja~1Ut4YIv@6B*ٰa*////2Y?Zz{}~=}?&?Y+TOHe0/BC&"t?!$wfǏ}9,?;ӟ]-S`-ʓ`u``XXunݺ~ ]mtkǏ[:yNם3He$@6|pz?An.>ټr{eiĶmۦ+>?J(z^POS`jCpyЖVH$ݼx߿ߔ؝R)@!C>x[cp2%9Y@4YQHg3ϮW,|3ʓ`!@*)^̑NR-K*Ϟ=Szj+7v 6tLIu59:vD$X?6 8%{?W?͏?, ܹMn ֭[ӢlӦM +}Lzo> 't&@ $40H_~ez-aUUUdEp&VKr#ر*޽[-[:$H)P^k59ZH`!@6h i}DD(?}ľ})@ pHBtJcǎP6HrbGe'OdgϞegΜaȑ#Ib; @͖fӟY_y"}JRfH}@???ZM )HdA" 1ܻw}YSwUֹs甯⪨>|؄e{aeeeԩSҥKڵkƍJʼr劒8 V*ߥ2hkgg$@y"sL}@KF*R H*ɀF˗/۷444K\TSy yi&>yDбׯ+$ڵK))}'J߮?W (Y8lg {gҢцa8FIĕD]ƍ*JH4BƎ9C2tH6f;W}<]Sg04{N֕p=,PY rb9s& .U&5_}rڵݻw'_|Em ƍaG [_h.o鯭R @ 5LgY6@}_ҝ;weG_~zVDBZ| ٱc<_*@_!H'rE@vvʕ\jU ~c~o MRKYID ӧO__;3O6}vhP*_ ./vMJV=C\>̢_uL>|8 pړ Q#%y曐"_~=̌Pd ko_G[X;A׭[ \g?\i&HFd4MPx̐Aj@gM~ɏ?8믃3|gC-a.0U~cWZ6@f],Y2b5Y/f(f(8*B7+)}ECW' g<޽{C=qqo, uq# Nu O]n aZr4:}:9I`lѣGCgv8v`\*.o_g6MH @hGvOq굸IyPn*Rd.0L]i7 zE-r~%ٚ= gvϦ1 q_\ڰzåfu@`P5# Z~sQ)k_v à5p~cRߔu:)bE\ub 4GAb9@  ?㹣q P$^k{饗vlٔwJu\#te:\,B'|2/|R \ =\!J @Uz'k农SԨ=*tSly.WxtxA,̀ HJH NЂiѓ([`MpN~9ϯ 1RTϺ7+(_fM˵дfȩ1°`@@@uA(21Aڪ%qu as~o~S߮/WK&t855{4غ@Fa(7Gw8d @ڡ@g='´~G_gWTS4qJ*%iBٳ' N ^ z6b0_KmoI{4=rojϺQJKl՟ruƂwatoIAf!"PSt" .T& _7ks5-_ZHc>ܛ\ @:8@tute)*q*RVo΃B6A#VSnKcoH_RruEɂ瀁r޽&Y2)`4gfH DlXY12hЌa}m J}_Iuwd{,To`@FbHAa!A|-z!Ma'Y& ?>rn-x5>j_mK4755r-$}e3G,H )8@ C8yGw-iG4zzgAGN}E_)7Wj|_mCѼ;t̢WCN.0 AK$=RJ!r]A΂.,TrvfCt~mծ{,Vr  @ AaRb@I _9\tT ǽ.KR/5<⺟ƩoGV8]Y,t?O^cۋ/ꁂ øA B=ܜK#eY)Ok={6\KR/~vG\S>\vbY  {I;*X`^\ z]RTc M[S>\vme~1BOn pkmn ^5 T[JyS17=lohQ]vm\bEX,|@.oߞA#Jqvĉ'"Xwjqܓtx9u_*-z74U.W,Z/\ uzj4F Bȑ#~85r@-5z.s^z]JwK)o7G7=Eru̢/] H:LM2"ġ qD9CC`L} ǏPZݒK%XL^7Y,v p`yƯcǂKܿ\!uB@H-5$< ۫_.͹\o⎯mz ).WvX,~Hky/`b<7H8ARc\!1uB`hd15\s֭I圞^պT;&jzh~˖-Ap64%,tMϝ; xƍ͛7!10EpC:<38.ˁ/Uu}wl mzشio\ub<`a-@JNJ $5 E" 6HB_;w̦%赹KR17k`28\EaETX` xʕy >H*P@s{y:.< ˥%WJyoĎhs.W7m Xt{G!\!aqSj~%w z}դ9~Deҥ?.BEͲ@ 8SN7Z #=dzK+ zCY.WwMhY k׮ӧ'/^ [C9C-m-a$4`DF7BAt%EZԭ.?+~ҍ;F Vޜ;O}t9$y~Ɠ}g!(ܔ a!ofooy* 6S"󉔝)<_酵>n/J~rs+rA/!9@ K Jj2y);)<)jW|(?7/\. ='h M!q-Lv.٤lu}ʛ&4T]gB?nMdhbcB|/-Vw^r񃐧a aCd%A)B)C)Dm1MzayvקkbZ*7'Ee5hPb2#=d'} ARGH B 6JJ!R):);W{%=_E~F!O *+ l)A&B-C]rt &;l ks/mU+V C$ijMRq#?%0'lnҨl6%T*Rf5(E(e((c&8\‹mqW|QU_Z2 ?Q@P єoamq%>[77o(!$B)-A"\l ef&;)<__X)!2>; i(3.Ǜb, )BKJ!Z¤gU6=Aҏ60$I@M &J/sKC+9[_Bn>oJ8  el1_U*=Vn."sđ ] "2B' ޺ZHBHW?8 )B)C)D)$N WzK-w~ l!S:R\]s&(鹪Q9"p-V!)FWdgKzj/'<珐*CR)DSda׹dg^R.>~ssu#$rrJJJ!J)F^+eg^KOa}}5Oy!$!ģEe#yMx](GU7BHj6e((8dׅ“WcGH[e|"rٙ! V,[do.;;;\%f$2`)C੅csI/m|ƒ SpKR8 /-^ ;<>.>{Ƃ& §_ '&&~)}ZXXޞ!=拡wJb{TjżacrrܻA%KU!U{ccc_?T[gĆܫVo*_>oUZXB!B!B!B!@PUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUځCA_ Lz@IENDB`drawterm-20110822.orig/resource.h0000644000175000017500000000071111245145712016072 0ustar tinchotincho//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by drawterm.rc // #define IDI_ICON1 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif drawterm-20110822.orig/posix-mips/0000755000175000017500000000000011245145712016203 5ustar tinchotinchodrawterm-20110822.orig/posix-mips/md5block.c0000644000175000017500000001165011245145712020052 0ustar tinchotincho#include #include #include /* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ /* * Rotate ammounts used in the algorithm */ enum { S11= 7, S12= 12, S13= 17, S14= 22, S21= 5, S22= 9, S23= 14, S24= 20, S31= 4, S32= 11, S33= 16, S34= 23, S41= 6, S42= 10, S43= 15, S44= 21, }; static u32int md5tab[] = { /* round 1 */ /*[0]*/ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, /* round 2 */ /*[16]*/0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, /* round 3 */ /*[32]*/0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, /* round 4 */ /*[48]*/0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static void decode(u32int*, uchar*, ulong); extern void _md5block(uchar *p, ulong len, u32int *s); void _md5block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, sh; u32int *t; uchar *end; u32int x[16]; for(end = p+len; p < end; p += 64){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; decode(x, p, 64); t = md5tab; sh = 0; for(; sh != 16; t += 4){ a += ((c ^ d) & b) ^ d; a += x[sh] + t[0]; a = (a << S11) | (a >> (32 - S11)); a += b; d += ((b ^ c) & a) ^ c; d += x[sh + 1] + t[1]; d = (d << S12) | (d >> (32 - S12)); d += a; c += ((a ^ b) & d) ^ b; c += x[sh + 2] + t[2]; c = (c << S13) | (c >> (32 - S13)); c += d; b += ((d ^ a) & c) ^ a; b += x[sh + 3] + t[3]; b = (b << S14) | (b >> (32 - S14)); b += c; sh += 4; } sh = 1; for(; sh != 1+20*4; t += 4){ a += ((b ^ c) & d) ^ c; a += x[sh & 0xf] + t[0]; a = (a << S21) | (a >> (32 - S21)); a += b; d += ((a ^ b) & c) ^ b; d += x[(sh + 5) & 0xf] + t[1]; d = (d << S22) | (d >> (32 - S22)); d += a; c += ((d ^ a) & b) ^ a; c += x[(sh + 10) & 0xf] + t[2]; c = (c << S23) | (c >> (32 - S23)); c += d; b += ((c ^ d) & a) ^ d; b += x[(sh + 15) & 0xf] + t[3]; b = (b << S24) | (b >> (32 - S24)); b += c; sh += 20; } sh = 5; for(; sh != 5+12*4; t += 4){ a += b ^ c ^ d; a += x[sh & 0xf] + t[0]; a = (a << S31) | (a >> (32 - S31)); a += b; d += a ^ b ^ c; d += x[(sh + 3) & 0xf] + t[1]; d = (d << S32) | (d >> (32 - S32)); d += a; c += d ^ a ^ b; c += x[(sh + 6) & 0xf] + t[2]; c = (c << S33) | (c >> (32 - S33)); c += d; b += c ^ d ^ a; b += x[(sh + 9) & 0xf] + t[3]; b = (b << S34) | (b >> (32 - S34)); b += c; sh += 12; } sh = 0; for(; sh != 28*4; t += 4){ a += c ^ (b | ~d); a += x[sh & 0xf] + t[0]; a = (a << S41) | (a >> (32 - S41)); a += b; d += b ^ (a | ~c); d += x[(sh + 7) & 0xf] + t[1]; d = (d << S42) | (d >> (32 - S42)); d += a; c += a ^ (d | ~b); c += x[(sh + 14) & 0xf] + t[2]; c = (c << S43) | (c >> (32 - S43)); c += d; b += d ^ (c | ~a); b += x[(sh + 21) & 0xf] + t[3]; b = (b << S44) | (b >> (32 - S44)); b += c; sh += 28; } s[0] += a; s[1] += b; s[2] += c; s[3] += d; } } /* * decodes input (uchar) into output (u32int). Assumes len is * a multiple of 4. */ static void decode(u32int *output, uchar *input, ulong len) { uchar *e; for(e = input+len; input < e; input += 4) *output++ = input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24); } drawterm-20110822.orig/posix-mips/tas.s0000644000175000017500000000057111245145712017161 0ustar tinchotincho#include #include .globl tas .ent tas 2 tas: .set noreorder 1: ori t1, zero, 12345 /* t1 = 12345 */ ll t0, (a0) /* t0 = *a0 */ sc t1, (a0) /* *a0 = t1 if *a0 hasn't changed; t1=success */ beq t1, zero, 1b /* repeat if *a0 did change */ nop j $31 /* return */ or v0, t0, zero /* set return value on way out */ .set reorder .end tas drawterm-20110822.orig/posix-mips/Makefile0000644000175000017500000000045611245145712017650 0ustar tinchotinchoROOT=.. include ../Make.config LIB=../libmachdep.a OFILES=\ getcallerpc.$O\ md5block.$O\ sha1block.$O\ tas.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c %.$O: %.s $(AS) $(ASFLAGS) -o $*.$O $*.s %.s: %.spp cpp $*.spp >$*.s drawterm-20110822.orig/posix-mips/sha1block.c0000644000175000017500000001114611245145712020221 0ustar tinchotincho#include #include #include void _sha1block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, e, x; uchar *end; u32int *wp, *wend; u32int w[80]; /* at this point, we have a multiple of 64 bytes */ for(end = p+len; p < end;){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; e = s[4]; wend = w + 15; for(wp = w; wp < wend; wp += 5){ wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); wp[1] = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7]; d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); wp[2] = (p[8]<<24) | (p[9]<<16) | (p[10]<<8) | p[11]; c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); wp[3] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); wp[4] = (p[16]<<24) | (p[17]<<16) | (p[18]<<8) | p[19]; a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); p += 20; } wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); wp += 5; p += 4; wend = w + 40; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x6ed9eba1 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x6ed9eba1 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x6ed9eba1 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x6ed9eba1 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x6ed9eba1 + (c^d^e); c = (c<<30)|(c>>2); } wend = w + 60; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x8f1bbcdc + ((b&c)|((b|c)&d)); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x8f1bbcdc + ((a&b)|((a|b)&c)); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x8f1bbcdc + ((e&a)|((e|a)&b)); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x8f1bbcdc + ((d&e)|((d|e)&a)); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x8f1bbcdc + ((c&d)|((c|d)&e)); c = (c<<30)|(c>>2); } wend = w + 80; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0xca62c1d6 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0xca62c1d6 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0xca62c1d6 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0xca62c1d6 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0xca62c1d6 + (c^d^e); c = (c<<30)|(c>>2); } /* save state */ s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; } } drawterm-20110822.orig/posix-mips/getcallerpc.c0000644000175000017500000000013211245145712020630 0ustar tinchotincho#include "u.h" #include "libc.h" ulong getcallerpc(void *a) { return ((ulong*)a)[-1]; } drawterm-20110822.orig/Make.osx0000644000175000017500000000063611245145711015507 0ustar tinchotincho# Mac OS X PTHREAD= # for Mac AR=ar AS=as RANLIB=ranlib CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=osx LDADD=-ggdb -framework Carbon -framework QuickTime LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \ (cd posix-$$arch && make) drawterm-20110822.orig/libmp/0000755000175000017500000000000011245145712015176 5ustar tinchotinchodrawterm-20110822.orig/libmp/mpmod.c0000644000175000017500000000036711245145712016464 0ustar tinchotincho#include "os.h" #include #include "dat.h" // remainder = b mod m // // knuth, vol 2, pp 398-400 void mpmod(mpint *b, mpint *m, mpint *remainder) { mpdiv(b, m, nil, remainder); if(remainder->sign < 0) mpadd(m, remainder, remainder); } drawterm-20110822.orig/libmp/mpeuclid.c0000644000175000017500000000231211245145712017142 0ustar tinchotincho#include "os.h" #include // extended euclid // // For a and b it solves, d = gcd(a,b) and finds x and y s.t. // ax + by = d // // Handbook of Applied Cryptography, Menezes et al, 1997, pg 67 void mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y) { mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r; if(mpcmp(a, b) < 0){ tmp = a; a = b; b = tmp; tmp = x; x = y; y = tmp; } if(b->top == 0){ mpassign(a, d); mpassign(mpone, x); mpassign(mpzero, y); return; } a = mpcopy(a); b = mpcopy(b); x0 = mpnew(0); x1 = mpcopy(mpzero); x2 = mpcopy(mpone); y0 = mpnew(0); y1 = mpcopy(mpone); y2 = mpcopy(mpzero); q = mpnew(0); r = mpnew(0); while(b->top != 0 && b->sign > 0){ // q = a/b // r = a mod b mpdiv(a, b, q, r); // x0 = x2 - qx1 mpmul(q, x1, x0); mpsub(x2, x0, x0); // y0 = y2 - qy1 mpmul(q, y1, y0); mpsub(y2, y0, y0); // rotate values tmp = a; a = b; b = r; r = tmp; tmp = x2; x2 = x1; x1 = x0; x0 = tmp; tmp = y2; y2 = y1; y1 = y0; y0 = tmp; } mpassign(a, d); mpassign(x2, x); mpassign(y2, y); mpfree(x0); mpfree(x1); mpfree(x2); mpfree(y0); mpfree(y1); mpfree(y2); mpfree(q); mpfree(r); mpfree(a); mpfree(b); } drawterm-20110822.orig/libmp/mptov.c0000644000175000017500000000174311245145712016514 0ustar tinchotincho#include "os.h" #include #include "dat.h" #define VLDIGITS (sizeof(vlong)/sizeof(mpdigit)) /* * this code assumes that a vlong is an integral number of * mpdigits long. */ mpint* vtomp(vlong v, mpint *b) { int s; uvlong uv; if(b == nil) b = mpnew(VLDIGITS*sizeof(mpdigit)); else mpbits(b, VLDIGITS*sizeof(mpdigit)); mpassign(mpzero, b); if(v == 0) return b; if(v < 0){ b->sign = -1; uv = -v; } else uv = v; for(s = 0; s < VLDIGITS && uv != 0; s++){ b->p[s] = uv; uv >>= sizeof(mpdigit)*8; } b->top = s; return b; } vlong mptov(mpint *b) { uvlong v; int s; if(b->top == 0) return (vlong) 0; mpnorm(b); if(b->top > VLDIGITS){ if(b->sign > 0) return (vlong)MAXVLONG; else return (vlong)MINVLONG; } v = (uvlong) 0; for(s = 0; s < b->top; s++) v |= b->p[s]<<(s*sizeof(mpdigit)*8); if(b->sign > 0){ if(v > MAXVLONG) v = MAXVLONG; } else { if(v > MINVLONG) v = MINVLONG; else v = -(vlong)v; } return (vlong)v; } drawterm-20110822.orig/libmp/mpdigdiv.c0000644000175000017500000000133411245145712017146 0ustar tinchotincho#include "os.h" #include #include "dat.h" // // divide two digits by one and return quotient // void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient) { mpdigit hi, lo, q, x, y; int i; hi = dividend[1]; lo = dividend[0]; // return highest digit value if the result >= 2**32 if(hi >= divisor || divisor == 0){ divisor = 0; *quotient = ~divisor; return; } // at this point we know that hi < divisor // just shift and subtract till we're done q = 0; x = divisor; for(i = Dbits-1; hi > 0 && i >= 0; i--){ x >>= 1; if(x > hi) continue; y = divisor< lo) continue; if(y > lo) hi--; lo -= y; hi -= x; q |= 1< #define iseven(a) (((a)->p[0] & 1) == 0) // use extended gcd to find the multiplicative inverse // res = b**-1 mod m void mpinvert(mpint *b, mpint *m, mpint *res) { mpint *dc1, *dc2; // don't care dc1 = mpnew(0); dc2 = mpnew(0); mpextendedgcd(b, m, dc1, res, dc2); if(mpcmp(dc1, mpone) != 0) abort(); mpmod(res, m, res); mpfree(dc1); mpfree(dc2); } drawterm-20110822.orig/libmp/mptouv.c0000644000175000017500000000132711245145712016677 0ustar tinchotincho#include "os.h" #include #include "dat.h" #define VLDIGITS (sizeof(vlong)/sizeof(mpdigit)) /* * this code assumes that a vlong is an integral number of * mpdigits long. */ mpint* uvtomp(uvlong v, mpint *b) { int s; if(b == nil) b = mpnew(VLDIGITS*sizeof(mpdigit)); else mpbits(b, VLDIGITS*sizeof(mpdigit)); mpassign(mpzero, b); if(v == 0) return b; for(s = 0; s < VLDIGITS && v != 0; s++){ b->p[s] = v; v >>= sizeof(mpdigit)*8; } b->top = s; return b; } uvlong mptouv(mpint *b) { uvlong v; int s; if(b->top == 0) return (vlong) 0; mpnorm(b); if(b->top > VLDIGITS) return MAXVLONG; v = (uvlong) 0; for(s = 0; s < b->top; s++) v |= b->p[s]<<(s*sizeof(mpdigit)*8); return v; } drawterm-20110822.orig/libmp/strtomp.c0000644000175000017500000000572211245145712017060 0ustar tinchotincho#include "os.h" #include #include #include "dat.h" static struct { int inited; uchar t64[256]; uchar t32[256]; uchar t16[256]; uchar t10[256]; } tab; enum { INVAL= 255 }; static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz"; static char set16[] = "0123456789ABCDEF0123456789abcdef"; static char set10[] = "0123456789"; static void init(void) { char *p; memset(tab.t64, INVAL, sizeof(tab.t64)); memset(tab.t32, INVAL, sizeof(tab.t32)); memset(tab.t16, INVAL, sizeof(tab.t16)); memset(tab.t10, INVAL, sizeof(tab.t10)); for(p = set64; *p; p++) tab.t64[(uchar)*p] = p-set64; for(p = set32; *p; p++) tab.t32[(uchar)*p] = p-set32; for(p = set16; *p; p++) tab.t16[(uchar)*p] = (p-set16)%16; for(p = set10; *p; p++) tab.t10[(uchar)*p] = (p-set10); tab.inited = 1; } static char* from16(char *a, mpint *b) { char *p, *next; int i; mpdigit x; b->top = 0; for(p = a; *p; p++) if(tab.t16[(uchar)*p] == INVAL) break; mpbits(b, (p-a)*4); b->top = 0; next = p; while(p > a){ x = 0; for(i = 0; i < Dbits; i += 4){ if(p <= a) break; x |= tab.t16[(uchar)*--p]<p[b->top++] = x; } return next; } static ulong mppow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static char* from10(char *a, mpint *b) { ulong x, y; mpint *pow, *r; int i; pow = mpnew(0); r = mpnew(0); b->top = 0; for(;;){ // do a billion at a time in native arithmetic x = 0; for(i = 0; i < 9; i++){ y = tab.t10[(uchar)*a]; if(y == INVAL) break; a++; x *= 10; x += y; } if(i == 0) break; // accumulate into mpint uitomp(mppow10[i], pow); uitomp(x, r); mpmul(b, pow, b); mpadd(b, r, b); if(i != 9) break; } mpfree(pow); mpfree(r); return a; } static char* from64(char *a, mpint *b) { char *buf = a; uchar *p; int n, m; for(; tab.t64[(uchar)*a] != INVAL; a++) ; n = a-buf; mpbits(b, n*6); p = malloc(n); if(p == nil) return a; m = dec64(p, n, buf, n); betomp(p, m, b); free(p); return a; } static char* from32(char *a, mpint *b) { char *buf = a; uchar *p; int n, m; for(; tab.t64[(uchar)*a] != INVAL; a++) ; n = a-buf; mpbits(b, n*5); p = malloc(n); if(p == nil) return a; m = dec32(p, n, buf, n); betomp(p, m, b); free(p); return a; } mpint* strtomp(char *a, char **pp, int base, mpint *b) { int sign; char *e; if(b == nil) b = mpnew(0); if(tab.inited == 0) init(); while(*a==' ' || *a=='\t') a++; sign = 1; for(;; a++){ switch(*a){ case '-': sign *= -1; continue; } break; } switch(base){ case 10: e = from10(a, b); break; default: case 16: e = from16(a, b); break; case 32: e = from32(a, b); break; case 64: e = from64(a, b); break; } // if no characters parsed, there wasn't a number to convert if(e == a) return nil; mpnorm(b); b->sign = sign; if(pp != nil) *pp = e; return b; } drawterm-20110822.orig/libmp/mpadd.c0000644000175000017500000000141711245145712016432 0ustar tinchotincho#include "os.h" #include #include "dat.h" // sum = abs(b1) + abs(b2), i.e., add the magnitudes void mpmagadd(mpint *b1, mpint *b2, mpint *sum) { int m, n; mpint *t; // get the sizes right if(b2->top > b1->top){ t = b1; b1 = b2; b2 = t; } n = b1->top; m = b2->top; if(n == 0){ mpassign(mpzero, sum); return; } if(m == 0){ mpassign(b1, sum); return; } mpbits(sum, (n+1)*Dbits); sum->top = n+1; mpvecadd(b1->p, n, b2->p, m, sum->p); sum->sign = 1; mpnorm(sum); } // sum = b1 + b2 void mpadd(mpint *b1, mpint *b2, mpint *sum) { int sign; if(b1->sign != b2->sign){ if(b1->sign < 0) mpmagsub(b2, b1, sum); else mpmagsub(b1, b2, sum); } else { sign = b1->sign; mpmagadd(b1, b2, sum); if(sum->top != 0) sum->sign = sign; } } drawterm-20110822.orig/libmp/reduce0000644000175000017500000000046211245145712016372 0ustar tinchotinchoO=$1 shift objtype=$1 shift ls -p ../$objtype/*.[cs] >[2]/dev/null | sed 's/..$//' > /tmp/reduce.$pid # # if empty directory, just return the input files # if (! ~ $status '|') { echo $* rm /tmp/reduce.$pid exit 0 } echo $* | tr ' ' \012 | grep -v -f /tmp/reduce.$pid | tr \012 ' ' rm /tmp/reduce.$pid drawterm-20110822.orig/libmp/mpvecsub.c0000644000175000017500000000101311245145712017161 0ustar tinchotincho#include "os.h" #include #include "dat.h" // prereq: a >= b, alen >= blen, diff has at least alen digits void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff) { int i, borrow; mpdigit x, y; borrow = 0; for(i = 0; i < blen; i++){ x = *a++; y = *b++; y += borrow; if(y < borrow) borrow = 1; else borrow = 0; if(x < y) borrow++; *diff++ = x - y; } for(; i < alen; i++){ x = *a++; y = x - borrow; if(y > x) borrow = 1; else borrow = 0; *diff++ = y; } } drawterm-20110822.orig/libmp/os.h0000644000175000017500000000004211245145712015764 0ustar tinchotincho#include #include drawterm-20110822.orig/libmp/crttest.c0000644000175000017500000000145511245145712017037 0ustar tinchotincho#include "os.h" #include #include void testcrt(mpint **p) { CRTpre *crt; CRTres *res; mpint *m, *x, *y; int i; fmtinstall('B', mpconv); // get a modulus and a test number m = mpnew(1024+160); mpmul(p[0], p[1], m); x = mpnew(1024+160); mpadd(m, mpone, x); // do the precomputation for crt conversion crt = crtpre(2, p); // convert x to residues res = crtin(crt, x); // convert back y = mpnew(1024+160); crtout(crt, res, y); print("x %B\ny %B\n", x, y); mpfree(m); mpfree(x); mpfree(y); } void main(void) { int i; mpint *p[2]; long start; start = time(0); for(i = 0; i < 10; i++){ p[0] = mpnew(1024); p[1] = mpnew(1024); DSAprimes(p[0], p[1], nil); testcrt(p); mpfree(p[0]); mpfree(p[1]); } print("%d secs with more\n", time(0)-start); exits(0); } drawterm-20110822.orig/libmp/mpdiv.c0000644000175000017500000000456711245145712016475 0ustar tinchotincho#include "os.h" #include #include "dat.h" // division ala knuth, seminumerical algorithms, pp 237-238 // the numbers are stored backwards to what knuth expects so j // counts down rather than up. void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder) { int j, s, vn, sign; mpdigit qd, *up, *vp, *qp; mpint *u, *v, *t; // divide bv zero if(divisor->top == 0) abort(); // quick check if(mpmagcmp(dividend, divisor) < 0){ if(remainder != nil) mpassign(dividend, remainder); if(quotient != nil) mpassign(mpzero, quotient); return; } // D1: shift until divisor, v, has hi bit set (needed to make trial // divisor accurate) qd = divisor->p[divisor->top-1]; for(s = 0; (qd & mpdighi) == 0; s++) qd <<= 1; u = mpnew((dividend->top+2)*Dbits + s); if(s == 0 && divisor != quotient && divisor != remainder) { mpassign(dividend, u); v = divisor; } else { mpleft(dividend, s, u); v = mpnew(divisor->top*Dbits); mpleft(divisor, s, v); } up = u->p+u->top-1; vp = v->p+v->top-1; vn = v->top; // D1a: make sure high digit of dividend is less than high digit of divisor if(*up >= *vp){ *++up = 0; u->top++; } // storage for multiplies t = mpnew(4*Dbits); qp = nil; if(quotient != nil){ mpbits(quotient, (u->top - v->top)*Dbits); quotient->top = u->top - v->top; qp = quotient->p+quotient->top-1; } // D2, D7: loop on length of dividend for(j = u->top; j > vn; j--){ // D3: calculate trial divisor mpdigdiv(up-1, *vp, &qd); // D3a: rule out trial divisors 2 greater than real divisor if(vn > 1) for(;;){ memset(t->p, 0, 3*Dbytes); // mpvecdigmuladd adds to what's there mpvecdigmuladd(vp-1, 2, qd, t->p); if(mpveccmp(t->p, 3, up-2, 3) > 0) qd--; else break; } // D4: u -= v*qd << j*Dbits sign = mpvecdigmulsub(v->p, vn, qd, up-vn); if(sign < 0){ // D6: trial divisor was too high, add back borrowed // value and decrease divisor mpvecadd(up-vn, vn+1, v->p, vn, up-vn); qd--; } // D5: save quotient digit if(qp != nil) *qp-- = qd; // push top of u down one u->top--; *up-- = 0; } if(qp != nil){ mpnorm(quotient); if(dividend->sign != divisor->sign) quotient->sign = -1; } if(remainder != nil){ mpright(u, s, remainder); // u is the remainder shifted remainder->sign = dividend->sign; } mpfree(t); mpfree(u); if(v != divisor) mpfree(v); } drawterm-20110822.orig/libmp/mpvecdigmuladd.c0000644000175000017500000000305611245145712020333 0ustar tinchotincho#include "os.h" #include #include "dat.h" #define LO(x) ((x) & ((1<<(Dbits/2))-1)) #define HI(x) ((x) >> (Dbits/2)) static void mpdigmul(mpdigit a, mpdigit b, mpdigit *p) { mpdigit x, ah, al, bh, bl, p1, p2, p3, p4; int carry; // half digits ah = HI(a); al = LO(a); bh = HI(b); bl = LO(b); // partial products p1 = ah*bl; p2 = bh*al; p3 = bl*al; p4 = ah*bh; // p = ((p1+p2)<<(Dbits/2)) + (p4< x) borrow = 1; else borrow = 0; x = part[1]; mpdigmul(*b++, m, part); x += part[0]; if(x < part[0]) borrow++; x = y - x; if(x > y) borrow++; *p++ = x; } x = *p; y = x - borrow - part[1]; *p = y; if(y > x) return -1; else return 1; } drawterm-20110822.orig/libmp/mptobe.c0000644000175000017500000000155711245145712016640 0ustar tinchotincho#include "os.h" #include #include "dat.h" // convert an mpint into a big endian byte array (most significant byte first) // return number of bytes converted // if p == nil, allocate and result array int mptobe(mpint *b, uchar *p, uint n, uchar **pp) { int i, j, suppress; mpdigit x; uchar *e, *s, c; if(p == nil){ n = (b->top+1)*Dbytes; p = malloc(n); } if(p == nil) return -1; if(pp != nil) *pp = p; memset(p, 0, n); // special case 0 if(b->top == 0){ if(n < 1) return -1; else return 1; } s = p; e = s+n; suppress = 1; for(i = b->top-1; i >= 0; i--){ x = b->p[i]; for(j = Dbits-8; j >= 0; j -= 8){ c = x>>j; if(c == 0 && suppress) continue; if(p >= e) return -1; *p++ = c; suppress = 0; } } // guarantee at least one byte if(s == p){ if(p >= e) return -1; *p++ = 0; } return p - s; } drawterm-20110822.orig/libmp/mptoui.c0000644000175000017500000000063511245145712016663 0ustar tinchotincho#include "os.h" #include #include "dat.h" /* * this code assumes that mpdigit is at least as * big as an int. */ mpint* uitomp(uint i, mpint *b) { if(b == nil) b = mpnew(0); mpassign(mpzero, b); if(i != 0) b->top = 1; *b->p = i; return b; } uint mptoui(mpint *b) { uint x; x = *b->p; if(b->sign < 0){ x = 0; } else { if(b->top > 1 || x > MAXUINT) x = MAXUINT; } return x; } drawterm-20110822.orig/libmp/mpright.c0000644000175000017500000000126711245145712017022 0ustar tinchotincho#include "os.h" #include #include "dat.h" // res = b >> shift void mpright(mpint *b, int shift, mpint *res) { int d, l, r, i; mpdigit this, last; // a negative right shift is a left shift if(shift < 0){ mpleft(b, -shift, res); return; } if(res != b) mpbits(res, b->top*Dbits - shift); d = shift/Dbits; r = shift - d*Dbits; l = Dbits - r; // special case digit shifts if(r == 0){ for(i = 0; i < b->top-d; i++) res->p[i] = b->p[i+d]; } else { last = b->p[d]; for(i = 0; i < b->top-d-1; i++){ this = b->p[i+d+1]; res->p[i] = (this<>r); last = this; } res->p[i++] = last>>r; } while(i > 0 && res->p[i-1] == 0) i--; res->top = i; } drawterm-20110822.orig/libmp/mpfmt.c0000644000175000017500000000525111245145712016470 0ustar tinchotincho#include "os.h" #include #include #include "dat.h" static int to64(mpint *b, char *buf, int len) { uchar *p; int n, rv; p = nil; n = mptobe(b, nil, 0, &p); if(n < 0) return -1; rv = enc64(buf, len, p, n); free(p); return rv; } static int to32(mpint *b, char *buf, int len) { uchar *p; int n, rv; // leave room for a multiple of 5 buffer size n = b->top*Dbytes + 5; p = malloc(n); if(p == nil) return -1; n = mptobe(b, p, n, nil); if(n < 0) return -1; // round up buffer size, enc32 only accepts a multiple of 5 if(n%5) n += 5 - (n%5); rv = enc32(buf, len, p, n); free(p); return rv; } static char set16[] = "0123456789ABCDEF"; static int to16(mpint *b, char *buf, int len) { mpdigit *p, x; int i, j; char *out, *eout; if(len < 1) return -1; out = buf; eout = buf+len; for(p = &b->p[b->top-1]; p >= b->p; p--){ x = *p; for(i = Dbits-4; i >= 0; i -= 4){ j = 0xf & (x>>i); if(j != 0 || out != buf){ if(out >= eout) return -1; *out++ = set16[j]; } } } if(out == buf) *out++ = '0'; if(out >= eout) return -1; *out = 0; return 0; } static char* modbillion(int rem, ulong r, char *out, char *buf) { ulong rr; int i; for(i = 0; i < 9; i++){ rr = r%10; r /= 10; if(out <= buf) return nil; *--out = '0' + rr; if(rem == 0 && r == 0) break; } return out; } static int to10(mpint *b, char *buf, int len) { mpint *d, *r, *billion; char *out; if(len < 1) return -1; d = mpcopy(b); r = mpnew(0); billion = uitomp(1000000000, nil); out = buf+len; *--out = 0; do { mpdiv(d, billion, d, r); out = modbillion(d->top, r->p[0], out, buf); if(out == nil) break; } while(d->top != 0); mpfree(d); mpfree(r); mpfree(billion); if(out == nil) return -1; len -= out-buf; if(out != buf) memmove(buf, out, len); return 0; } int mpfmt(Fmt *fmt) { mpint *b; char *p; b = va_arg(fmt->args, mpint*); if(b == nil) return fmtstrcpy(fmt, "*"); p = mptoa(b, fmt->prec, nil, 0); fmt->flags &= ~FmtPrec; if(p == nil) return fmtstrcpy(fmt, "*"); else{ fmtstrcpy(fmt, p); free(p); return 0; } } char* mptoa(mpint *b, int base, char *buf, int len) { char *out; int rv, alloced; alloced = 0; if(buf == nil){ len = ((b->top+1)*Dbits+2)/3 + 1; buf = malloc(len); if(buf == nil) return nil; alloced = 1; } if(len < 2) return nil; out = buf; if(b->sign < 0){ *out++ = '-'; len--; } switch(base){ case 64: rv = to64(b, out, len); break; case 32: rv = to32(b, out, len); break; default: case 16: rv = to16(b, out, len); break; case 10: rv = to10(b, out, len); break; } if(rv < 0){ if(alloced) free(buf); return nil; } return buf; } drawterm-20110822.orig/libmp/mpaux.c0000644000175000017500000000500411245145712016473 0ustar tinchotincho#include "os.h" #include #include "dat.h" static mpdigit _mptwodata[1] = { 2 }; static mpint _mptwo = { 1, 1, 1, _mptwodata, MPstatic }; mpint *mptwo = &_mptwo; static mpdigit _mponedata[1] = { 1 }; static mpint _mpone = { 1, 1, 1, _mponedata, MPstatic }; mpint *mpone = &_mpone; static mpdigit _mpzerodata[1] = { 0 }; static mpint _mpzero = { 1, 1, 0, _mpzerodata, MPstatic }; mpint *mpzero = &_mpzero; static int mpmindigits = 33; // set minimum digit allocation void mpsetminbits(int n) { if(n == 0) n = 1; mpmindigits = DIGITS(n); } // allocate an n bit 0'd number mpint* mpnew(int n) { mpint *b; b = mallocz(sizeof(mpint), 1); if(b == nil) sysfatal("mpnew: %r"); n = DIGITS(n); if(n < mpmindigits) n = mpmindigits; n = n; b->p = (mpdigit*)mallocz(n*Dbytes, 1); if(b->p == nil) sysfatal("mpnew: %r"); b->size = n; b->sign = 1; return b; } // guarantee at least n significant bits void mpbits(mpint *b, int m) { int n; n = DIGITS(m); if(b->size >= n){ if(b->top >= n) return; memset(&b->p[b->top], 0, Dbytes*(n - b->top)); b->top = n; return; } b->p = (mpdigit*)realloc(b->p, n*Dbytes); if(b->p == nil) sysfatal("mpbits: %r"); memset(&b->p[b->top], 0, Dbytes*(n - b->top)); b->size = n; b->top = n; } void mpfree(mpint *b) { if(b == nil) return; if(b->flags & MPstatic) sysfatal("freeing mp constant"); memset(b->p, 0, b->top*Dbytes); // information hiding free(b->p); free(b); } void mpnorm(mpint *b) { int i; for(i = b->top-1; i >= 0; i--) if(b->p[i] != 0) break; b->top = i+1; if(b->top == 0) b->sign = 1; } mpint* mpcopy(mpint *old) { mpint *new; new = mpnew(Dbits*old->size); new->top = old->top; new->sign = old->sign; memmove(new->p, old->p, Dbytes*old->top); return new; } void mpassign(mpint *old, mpint *new) { mpbits(new, Dbits*old->top); new->sign = old->sign; new->top = old->top; memmove(new->p, old->p, Dbytes*old->top); } // number of significant bits in mantissa int mpsignif(mpint *n) { int i, j; mpdigit d; if(n->top == 0) return 0; for(i = n->top-1; i >= 0; i--){ d = n->p[i]; for(j = Dbits-1; j >= 0; j--){ if(d & (((mpdigit)1)<top==0) return 0; k = 0; bit = 0; digit = 0; d = n->p[0]; for(;;){ if(d & (1<= n->top) return 0; d = n->p[digit]; bit = 0; } } return k; } drawterm-20110822.orig/libmp/dat.h0000644000175000017500000000072111245145712016117 0ustar tinchotincho#define mpdighi (mpdigit)(1U<<(Dbits-1)) #define DIGITS(x) ((Dbits - 1 + (x))/Dbits) // for converting between int's and mpint's #define MAXUINT ((uint)-1) #define MAXINT (MAXUINT>>1) #define MININT (MAXINT+1) // for converting between vlongs's and mpint's // #define MAXUVLONG (~0ULL) // #define MAXVLONG (MAXUVLONG>>1) // #define MINVLONG (MAXVLONG+1ULL) #define MAXUVLONG ((uvlong) ~0) #define MAXVLONG (MAXUVLONG>>1) #define MINVLONG (MAXVLONG+((uvlong) 1)) drawterm-20110822.orig/libmp/mpextendedgcd.c0000644000175000017500000000311511245145712020155 0ustar tinchotincho#include "os.h" #include #define iseven(a) (((a)->p[0] & 1) == 0) // extended binary gcd // // For a anv b it solves, v = gcd(a,b) and finds x and y s.t. // ax + by = v // // Handbook of Applied Cryptography, Menezes et al, 1997, pg 608. void mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y) { mpint *u, *A, *B, *C, *D; int g; if(a->top == 0){ mpassign(b, v); mpassign(mpone, y); mpassign(mpzero, x); return; } if(b->top == 0){ mpassign(a, v); mpassign(mpone, x); mpassign(mpzero, y); return; } g = 0; a = mpcopy(a); b = mpcopy(b); while(iseven(a) && iseven(b)){ mpright(a, 1, a); mpright(b, 1, b); g++; } u = mpcopy(a); mpassign(b, v); A = mpcopy(mpone); B = mpcopy(mpzero); C = mpcopy(mpzero); D = mpcopy(mpone); for(;;) { // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); while(iseven(u)){ mpright(u, 1, u); if(!iseven(A) || !iseven(B)) { mpadd(A, b, A); mpsub(B, a, B); } mpright(A, 1, A); mpright(B, 1, B); } // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); while(iseven(v)){ mpright(v, 1, v); if(!iseven(C) || !iseven(D)) { mpadd(C, b, C); mpsub(D, a, D); } mpright(C, 1, C); mpright(D, 1, D); } // print("%B %B %B %B %B %B\n", u, v, A, B, C, D); if(mpcmp(u, v) >= 0){ mpsub(u, v, u); mpsub(A, C, A); mpsub(B, D, B); } else { mpsub(v, u, v); mpsub(C, A, C); mpsub(D, B, D); } if(u->top == 0) break; } mpassign(C, x); mpassign(D, y); mpleft(v, g, v); mpfree(A); mpfree(B); mpfree(C); mpfree(D); mpfree(u); mpfree(a); mpfree(b); } drawterm-20110822.orig/libmp/mpcmp.c0000644000175000017500000000071611245145712016462 0ustar tinchotincho#include "os.h" #include #include "dat.h" // return 1, 0, -1 as abs(b1)-abs(b2) is neg, 0, pos int mpmagcmp(mpint *b1, mpint *b2) { int i; i = b1->top - b2->top; if(i) return i; return mpveccmp(b1->p, b1->top, b2->p, b2->top); } // return neg, 0, pos as b1-b2 is neg, 0, pos int mpcmp(mpint *b1, mpint *b2) { if(b1->sign != b2->sign) return b1->sign - b2->sign; if(b1->sign < 0) return mpmagcmp(b2, b1); else return mpmagcmp(b1, b2); } drawterm-20110822.orig/libmp/mpveccmp.c0000644000175000017500000000062211245145712017154 0ustar tinchotincho#include "os.h" #include #include "dat.h" // prereq: alen >= blen int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen) { mpdigit x; while(alen > blen) if(a[--alen] != 0) return 1; while(blen > alen) if(b[--blen] != 0) return -1; while(alen > 0){ --alen; x = a[alen] - b[alen]; if(x == 0) continue; if(x > a[alen]) return -1; else return 1; } return 0; } drawterm-20110822.orig/libmp/crt.c0000644000175000017500000000400211245145712016126 0ustar tinchotincho#include "os.h" #include #include // chinese remainder theorem // // handbook of applied cryptography, menezes et al, 1997, pp 610 - 613 struct CRTpre { int n; // number of moduli mpint **m; // pointer to moduli mpint **c; // precomputed coefficients mpint **p; // precomputed products mpint *a[1]; // local storage }; // setup crt info, returns a newly created structure CRTpre* crtpre(int n, mpint **m) { CRTpre *crt; int i, j; mpint *u; crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n); if(crt == nil) sysfatal("crtpre: %r"); crt->m = crt->a; crt->c = crt->a+n; crt->p = crt->c+n; crt->n = n; // make a copy of the moduli for(i = 0; i < n; i++) crt->m[i] = mpcopy(m[i]); // precompute the products u = mpcopy(mpone); for(i = 0; i < n; i++){ mpmul(u, m[i], u); crt->p[i] = mpcopy(u); } // precompute the coefficients for(i = 1; i < n; i++){ crt->c[i] = mpcopy(mpone); for(j = 0; j < i; j++){ mpinvert(m[j], m[i], u); mpmul(u, crt->c[i], u); mpmod(u, m[i], crt->c[i]); } } mpfree(u); return crt; } void crtprefree(CRTpre *crt) { int i; for(i = 0; i < crt->n; i++){ if(i != 0) mpfree(crt->c[i]); mpfree(crt->p[i]); mpfree(crt->m[i]); } free(crt); } // convert to residues, returns a newly created structure CRTres* crtin(CRTpre *crt, mpint *x) { int i; CRTres *res; res = malloc(sizeof(CRTres)+sizeof(mpint)*crt->n); if(res == nil) sysfatal("crtin: %r"); res->n = crt->n; for(i = 0; i < res->n; i++){ res->r[i] = mpnew(0); mpmod(x, crt->m[i], res->r[i]); } return res; } // garners algorithm for converting residue form to linear void crtout(CRTpre *crt, CRTres *res, mpint *x) { mpint *u; int i; u = mpnew(0); mpassign(res->r[0], x); for(i = 1; i < crt->n; i++){ mpsub(res->r[i], x, u); mpmul(u, crt->c[i], u); mpmod(u, crt->m[i], u); mpmul(u, crt->p[i-1], u); mpadd(x, u, x); } mpfree(u); } // free the residue void crtresfree(CRTres *res) { int i; for(i = 0; i < res->n; i++) mpfree(res->r[i]); free(res); } drawterm-20110822.orig/libmp/letomp.c0000644000175000017500000000070711245145712016646 0ustar tinchotincho#include "os.h" #include #include "dat.h" // convert a little endian byte array (least significant byte first) to an mpint mpint* letomp(uchar *s, uint n, mpint *b) { int i=0, m = 0; mpdigit x=0; if(b == nil) b = mpnew(0); mpbits(b, 8*n); b->top = DIGITS(8*n); for(; n > 0; n--){ x |= ((mpdigit)(*s++)) << i; i += 8; if(i == Dbits){ b->p[m++] = x; i = 0; x = 0; } } if(i > 0) b->p[m++] = x; b->top = m; return b; } drawterm-20110822.orig/libmp/mpmul.c0000644000175000017500000000604611245145712016502 0ustar tinchotincho#include "os.h" #include #include "dat.h" // // from knuth's 1969 seminumberical algorithms, pp 233-235 and pp 258-260 // // mpvecmul is an assembly language routine that performs the inner // loop. // // the karatsuba trade off is set empiricly by measuring the algs on // a 400 MHz Pentium II. // // karatsuba like (see knuth pg 258) // prereq: p is already zeroed static void mpkaratsuba(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p) { mpdigit *t, *u0, *u1, *v0, *v1, *u0v0, *u1v1, *res, *diffprod; int u0len, u1len, v0len, v1len, reslen; int sign, n; // divide each piece in half n = alen/2; if(alen&1) n++; u0len = n; u1len = alen-n; if(blen > n){ v0len = n; v1len = blen-n; } else { v0len = blen; v1len = 0; } u0 = a; u1 = a + u0len; v0 = b; v1 = b + v0len; // room for the partial products t = mallocz(Dbytes*5*(2*n+1), 1); if(t == nil) sysfatal("mpkaratsuba: %r"); u0v0 = t; u1v1 = t + (2*n+1); diffprod = t + 2*(2*n+1); res = t + 3*(2*n+1); reslen = 4*n+1; // t[0] = (u1-u0) sign = 1; if(mpveccmp(u1, u1len, u0, u0len) < 0){ sign = -1; mpvecsub(u0, u0len, u1, u1len, u0v0); } else mpvecsub(u1, u1len, u0, u1len, u0v0); // t[1] = (v0-v1) if(mpveccmp(v0, v0len, v1, v1len) < 0){ sign *= -1; mpvecsub(v1, v1len, v0, v1len, u1v1); } else mpvecsub(v0, v0len, v1, v1len, u1v1); // t[4:5] = (u1-u0)*(v0-v1) mpvecmul(u0v0, u0len, u1v1, v0len, diffprod); // t[0:1] = u1*v1 memset(t, 0, 2*(2*n+1)*Dbytes); if(v1len > 0) mpvecmul(u1, u1len, v1, v1len, u1v1); // t[2:3] = u0v0 mpvecmul(u0, u0len, v0, v0len, u0v0); // res = u0*v0< 0){ mpvecadd(res+n, reslen-n, u1v1, u1len+v1len, res+n); mpvecadd(res+2*n, reslen-2*n, u1v1, u1len+v1len, res+2*n); } // res += (u1-u0)*(v0-v1)<= KARATSUBAMIN && blen > 1){ // O(n^1.585) mpkaratsuba(a, alen, b, blen, p); } else { // O(n^2) for(i = 0; i < blen; i++){ d = b[i]; if(d != 0) mpvecdigmuladd(a, alen, d, &p[i]); } } } void mpmul(mpint *b1, mpint *b2, mpint *prod) { mpint *oprod; oprod = nil; if(prod == b1 || prod == b2){ oprod = prod; prod = mpnew(0); } prod->top = 0; mpbits(prod, (b1->top+b2->top+1)*Dbits); mpvecmul(b1->p, b1->top, b2->p, b2->top, prod->p); prod->top = b1->top+b2->top+1; prod->sign = b1->sign*b2->sign; mpnorm(prod); if(oprod != nil){ mpassign(prod, oprod); mpfree(prod); } } drawterm-20110822.orig/libmp/Makefile0000644000175000017500000000113211245145712016633 0ustar tinchotinchoROOT=.. include ../Make.config # N.B. This is used only for secstore. It needn't be fast. LIB=libmp.a OFILES=\ betomp.$O\ crt.$O\ letomp.$O\ mpadd.$O\ mpaux.$O\ mpcmp.$O\ mpdigdiv.$O\ mpdiv.$O\ mpeuclid.$O\ mpexp.$O\ mpextendedgcd.$O\ mpfmt.$O\ mpinvert.$O\ mpleft.$O\ mpmod.$O\ mpmul.$O\ mprand.$O\ mpright.$O\ mpsub.$O\ mptobe.$O\ mptoi.$O\ mptole.$O\ mptoui.$O\ mptouv.$O\ mptov.$O\ mpvecadd.$O\ mpveccmp.$O\ mpvecdigmuladd.$O\ mpvecsub.$O\ strtomp.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/libmp/mptoi.c0000644000175000017500000000105111245145712016467 0ustar tinchotincho#include "os.h" #include #include "dat.h" /* * this code assumes that mpdigit is at least as * big as an int. */ mpint* itomp(int i, mpint *b) { if(b == nil) b = mpnew(0); mpassign(mpzero, b); if(i != 0) b->top = 1; if(i < 0){ b->sign = -1; *b->p = -i; } else *b->p = i; return b; } int mptoi(mpint *b) { uint x; x = *b->p; if(b->sign > 0){ if(b->top > 1 || (x > MAXINT)) x = (int)MAXINT; else x = (int)x; } else { if(b->top > 1 || x > MAXINT+1) x = (int)MININT; else x = -(int)x; } return x; } drawterm-20110822.orig/libmp/betomp.c0000644000175000017500000000110111245145712016621 0ustar tinchotincho#include "os.h" #include #include "dat.h" // convert a big-endian byte array (most significant byte first) to an mpint mpint* betomp(uchar *p, uint n, mpint *b) { int m, s; mpdigit x; if(b == nil) b = mpnew(0); // dump leading zeros while(*p == 0 && n > 1){ p++; n--; } // get the space mpbits(b, n*8); b->top = DIGITS(n*8); m = b->top-1; // first digit might not be Dbytes long s = ((n-1)*8)%Dbits; x = 0; for(; n > 0; n--){ x |= ((mpdigit)(*p++)) << s; s -= 8; if(s < 0){ b->p[m--] = x; s = Dbits-8; x = 0; } } return b; } drawterm-20110822.orig/libmp/mpsub.c0000644000175000017500000000143011245145712016466 0ustar tinchotincho#include "os.h" #include #include "dat.h" // diff = abs(b1) - abs(b2), i.e., subtract the magnitudes void mpmagsub(mpint *b1, mpint *b2, mpint *diff) { int n, m, sign; mpint *t; // get the sizes right if(mpmagcmp(b1, b2) < 0){ sign = -1; t = b1; b1 = b2; b2 = t; } else sign = 1; n = b1->top; m = b2->top; if(m == 0){ mpassign(b1, diff); diff->sign = sign; return; } mpbits(diff, n*Dbits); mpvecsub(b1->p, n, b2->p, m, diff->p); diff->sign = sign; diff->top = n; mpnorm(diff); } // diff = b1 - b2 void mpsub(mpint *b1, mpint *b2, mpint *diff) { int sign; if(b1->sign != b2->sign){ sign = b1->sign; mpmagadd(b1, b2, diff); diff->sign = sign; return; } sign = b1->sign; mpmagsub(b1, b2, diff); if(diff->top != 0) diff->sign *= sign; } drawterm-20110822.orig/libmp/mpleft.c0000644000175000017500000000150611245145712016633 0ustar tinchotincho#include "os.h" #include #include "dat.h" // res = b << shift void mpleft(mpint *b, int shift, mpint *res) { int d, l, r, i, otop; mpdigit this, last; // a negative left shift is a right shift if(shift < 0){ mpright(b, -shift, res); return; } // b and res may be the same so remember the old top otop = b->top; // shift mpbits(res, otop*Dbits + shift); // overkill res->top = DIGITS(otop*Dbits + shift); d = shift/Dbits; l = shift - d*Dbits; r = Dbits - l; if(l == 0){ for(i = otop-1; i >= 0; i--) res->p[i+d] = b->p[i]; } else { last = 0; for(i = otop-1; i >= 0; i--) { this = b->p[i]; res->p[i+d+1] = (last<>r); last = this; } res->p[d] = last<p[i] = 0; // normalize while(res->top > 0 && res->p[res->top-1] == 0) res->top--; } drawterm-20110822.orig/libmp/mprand.c0000644000175000017500000000111011245145712016614 0ustar tinchotincho#include "os.h" #include #include #include "dat.h" mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b) { int n, m; mpdigit mask; uchar *p; n = DIGITS(bits); if(b == nil) b = mpnew(bits); else mpbits(b, bits); p = malloc(n*Dbytes); if(p == nil) return nil; (*gen)(p, n*Dbytes); betomp(p, n*Dbytes, b); free(p); // make sure we don't give too many bits m = bits%Dbits; n--; if(m > 0){ mask = 1; mask <<= m; mask--; b->p[n] &= mask; } for(; n >= 0; n--) if(b->p[n] != 0) break; b->top = n+1; b->sign = 1; return b; } drawterm-20110822.orig/libmp/mpexp.c0000644000175000017500000000217511245145712016500 0ustar tinchotincho#include "os.h" #include #include "dat.h" // res = b**e // // knuth, vol 2, pp 398-400 enum { Freeb= 0x1, Freee= 0x2, Freem= 0x4, }; //int expdebug; void mpexp(mpint *b, mpint *e, mpint *m, mpint *res) { mpint *t[2]; int tofree; mpdigit d, bit; int i, j; t[0] = mpcopy(b); t[1] = res; tofree = 0; if(res == b){ b = mpcopy(b); tofree |= Freeb; } if(res == e){ e = mpcopy(e); tofree |= Freee; } if(res == m){ m = mpcopy(m); tofree |= Freem; } // skip first bit i = e->top-1; d = e->p[i]; for(bit = mpdighi; (bit & d) == 0; bit >>= 1) ; bit >>= 1; j = 0; for(;;){ for(; bit != 0; bit >>= 1){ mpmul(t[j], t[j], t[j^1]); if(bit & d) mpmul(t[j^1], b, t[j]); else j ^= 1; if(m != nil && t[j]->top > m->top){ mpmod(t[j], m, t[j^1]); j ^= 1; } } if(--i < 0) break; bit = mpdighi; d = e->p[i]; } if(m != nil){ mpmod(t[j], m, t[j^1]); j ^= 1; } if(t[j] == res){ mpfree(t[j^1]); } else { mpassign(t[j], res); mpfree(t[j]); } if(tofree){ if(tofree & Freeb) mpfree(b); if(tofree & Freee) mpfree(e); if(tofree & Freem) mpfree(m); } } drawterm-20110822.orig/libmp/mpvecadd.c0000644000175000017500000000100711245145712017123 0ustar tinchotincho#include "os.h" #include #include "dat.h" // prereq: alen >= blen, sum has at least blen+1 digits void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum) { int i, carry; mpdigit x, y; carry = 0; for(i = 0; i < blen; i++){ x = *a++; y = *b++; x += carry; if(x < carry) carry = 1; else carry = 0; x += y; if(x < y) carry++; *sum++ = x; } for(; i < alen; i++){ x = *a++ + carry; if(x < carry) carry = 1; else carry = 0; *sum++ = x; } *sum = carry; } drawterm-20110822.orig/libmp/mptole.c0000644000175000017500000000142211245145712016641 0ustar tinchotincho#include "os.h" #include #include "dat.h" // convert an mpint into a little endian byte array (least significant byte first) // return number of bytes converted // if p == nil, allocate and result array int mptole(mpint *b, uchar *p, uint n, uchar **pp) { int i, j; mpdigit x; uchar *e, *s; if(p == nil){ n = (b->top+1)*Dbytes; p = malloc(n); } if(pp != nil) *pp = p; if(p == nil) return -1; memset(p, 0, n); // special case 0 if(b->top == 0){ if(n < 1) return -1; else return 0; } s = p; e = s+n; for(i = 0; i < b->top-1; i++){ x = b->p[i]; for(j = 0; j < Dbytes; j++){ if(p >= e) return -1; *p++ = x; x >>= 8; } } x = b->p[i]; while(x > 0){ if(p >= e) return -1; *p++ = x; x >>= 8; } return p - s; } drawterm-20110822.orig/cpu-bl.c0000644000175000017500000003344611245145711015432 0ustar tinchotincho/* * cpu.c - Make a connection to a cpu server * * Invoked by listen as 'cpu -R | -N service net netdir' * by users as 'cpu [-h system] [-c cmd args ...]' */ #include #include #include #include #include #include #include "args.h" #include "drawterm.h" #define Maxfdata 8192 #define MaxStr 128 static void fatal(int, char*, ...); static void usage(void); static void writestr(int, char*, char*, int); static int readstr(int, char*, int); static char *rexcall(int*, char*, char*); static char *keyspec = ""; static AuthInfo *p9any(int); #define system csystem static char *system; static int cflag; extern int dbg; static char *srvname = "ncpu"; static char *ealgs = "rc4_256 sha1"; /* message size for exportfs; may be larger so we can do big graphics in CPU window */ static int msgsize = Maxfdata+IOHDRSZ; /* authentication mechanisms */ static int netkeyauth(int); static int netkeysrvauth(int, char*); static int p9auth(int); static int srvp9auth(int, char*); char *authserver; typedef struct AuthMethod AuthMethod; struct AuthMethod { char *name; /* name of method */ int (*cf)(int); /* client side authentication */ int (*sf)(int, char*); /* server side authentication */ } authmethod[] = { { "p9", p9auth, srvp9auth,}, { "netkey", netkeyauth, netkeysrvauth,}, // { "none", noauth, srvnoauth,}, { nil, nil} }; AuthMethod *am = authmethod; /* default is p9 */ char *p9authproto = "p9any"; int setam(char*); void exits(char *s) { print("\ngoodbye\n"); for(;;) osyield(); } void usage(void) { fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n"); exits("usage"); } int fdd; int mountfactotum(void) { int fd; if((fd = dialfactotum()) < 0) return -1; if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){ fprint(2, "mount factotum: %r\n"); return -1; } if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){ fprint(2, "open /mnt/factotum/ctl: %r\n"); return -1; } close(fd); return 0; } void cpumain(int argc, char **argv) { char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *err, *secstoreserver, *p, *s; int fd, ms, data; /* see if we should use a larger message size */ fd = open("/dev/draw", OREAD); if(fd > 0){ ms = iounit(fd); if(msgsize < ms+IOHDRSZ) msgsize = ms+IOHDRSZ; close(fd); } user = getenv("USER"); if(user == nil) user = readcons("user", nil, 0); secstoreserver = nil; authserver = getenv("auth"); if(authserver == nil) authserver = "lookout.cs.bell-labs.com"; system = getenv("cpu"); if(system == nil) system = "anna.cs.bell-labs.com"; ARGBEGIN{ case 'o': authserver = "plan9.bell-labs.com"; system = "plan9.bell-labs.com"; break; case 'a': authserver = EARGF(usage()); break; case 'c': system = EARGF(usage()); break; case 'd': dbg++; break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'C': cflag++; cmd[0] = '!'; cmd[1] = '\0'; while((p = ARGF()) != nil) { strcat(cmd, " "); strcat(cmd, p); } break; case 'k': keyspec = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; case 's': secstoreserver = EARGF(usage()); break; default: usage(); }ARGEND; if(argc != 0) usage(); if(mountfactotum() < 0){ if(secstoreserver == nil) secstoreserver = authserver; if(havesecstore(secstoreserver, user)){ s = secstorefetch(secstoreserver, user, nil); if(s){ if(strlen(s) >= sizeof secstorebuf) sysfatal("secstore data too big"); strcpy(secstorebuf, s); } } } if((err = rexcall(&data, system, srvname))) fatal(1, "%s: %s", err, system); /* Tell the remote side the command to execute and where our working directory is */ if(cflag) writestr(data, cmd, "command", 0); if(getcwd(dat, sizeof(dat)) == 0) writestr(data, "NO", "dir", 0); else writestr(data, dat, "dir", 0); /* * Wait for the other end to execute and start our file service * of /mnt/term */ if(readstr(data, buf, sizeof(buf)) < 0) fatal(1, "waiting for FS: %r"); if(strncmp("FS", buf, 2) != 0) { print("remote cpu: %s", buf); exits(buf); } if(readstr(data, buf, sizeof buf) < 0) fatal(1, "waiting for remote export: %r"); if(strcmp(buf, "/") != 0){ print("remote cpu: %s" , buf); exits(buf); } write(data, "OK", 2); /* Begin serving the gnot namespace */ exportfs(data, msgsize); fatal(1, "starting exportfs"); } void fatal(int syserr, char *fmt, ...) { Fmt f; char *str; va_list arg; fmtstrinit(&f); fmtprint(&f, "cpu: "); va_start(arg, fmt); fmtvprint(&f, fmt, arg); va_end(arg); if(syserr) fmtprint(&f, ": %r"); fmtprint(&f, "\n"); str = fmtstrflush(&f); write(2, str, strlen(str)); exits(str); } char *negstr = "negotiating authentication method"; char bug[256]; char* rexcall(int *fd, char *host, char *service) { char *na; char dir[MaxStr]; char err[ERRMAX]; char msg[MaxStr]; int n; na = netmkaddr(host, "tcp", "17010"); if((*fd = dial(na, 0, dir, 0)) < 0) return "can't dial"; /* negotiate authentication mechanism */ if(ealgs != nil) snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); else snprint(msg, sizeof(msg), "%s", am->name); writestr(*fd, msg, negstr, 0); n = readstr(*fd, err, sizeof err); if(n < 0) return negstr; if(*err){ werrstr(err); return negstr; } /* authenticate */ *fd = (*am->cf)(*fd); if(*fd < 0) return "can't authenticate"; return 0; } void writestr(int fd, char *str, char *thing, int ignore) { int l, n; l = strlen(str); n = write(fd, str, l+1); if(!ignore && n < 0) fatal(1, "writing network: %s", thing); } int readstr(int fd, char *str, int len) { int n; while(len) { n = read(fd, str, 1); if(n < 0) return -1; if(*str == '\0') return 0; str++; len--; } return -1; } static int readln(char *buf, int n) { int i; char *p; n--; /* room for \0 */ p = buf; for(i=0; isecret, ai->nsecret); if(ealgs == nil) return fd; /* exchange random numbers */ for(i = 0; i < 4; i++) key[i] = fastrand(); if(write(fd, key, 4) != 4) return -1; if(readn(fd, key+12, 4) != 4) return -1; /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); /* set up encryption */ i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); if(i < 0) werrstr("can't establish ssl connection: %r"); return i; } int authdial(char *net, char *dom) { int fd; fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0); //print("authdial %d\n", fd); return fd; } static int getastickets(Ticketreq *tr, char *trbuf, char *tbuf) { int asfd, rv; char *dom; dom = tr->authdom; asfd = authdial(nil, dom); if(asfd < 0) return -1; rv = _asgetticket(asfd, trbuf, tbuf); close(asfd); return rv; } static int mkserverticket(Ticketreq *tr, char *authkey, char *tbuf) { int i; Ticket t; if(strcmp(tr->authid, tr->hostid) != 0) return -1; memset(&t, 0, sizeof(t)); memmove(t.chal, tr->chal, CHALLEN); strcpy(t.cuid, tr->uid); strcpy(t.suid, tr->uid); for(i=0; i= 0) return 0; return mkserverticket(tr, key, tbuf); } /* * prompt user for a key. don't care about memory leaks, runs standalone */ static Attr* promptforkey(char *params) { char *v; int fd; Attr *a, *attr; char *def; fd = open("/dev/cons", ORDWR); if(fd < 0) sysfatal("opening /dev/cons: %r"); attr = _parseattr(params); fprint(fd, "\n!Adding key:"); for(a=attr; a; a=a->next) if(a->type != AttrQuery && a->name[0] != '!') fprint(fd, " %q=%q", a->name, a->val); fprint(fd, "\n"); for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]=='!') continue; def = nil; if(strcmp(v, "user") == 0) def = getuser(); a->val = readcons(v, def, 0); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]!='!') continue; def = nil; if(strcmp(v+1, "user") == 0) def = getuser(); a->val = readcons(v+1, def, 1); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } fprint(fd, "!\n"); close(fd); return attr; } /* * send a key to the mounted factotum */ static int sendkey(Attr *attr) { int fd, rv; char buf[1024]; fd = open("/mnt/factotum/ctl", ORDWR); if(fd < 0) sysfatal("opening /mnt/factotum/ctl: %r"); rv = fprint(fd, "key %A\n", attr); read(fd, buf, sizeof buf); close(fd); return rv; } int askuser(char *params) { Attr *attr; fmtinstall('A', _attrfmt); attr = promptforkey(params); if(attr == nil) sysfatal("no key supplied"); if(sendkey(attr) < 0) sysfatal("sending key to factotum: %r"); return 0; } AuthInfo* p9anyfactotum(int fd, int afd) { return auth_proxy(fd, askuser, "proto=p9any role=client %s", keyspec); } AuthInfo* p9any(int fd) { char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u; char *pass; char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN]; char authkey[DESKEYLEN]; Authenticator auth; int afd, i, v2; Ticketreq tr; Ticket t; AuthInfo *ai; if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) return p9anyfactotum(fd, afd); if(readstr(fd, buf, sizeof buf) < 0) fatal(1, "cannot read p9any negotiation"); bbuf = buf; v2 = 0; if(strncmp(buf, "v.2 ", 4) == 0){ v2 = 1; bbuf += 4; } if((p = strchr(bbuf, ' '))) *p = 0; p = bbuf; if((dom = strchr(p, '@')) == nil) fatal(1, "bad p9any domain"); *dom++ = 0; if(strcmp(p, "p9sk1") != 0) fatal(1, "server did not offer p9sk1"); sprint(buf2, "%s %s", p, dom); if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1) fatal(1, "cannot write user/domain choice in p9any"); if(v2){ if(readstr(fd, buf, sizeof buf) != 3) fatal(1, "cannot read OK in p9any"); if(memcmp(buf, "OK\0", 3) != 0) fatal(1, "did not get OK in p9any"); } for(i=0; isecret = mallocz(8, 1); des56to64((uchar*)t.key, ai->secret); ai->nsecret = 8; ai->suid = strdup(t.suid); ai->cuid = strdup(t.cuid); memset(authkey, 0, sizeof authkey); return ai; } /* static int noauth(int fd) { ealgs = nil; return fd; } static int srvnoauth(int fd, char *user) { strecpy(user, user+MaxStr, getuser()); ealgs = nil; return fd; } */ void loghex(uchar *p, int n) { char buf[100]; int i; for(i = 0; i < n; i++) sprint(buf+2*i, "%2.2ux", p[i]); // syslog(0, "cpu", buf); } static int srvp9auth(int fd, char *user) { return -1; } /* * set authentication mechanism */ int setam(char *name) { for(am = authmethod; am->name != nil; am++) if(strcmp(am->name, name) == 0) return 0; am = authmethod; return -1; } /* * set authentication mechanism and encryption/hash algs * int setamalg(char *s) { ealgs = strchr(s, ' '); if(ealgs != nil) *ealgs++ = 0; return setam(s); } */ drawterm-20110822.orig/Make.unix0000644000175000017500000000074511245145711015662 0ustar tinchotincho# Unix #PTHREAD= # for Mac PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm # AUDIO=none AUDIO=unix all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/'`; \ (cd posix-$$arch && make) drawterm-20110822.orig/secstore.c0000644000175000017500000003657611245145712016107 0ustar tinchotincho/* * Various files from /sys/src/cmd/auth/secstore, just enough * to download a file at boot time. */ #include #include #include #include #include "drawterm.h" static void* emalloc(ulong n) { return mallocz(n, 1); } enum{ CHK = 16}; enum{ MAXFILESIZE = 10*1024*1024 }; enum{// PW status bits Enabled = (1<<0), STA = (1<<1), // extra SecurID step }; static char testmess[] = "__secstore\tPAK\nC=%s\nm=0\n"; int secdial(char *secstore) { char *p, buf[80], *f[3]; int fd, nf; p = secstore; /* take it from writehostowner, if set there */ if(*p == 0) /* else use the authserver */ p = "$auth"; /* translate $auth ourselves. * authaddr is something like il!host!566 or tcp!host!567. * extract host, accounting for a change of format to something * like il!host or tcp!host or host. */ if(strcmp(p, "$auth")==0){ if(authserver == nil) return -1; strecpy(buf, buf+sizeof buf, authserver); nf = getfields(buf, f, nelem(f), 0, "!"); switch(nf){ default: return -1; case 1: p = f[0]; break; case 2: case 3: p = f[1]; break; } } fd = dial(netmkaddr(p, "tcp", "5356"), 0, 0, 0); if(fd >= 0) return fd; return -1; } int havesecstore(char *addr, char *owner) { int m, n, fd; uchar buf[500]; n = snprint((char*)buf, sizeof buf, testmess, owner); hnputs(buf, 0x8000+n-2); fd = secdial(addr); if(fd < 0) return 0; if(write(fd, buf, n) != n || readn(fd, buf, 2) != 2){ close(fd); return 0; } n = ((buf[0]&0x7f)<<8) + buf[1]; if(n+1 > sizeof buf){ werrstr("implausibly large count %d", n); close(fd); return 0; } m = readn(fd, buf, n); close(fd); if(m != n){ if(m >= 0) werrstr("short read from secstore"); return 0; } buf[n] = 0; if(strcmp((char*)buf, "!account expired") == 0){ werrstr("account expired"); return 0; } return strcmp((char*)buf, "!account exists") == 0; } // delimited, authenticated, encrypted connection enum{ Maxmsg=4096 }; // messages > Maxmsg bytes are truncated typedef struct SConn SConn; extern SConn* newSConn(int); // arg is open file descriptor struct SConn{ void *chan; int secretlen; int (*secret)(SConn*, uchar*, int);// int (*read)(SConn*, uchar*, int); // <0 if error; errmess in buffer int (*write)(SConn*, uchar*, int); void (*free)(SConn*); // also closes file descriptor }; // secret(s,b,dir) sets secret for digest, encrypt, using the secretlen // bytes in b to form keys for the two directions; // set dir=0 in client, dir=1 in server // error convention: write !message in-band #define readstr secstore_readstr static void writerr(SConn*, char*); static int readstr(SConn*, char*); // call with buf of size Maxmsg+1 // returns -1 upon error, with error message in buf typedef struct ConnState { uchar secret[SHA1dlen]; ulong seqno; RC4state rc4; } ConnState; typedef struct SS{ int fd; // file descriptor for read/write of encrypted data int alg; // if nonzero, "alg sha rc4_128" ConnState in, out; } SS; static int SC_secret(SConn *conn, uchar *sigma, int direction) { SS *ss = (SS*)(conn->chan); int nsigma = conn->secretlen; if(direction != 0){ hmac_sha1(sigma, nsigma, (uchar*)"one", 3, ss->out.secret, nil); hmac_sha1(sigma, nsigma, (uchar*)"two", 3, ss->in.secret, nil); }else{ hmac_sha1(sigma, nsigma, (uchar*)"two", 3, ss->out.secret, nil); hmac_sha1(sigma, nsigma, (uchar*)"one", 3, ss->in.secret, nil); } setupRC4state(&ss->in.rc4, ss->in.secret, 16); // restrict to 128 bits setupRC4state(&ss->out.rc4, ss->out.secret, 16); ss->alg = 1; return 0; } static void hash(uchar secret[SHA1dlen], uchar *data, int len, int seqno, uchar d[SHA1dlen]) { DigestState sha; uchar seq[4]; seq[0] = seqno>>24; seq[1] = seqno>>16; seq[2] = seqno>>8; seq[3] = seqno; memset(&sha, 0, sizeof sha); sha1(secret, SHA1dlen, nil, &sha); sha1(data, len, nil, &sha); sha1(seq, 4, d, &sha); } static int verify(uchar secret[SHA1dlen], uchar *data, int len, int seqno, uchar d[SHA1dlen]) { DigestState sha; uchar seq[4]; uchar digest[SHA1dlen]; seq[0] = seqno>>24; seq[1] = seqno>>16; seq[2] = seqno>>8; seq[3] = seqno; memset(&sha, 0, sizeof sha); sha1(secret, SHA1dlen, nil, &sha); sha1(data, len, nil, &sha); sha1(seq, 4, digest, &sha); return memcmp(d, digest, SHA1dlen); } static int SC_read(SConn *conn, uchar *buf, int n) { SS *ss = (SS*)(conn->chan); uchar count[2], digest[SHA1dlen]; int len, nr; if(read(ss->fd, count, 2) != 2 || (count[0]&0x80) == 0){ werrstr("!SC_read invalid count"); return -1; } len = (count[0]&0x7f)<<8 | count[1]; // SSL-style count; no pad if(ss->alg){ len -= SHA1dlen; if(len <= 0 || readn(ss->fd, digest, SHA1dlen) != SHA1dlen){ werrstr("!SC_read missing sha1"); return -1; } if(len > n || readn(ss->fd, buf, len) != len){ werrstr("!SC_read missing data"); return -1; } rc4(&ss->in.rc4, digest, SHA1dlen); rc4(&ss->in.rc4, buf, len); if(verify(ss->in.secret, buf, len, ss->in.seqno, digest) != 0){ werrstr("!SC_read integrity check failed"); return -1; } }else{ if(len <= 0 || len > n){ werrstr("!SC_read implausible record length"); return -1; } if( (nr = readn(ss->fd, buf, len)) != len){ werrstr("!SC_read expected %d bytes, but got %d", len, nr); return -1; } } ss->in.seqno++; return len; } static int SC_write(SConn *conn, uchar *buf, int n) { SS *ss = (SS*)(conn->chan); uchar count[2], digest[SHA1dlen]; int len; if(n <= 0 || n > Maxmsg+1){ werrstr("!SC_write invalid n %d", n); return -1; } len = n; if(ss->alg) len += SHA1dlen; count[0] = 0x80 | len>>8; count[1] = len; if(write(ss->fd, count, 2) != 2){ werrstr("!SC_write invalid count"); return -1; } if(ss->alg){ hash(ss->out.secret, buf, n, ss->out.seqno, digest); rc4(&ss->out.rc4, digest, SHA1dlen); rc4(&ss->out.rc4, buf, n); if(write(ss->fd, digest, SHA1dlen) != SHA1dlen || write(ss->fd, buf, n) != n){ werrstr("!SC_write error on send"); return -1; } }else{ if(write(ss->fd, buf, n) != n){ werrstr("!SC_write error on send"); return -1; } } ss->out.seqno++; return n; } static void SC_free(SConn *conn) { SS *ss = (SS*)(conn->chan); close(ss->fd); free(ss); free(conn); } SConn* newSConn(int fd) { SS *ss; SConn *conn; if(fd < 0) return nil; ss = (SS*)emalloc(sizeof(*ss)); conn = (SConn*)emalloc(sizeof(*conn)); ss->fd = fd; ss->alg = 0; conn->chan = (void*)ss; conn->secretlen = SHA1dlen; conn->free = SC_free; conn->secret = SC_secret; conn->read = SC_read; conn->write = SC_write; return conn; } static void writerr(SConn *conn, char *s) { char buf[Maxmsg]; snprint(buf, Maxmsg, "!%s", s); conn->write(conn, (uchar*)buf, strlen(buf)); } static int readstr(SConn *conn, char *s) { int n; n = conn->read(conn, (uchar*)s, Maxmsg); if(n >= 0){ s[n] = 0; if(s[0] == '!'){ memmove(s, s+1, n); n = -1; } }else{ strcpy(s, "read error"); } return n; } static char* getfile(SConn *conn, uchar *key, int nkey) { char *buf; int nbuf, n, nr, len; char s[Maxmsg+1], *gf; uchar skey[SHA1dlen], ib[Maxmsg+CHK], *ibr, *ibw; AESstate aes; DigestState *sha; gf = "factotum"; memset(&aes, 0, sizeof aes); snprint(s, Maxmsg, "GET %s\n", gf); conn->write(conn, (uchar*)s, strlen(s)); /* get file size */ s[0] = '\0'; if(readstr(conn, s) < 0){ werrstr("secstore: %r"); return nil; } if((len = atoi(s)) < 0){ werrstr("secstore: remote file %s does not exist", gf); return nil; }else if(len > MAXFILESIZE){//assert werrstr("secstore: implausible file size %d for %s", len, gf); return nil; } ibr = ibw = ib; buf = nil; nbuf = 0; for(nr=0; nr < len;){ if((n = conn->read(conn, ibw, Maxmsg)) <= 0){ werrstr("secstore: empty file chunk n=%d nr=%d len=%d: %r", n, nr, len); return nil; } nr += n; ibw += n; if(!aes.setup){ /* first time, read 16 byte IV */ if(n < 16){ werrstr("secstore: no IV in file"); return nil; } sha = sha1((uchar*)"aescbc file", 11, nil, nil); sha1(key, nkey, skey, sha); setupAESstate(&aes, skey, AESbsize, ibr); memset(skey, 0, sizeof skey); ibr += AESbsize; n -= AESbsize; } aesCBCdecrypt(ibw-n, n, &aes); n = ibw-ibr-CHK; if(n > 0){ buf = realloc(buf, nbuf+n+1); if(buf == nil) sysfatal("out of memory"); memmove(buf+nbuf, ibr, n); nbuf += n; ibr += n; } memmove(ib, ibr, ibw-ibr); ibw = ib + (ibw-ibr); ibr = ib; } n = ibw-ibr; if((n != CHK) || (memcmp(ib, "XXXXXXXXXXXXXXXX", CHK) != 0)){ werrstr("secstore: decrypted file failed to authenticate!"); free(buf); return nil; } if(nbuf == 0){ werrstr("secstore got empty file"); return nil; } buf[nbuf] = '\0'; return buf; } static char VERSION[] = "secstore"; typedef struct PAKparams{ mpint *q, *p, *r, *g; } PAKparams; static PAKparams *pak; // This group was generated by the seed EB7B6E35F7CD37B511D96C67D6688CC4DD440E1E. static void initPAKparams(void) { if(pak) return; pak = (PAKparams*)emalloc(sizeof(*pak)); pak->q = strtomp("E0F0EF284E10796C5A2A511E94748BA03C795C13", nil, 16, nil); pak->p = strtomp("C41CFBE4D4846F67A3DF7DE9921A49D3B42DC33728427AB159CEC8CBBD" "B12B5F0C244F1A734AEB9840804EA3C25036AD1B61AFF3ABBC247CD4B384224567A86" "3A6F020E7EE9795554BCD08ABAD7321AF27E1E92E3DB1C6E7E94FAAE590AE9C48F96D9" "3D178E809401ABE8A534A1EC44359733475A36A70C7B425125062B1142D", nil, 16, nil); pak->r = strtomp("DF310F4E54A5FEC5D86D3E14863921E834113E060F90052AD332B3241CEF" "2497EFA0303D6344F7C819691A0F9C4A773815AF8EAECFB7EC1D98F039F17A32A7E887" "D97251A927D093F44A55577F4D70444AEBD06B9B45695EC23962B175F266895C67D21" "C4656848614D888A4", nil, 16, nil); pak->g = strtomp("2F1C308DC46B9A44B52DF7DACCE1208CCEF72F69C743ADD4D2327173444" "ED6E65E074694246E07F9FD4AE26E0FDDD9F54F813C40CB9BCD4338EA6F242AB94CD41" "0E676C290368A16B1A3594877437E516C53A6EEE5493A038A017E955E218E7819734E3E" "2A6E0BAE08B14258F8C03CC1B30E0DDADFCF7CEDF0727684D3D255F1", nil, 16, nil); } // H = (sha(ver,C,sha(passphrase)))^r mod p, // a hash function expensive to attack by brute force. static void longhash(char *ver, char *C, uchar *passwd, mpint *H) { uchar *Cp; int i, n, nver, nC; uchar buf[140], key[1]; nver = strlen(ver); nC = strlen(C); n = nver + nC + SHA1dlen; Cp = (uchar*)emalloc(n); memmove(Cp, ver, nver); memmove(Cp+nver, C, nC); memmove(Cp+nver+nC, passwd, SHA1dlen); for(i = 0; i < 7; i++){ key[0] = 'A'+i; hmac_sha1(Cp, n, key, sizeof key, buf+i*SHA1dlen, nil); } memset(Cp, 0, n); free(Cp); betomp(buf, sizeof buf, H); mpmod(H, pak->p, H); mpexp(H, pak->r, pak->p, H); } // Hi = H^-1 mod p static char * PAK_Hi(char *C, char *passphrase, mpint *H, mpint *Hi) { uchar passhash[SHA1dlen]; sha1((uchar *)passphrase, strlen(passphrase), passhash, nil); initPAKparams(); longhash(VERSION, C, passhash, H); mpinvert(H, pak->p, Hi); return mptoa(Hi, 64, nil, 0); } // another, faster, hash function for each party to // confirm that the other has the right secrets. static void shorthash(char *mess, char *C, char *S, char *m, char *mu, char *sigma, char *Hi, uchar *digest) { SHA1state *state; state = sha1((uchar*)mess, strlen(mess), 0, 0); state = sha1((uchar*)C, strlen(C), 0, state); state = sha1((uchar*)S, strlen(S), 0, state); state = sha1((uchar*)m, strlen(m), 0, state); state = sha1((uchar*)mu, strlen(mu), 0, state); state = sha1((uchar*)sigma, strlen(sigma), 0, state); state = sha1((uchar*)Hi, strlen(Hi), 0, state); state = sha1((uchar*)mess, strlen(mess), 0, state); state = sha1((uchar*)C, strlen(C), 0, state); state = sha1((uchar*)S, strlen(S), 0, state); state = sha1((uchar*)m, strlen(m), 0, state); state = sha1((uchar*)mu, strlen(mu), 0, state); state = sha1((uchar*)sigma, strlen(sigma), 0, state); sha1((uchar*)Hi, strlen(Hi), digest, state); } // On input, conn provides an open channel to the server; // C is the name this client calls itself; // pass is the user's passphrase // On output, session secret has been set in conn // (unless return code is negative, which means failure). // If pS is not nil, it is set to the (alloc'd) name the server calls itself. static int PAKclient(SConn *conn, char *C, char *pass, char **pS) { char *mess, *mess2, *eol, *S, *hexmu, *ks, *hexm, *hexsigma = nil, *hexHi; char kc[2*SHA1dlen+1]; uchar digest[SHA1dlen]; int rc = -1, n; mpint *x, *m = mpnew(0), *mu = mpnew(0), *sigma = mpnew(0); mpint *H = mpnew(0), *Hi = mpnew(0); hexHi = PAK_Hi(C, pass, H, Hi); // random 1<=x<=q-1; send C, m=g**x H x = mprand(164, genrandom, nil); mpmod(x, pak->q, x); if(mpcmp(x, mpzero) == 0) mpassign(mpone, x); mpexp(pak->g, x, pak->p, m); mpmul(m, H, m); mpmod(m, pak->p, m); hexm = mptoa(m, 64, nil, 0); mess = (char*)emalloc(2*Maxmsg+2); mess2 = mess+Maxmsg+1; snprint(mess, Maxmsg, "%s\tPAK\nC=%s\nm=%s\n", VERSION, C, hexm); conn->write(conn, (uchar*)mess, strlen(mess)); // recv g**y, S, check hash1(g**xy) if(readstr(conn, mess) < 0){ fprint(2, "error: %s\n", mess); writerr(conn, "couldn't read g**y"); goto done; } eol = strchr(mess, '\n'); if(strncmp("mu=", mess, 3) != 0 || !eol || strncmp("\nk=", eol, 3) != 0){ writerr(conn, "verifier syntax error"); goto done; } hexmu = mess+3; *eol = 0; ks = eol+3; eol = strchr(ks, '\n'); if(!eol || strncmp("\nS=", eol, 3) != 0){ writerr(conn, "verifier syntax error for secstore 1.0"); goto done; } *eol = 0; S = eol+3; eol = strchr(S, '\n'); if(!eol){ writerr(conn, "verifier syntax error for secstore 1.0"); goto done; } *eol = 0; if(pS) *pS = strdup(S); strtomp(hexmu, nil, 64, mu); mpexp(mu, x, pak->p, sigma); hexsigma = mptoa(sigma, 64, nil, 0); shorthash("server", C, S, hexm, hexmu, hexsigma, hexHi, digest); enc64(kc, sizeof kc, digest, SHA1dlen); if(strcmp(ks, kc) != 0){ writerr(conn, "verifier didn't match"); goto done; } // send hash2(g**xy) shorthash("client", C, S, hexm, hexmu, hexsigma, hexHi, digest); enc64(kc, sizeof kc, digest, SHA1dlen); snprint(mess2, Maxmsg, "k'=%s\n", kc); conn->write(conn, (uchar*)mess2, strlen(mess2)); // set session key shorthash("session", C, S, hexm, hexmu, hexsigma, hexHi, digest); memset(hexsigma, 0, strlen(hexsigma)); n = conn->secret(conn, digest, 0); memset(digest, 0, SHA1dlen); if(n < 0){//assert writerr(conn, "can't set secret"); goto done; } rc = 0; done: mpfree(x); mpfree(sigma); mpfree(mu); mpfree(m); mpfree(Hi); mpfree(H); free(hexsigma); free(hexHi); free(hexm); free(mess); return rc; } char* secstorefetch(char *addr, char *owner, char *password) { int fd; char *rv; char s[Maxmsg+1], bye[10]; SConn *conn; char *pass, *sta; sta = nil; conn = nil; rv = nil; if(password != nil && *password) pass = strdup(password); else pass = readcons("secstore password", nil, 1); if(pass==nil || strlen(pass)==0){ werrstr("cancel"); goto Out; } if((fd = secdial(addr)) < 0) goto Out; if((conn = newSConn(fd)) == nil) goto Out; if(PAKclient(conn, owner, pass, nil) < 0){ werrstr("password mistyped?"); goto Out; } if(readstr(conn, s) < 0) goto Out; if(strcmp(s, "STA") == 0){ sta = readcons("STA PIN+SecureID", nil, 1); if(sta==nil || strlen(sta)==0){ werrstr("cancel"); goto Out; } if(strlen(sta) >= sizeof s - 3){ werrstr("STA response too long"); goto Out; } strcpy(s+3, sta); conn->write(conn, (uchar*)s, strlen(s)); readstr(conn, s); } if(strcmp(s, "OK") !=0){ werrstr("%s", s); goto Out; } if((rv = getfile(conn, (uchar*)pass, strlen(pass))) == nil) goto Out; strcpy(bye, "BYE"); conn->write(conn, (uchar*)bye, 3); Out: if(conn) conn->free(conn); if(pass) free(pass); if(sta) free(sta); return rv; } drawterm-20110822.orig/readcons.c0000644000175000017500000000346211245145712016042 0ustar tinchotincho#include #include #include "drawterm.h" void* erealloc(void *v, ulong n) { v = realloc(v, n); if(v == nil) sysfatal("out of memory"); return v; } char* estrdup(char *s) { s = strdup(s); if(s == nil) sysfatal("out of memory"); return s; } char* estrappend(char *s, char *fmt, ...) { char *t; va_list arg; va_start(arg, fmt); t = vsmprint(fmt, arg); if(t == nil) sysfatal("out of memory"); va_end(arg); s = erealloc(s, strlen(s)+strlen(t)+1); strcat(s, t); free(t); return s; } /* * prompt for a string with a possible default response */ char* readcons(char *prompt, char *def, int raw) { int fdin, fdout, ctl, n; char line[10]; char *s; fdin = open("/dev/cons", OREAD); if(fdin < 0) fdin = 0; fdout = open("/dev/cons", OWRITE); if(fdout < 0) fdout = 1; if(def != nil) fprint(fdout, "%s[%s]: ", prompt, def); else fprint(fdout, "%s: ", prompt); if(raw){ ctl = open("/dev/consctl", OWRITE); if(ctl >= 0) write(ctl, "rawon", 5); } else ctl = -1; s = estrdup(""); for(;;){ n = read(fdin, line, 1); if(n == 0){ Error: close(fdin); close(fdout); if(ctl >= 0) close(ctl); free(s); return nil; } if(n < 0) goto Error; if(line[0] == 0x7f) goto Error; if(n == 0 || line[0] == '\n' || line[0] == '\r'){ if(raw){ write(ctl, "rawoff", 6); write(fdout, "\n", 1); } close(ctl); close(fdin); close(fdout); if(*s == 0 && def != nil) s = estrappend(s, "%s", def); return s; } if(line[0] == '\b'){ if(strlen(s) > 0) s[strlen(s)-1] = 0; } else if(line[0] == 0x15) { /* ^U: line kill */ if(def != nil) fprint(fdout, "\n%s[%s]: ", prompt, def); else fprint(fdout, "\n%s: ", prompt); s[0] = 0; } else { s = estrappend(s, "%c", line[0]); } } return nil; /* not reached */ } drawterm-20110822.orig/posix-386/0000755000175000017500000000000011245145712015553 5ustar tinchotinchodrawterm-20110822.orig/posix-386/md5block.spp0000644000175000017500000001454711245145712020012 0ustar tinchotincho/* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 #define PAYME(x) $##x /* * SI is data * a += FN(B,C,D); * a += x[sh] + t[sh]; * a = (a << S11) | (a >> (32 - S11)); * a += b; */ #define BODY1(off,V,FN,SH,A,B,C,D)\ FN(B,C,D)\ leal V(A, %edi, 1), A;\ addl off(%ebp), A;\ roll PAYME(SH), A;\ addl B, A;\ #define BODY(off,V,FN,SH,A,B,C,D)\ FN(B,C,D)\ leal V(A, %edi, 1), A;\ addl (off)(%ebp), A;\ roll PAYME(SH), A;\ addl B,A;\ /* * fn1 = ((c ^ d) & b) ^ d */ #define FN1(B,C,D)\ movl C, %edi;\ xorl D, %edi;\ andl B, %edi;\ xorl D, %edi;\ /* * fn2 = ((b ^ c) & d) ^ c; */ #define FN2(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ andl D, %edi;\ xorl C, %edi;\ /* * fn3 = b ^ c ^ d; */ #define FN3(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ xorl D, %edi;\ /* * fn4 = c ^ (b | ~d); */ #define FN4(B,C,D)\ movl D, %edi;\ xorl $-1, %edi;\ orl B, %edi;\ xorl C, %edi;\ #define STACKSIZE 20 #define DATA (STACKSIZE+8) #define LEN (STACKSIZE+12) #define STATE (STACKSIZE+16) #define EDATA (STACKSIZE-4) #define OLDEBX (STACKSIZE-8) #define OLDESI (STACKSIZE-12) #define OLDEDI (STACKSIZE-16) .text .p2align 2,0x90 #ifdef __APPLE__ .globl __md5block __md5block: #else .globl _md5block _md5block: #endif /* Prelude */ pushl %ebp subl $(STACKSIZE), %esp movl %ebx, OLDEBX(%esp) movl %esi, OLDESI(%esp) movl %edi, OLDEDI(%esp) movl DATA(%esp), %eax addl LEN(%esp), %eax movl %eax, EDATA(%esp) movl DATA(%esp), %ebp 0: movl STATE(%esp), %esi movl (%esi), %eax movl 4(%esi), %ebx movl 8(%esi), %ecx movl 12(%esi), %edx BODY1( 0*4,0xd76aa478,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1( 1*4,0xe8c7b756,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1( 2*4,0x242070db,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1( 3*4,0xc1bdceee,FN1,S14,%ebx,%ecx,%edx,%eax) BODY1( 4*4,0xf57c0faf,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1( 5*4,0x4787c62a,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1( 6*4,0xa8304613,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1( 7*4,0xfd469501,FN1,S14,%ebx,%ecx,%edx,%eax) BODY1( 8*4,0x698098d8,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1( 9*4,0x8b44f7af,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1(10*4,0xffff5bb1,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1(11*4,0x895cd7be,FN1,S14,%ebx,%ecx,%edx,%eax) BODY1(12*4,0x6b901122,FN1,S11,%eax,%ebx,%ecx,%edx) BODY1(13*4,0xfd987193,FN1,S12,%edx,%eax,%ebx,%ecx) BODY1(14*4,0xa679438e,FN1,S13,%ecx,%edx,%eax,%ebx) BODY1(15*4,0x49b40821,FN1,S14,%ebx,%ecx,%edx,%eax) BODY( 1*4,0xf61e2562,FN2,S21,%eax,%ebx,%ecx,%edx) BODY( 6*4,0xc040b340,FN2,S22,%edx,%eax,%ebx,%ecx) BODY(11*4,0x265e5a51,FN2,S23,%ecx,%edx,%eax,%ebx) BODY( 0*4,0xe9b6c7aa,FN2,S24,%ebx,%ecx,%edx,%eax) BODY( 5*4,0xd62f105d,FN2,S21,%eax,%ebx,%ecx,%edx) BODY(10*4,0x02441453,FN2,S22,%edx,%eax,%ebx,%ecx) BODY(15*4,0xd8a1e681,FN2,S23,%ecx,%edx,%eax,%ebx) BODY( 4*4,0xe7d3fbc8,FN2,S24,%ebx,%ecx,%edx,%eax) BODY( 9*4,0x21e1cde6,FN2,S21,%eax,%ebx,%ecx,%edx) BODY(14*4,0xc33707d6,FN2,S22,%edx,%eax,%ebx,%ecx) BODY( 3*4,0xf4d50d87,FN2,S23,%ecx,%edx,%eax,%ebx) BODY( 8*4,0x455a14ed,FN2,S24,%ebx,%ecx,%edx,%eax) BODY(13*4,0xa9e3e905,FN2,S21,%eax,%ebx,%ecx,%edx) BODY( 2*4,0xfcefa3f8,FN2,S22,%edx,%eax,%ebx,%ecx) BODY( 7*4,0x676f02d9,FN2,S23,%ecx,%edx,%eax,%ebx) BODY(12*4,0x8d2a4c8a,FN2,S24,%ebx,%ecx,%edx,%eax) BODY( 5*4,0xfffa3942,FN3,S31,%eax,%ebx,%ecx,%edx) BODY( 8*4,0x8771f681,FN3,S32,%edx,%eax,%ebx,%ecx) BODY(11*4,0x6d9d6122,FN3,S33,%ecx,%edx,%eax,%ebx) BODY(14*4,0xfde5380c,FN3,S34,%ebx,%ecx,%edx,%eax) BODY( 1*4,0xa4beea44,FN3,S31,%eax,%ebx,%ecx,%edx) BODY( 4*4,0x4bdecfa9,FN3,S32,%edx,%eax,%ebx,%ecx) BODY( 7*4,0xf6bb4b60,FN3,S33,%ecx,%edx,%eax,%ebx) BODY(10*4,0xbebfbc70,FN3,S34,%ebx,%ecx,%edx,%eax) BODY(13*4,0x289b7ec6,FN3,S31,%eax,%ebx,%ecx,%edx) BODY( 0*4,0xeaa127fa,FN3,S32,%edx,%eax,%ebx,%ecx) BODY( 3*4,0xd4ef3085,FN3,S33,%ecx,%edx,%eax,%ebx) BODY( 6*4,0x04881d05,FN3,S34,%ebx,%ecx,%edx,%eax) BODY( 9*4,0xd9d4d039,FN3,S31,%eax,%ebx,%ecx,%edx) BODY(12*4,0xe6db99e5,FN3,S32,%edx,%eax,%ebx,%ecx) BODY(15*4,0x1fa27cf8,FN3,S33,%ecx,%edx,%eax,%ebx) BODY( 2*4,0xc4ac5665,FN3,S34,%ebx,%ecx,%edx,%eax) BODY( 0*4,0xf4292244,FN4,S41,%eax,%ebx,%ecx,%edx) BODY( 7*4,0x432aff97,FN4,S42,%edx,%eax,%ebx,%ecx) BODY(14*4,0xab9423a7,FN4,S43,%ecx,%edx,%eax,%ebx) BODY( 5*4,0xfc93a039,FN4,S44,%ebx,%ecx,%edx,%eax) BODY(12*4,0x655b59c3,FN4,S41,%eax,%ebx,%ecx,%edx) BODY( 3*4,0x8f0ccc92,FN4,S42,%edx,%eax,%ebx,%ecx) BODY(10*4,0xffeff47d,FN4,S43,%ecx,%edx,%eax,%ebx) BODY( 1*4,0x85845dd1,FN4,S44,%ebx,%ecx,%edx,%eax) BODY( 8*4,0x6fa87e4f,FN4,S41,%eax,%ebx,%ecx,%edx) BODY(15*4,0xfe2ce6e0,FN4,S42,%edx,%eax,%ebx,%ecx) BODY( 6*4,0xa3014314,FN4,S43,%ecx,%edx,%eax,%ebx) BODY(13*4,0x4e0811a1,FN4,S44,%ebx,%ecx,%edx,%eax) BODY( 4*4,0xf7537e82,FN4,S41,%eax,%ebx,%ecx,%edx) BODY(11*4,0xbd3af235,FN4,S42,%edx,%eax,%ebx,%ecx) BODY( 2*4,0x2ad7d2bb,FN4,S43,%ecx,%edx,%eax,%ebx) BODY( 9*4,0xeb86d391,FN4,S44,%ebx,%ecx,%edx,%eax) addl $(16*4), %ebp movl STATE(%esp), %edi addl %eax,0(%edi) addl %ebx,4(%edi) addl %ecx,8(%edi) addl %edx,12(%edi) movl EDATA(%esp), %edi cmpl %edi, %ebp jb 0b /* Postlude */ movl OLDEBX(%esp), %ebx movl OLDESI(%esp), %esi movl OLDEDI(%esp), %edi addl $(STACKSIZE), %esp popl %ebp ret drawterm-20110822.orig/posix-386/tas.c0000644000175000017500000000041611245145712016507 0ustar tinchotincho#include "u.h" #include "libc.h" int tas(long *x) { int v; __asm__( "movl $1, %%eax\n\t" "xchgl %%eax,(%%ecx)" : "=a" (v) : "c" (x) ); switch(v) { case 0: case 1: return v; default: print("canlock: corrupted 0x%lux\n", v); return 1; } } drawterm-20110822.orig/posix-386/sha1block.spp0000644000175000017500000001125611245145712020153 0ustar tinchotincho.text .p2align 2,0x90 #ifdef __APPLE__ .globl __sha1block __sha1block: #else .globl _sha1block _sha1block: #endif /* x = (wp[off-f] ^ wp[off-8] ^ wp[off-14] ^ wp[off-16]) <<< 1; * wp[off] = x; * x += A <<< 5; * E += 0xca62c1d6 + x; * x = FN(B,C,D); * E += x; * B >>> 2 */ #define BSWAPDI BYTE $0x0f; BYTE $0xcf; #define BODY(off,FN,V,A,B,C,D,E)\ movl (off-64)(%ebp), %edi;\ xorl (off-56)(%ebp), %edi;\ xorl (off-32)(%ebp), %edi;\ xorl (off-12)(%ebp), %edi;\ roll $1, %edi;\ movl %edi, off(%ebp);\ leal V(%edi, E, 1), E;\ movl A, %edi;\ roll $5, %edi;\ addl %edi, E;\ FN(B,C,D)\ addl %edi, E;\ rorl $2, B;\ #define BODY0(off,FN,V,A,B,C,D,E)\ movl off(%ebx), %edi;\ bswap %edi;\ movl %edi, off(%ebp);\ leal V(%edi,E,1), E;\ movl A, %edi;\ roll $5,%edi;\ addl %edi,E;\ FN(B,C,D)\ addl %edi,E;\ rorl $2,B;\ /* * fn1 = (((C^D)&B)^D); */ #define FN1(B,C,D)\ movl C, %edi;\ xorl D, %edi;\ andl B, %edi;\ xorl D, %edi;\ /* * fn24 = B ^ C ^ D */ #define FN24(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ xorl D, %edi;\ /* * fn3 = ((B ^ C) & (D ^= B)) ^ B * D ^= B to restore D */ #define FN3(B,C,D)\ movl B, %edi;\ xorl C, %edi;\ xorl B, D;\ andl D, %edi;\ xorl B, %edi;\ xorl B, D;\ /* * stack offsets * void sha1block(uchar *DATA, int LEN, ulong *STATE) */ #define STACKSIZE (48+80*4) #define DATA (STACKSIZE+8) #define LEN (STACKSIZE+12) #define STATE (STACKSIZE+16) /* * stack offsets for locals * ulong w[80]; * uchar *edata; * ulong *w15, *w40, *w60, *w80; * register local * ulong *wp = %ebp * ulong a = eax, b = ebx, c = ecx, d = edx, e = esi * ulong tmp = edi */ #define WARRAY (STACKSIZE-4-(80*4)) #define TMP1 (STACKSIZE-8-(80*4)) #define TMP2 (STACKSIZE-12-(80*4)) #define W15 (STACKSIZE-16-(80*4)) #define W40 (STACKSIZE-20-(80*4)) #define W60 (STACKSIZE-24-(80*4)) #define W80 (STACKSIZE-28-(80*4)) #define EDATA (STACKSIZE-32-(80*4)) #define OLDEBX (STACKSIZE-36-(80*4)) #define OLDESI (STACKSIZE-40-(80*4)) #define OLDEDI (STACKSIZE-44-(80*4)) /* Prelude */ pushl %ebp subl $(STACKSIZE), %esp mov %ebx, OLDEBX(%esp) mov %esi, OLDESI(%esp) mov %edi, OLDEDI(%esp) movl DATA(%esp), %eax addl LEN(%esp), %eax movl %eax, EDATA(%esp) leal (WARRAY+15*4)(%esp), %edi /* aw15 */ movl %edi, W15(%esp) leal (WARRAY+40*4)(%esp), %edx /* aw40 */ movl %edx, W40(%esp) leal (WARRAY+60*4)(%esp), %ecx /* aw60 */ movl %ecx, W60(%esp) leal (WARRAY+80*4)(%esp), %edi /* aw80 */ movl %edi, W80(%esp) 0: leal WARRAY(%esp), %ebp /* warray */ movl STATE(%esp), %edi /* state */ movl (%edi),%eax movl 4(%edi),%ebx movl %ebx, TMP1(%esp) /* tmp1 */ movl 8(%edi), %ecx movl 12(%edi), %edx movl 16(%edi), %esi movl DATA(%esp), %ebx /* data */ 1: BODY0(0,FN1,0x5a827999,%eax,TMP1(%esp),%ecx,%edx,%esi) movl %esi,TMP2(%esp) BODY0(4,FN1,0x5a827999,%esi,%eax,TMP1(%esp),%ecx,%edx) movl TMP1(%esp),%esi BODY0(8,FN1,0x5a827999,%edx,TMP2(%esp),%eax,%esi,%ecx) BODY0(12,FN1,0x5a827999,%ecx,%edx,TMP2(%esp),%eax,%esi) movl %esi,TMP1(%esp) BODY0(16,FN1,0x5a827999,%esi,%ecx,%edx,TMP2(%esp),%eax) movl TMP2(%esp),%esi addl $20, %ebx addl $20, %ebp cmpl W15(%esp), %ebp /* w15 */ jb 1b BODY0(0,FN1,0x5a827999,%eax,TMP1(%esp),%ecx,%edx,%esi) addl $4, %ebx MOVL %ebx, DATA(%esp) /* data */ MOVL TMP1(%esp),%ebx BODY(4,FN1,0x5a827999,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN1,0x5a827999,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN1,0x5a827999,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN1,0x5a827999,%ebx,%ecx,%edx,%esi,%eax) addl $20, %ebp 2: BODY(0,FN24,0x6ed9eba1,%eax,%ebx,%ecx,%edx,%esi) BODY(4,FN24,0x6ed9eba1,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN24,0x6ed9eba1,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN24,0x6ed9eba1,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN24,0x6ed9eba1,%ebx,%ecx,%edx,%esi,%eax) addl $20,%ebp cmpl W40(%esp), %ebp jb 2b 3: BODY(0,FN3,0x8f1bbcdc,%eax,%ebx,%ecx,%edx,%esi) BODY(4,FN3,0x8f1bbcdc,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN3,0x8f1bbcdc,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN3,0x8f1bbcdc,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN3,0x8f1bbcdc,%ebx,%ecx,%edx,%esi,%eax) addl $20, %ebp cmpl W60(%esp), %ebp /* w60 */ jb 3b 4: BODY(0,FN24,0xca62c1d6,%eax,%ebx,%ecx,%edx,%esi) BODY(4,FN24,0xca62c1d6,%esi,%eax,%ebx,%ecx,%edx) BODY(8,FN24,0xca62c1d6,%edx,%esi,%eax,%ebx,%ecx) BODY(12,FN24,0xca62c1d6,%ecx,%edx,%esi,%eax,%ebx) BODY(16,FN24,0xca62c1d6,%ebx,%ecx,%edx,%esi,%eax) addl $20, %ebp cmpl W80(%esp), %ebp /* w80 */ jb 4b movl STATE(%esp), %edi /* state */ addl %eax, 0(%edi) addl %ebx, 4(%edi) addl %ecx, 8(%edi) addl %edx, 12(%edi) addl %esi, 16(%edi) movl EDATA(%esp), %edi /* edata */ cmpl %edi, DATA(%esp) /* data */ jb 0b /* Postlude */ mov OLDEBX(%esp), %ebx mov OLDESI(%esp), %esi mov OLDEDI(%esp), %edi addl $(STACKSIZE), %esp popl %ebp ret drawterm-20110822.orig/posix-386/Makefile0000644000175000017500000000060611245145712017215 0ustar tinchotinchoROOT=.. include ../Make.config LIB=../libmachdep.a OFILES=\ getcallerpc.$O\ md5block.$O\ sha1block.$O\ tas.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c %.$O: %.s $(AS) -o $*.$O $*.s md5block.s: md5block.spp gcc -E - < md5block.spp >md5block.s sha1block.s: sha1block.spp gcc -E - < sha1block.spp >sha1block.s drawterm-20110822.orig/posix-386/getcallerpc.c0000644000175000017500000000013611245145712020204 0ustar tinchotincho#include "u.h" #include "libc.h" uintptr getcallerpc(void *a) { return ((uintptr*)a)[-1]; } drawterm-20110822.orig/posix-power/0000755000175000017500000000000011245145712016367 5ustar tinchotinchodrawterm-20110822.orig/posix-power/tas.c0000644000175000017500000000165711245145712017333 0ustar tinchotincho#include "u.h" #include "libc.h" /* * first argument (l) is in r3 at entry. * r3 contains return value upon return. */ int tas(long *x) { int v; /* * this __asm__ works with gcc 2.95.2 (mac os x 10.1). * this assembly language destroys r0 (0), some other register (v), * r4 (x) and r5 (temp). */ __asm__("\n sync\n" " li r0,0\n" " mr r4,%1 /* &l->val */\n" " lis r5,0xdead /* assemble constant 0xdeaddead */\n" " ori r5,r5,0xdead /* \" */\n" "tas1:\n" " dcbf r4,r0 /* cache flush; \"fix for 603x bug\" */\n" " lwarx %0,r4,r0 /* v = l->val with reservation */\n" " cmp cr0,0,%0,r0 /* v == 0 */\n" " bne tas0\n" " stwcx. r5,r4,r0 /* if (l->val same) l->val = 0xdeaddead */\n" " bne tas1\n" "tas0:\n" " sync\n" " isync\n" : "=r" (v) : "r" (x) : "cc", "memory", "r0", "r4", "r5" ); switch(v) { case 0: return 0; case 0xdeaddead: return 1; default: print("tas: corrupted 0x%lux\n", v); } return 0; } drawterm-20110822.orig/posix-power/md5block.c0000644000175000017500000001165011245145712020236 0ustar tinchotincho#include #include #include /* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ /* * Rotate ammounts used in the algorithm */ enum { S11= 7, S12= 12, S13= 17, S14= 22, S21= 5, S22= 9, S23= 14, S24= 20, S31= 4, S32= 11, S33= 16, S34= 23, S41= 6, S42= 10, S43= 15, S44= 21, }; static u32int md5tab[] = { /* round 1 */ /*[0]*/ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, /* round 2 */ /*[16]*/0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, /* round 3 */ /*[32]*/0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, /* round 4 */ /*[48]*/0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static void decode(u32int*, uchar*, ulong); extern void _md5block(uchar *p, ulong len, u32int *s); void _md5block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, sh; u32int *t; uchar *end; u32int x[16]; for(end = p+len; p < end; p += 64){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; decode(x, p, 64); t = md5tab; sh = 0; for(; sh != 16; t += 4){ a += ((c ^ d) & b) ^ d; a += x[sh] + t[0]; a = (a << S11) | (a >> (32 - S11)); a += b; d += ((b ^ c) & a) ^ c; d += x[sh + 1] + t[1]; d = (d << S12) | (d >> (32 - S12)); d += a; c += ((a ^ b) & d) ^ b; c += x[sh + 2] + t[2]; c = (c << S13) | (c >> (32 - S13)); c += d; b += ((d ^ a) & c) ^ a; b += x[sh + 3] + t[3]; b = (b << S14) | (b >> (32 - S14)); b += c; sh += 4; } sh = 1; for(; sh != 1+20*4; t += 4){ a += ((b ^ c) & d) ^ c; a += x[sh & 0xf] + t[0]; a = (a << S21) | (a >> (32 - S21)); a += b; d += ((a ^ b) & c) ^ b; d += x[(sh + 5) & 0xf] + t[1]; d = (d << S22) | (d >> (32 - S22)); d += a; c += ((d ^ a) & b) ^ a; c += x[(sh + 10) & 0xf] + t[2]; c = (c << S23) | (c >> (32 - S23)); c += d; b += ((c ^ d) & a) ^ d; b += x[(sh + 15) & 0xf] + t[3]; b = (b << S24) | (b >> (32 - S24)); b += c; sh += 20; } sh = 5; for(; sh != 5+12*4; t += 4){ a += b ^ c ^ d; a += x[sh & 0xf] + t[0]; a = (a << S31) | (a >> (32 - S31)); a += b; d += a ^ b ^ c; d += x[(sh + 3) & 0xf] + t[1]; d = (d << S32) | (d >> (32 - S32)); d += a; c += d ^ a ^ b; c += x[(sh + 6) & 0xf] + t[2]; c = (c << S33) | (c >> (32 - S33)); c += d; b += c ^ d ^ a; b += x[(sh + 9) & 0xf] + t[3]; b = (b << S34) | (b >> (32 - S34)); b += c; sh += 12; } sh = 0; for(; sh != 28*4; t += 4){ a += c ^ (b | ~d); a += x[sh & 0xf] + t[0]; a = (a << S41) | (a >> (32 - S41)); a += b; d += b ^ (a | ~c); d += x[(sh + 7) & 0xf] + t[1]; d = (d << S42) | (d >> (32 - S42)); d += a; c += a ^ (d | ~b); c += x[(sh + 14) & 0xf] + t[2]; c = (c << S43) | (c >> (32 - S43)); c += d; b += d ^ (c | ~a); b += x[(sh + 21) & 0xf] + t[3]; b = (b << S44) | (b >> (32 - S44)); b += c; sh += 28; } s[0] += a; s[1] += b; s[2] += c; s[3] += d; } } /* * decodes input (uchar) into output (u32int). Assumes len is * a multiple of 4. */ static void decode(u32int *output, uchar *input, ulong len) { uchar *e; for(e = input+len; input < e; input += 4) *output++ = input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24); } drawterm-20110822.orig/posix-power/Makefile0000644000175000017500000000044311245145712020030 0ustar tinchotinchoROOT=.. include ../Make.config LIB=../libmachdep.a OFILES=\ getcallerpc.$O\ md5block.$O\ sha1block.$O\ tas.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c %.$O: %.s $(AS) -o $*.$O $*.s %.s: %.spp cpp $*.spp >$*.s drawterm-20110822.orig/posix-power/sha1block.c0000644000175000017500000001114611245145712020405 0ustar tinchotincho#include #include #include void _sha1block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, e, x; uchar *end; u32int *wp, *wend; u32int w[80]; /* at this point, we have a multiple of 64 bytes */ for(end = p+len; p < end;){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; e = s[4]; wend = w + 15; for(wp = w; wp < wend; wp += 5){ wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); wp[1] = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7]; d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); wp[2] = (p[8]<<24) | (p[9]<<16) | (p[10]<<8) | p[11]; c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); wp[3] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); wp[4] = (p[16]<<24) | (p[17]<<16) | (p[18]<<8) | p[19]; a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); p += 20; } wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); wp += 5; p += 4; wend = w + 40; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x6ed9eba1 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x6ed9eba1 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x6ed9eba1 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x6ed9eba1 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x6ed9eba1 + (c^d^e); c = (c<<30)|(c>>2); } wend = w + 60; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x8f1bbcdc + ((b&c)|((b|c)&d)); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x8f1bbcdc + ((a&b)|((a|b)&c)); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x8f1bbcdc + ((e&a)|((e|a)&b)); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x8f1bbcdc + ((d&e)|((d|e)&a)); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x8f1bbcdc + ((c&d)|((c|d)&e)); c = (c<<30)|(c>>2); } wend = w + 80; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0xca62c1d6 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0xca62c1d6 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0xca62c1d6 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0xca62c1d6 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0xca62c1d6 + (c^d^e); c = (c<<30)|(c>>2); } /* save state */ s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; } } drawterm-20110822.orig/posix-power/getcallerpc.c0000644000175000017500000000013611245145712021020 0ustar tinchotincho#include "u.h" #include "libc.h" uintptr getcallerpc(void *a) { return ((uintptr*)a)[-1]; } drawterm-20110822.orig/libmemlayer/0000755000175000017500000000000011245145712016375 5ustar tinchotinchodrawterm-20110822.orig/libmemlayer/unload.c0000644000175000017500000000175511245145712020033 0ustar tinchotincho#include #include #include #include #include int memunload(Memimage *src, Rectangle r, uchar *data, int n) { Memimage *tmp; Memlayer *dl; Rectangle lr; int dx; Top: dl = src->layer; if(dl == nil) return unloadmemimage(src, r, data, n); /* * Convert to screen coordinates. */ lr = r; r.min.x += dl->delta.x; r.min.y += dl->delta.y; r.max.x += dl->delta.x; r.max.y += dl->delta.y; dx = dl->delta.x&(7/src->depth); if(dl->clear && dx==0){ src = dl->screen->image; goto Top; } /* * src is an obscured layer or data is unaligned */ if(dl->save && dx==0){ if(dl->refreshfn != 0) return -1; /* can't unload window if it's not Refbackup */ if(n > 0) memlhide(src, r); n = unloadmemimage(dl->save, lr, data, n); return n; } tmp = allocmemimage(lr, src->chan); if(tmp == nil) return -1; memdraw(tmp, lr, src, lr.min, nil, lr.min, S); n = unloadmemimage(tmp, lr, data, n); freememimage(tmp); return n; } drawterm-20110822.orig/libmemlayer/lhide.c0000644000175000017500000000321311245145712017625 0ustar tinchotincho#include #include #include #include #include /* * Hide puts that portion of screenr now on the screen into the window's save area. * Expose puts that portion of screenr now in the save area onto the screen. * * Hide and Expose both require that the layer structures in the screen * match the geometry they are being asked to update, that is, they update the * save area (hide) or screen (expose) based on what those structures tell them. * This means they must be called at the correct time during window shuffles. */ static void lhideop(Memimage *src, Rectangle screenr, Rectangle clipr, void *etc, int insave) { Rectangle r; Memlayer *l; USED(clipr.min.x); USED(insave); l = etc; if(src != l->save){ /* do nothing if src is already in save area */ r = rectsubpt(screenr, l->delta); memdraw(l->save, r, src, screenr.min, nil, screenr.min, S); } } void memlhide(Memimage *i, Rectangle screenr) { if(i->layer->save == nil) return; if(rectclip(&screenr, i->layer->screen->image->r) == 0) return; _memlayerop(lhideop, i, screenr, screenr, i->layer); } static void lexposeop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave) { Memlayer *l; Rectangle r; USED(clipr.min.x); if(insave) /* if dst is save area, don't bother */ return; l = etc; r = rectsubpt(screenr, l->delta); if(l->save) memdraw(dst, screenr, l->save, r.min, nil, r.min, S); else l->refreshfn(dst, r, l->refreshptr); } void memlexpose(Memimage *i, Rectangle screenr) { if(rectclip(&screenr, i->layer->screen->image->r) == 0) return; _memlayerop(lexposeop, i, screenr, screenr, i->layer); } drawterm-20110822.orig/libmemlayer/lsetrefresh.c0000644000175000017500000000126711245145712021075 0ustar tinchotincho#include #include #include #include #include int memlsetrefresh(Memimage *i, Refreshfn fn, void *ptr) { Memlayer *l; l = i->layer; if(l->refreshfn!=0 && fn!=0){ /* just change functions */ l->refreshfn = fn; l->refreshptr = ptr; return 1; } if(l->refreshfn == 0){ /* is using backup image; just free it */ freememimage(l->save); l->save = nil; l->refreshfn = fn; l->refreshptr = ptr; return 1; } l->save = allocmemimage(i->r, i->chan); if(l->save == nil) return 0; /* easiest way is just to update the entire save area */ l->refreshfn(i, i->r, l->refreshptr); l->refreshfn = 0; l->refreshptr = nil; return 1; } drawterm-20110822.orig/libmemlayer/Makefile0000644000175000017500000000047711245145712020045 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libmemlayer.a OFILES=\ draw.$O\ lalloc.$O\ layerop.$O\ ldelete.$O\ lhide.$O\ line.$O\ load.$O\ lorigin.$O\ lsetrefresh.$O\ ltofront.$O\ ltorear.$O\ unload.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/libmemlayer/lorigin.c0000644000175000017500000000471311245145712020211 0ustar tinchotincho#include #include #include #include #include /* * Place i so i->r.min = log, i->layer->screenr.min == scr. */ int memlorigin(Memimage *i, Point log, Point scr) { Memlayer *l; Memscreen *s; Memimage *t, *shad, *nsave; Rectangle x, newr, oldr; Point delta; int overlap, eqlog, eqscr, wasclear; l = i->layer; s = l->screen; oldr = l->screenr; newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr)); eqscr = eqpt(scr, oldr.min); eqlog = eqpt(log, i->r.min); if(eqscr && eqlog) return 0; nsave = nil; if(eqlog==0 && l->save!=nil){ nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan); if(nsave == nil) return -1; } /* * Bring it to front and move logical coordinate system. */ memltofront(i); wasclear = l->clear; if(nsave){ if(!wasclear) memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S); freememimage(l->save); l->save = nsave; } delta = subpt(log, i->r.min); i->r = rectaddpt(i->r, delta); i->clipr = rectaddpt(i->clipr, delta); l->delta = subpt(l->screenr.min, i->r.min); if(eqscr) return 0; /* * To clean up old position, make a shadow window there, don't paint it, * push it behind this one, and (later) delete it. Because the refresh function * for this fake window is a no-op, this will cause no graphics action except * to restore the background and expose the windows previously hidden. */ shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill); if(shad == nil) return -1; s->frontmost = i; if(s->rearmost == i) s->rearmost = shad; else l->rear->layer->front = shad; shad->layer->front = i; shad->layer->rear = l->rear; l->rear = shad; l->front = nil; shad->layer->clear = 0; /* * Shadow is now holding down the fort at the old position. * Move the window and hide things obscured by new position. */ for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){ x = newr; overlap = rectclip(&x, t->layer->screenr); if(overlap){ memlhide(t, x); t->layer->clear = 0; } } l->screenr = newr; l->delta = subpt(scr, i->r.min); l->clear = rectinrect(newr, l->screen->image->clipr); /* * Everything's covered. Copy to new position and delete shadow window. */ if(wasclear) memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S); else memlexpose(i, newr); memldelete(shad); return 1; } void memlnorefresh(Memimage *l, Rectangle r, void *v) { USED(l); USED(r.min.x); USED(v); } drawterm-20110822.orig/libmemlayer/ltorear.c0000644000175000017500000000204611245145712020213 0ustar tinchotincho#include #include #include #include #include void _memltorear(Memimage *i, Memimage *rear) { Memlayer *l; Memscreen *s; Memimage *f, *r, *rr; Rectangle x; int overlap; l = i->layer; s = l->screen; while(l->rear != rear){ r = l->rear; x = l->screenr; overlap = rectclip(&x, r->layer->screenr); if(overlap){ memlhide(i, x); l->clear = 0; } /* swap l and r in screen's list */ rr = r->layer->rear; f = l->front; if(rr == nil) s->rearmost = i; else rr->layer->front = i; if(f == nil) s->frontmost = r; else f->layer->rear = r; l->rear = rr; l->front = r; r->layer->rear = i; r->layer->front = f; if(overlap) memlexpose(r, x); } } void memltorear(Memimage *i) { _memltorear(i, nil); _memlsetclear(i->layer->screen); } void memltorearn(Memimage **ip, int n) { Memimage *i, *rear; Memscreen *s; if(n == 0) return; rear = nil; while(--n >= 0){ i = *ip++; _memltorear(i, rear); rear = i; } s = rear->layer->screen; _memlsetclear(s); } drawterm-20110822.orig/libmemlayer/ldelete.c0000644000175000017500000000223711245145712020163 0ustar tinchotincho#include #include #include #include #include void memldelete(Memimage *i) { Memscreen *s; Memlayer *l; l = i->layer; /* free backing store and disconnect refresh, to make pushback fast */ freememimage(l->save); l->save = nil; l->refreshptr = nil; memltorear(i); /* window is now the rearmost; clean up screen structures and deallocate */ s = i->layer->screen; if(s->fill){ i->clipr = i->r; memdraw(i, i->r, s->fill, i->r.min, nil, i->r.min, S); } if(l->front){ l->front->layer->rear = nil; s->rearmost = l->front; }else{ s->frontmost = nil; s->rearmost = nil; } free(l); freememimage(i); } /* * Just free the data structures, don't do graphics */ void memlfree(Memimage *i) { Memlayer *l; l = i->layer; freememimage(l->save); free(l); freememimage(i); } void _memlsetclear(Memscreen *s) { Memimage *i, *j; Memlayer *l; for(i=s->rearmost; i; i=i->layer->front){ l = i->layer; l->clear = rectinrect(l->screenr, l->screen->image->clipr); if(l->clear) for(j=l->front; j; j=j->layer->front) if(rectXrect(l->screenr, j->layer->screenr)){ l->clear = 0; break; } } } drawterm-20110822.orig/libmemlayer/line.c0000644000175000017500000000503311245145712017471 0ustar tinchotincho#include #include #include #include #include struct Lline { Point p0; Point p1; Point delta; int end0; int end1; int radius; Point sp; Memlayer *dstlayer; Memimage *src; int op; }; static void llineop(Memimage*, Rectangle, Rectangle, void*, int); static void _memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op) { Rectangle r; struct Lline ll; Point d; int srcclipped; Memlayer *dl; if(radius < 0) return; if(src->layer) /* can't draw line with layered source */ return; srcclipped = 0; Top: dl = dst->layer; if(dl == nil){ _memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op); return; } if(!srcclipped){ d = subpt(sp, p0); if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0) return; if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0) return; srcclipped = 1; } /* dst is known to be a layer */ p0.x += dl->delta.x; p0.y += dl->delta.y; p1.x += dl->delta.x; p1.y += dl->delta.y; clipr.min.x += dl->delta.x; clipr.min.y += dl->delta.y; clipr.max.x += dl->delta.x; clipr.max.y += dl->delta.y; if(dl->clear){ dst = dst->layer->screen->image; goto Top; } /* XXX */ /* this is not the correct set of tests */ // if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3) // return; /* can't use sutherland-cohen clipping because lines are wide */ r = memlinebbox(p0, p1, end0, end1, radius); /* * r is now a bounding box for the line; * use it as a clipping rectangle for subdivision */ if(rectclip(&r, clipr) == 0) return; ll.p0 = p0; ll.p1 = p1; ll.end0 = end0; ll.end1 = end1; ll.sp = sp; ll.dstlayer = dst->layer; ll.src = src; ll.radius = radius; ll.delta = dl->delta; ll.op = op; _memlayerop(llineop, dst, r, r, &ll); } static void llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave) { struct Lline *ll; Point p0, p1; USED(screenr.min.x); ll = etc; if(insave && ll->dstlayer->save==nil) return; if(!rectclip(&clipr, screenr)) return; if(insave){ p0 = subpt(ll->p0, ll->delta); p1 = subpt(ll->p1, ll->delta); clipr = rectsubpt(clipr, ll->delta); }else{ p0 = ll->p0; p1 = ll->p1; } _memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr, ll->op); } void memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op) { _memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op); } drawterm-20110822.orig/libmemlayer/load.c0000644000175000017500000000201011245145712017451 0ustar tinchotincho#include #include #include #include #include int memload(Memimage *dst, Rectangle r, uchar *data, int n, int iscompressed) { int (*loadfn)(Memimage*, Rectangle, uchar*, int); Memimage *tmp; Memlayer *dl; Rectangle lr; int dx; loadfn = loadmemimage; if(iscompressed) loadfn = cloadmemimage; Top: dl = dst->layer; if(dl == nil) return loadfn(dst, r, data, n); /* * Convert to screen coordinates. */ lr = r; r.min.x += dl->delta.x; r.min.y += dl->delta.y; r.max.x += dl->delta.x; r.max.y += dl->delta.y; dx = dl->delta.x&(7/dst->depth); if(dl->clear && dx==0){ dst = dl->screen->image; goto Top; } /* * dst is an obscured layer or data is unaligned */ if(dl->save && dx==0){ n = loadfn(dl->save, lr, data, n); if(n > 0) memlexpose(dst, r); return n; } tmp = allocmemimage(lr, dst->chan); if(tmp == nil) return -1; n = loadfn(tmp, lr, data, n); memdraw(dst, lr, tmp, lr.min, nil, lr.min, S); freememimage(tmp); return n; } drawterm-20110822.orig/libmemlayer/draw.c0000644000175000017500000000774011245145712017506 0ustar tinchotincho#include #include #include #include #include struct Draw { Point deltas; Point deltam; Memlayer *dstlayer; Memimage *src; Memimage *mask; int op; }; static void ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave) { struct Draw *d; Point p0, p1; Rectangle oclipr, srcr, r, mr; int ok; d = etc; if(insave && d->dstlayer->save==nil) return; p0 = addpt(screenr.min, d->deltas); p1 = addpt(screenr.min, d->deltam); if(insave){ r = rectsubpt(screenr, d->dstlayer->delta); clipr = rectsubpt(clipr, d->dstlayer->delta); }else r = screenr; /* now in logical coordinates */ /* clipr may have narrowed what we should draw on, so clip if necessary */ if(!rectinrect(r, clipr)){ oclipr = dst->clipr; dst->clipr = clipr; ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr); dst->clipr = oclipr; if(!ok) return; } memdraw(dst, r, d->src, p0, d->mask, p1, d->op); } void memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op) { struct Draw d; Rectangle srcr, tr, mr; Memlayer *dl, *sl; if(drawdebug) iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1); if(mask == nil) mask = memopaque; if(mask->layer){ if(drawdebug) iprint("mask->layer != nil\n"); return; /* too hard, at least for now */ } Top: if(dst->layer==nil && src->layer==nil){ memimagedraw(dst, r, src, p0, mask, p1, op); return; } if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){ if(drawdebug) iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr); return; } /* * Convert to screen coordinates. */ dl = dst->layer; if(dl != nil){ r.min.x += dl->delta.x; r.min.y += dl->delta.y; r.max.x += dl->delta.x; r.max.y += dl->delta.y; } Clearlayer: if(dl!=nil && dl->clear){ if(src == dst){ p0.x += dl->delta.x; p0.y += dl->delta.y; src = dl->screen->image; } dst = dl->screen->image; goto Top; } sl = src->layer; if(sl != nil){ p0.x += sl->delta.x; p0.y += sl->delta.y; srcr.min.x += sl->delta.x; srcr.min.y += sl->delta.y; srcr.max.x += sl->delta.x; srcr.max.y += sl->delta.y; } /* * Now everything is in screen coordinates. * mask is an image. dst and src are images or obscured layers. */ /* * if dst and src are the same layer, just draw in save area and expose. */ if(dl!=nil && dst==src){ if(dl->save == nil) return; /* refresh function makes this case unworkable */ if(rectXrect(r, srcr)){ tr = r; if(srcr.min.x < tr.min.x){ p1.x += tr.min.x - srcr.min.x; tr.min.x = srcr.min.x; } if(srcr.min.y < tr.min.y){ p1.y += tr.min.x - srcr.min.x; tr.min.y = srcr.min.y; } if(srcr.max.x > tr.max.x) tr.max.x = srcr.max.x; if(srcr.max.y > tr.max.y) tr.max.y = srcr.max.y; memlhide(dst, tr); }else{ memlhide(dst, r); memlhide(dst, srcr); } memdraw(dl->save, rectsubpt(r, dl->delta), dl->save, subpt(srcr.min, src->layer->delta), mask, p1, op); memlexpose(dst, r); return; } if(sl){ if(sl->clear){ src = sl->screen->image; if(dl != nil){ r.min.x -= dl->delta.x; r.min.y -= dl->delta.y; r.max.x -= dl->delta.x; r.max.y -= dl->delta.y; } goto Top; } /* relatively rare case; use save area */ if(sl->save == nil) return; /* refresh function makes this case unworkable */ memlhide(src, srcr); /* convert back to logical coordinates */ p0.x -= sl->delta.x; p0.y -= sl->delta.y; srcr.min.x -= sl->delta.x; srcr.min.y -= sl->delta.y; srcr.max.x -= sl->delta.x; srcr.max.y -= sl->delta.y; src = src->layer->save; } /* * src is now an image. dst may be an image or a clear layer */ if(dst->layer==nil) goto Top; if(dst->layer->clear) goto Clearlayer; /* * dst is an obscured layer */ d.deltas = subpt(p0, r.min); d.deltam = subpt(p1, r.min); d.dstlayer = dl; d.src = src; d.op = op; d.mask = mask; _memlayerop(ldrawop, dst, r, r, &d); } drawterm-20110822.orig/libmemlayer/ltofront.c0000644000175000017500000000241111245145712020406 0ustar tinchotincho#include #include #include #include #include /* * Pull i towards top of screen, just behind front */ static void _memltofront(Memimage *i, Memimage *front, int fill) { Memlayer *l; Memscreen *s; Memimage *f, *ff, *rr; Rectangle x; int overlap; l = i->layer; s = l->screen; while(l->front != front){ f = l->front; x = l->screenr; overlap = rectclip(&x, f->layer->screenr); if(overlap){ memlhide(f, x); f->layer->clear = 0; } /* swap l and f in screen's list */ ff = f->layer->front; rr = l->rear; if(ff == nil) s->frontmost = i; else ff->layer->rear = i; if(rr == nil) s->rearmost = f; else rr->layer->front = f; l->front = ff; l->rear = f; f->layer->front = i; f->layer->rear = rr; if(overlap && fill) memlexpose(i, x); } } void _memltofrontfill(Memimage *i, int fill) { _memltofront(i, nil, fill); _memlsetclear(i->layer->screen); } void memltofront(Memimage *i) { _memltofront(i, nil, 1); _memlsetclear(i->layer->screen); } void memltofrontn(Memimage **ip, int n) { Memimage *i, *front; Memscreen *s; if(n == 0) return; front = nil; while(--n >= 0){ i = *ip++; _memltofront(i, front, 1); front = i; } s = front->layer->screen; _memlsetclear(s); } drawterm-20110822.orig/libmemlayer/lalloc.c0000644000175000017500000000340211245145712020006 0ustar tinchotincho#include #include #include #include #include Memimage* memlalloc(Memscreen *s, Rectangle screenr, Refreshfn refreshfn, void *refreshptr, ulong val) { Memlayer *l; Memimage *n; static Memimage *paint; if(paint == nil){ paint = allocmemimage(Rect(0,0,1,1), RGBA32); if(paint == nil) return nil; paint->flags |= Frepl; paint->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); } n = allocmemimaged(screenr, s->image->chan, s->image->data, s->image->X); if(n == nil) return nil; l = malloc(sizeof(Memlayer)); if(l == nil){ free(n); return nil; } l->screen = s; if(refreshfn) l->save = nil; else{ l->save = allocmemimage(screenr, s->image->chan); if(l->save == nil){ free(l); free(n); return nil; } /* allocmemimage doesn't initialize memory; this paints save area */ if(val != DNofill) memfillcolor(l->save, val); } l->refreshfn = refreshfn; l->refreshptr = nil; /* don't set it until we're done */ l->screenr = screenr; l->delta = Pt(0,0); n->data->ref++; n->zero = s->image->zero; n->width = s->image->width; n->layer = l; /* start with new window behind all existing ones */ l->front = s->rearmost; l->rear = nil; if(s->rearmost) s->rearmost->layer->rear = n; s->rearmost = n; if(s->frontmost == nil) s->frontmost = n; l->clear = 0; /* now pull new window to front */ _memltofrontfill(n, val != DNofill); l->refreshptr = refreshptr; /* * paint with requested color; previously exposed areas are already right * if this window has backing store, but just painting the whole thing is simplest. */ if(val != DNofill){ memsetchan(paint, n->chan); memfillcolor(paint, val); memdraw(n, n->r, paint, n->r.min, nil, n->r.min, S); } return n; } drawterm-20110822.orig/libmemlayer/layerop.c0000644000175000017500000000512111245145712020213 0ustar tinchotincho#include #include #include #include #include #define RECUR(a,b,c,d) _layerop(fn, i, Rect(a.x, b.y, c.x, d.y), clipr, etc, front->layer->rear); static void _layerop( void (*fn)(Memimage*, Rectangle, Rectangle, void*, int), Memimage *i, Rectangle r, Rectangle clipr, void *etc, Memimage *front) { Rectangle fr; Top: if(front == i){ /* no one is in front of this part of window; use the screen */ fn(i->layer->screen->image, r, clipr, etc, 0); return; } fr = front->layer->screenr; if(rectXrect(r, fr) == 0){ /* r doesn't touch this window; continue on next rearmost */ // assert(front && front->layer && front->layer->screen && front->layer->rear); front = front->layer->rear; goto Top; } if(fr.max.y < r.max.y){ RECUR(r.min, fr.max, r.max, r.max); r.max.y = fr.max.y; } if(r.min.y < fr.min.y){ RECUR(r.min, r.min, r.max, fr.min); r.min.y = fr.min.y; } if(fr.max.x < r.max.x){ RECUR(fr.max, r.min, r.max, r.max); r.max.x = fr.max.x; } if(r.min.x < fr.min.x){ RECUR(r.min, r.min, fr.min, r.max); r.min.x = fr.min.x; } /* r is covered by front, so put in save area */ (*fn)(i->layer->save, r, clipr, etc, 1); } /* * Assumes incoming rectangle has already been clipped to i's logical r and clipr */ void _memlayerop( void (*fn)(Memimage*, Rectangle, Rectangle, void*, int), Memimage *i, Rectangle screenr, /* clipped to window boundaries */ Rectangle clipr, /* clipped also to clipping rectangles of hierarchy */ void *etc) { Memlayer *l; Rectangle r, scr; l = i->layer; if(!rectclip(&screenr, l->screenr)) return; if(l->clear){ fn(l->screen->image, screenr, clipr, etc, 0); return; } r = screenr; scr = l->screen->image->clipr; /* * Do the piece on the screen */ if(rectclip(&screenr, scr)) _layerop(fn, i, screenr, clipr, etc, l->screen->frontmost); if(rectinrect(r, scr)) return; /* * Do the piece off the screen */ if(!rectXrect(r, scr)){ /* completely offscreen; easy */ fn(l->save, r, clipr, etc, 1); return; } if(r.min.y < scr.min.y){ /* above screen */ fn(l->save, Rect(r.min.x, r.min.y, r.max.x, scr.min.y), clipr, etc, 1); r.min.y = scr.min.y; } if(r.max.y > scr.max.y){ /* below screen */ fn(l->save, Rect(r.min.x, scr.max.y, r.max.x, r.max.y), clipr, etc, 1); r.max.y = scr.max.y; } if(r.min.x < scr.min.x){ /* left of screen */ fn(l->save, Rect(r.min.x, r.min.y, scr.min.x, r.max.y), clipr, etc, 1); r.min.x = scr.min.x; } if(r.max.x > scr.max.x){ /* right of screen */ fn(l->save, Rect(scr.max.x, r.min.y, r.max.x, r.max.y), clipr, etc, 1); } } drawterm-20110822.orig/libc/0000755000175000017500000000000011245145712015004 5ustar tinchotinchodrawterm-20110822.orig/libc/sprint.c0000644000175000017500000000071611245145712016473 0ustar tinchotincho#include #include #include "fmtdef.h" int sprint(char *buf, char *fmt, ...) { int n; uint len; va_list args; len = 1<<30; /* big number, but sprint is deprecated anyway */ /* * on PowerPC, the stack is near the top of memory, so * we must be sure not to overflow a 32-bit pointer. */ if((uintptr)buf+len < (uintptr)buf) len = -(uintptr)buf-1; va_start(args, fmt); n = vsnprint(buf, len, fmt, args); va_end(args); return n; } drawterm-20110822.orig/libc/fmtlock.c0000644000175000017500000000021011245145712016600 0ustar tinchotincho#include #include static Lock fmtl; void __fmtlock(void) { lock(&fmtl); } void __fmtunlock(void) { unlock(&fmtl); } drawterm-20110822.orig/libc/runesprint.c0000644000175000017500000000032411245145712017360 0ustar tinchotincho#include #include #include "fmtdef.h" int runesprint(Rune *buf, char *fmt, ...) { int n; va_list args; va_start(args, fmt); n = runevsnprint(buf, 256, fmt, args); va_end(args); return n; } drawterm-20110822.orig/libc/runestrdup.c0000644000175000017500000000026411245145712017365 0ustar tinchotincho#include #include Rune* runestrdup(Rune *s) { Rune *ns; ns = malloc(sizeof(Rune)*(runestrlen(s) + 1)); if(ns == 0) return 0; return runestrcpy(ns, s); } drawterm-20110822.orig/libc/time.c0000644000175000017500000000155611245145712016115 0ustar tinchotincho#include #include /* * After a fork with fd's copied, both fd's are pointing to * the same Chan structure. Since the offset is kept in the Chan * structure, the seek's and read's in the two processes can * compete at moving the offset around. Hence the unusual loop * in the middle of this routine. */ static long oldtime(long *tp) { char b[20]; static int f = -1; int i, retries; long t; memset(b, 0, sizeof(b)); for(retries = 0; retries < 100; retries++){ if(f < 0) f = open("/dev/time", OREAD|OCEXEC); if(f < 0) break; if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof(b))) < 0){ close(f); f = -1; } else { if(i != 0) break; } } t = atol(b); if(tp) *tp = t; return t; } long time(long *tp) { vlong t; t = nsec()/((vlong)1000000000); if(t == 0) t = oldtime(0); if(tp != nil) *tp = t; return t; } drawterm-20110822.orig/libc/tokenize.c0000644000175000017500000000323311245145712017001 0ustar tinchotincho#include #include static char qsep[] = " \t\r\n"; static char* qtoken(char *s, char *sep) { int quoting; char *t; quoting = 0; t = s; /* s is output string, t is input string */ while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){ if(*t != '\''){ *s++ = *t++; continue; } /* *t is a quote */ if(!quoting){ quoting = 1; t++; continue; } /* quoting and we're on a quote */ if(t[1] != '\''){ /* end of quoted section; absorb closing quote */ t++; quoting = 0; continue; } /* doubled quote; fold one quote into two */ t++; *s++ = *t++; } if(*s != '\0'){ *s = '\0'; if(t == s) t++; } return t; } static char* etoken(char *t, char *sep) { int quoting; /* move to end of next token */ quoting = 0; while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){ if(*t != '\''){ t++; continue; } /* *t is a quote */ if(!quoting){ quoting = 1; t++; continue; } /* quoting and we're on a quote */ if(t[1] != '\''){ /* end of quoted section; absorb closing quote */ t++; quoting = 0; continue; } /* doubled quote; fold one quote into two */ t += 2; } return t; } int gettokens(char *s, char **args, int maxargs, char *sep) { int nargs; for(nargs=0; nargs #include #include "fmtdef.h" int snprint(char *buf, int len, char *fmt, ...) { int n; va_list args; va_start(args, fmt); n = vsnprint(buf, len, fmt, args); va_end(args); return n; } drawterm-20110822.orig/libc/fmtdef.h0000644000175000017500000000523211245145712016424 0ustar tinchotincho/* * dofmt -- format to a buffer * the number of characters formatted is returned, * or -1 if there was an error. * if the buffer is ever filled, flush is called. * it should reset the buffer and return whether formatting should continue. */ typedef int (*Fmts)(Fmt*); typedef struct Quoteinfo Quoteinfo; struct Quoteinfo { int quoted; /* if set, string must be quoted */ int nrunesin; /* number of input runes that can be accepted */ int nbytesin; /* number of input bytes that can be accepted */ int nrunesout; /* number of runes that will be generated */ int nbytesout; /* number of bytes that will be generated */ }; /* Edit .+1,/^$/ |cfn |grep -v static | grep __ */ double __Inf(int sign); double __NaN(void); int __badfmt(Fmt *f); int __charfmt(Fmt *f); int __countfmt(Fmt *f); int __efgfmt(Fmt *fmt); int __errfmt(Fmt *f); int __flagfmt(Fmt *f); int __fmtFdFlush(Fmt *f); int __fmtcpy(Fmt *f, const void *vm, int n, int sz); void* __fmtdispatch(Fmt *f, void *fmt, int isrunes); void * __fmtflush(Fmt *f, void *t, int len); void __fmtlock(void); int __fmtpad(Fmt *f, int n); double __fmtpow10(int n); int __fmtrcpy(Fmt *f, const void *vm, int n); void __fmtunlock(void); int __ifmt(Fmt *f); int __isInf(double d, int sign); int __isNaN(double d); int __needsquotes(char *s, int *quotelenp); int __percentfmt(Fmt *f); void __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout); int __quotestrfmt(int runesin, Fmt *f); int __rfmtpad(Fmt *f, int n); int __runefmt(Fmt *f); int __runeneedsquotes(Rune *r, int *quotelenp); int __runesfmt(Fmt *f); int __strfmt(Fmt *f); #define FMTCHAR(f, t, s, c)\ do{\ if(t + 1 > (char*)s){\ t = __fmtflush(f, t, 1);\ if(t != nil)\ s = f->stop;\ else\ return -1;\ }\ *t++ = c;\ }while(0) #define FMTRCHAR(f, t, s, c)\ do{\ if(t + 1 > (Rune*)s){\ t = __fmtflush(f, t, sizeof(Rune));\ if(t != nil)\ s = f->stop;\ else\ return -1;\ }\ *t++ = c;\ }while(0) #define FMTRUNE(f, t, s, r)\ do{\ Rune _rune;\ int _runelen;\ if(t + UTFmax > (char*)s && t + (_runelen = runelen(r)) > (char*)s){\ t = __fmtflush(f, t, _runelen);\ if(t != nil)\ s = f->stop;\ else\ return -1;\ }\ if(r < Runeself)\ *t++ = r;\ else{\ _rune = r;\ t += runetochar(t, &_rune);\ }\ }while(0) #ifdef va_copy # define VA_COPY(a,b) va_copy(a,b) # define VA_END(a) va_end(a) #else # define VA_COPY(a,b) (a) = (b) # define VA_END(a) #endif #define PLAN9PORT drawterm-20110822.orig/libc/runeseprint.c0000644000175000017500000000034011245145712017523 0ustar tinchotincho#include #include #include "fmtdef.h" Rune* runeseprint(Rune *buf, Rune *e, char *fmt, ...) { Rune *p; va_list args; va_start(args, fmt); p = runevseprint(buf, e, fmt, args); va_end(args); return p; } drawterm-20110822.orig/libc/encodefmt.c0000644000175000017500000000211411245145712017112 0ustar tinchotincho#include #include #include int encodefmt(Fmt *f) { char *out; char *buf; int len; int ilen; int rv; uchar *b; char *p; char obuf[64]; // rsc optimization if(!(f->flags&FmtPrec) || f->prec < 1) goto error; b = va_arg(f->args, uchar*); if(b == 0) return fmtstrcpy(f, ""); ilen = f->prec; f->prec = 0; f->flags &= ~FmtPrec; switch(f->r){ case '<': len = (8*ilen+4)/5 + 3; break; case '[': len = (8*ilen+5)/6 + 4; break; case 'H': len = 2*ilen + 1; break; default: goto error; } if(len > sizeof(obuf)){ buf = malloc(len); if(buf == nil) goto error; } else buf = obuf; // convert out = buf; switch(f->r){ case '<': rv = enc32(out, len, b, ilen); break; case '[': rv = enc64(out, len, b, ilen); break; case 'H': rv = enc16(out, len, b, ilen); if(rv >= 0 && (f->flags & FmtLong)) for(p = buf; *p; p++) *p = tolower(*p); break; default: rv = -1; break; } if(rv < 0) goto error; fmtstrcpy(f, buf); if(buf != obuf) free(buf); return 0; error: return fmtstrcpy(f, ""); } drawterm-20110822.orig/libc/u16.c0000644000175000017500000000146711245145712015573 0ustar tinchotincho#include #include static char t16e[] = "0123456789ABCDEF"; int dec16(uchar *out, int lim, char *in, int n) { int c, w = 0, i = 0; uchar *start = out; uchar *eout = out + lim; while(n-- > 0){ c = *in++; if('0' <= c && c <= '9') c = c - '0'; else if('a' <= c && c <= 'z') c = c - 'a' + 10; else if('A' <= c && c <= 'Z') c = c - 'A' + 10; else continue; w = (w<<4) + c; i++; if(i == 2){ if(out + 1 > eout) goto exhausted; *out++ = w; w = 0; i = 0; } } exhausted: return out - start; } int enc16(char *out, int lim, uchar *in, int n) { uint c; char *eout = out + lim; char *start = out; while(n-- > 0){ c = *in++; if(out + 2 >= eout) goto exhausted; *out++ = t16e[c>>4]; *out++ = t16e[c&0xf]; } exhausted: *out = 0; return out - start; } drawterm-20110822.orig/libc/charstod.c0000644000175000017500000000226311245145712016762 0ustar tinchotincho#include #include #include "fmtdef.h" /* * Reads a floating-point number by interpreting successive characters * returned by (*f)(vp). The last call it makes to f terminates the * scan, so is not a character in the number. It may therefore be * necessary to back up the input stream up one byte after calling charstod. */ double fmtcharstod(int(*f)(void*), void *vp) { double num, dem; int neg, eneg, dig, exp, c; num = 0; neg = 0; dig = 0; exp = 0; eneg = 0; c = (*f)(vp); while(c == ' ' || c == '\t') c = (*f)(vp); if(c == '-' || c == '+'){ if(c == '-') neg = 1; c = (*f)(vp); } while(c >= '0' && c <= '9'){ num = num*10 + c-'0'; c = (*f)(vp); } if(c == '.') c = (*f)(vp); while(c >= '0' && c <= '9'){ num = num*10 + c-'0'; dig++; c = (*f)(vp); } if(c == 'e' || c == 'E'){ c = (*f)(vp); if(c == '-' || c == '+'){ if(c == '-'){ dig = -dig; eneg = 1; } c = (*f)(vp); } while(c >= '0' && c <= '9'){ exp = exp*10 + c-'0'; c = (*f)(vp); } } exp -= dig; if(exp < 0){ exp = -exp; eneg = !eneg; } dem = __fmtpow10(exp); if(eneg) num /= dem; else num *= dem; if(neg) return -num; return num; } drawterm-20110822.orig/libc/runestrcmp.c0000644000175000017500000000033511245145712017353 0ustar tinchotincho#include #include int runestrcmp(Rune *s1, Rune *s2) { Rune c1, c2; for(;;) { c1 = *s1++; c2 = *s2++; if(c1 != c2) { if(c1 > c2) return 1; return -1; } if(c1 == 0) return 0; } } drawterm-20110822.orig/libc/vseprint.c0000644000175000017500000000054611245145712017027 0ustar tinchotincho#include #include #include "fmtdef.h" char* vseprint(char *buf, char *e, char *fmt, va_list args) { Fmt f; if(e <= buf) return nil; f.runes = 0; f.start = buf; f.to = buf; f.stop = e - 1; f.flush = 0; f.farg = nil; f.nfmt = 0; VA_COPY(f.args,args); dofmt(&f, fmt); VA_END(f.args); *(char*)f.to = '\0'; return (char*)f.to; } drawterm-20110822.orig/libc/dirwstat.c0000644000175000017500000000036611245145712017016 0ustar tinchotincho#include #include #include int dirwstat(char *name, Dir *d) { uchar *buf; int r; r = sizeD2M(d); buf = malloc(r); if(buf == nil) return -1; convD2M(d, buf, r); r = wstat(name, buf, r); free(buf); return r; } drawterm-20110822.orig/libc/runestrrchr.c0000644000175000017500000000026611245145712017535 0ustar tinchotincho#include #include Rune* runestrrchr(Rune *s, Rune c) { Rune *r; if(c == 0) return runestrchr(s, 0); r = 0; while(s = runestrchr(s, c)) r = s++; return r; } drawterm-20110822.orig/libc/vfprint.c0000644000175000017500000000044711245145712016645 0ustar tinchotincho#include #include #include "fmtdef.h" int vfprint(int fd, char *fmt, va_list args) { Fmt f; char buf[256]; int n; fmtfdinit(&f, fd, buf, sizeof(buf)); VA_COPY(f.args,args); n = dofmt(&f, fmt); VA_END(f.args); if(n > 0 && __fmtFdFlush(&f) == 0) return -1; return n; } drawterm-20110822.orig/libc/dofmt.c0000644000175000017500000002164111245145712016265 0ustar tinchotincho#include #include #include "fmtdef.h" /* format the output into f->to and return the number of characters fmted */ int dofmt(Fmt *f, char *fmt) { Rune rune, *rt, *rs; int r; char *t, *s; int n, nfmt; nfmt = f->nfmt; for(;;){ if(f->runes){ rt = (Rune*)f->to; rs = (Rune*)f->stop; while((r = *(uchar*)fmt) && r != '%'){ if(r < Runeself) fmt++; else{ fmt += chartorune(&rune, fmt); r = rune; } FMTRCHAR(f, rt, rs, r); } fmt++; f->nfmt += rt - (Rune *)f->to; f->to = rt; if(!r) return f->nfmt - nfmt; f->stop = rs; }else{ t = (char*)f->to; s = (char*)f->stop; while((r = *(uchar*)fmt) && r != '%'){ if(r < Runeself){ FMTCHAR(f, t, s, r); fmt++; }else{ n = chartorune(&rune, fmt); if(t + n > s){ t = (char*)__fmtflush(f, t, n); if(t != nil) s = (char*)f->stop; else return -1; } while(n--) *t++ = *fmt++; } } fmt++; f->nfmt += t - (char *)f->to; f->to = t; if(!r) return f->nfmt - nfmt; f->stop = s; } fmt = (char*)__fmtdispatch(f, fmt, 0); if(fmt == nil) return -1; } } void * __fmtflush(Fmt *f, void *t, int len) { if(f->runes) f->nfmt += (Rune*)t - (Rune*)f->to; else f->nfmt += (char*)t - (char *)f->to; f->to = t; if(f->flush == 0 || (*f->flush)(f) == 0 || (char*)f->to + len > (char*)f->stop){ f->stop = f->to; return nil; } return f->to; } /* * put a formatted block of memory sz bytes long of n runes into the output buffer, * left/right justified in a field of at least f->width charactes */ int __fmtpad(Fmt *f, int n) { char *t, *s; int i; t = (char*)f->to; s = (char*)f->stop; for(i = 0; i < n; i++) FMTCHAR(f, t, s, ' '); f->nfmt += t - (char *)f->to; f->to = t; return 0; } int __rfmtpad(Fmt *f, int n) { Rune *t, *s; int i; t = (Rune*)f->to; s = (Rune*)f->stop; for(i = 0; i < n; i++) FMTRCHAR(f, t, s, ' '); f->nfmt += t - (Rune *)f->to; f->to = t; return 0; } int __fmtcpy(Fmt *f, const void *vm, int n, int sz) { Rune *rt, *rs, r; char *t, *s, *m, *me; ulong fl; int nc, w; m = (char*)vm; me = m + sz; w = f->width; fl = f->flags; if((fl & FmtPrec) && n > f->prec) n = f->prec; if(f->runes){ if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) return -1; rt = (Rune*)f->to; rs = (Rune*)f->stop; for(nc = n; nc > 0; nc--){ r = *(uchar*)m; if(r < Runeself) m++; else if((me - m) >= UTFmax || fullrune(m, me-m)) m += chartorune(&r, m); else break; FMTRCHAR(f, rt, rs, r); } f->nfmt += rt - (Rune *)f->to; f->to = rt; if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) return -1; }else{ if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) return -1; t = (char*)f->to; s = (char*)f->stop; for(nc = n; nc > 0; nc--){ r = *(uchar*)m; if(r < Runeself) m++; else if((me - m) >= UTFmax || fullrune(m, me-m)) m += chartorune(&r, m); else break; FMTRUNE(f, t, s, r); } f->nfmt += t - (char *)f->to; f->to = t; if(fl & FmtLeft && __fmtpad(f, w - n) < 0) return -1; } return 0; } int __fmtrcpy(Fmt *f, const void *vm, int n) { Rune r, *m, *me, *rt, *rs; char *t, *s; ulong fl; int w; m = (Rune*)vm; w = f->width; fl = f->flags; if((fl & FmtPrec) && n > f->prec) n = f->prec; if(f->runes){ if(!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) return -1; rt = (Rune*)f->to; rs = (Rune*)f->stop; for(me = m + n; m < me; m++) FMTRCHAR(f, rt, rs, *m); f->nfmt += rt - (Rune *)f->to; f->to = rt; if(fl & FmtLeft && __rfmtpad(f, w - n) < 0) return -1; }else{ if(!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) return -1; t = (char*)f->to; s = (char*)f->stop; for(me = m + n; m < me; m++){ r = *m; FMTRUNE(f, t, s, r); } f->nfmt += t - (char *)f->to; f->to = t; if(fl & FmtLeft && __fmtpad(f, w - n) < 0) return -1; } return 0; } /* fmt out one character */ int __charfmt(Fmt *f) { char x[1]; x[0] = va_arg(f->args, int); f->prec = 1; return __fmtcpy(f, (const char*)x, 1, 1); } /* fmt out one rune */ int __runefmt(Fmt *f) { Rune x[1]; x[0] = va_arg(f->args, int); return __fmtrcpy(f, (const void*)x, 1); } /* public helper routine: fmt out a null terminated string already in hand */ int fmtstrcpy(Fmt *f, char *s) { int i, j; Rune r; if(!s) return __fmtcpy(f, "", 5, 5); /* if precision is specified, make sure we don't wander off the end */ if(f->flags & FmtPrec){ i = 0; for(j=0; jprec && s[i]; j++) i += chartorune(&r, s+i); return __fmtcpy(f, s, j, i); } return __fmtcpy(f, s, utflen(s), strlen(s)); } /* fmt out a null terminated utf string */ int __strfmt(Fmt *f) { char *s; s = va_arg(f->args, char *); return fmtstrcpy(f, s); } /* public helper routine: fmt out a null terminated rune string already in hand */ int fmtrunestrcpy(Fmt *f, Rune *s) { Rune *e; int n, p; if(!s) return __fmtcpy(f, "", 5, 5); /* if precision is specified, make sure we don't wander off the end */ if(f->flags & FmtPrec){ p = f->prec; for(n = 0; n < p; n++) if(s[n] == 0) break; }else{ for(e = s; *e; e++) ; n = e - s; } return __fmtrcpy(f, s, n); } /* fmt out a null terminated rune string */ int __runesfmt(Fmt *f) { Rune *s; s = va_arg(f->args, Rune *); return fmtrunestrcpy(f, s); } /* fmt a % */ int __percentfmt(Fmt *f) { Rune x[1]; x[0] = f->r; f->prec = 1; return __fmtrcpy(f, (const void*)x, 1); } /* fmt an integer */ int __ifmt(Fmt *f) { char buf[70], *p, *conv; uvlong vu; ulong u; int neg, base, i, n, fl, w, isv; neg = 0; fl = f->flags; isv = 0; vu = 0; u = 0; /* * Unsigned verbs for ANSI C */ switch(f->r){ case 'x': case 'X': case 'o': case 'u': case 'p': fl |= FmtUnsigned; fl &= ~(FmtSign|FmtSpace); break; } if(f->r == 'p'){ if(sizeof(void*) == sizeof(uvlong)){ isv = 1; vu = (uvlong)va_arg(f->args, uvlong); }else u = (ulong)va_arg(f->args, ulong); f->r = 'x'; fl |= FmtUnsigned; }else if(fl & FmtVLong){ isv = 1; if(fl & FmtUnsigned) vu = va_arg(f->args, uvlong); else vu = va_arg(f->args, vlong); }else if(fl & FmtLong){ if(fl & FmtUnsigned) u = va_arg(f->args, ulong); else u = va_arg(f->args, long); }else if(fl & FmtByte){ if(fl & FmtUnsigned) u = (uchar)va_arg(f->args, int); else u = (char)va_arg(f->args, int); }else if(fl & FmtShort){ if(fl & FmtUnsigned) u = (ushort)va_arg(f->args, int); else u = (short)va_arg(f->args, int); }else{ if(fl & FmtUnsigned) u = va_arg(f->args, uint); else u = va_arg(f->args, int); } conv = "0123456789abcdef"; switch(f->r){ case 'd': case 'i': case 'u': base = 10; break; case 'x': base = 16; break; case 'X': base = 16; conv = "0123456789ABCDEF"; break; case 'b': base = 2; break; case 'o': base = 8; break; default: return -1; } if(!(fl & FmtUnsigned)){ if(isv && (vlong)vu < 0){ vu = -(vlong)vu; neg = 1; }else if(!isv && (long)u < 0){ u = -(long)u; neg = 1; } } p = buf + sizeof buf - 1; n = 0; if(isv){ while(vu){ i = vu % base; vu /= base; if((fl & FmtComma) && n % 4 == 3){ *p-- = ','; n++; } *p-- = conv[i]; n++; } }else{ while(u){ i = u % base; u /= base; if((fl & FmtComma) && n % 4 == 3){ *p-- = ','; n++; } *p-- = conv[i]; n++; } } if(n == 0){ *p-- = '0'; n = 1; } for(w = f->prec; n < w && p > buf+3; n++) *p-- = '0'; if(neg || (fl & (FmtSign|FmtSpace))) n++; if(fl & FmtSharp){ if(base == 16) n += 2; else if(base == 8){ if(p[1] == '0') fl &= ~FmtSharp; else n++; } } if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){ for(w = f->width; n < w && p > buf+3; n++) *p-- = '0'; f->width = 0; } if(fl & FmtSharp){ if(base == 16) *p-- = f->r; if(base == 16 || base == 8) *p-- = '0'; } if(neg) *p-- = '-'; else if(fl & FmtSign) *p-- = '+'; else if(fl & FmtSpace) *p-- = ' '; f->flags &= ~FmtPrec; return __fmtcpy(f, p + 1, n, n); } int __countfmt(Fmt *f) { void *p; ulong fl; fl = f->flags; p = va_arg(f->args, void*); if(fl & FmtVLong){ *(vlong*)p = f->nfmt; }else if(fl & FmtLong){ *(long*)p = f->nfmt; }else if(fl & FmtByte){ *(char*)p = f->nfmt; }else if(fl & FmtShort){ *(short*)p = f->nfmt; }else{ *(int*)p = f->nfmt; } return 0; } int __flagfmt(Fmt *f) { switch(f->r){ case ',': f->flags |= FmtComma; break; case '-': f->flags |= FmtLeft; break; case '+': f->flags |= FmtSign; break; case '#': f->flags |= FmtSharp; break; case ' ': f->flags |= FmtSpace; break; case 'u': f->flags |= FmtUnsigned; break; case 'h': if(f->flags & FmtShort) f->flags |= FmtByte; f->flags |= FmtShort; break; case 'L': f->flags |= FmtLDouble; break; case 'l': if(f->flags & FmtLong) f->flags |= FmtVLong; f->flags |= FmtLong; break; } return 1; } /* default error format */ int __badfmt(Fmt *f) { char x[3]; x[0] = '%'; x[1] = f->r; x[2] = '%'; f->prec = 3; __fmtcpy(f, (const void*)x, 3, 3); return 0; } drawterm-20110822.orig/libc/u32.c0000644000175000017500000000455611245145712015573 0ustar tinchotincho#include #include int dec32(uchar *dest, int ndest, char *src, int nsrc) { char *s, *tab; uchar *start; int i, u[8]; if(ndest+1 < (5*nsrc+7)/8) return -1; start = dest; tab = "23456789abcdefghijkmnpqrstuvwxyz"; while(nsrc>=8){ for(i=0; i<8; i++){ s = strchr(tab,(int)src[i]); u[i] = s ? s-tab : 0; } *dest++ = (u[0]<<3) | (0x7 & (u[1]>>2)); *dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4)); *dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1)); *dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3)); *dest++ = ((0x7 & u[6])<<5) | u[7]; src += 8; nsrc -= 8; } if(nsrc > 0){ if(nsrc == 1 || nsrc == 3 || nsrc == 6) return -1; for(i=0; i>2)); if(nsrc == 2) goto out; *dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4)); if(nsrc == 4) goto out; *dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1)); if(nsrc == 5) goto out; *dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3)); } out: return dest-start; } int enc32(char *dest, int ndest, uchar *src, int nsrc) { char *tab, *start; int j; if(ndest <= (8*nsrc+4)/5 ) return -1; start = dest; tab = "23456789abcdefghijkmnpqrstuvwxyz"; while(nsrc>=5){ j = (0x1f & (src[0]>>3)); *dest++ = tab[j]; j = (0x1c & (src[0]<<2)) | (0x03 & (src[1]>>6)); *dest++ = tab[j]; j = (0x1f & (src[1]>>1)); *dest++ = tab[j]; j = (0x10 & (src[1]<<4)) | (0x0f & (src[2]>>4)); *dest++ = tab[j]; j = (0x1e & (src[2]<<1)) | (0x01 & (src[3]>>7)); *dest++ = tab[j]; j = (0x1f & (src[3]>>2)); *dest++ = tab[j]; j = (0x18 & (src[3]<<3)) | (0x07 & (src[4]>>5)); *dest++ = tab[j]; j = (0x1f & (src[4])); *dest++ = tab[j]; src += 5; nsrc -= 5; } if(nsrc){ j = (0x1f & (src[0]>>3)); *dest++ = tab[j]; j = (0x1c & (src[0]<<2)); if(nsrc == 1) goto out; j |= (0x03 & (src[1]>>6)); *dest++ = tab[j]; j = (0x1f & (src[1]>>1)); if(nsrc == 2) goto out; *dest++ = tab[j]; j = (0x10 & (src[1]<<4)); if(nsrc == 3) goto out; j |= (0x0f & (src[2]>>4)); *dest++ = tab[j]; j = (0x1e & (src[2]<<1)); if(nsrc == 4) goto out; j |= (0x01 & (src[3]>>7)); *dest++ = tab[j]; j = (0x1f & (src[3]>>2)); *dest++ = tab[j]; j = (0x18 & (src[3]<<3)); out: *dest++ = tab[j]; } *dest = 0; return dest-start; } drawterm-20110822.orig/libc/nan64.c0000644000175000017500000000203311245145712016074 0ustar tinchotincho/* * 64-bit IEEE not-a-number routines. * This is big/little-endian portable assuming that * the 64-bit doubles and 64-bit integers have the * same byte ordering. */ #include #include #include "fmtdef.h" #if defined (__APPLE__) || (__powerpc__) #define _NEEDLL #endif static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x00000001; static uvlong uvinf = ((uvlong)0x7FF00000<<32)|0x00000000; static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000; double __NaN(void) { uvlong *p; /* gcc complains about "return *(double*)&uvnan;" */ p = &uvnan; return *(double*)p; } int __isNaN(double d) { uvlong x; double *p; p = &d; x = *(uvlong*)p; return (ulong)(x>>32)==0x7FF00000 && !__isInf(d, 0); } double __Inf(int sign) { uvlong *p; if(sign < 0) p = &uvinf; else p = &uvneginf; return *(double*)p; } int __isInf(double d, int sign) { uvlong x; double *p; p = &d; x = *(uvlong*)p; if(sign == 0) return x==uvinf || x==uvneginf; else if(sign > 0) return x==uvinf; else return x==uvneginf; } drawterm-20110822.orig/libc/runestrncpy.c0000644000175000017500000000035211245145712017544 0ustar tinchotincho#include #include Rune* runestrncpy(Rune *s1, Rune *s2, long n) { int i; Rune *os1; os1 = s1; for(i = 0; i < n; i++) if((*s1++ = *s2++) == 0) { while(++i < n) *s1++ = 0; return os1; } return os1; } drawterm-20110822.orig/libc/vsmprint.c0000644000175000017500000000175211245145712017037 0ustar tinchotincho#include #include #include "fmtdef.h" static int fmtStrFlush(Fmt *f) { char *s; int n; if(f->start == nil) return 0; n = (uintptr)f->farg; n *= 2; s = (char*)f->start; f->start = realloc(s, n); if(f->start == nil){ f->farg = nil; f->to = nil; f->stop = nil; free(s); return 0; } f->farg = (void*)(uintptr)n; f->to = (char*)f->start + ((char*)f->to - s); f->stop = (char*)f->start + n - 1; return 1; } int fmtstrinit(Fmt *f) { int n; memset(f, 0, sizeof *f); f->runes = 0; n = 32; f->start = malloc(n); if(f->start == nil) return -1; f->to = f->start; f->stop = (char*)f->start + n - 1; f->flush = fmtStrFlush; f->farg = (void*)(uintptr)n; f->nfmt = 0; return 0; } /* * print into an allocated string buffer */ char* vsmprint(char *fmt, va_list args) { Fmt f; int n; if(fmtstrinit(&f) < 0) return nil; VA_COPY(f.args,args); n = dofmt(&f, fmt); VA_END(f.args); if(n < 0){ free(f.start); return nil; } return fmtstrflush(&f); } drawterm-20110822.orig/libc/runestrcat.c0000644000175000017500000000017411245145712017344 0ustar tinchotincho#include #include Rune* runestrcat(Rune *s1, Rune *s2) { runestrcpy(runestrchr(s1, 0), s2); return s1; } drawterm-20110822.orig/libc/pushtls.c0000644000175000017500000000374711245145712016665 0ustar tinchotincho#include #include #include #include #include enum { TLSFinishedLen = 12, HFinished = 20, }; static int finished(int hand, int isclient) { int i, n; uchar buf[500], buf2[500]; buf[0] = HFinished; buf[1] = TLSFinishedLen>>16; buf[2] = TLSFinishedLen>>8; buf[3] = TLSFinishedLen; n = TLSFinishedLen+4; for(i=0; i<2; i++){ if(i==0) memmove(buf+4, "client finished", TLSFinishedLen); else memmove(buf+4, "server finished", TLSFinishedLen); if(isclient == 1-i){ if(write(hand, buf, n) != n) return -1; }else{ if(readn(hand, buf2, n) != n || memcmp(buf,buf2,n) != 0) return -1; } } return 1; } // given a plain fd and secrets established beforehand, return encrypted connection int pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *dir) { char buf[8]; char dname[64]; int n, data, ctl, hand; // open a new filter; get ctl fd data = hand = -1; // /net/tls uses decimal file descriptors to name channels, hence a // user-level file server can't stand in for #a; may as well hard-code it. ctl = open("#a/tls/clone", ORDWR); if(ctl < 0) goto error; n = read(ctl, buf, sizeof(buf)-1); if(n < 0) goto error; buf[n] = 0; if(dir) sprint(dir, "#a/tls/%s", buf); // get application fd sprint(dname, "#a/tls/%s/data", buf); data = open(dname, ORDWR); if(data < 0) goto error; // get handshake fd sprint(dname, "#a/tls/%s/hand", buf); hand = open(dname, ORDWR); if(hand < 0) goto error; // speak a minimal handshake if(fprint(ctl, "fd %d 0x301", fd) < 0 || fprint(ctl, "version 0x301") < 0 || fprint(ctl, "secret %s %s %d %s", hashalg, encalg, isclient, secret) < 0 || fprint(ctl, "changecipher") < 0 || finished(hand, isclient) < 0 || fprint(ctl, "opened") < 0){ close(hand); hand = -1; goto error; } close(ctl); close(hand); close(fd); return data; error: if(data>=0) close(data); if(ctl>=0) close(ctl); if(hand>=0) close(hand); return -1; } drawterm-20110822.orig/libc/getfields.c0000644000175000017500000000100411245145712017111 0ustar tinchotincho#include #include int getfields(char *str, char **args, int max, int mflag, char *set) { Rune r; int nr, intok, narg; if(max <= 0) return 0; narg = 0; args[narg] = str; if(!mflag) narg++; intok = 0; for(;; str += nr) { nr = chartorune(&r, str); if(r == 0) break; if(utfrune(set, r)) { if(narg >= max) break; *str = 0; intok = 0; args[narg] = str + nr; if(!mflag) narg++; } else { if(!intok && mflag) narg++; intok = 1; } } return narg; } drawterm-20110822.orig/libc/runestrecpy.c0000644000175000017500000000031211245145712017527 0ustar tinchotincho#include #include Rune* runestrecpy(Rune *s1, Rune *es1, Rune *s2) { if(s1 >= es1) return s1; while(*s1++ = *s2++){ if(s1 == es1){ *--s1 = '\0'; break; } } return s1; } drawterm-20110822.orig/libc/convD2M.c0000644000175000017500000000256611245145712016431 0ustar tinchotincho#include #include #include uint sizeD2M(Dir *d) { char *sv[4]; int i, ns; sv[0] = d->name; sv[1] = d->uid; sv[2] = d->gid; sv[3] = d->muid; ns = 0; for(i = 0; i < 4; i++) if(sv[i]) ns += strlen(sv[i]); return STATFIXLEN + ns; } uint convD2M(Dir *d, uchar *buf, uint nbuf) { uchar *p, *ebuf; char *sv[4]; int i, ns, nsv[4], ss; if(nbuf < BIT16SZ) return 0; p = buf; ebuf = buf + nbuf; sv[0] = d->name; sv[1] = d->uid; sv[2] = d->gid; sv[3] = d->muid; ns = 0; for(i = 0; i < 4; i++){ if(sv[i]) nsv[i] = strlen(sv[i]); else nsv[i] = 0; ns += nsv[i]; } ss = STATFIXLEN + ns; /* set size befor erroring, so user can know how much is needed */ /* note that length excludes count field itself */ PBIT16(p, ss-BIT16SZ); p += BIT16SZ; if(ss > nbuf) return BIT16SZ; PBIT16(p, d->type); p += BIT16SZ; PBIT32(p, d->dev); p += BIT32SZ; PBIT8(p, d->qid.type); p += BIT8SZ; PBIT32(p, d->qid.vers); p += BIT32SZ; PBIT64(p, d->qid.path); p += BIT64SZ; PBIT32(p, d->mode); p += BIT32SZ; PBIT32(p, d->atime); p += BIT32SZ; PBIT32(p, d->mtime); p += BIT32SZ; PBIT64(p, d->length); p += BIT64SZ; for(i = 0; i < 4; i++){ ns = nsv[i]; if(p + ns + BIT16SZ > ebuf) return 0; PBIT16(p, ns); p += BIT16SZ; if(ns) memmove(p, sv[i], ns); p += ns; } if(ss != p - buf) return 0; return p - buf; } drawterm-20110822.orig/libc/read9pmsg.c0000644000175000017500000000071611245145712017047 0ustar tinchotincho#include #include #include int read9pmsg(int fd, void *abuf, uint n) { int m, len; uchar *buf; buf = abuf; /* read count */ m = readn(fd, buf, BIT32SZ); if(m != BIT32SZ){ if(m < 0) return -1; return 0; } len = GBIT32(buf); if(len <= BIT32SZ || len > n){ werrstr("bad length in 9P2000 message header"); return -1; } len -= BIT32SZ; m = readn(fd, buf+BIT32SZ, len); if(m < len) return 0; return BIT32SZ+m; } drawterm-20110822.orig/libc/pow10.c0000644000175000017500000000225311245145712016120 0ustar tinchotincho#include #include #include "fmtdef.h" /* * this table might overflow 127-bit exponent representations. * in that case, truncate it after 1.0e38. * it is important to get all one can from this * routine since it is used in atof to scale numbers. * the presumption is that C converts fp numbers better * than multipication of lower powers of 10. */ static double tab[] = { 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,1.0e11,1.0e12,1.0e13,1.0e14,1.0e15,1.0e16,1.0e17,1.0e18,1.0e19, 1.0e20,1.0e21,1.0e22,1.0e23,1.0e24,1.0e25,1.0e26,1.0e27,1.0e28,1.0e29, 1.0e30,1.0e31,1.0e32,1.0e33,1.0e34,1.0e35,1.0e36,1.0e37,1.0e38,1.0e39, 1.0e40,1.0e41,1.0e42,1.0e43,1.0e44,1.0e45,1.0e46,1.0e47,1.0e48,1.0e49, 1.0e50,1.0e51,1.0e52,1.0e53,1.0e54,1.0e55,1.0e56,1.0e57,1.0e58,1.0e59, 1.0e60,1.0e61,1.0e62,1.0e63,1.0e64,1.0e65,1.0e66,1.0e67,1.0e68,1.0e69, }; double __fmtpow10(int n) { int m; if(n < 0) { n = -n; if(n < (int)(sizeof(tab)/sizeof(tab[0]))) return 1/tab[n]; m = n/2; return __fmtpow10(-m) * __fmtpow10(m-n); } if(n < (int)(sizeof(tab)/sizeof(tab[0]))) return tab[n]; m = n/2; return __fmtpow10(m) * __fmtpow10(n-m); } drawterm-20110822.orig/libc/frand.c0000644000175000017500000000032211245145712016237 0ustar tinchotincho#include #include #define MASK 0x7fffffffL #define NORM (1.0/(1.0+MASK)) double frand(void) { double x; do { x = lrand() * NORM; x = (x + lrand()) * NORM; } while(x >= 1); return x; } drawterm-20110822.orig/libc/utfrrune.c0000644000175000017500000000063611245145712017027 0ustar tinchotincho#include #include char* utfrrune(char *s, long c) { long c1; Rune r; char *s1; if(c < Runesync) /* not part of utf sequence */ return strrchr(s, c); s1 = 0; for(;;) { c1 = *(uchar*)s; if(c1 < Runeself) { /* one byte rune */ if(c1 == 0) return s1; if(c1 == c) s1 = s; s++; continue; } c1 = chartorune(&r, s); if(r == c) s1 = s; s += c1; } return 0; } drawterm-20110822.orig/libc/lock.c0000644000175000017500000000307411245145712016104 0ustar tinchotincho#include #include #ifdef PTHREAD static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; static void lockinit(Lock *lk) { pthread_mutexattr_t attr; pthread_mutex_lock(&initmutex); if(lk->init == 0){ pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); pthread_mutex_init(&lk->mutex, &attr); pthread_mutexattr_destroy(&attr); lk->init = 1; } pthread_mutex_unlock(&initmutex); } void lock(Lock *lk) { if(!lk->init) lockinit(lk); if(pthread_mutex_lock(&lk->mutex) != 0) abort(); } int canlock(Lock *lk) { int r; if(!lk->init) lockinit(lk); r = pthread_mutex_trylock(&lk->mutex); if(r == 0) return 1; if(r == EBUSY) return 0; abort(); } void unlock(Lock *lk) { if(pthread_mutex_unlock(&lk->mutex) != 0) abort(); } #else /* old, non-pthread systems */ int canlock(Lock *lk) { return !tas(&lk->key); } void lock(Lock *lk) { int i; /* easy case */ if(canlock(lk)) return; /* for multi processor machines */ for(i=0; i<100; i++) if(canlock(lk)) return; for(i=0; i<100; i++) { osyield(); if(canlock(lk)) return; } /* looking bad - make sure it is not a priority problem */ for(i=0; i<12; i++) { osmsleep(1<key, lk, getcallerpc(&lk)); osmsleep(1000); } } void unlock(Lock *lk) { assert(lk->key); lk->key = 0; } #endif void ilock(Lock *lk) { lock(lk); } void iunlock(Lock *lk) { unlock(lk); } drawterm-20110822.orig/libc/rand.c0000644000175000017500000000011711245145712016073 0ustar tinchotincho#include #include int rand(void) { return lrand() & 0x7fff; } drawterm-20110822.orig/libc/readn.c0000644000175000017500000000035211245145712016241 0ustar tinchotincho#include #include long readn(int f, void *av, long n) { char *a; long m, t; a = av; t = 0; while(t < n){ m = read(f, a+t, n-t); if(m <= 0){ if(t == 0) return m; break; } t += m; } return t; } drawterm-20110822.orig/libc/dirfwstat.c0000644000175000017500000000036211245145712017160 0ustar tinchotincho#include #include #include int dirfwstat(int fd, Dir *d) { uchar *buf; int r; r = sizeD2M(d); buf = malloc(r); if(buf == nil) return -1; convD2M(d, buf, r); r = fwstat(fd, buf, r); free(buf); return r; } drawterm-20110822.orig/libc/crypt.c0000644000175000017500000000202511245145712016310 0ustar tinchotincho/* * Data Encryption Standard * D.P.Mitchell 83/06/08. * * block_cipher(key, block, decrypting) * * these routines use the non-standard 7 byte format * for DES keys. */ #include #include #include #include /* * destructively encrypt the buffer, which * must be at least 8 characters long. */ int encrypt(void *key, void *vbuf, int n) { ulong ekey[32]; uchar *buf; int i, r; if(n < 8) return 0; key_setup(key, ekey); buf = vbuf; n--; r = n % 7; n /= 7; for(i = 0; i < n; i++){ block_cipher(ekey, buf, 0); buf += 7; } if(r) block_cipher(ekey, buf - 7 + r, 0); return 1; } /* * destructively decrypt the buffer, which * must be at least 8 characters long. */ int decrypt(void *key, void *vbuf, int n) { ulong ekey[128]; uchar *buf; int i, r; if(n < 8) return 0; key_setup(key, ekey); buf = vbuf; n--; r = n % 7; n /= 7; buf += n * 7; if(r) block_cipher(ekey, buf - 7 + r, 1); for(i = 0; i < n; i++){ buf -= 7; block_cipher(ekey, buf, 1); } return 1; } drawterm-20110822.orig/libc/dirfstat.c0000644000175000017500000000124411245145712016771 0ustar tinchotincho#include #include #include enum { DIRSIZE = STATFIXLEN + 16 * 4 /* enough for encoded stat buf + some reasonable strings */ }; Dir* dirfstat(int fd) { Dir *d; uchar *buf; int n, nd, i; nd = DIRSIZE; for(i=0; i<2; i++){ /* should work by the second try */ d = malloc(sizeof(Dir) + BIT16SZ + nd); if(d == nil) return nil; buf = (uchar*)&d[1]; n = fstat(fd, buf, BIT16SZ+nd); if(n < BIT16SZ){ free(d); return nil; } nd = GBIT16(buf); /* upper bound on size of Dir + strings */ if(nd <= n){ convM2D(buf, n, d, (char*)&d[1]); return d; } /* else sizeof(Dir)+BIT16SZ+nd is plenty */ free(d); } return nil; } drawterm-20110822.orig/libc/mallocz.c0000644000175000017500000000021511245145712016607 0ustar tinchotincho#include #include void* mallocz(ulong n, int clr) { void *v; v = malloc(n); if(v && clr) memset(v, 0, n); return v; } drawterm-20110822.orig/libc/netmkaddr.c0000644000175000017500000000153711245145712017127 0ustar tinchotincho#include #include #include /* * make an address, add the defaults */ char * netmkaddr(char *linear, char *defnet, char *defsrv) { static char addr[256]; char *cp; /* * dump network name */ cp = strchr(linear, '!'); if(cp == 0){ if(defnet==0){ if(defsrv) snprint(addr, sizeof(addr), "net!%s!%s", linear, defsrv); else snprint(addr, sizeof(addr), "net!%s", linear); } else { if(defsrv) snprint(addr, sizeof(addr), "%s!%s!%s", defnet, linear, defsrv); else snprint(addr, sizeof(addr), "%s!%s", defnet, linear); } return addr; } /* * if there is already a service, use it */ cp = strchr(cp+1, '!'); if(cp) return linear; /* * add default service */ if(defsrv == 0) return linear; snprint(addr, sizeof(addr), "%s!%s", linear, defsrv); return addr; } drawterm-20110822.orig/libc/runetype.c0000644000175000017500000007172711245145712017041 0ustar tinchotincho#include #include /* * alpha ranges - * only covers ranges not in lower||upper */ static Rune _alpha2[] = { 0x00d8, 0x00f6, /* Ø - ö */ 0x00f8, 0x01f5, /* ø - ǵ */ 0x0250, 0x02a8, /* ɐ - ʨ */ 0x038e, 0x03a1, /* Ύ - Ρ */ 0x03a3, 0x03ce, /* Σ - ώ */ 0x03d0, 0x03d6, /* ϐ - ϖ */ 0x03e2, 0x03f3, /* Ϣ - ϳ */ 0x0490, 0x04c4, /* Ґ - ӄ */ 0x0561, 0x0587, /* ա - և */ 0x05d0, 0x05ea, /* א - ת */ 0x05f0, 0x05f2, /* װ - ײ */ 0x0621, 0x063a, /* ء - غ */ 0x0640, 0x064a, /* ـ - ي */ 0x0671, 0x06b7, /* ٱ - ڷ */ 0x06ba, 0x06be, /* ں - ھ */ 0x06c0, 0x06ce, /* ۀ - ێ */ 0x06d0, 0x06d3, /* ې - ۓ */ 0x0905, 0x0939, /* अ - ह */ 0x0958, 0x0961, /* क़ - ॡ */ 0x0985, 0x098c, /* অ - ঌ */ 0x098f, 0x0990, /* এ - ঐ */ 0x0993, 0x09a8, /* ও - ন */ 0x09aa, 0x09b0, /* প - র */ 0x09b6, 0x09b9, /* শ - হ */ 0x09dc, 0x09dd, /* ড় - ঢ় */ 0x09df, 0x09e1, /* য় - ৡ */ 0x09f0, 0x09f1, /* ৰ - ৱ */ 0x0a05, 0x0a0a, /* ਅ - ਊ */ 0x0a0f, 0x0a10, /* ਏ - ਐ */ 0x0a13, 0x0a28, /* ਓ - ਨ */ 0x0a2a, 0x0a30, /* ਪ - ਰ */ 0x0a32, 0x0a33, /* ਲ - ਲ਼ */ 0x0a35, 0x0a36, /* ਵ - ਸ਼ */ 0x0a38, 0x0a39, /* ਸ - ਹ */ 0x0a59, 0x0a5c, /* ਖ਼ - ੜ */ 0x0a85, 0x0a8b, /* અ - ઋ */ 0x0a8f, 0x0a91, /* એ - ઑ */ 0x0a93, 0x0aa8, /* ઓ - ન */ 0x0aaa, 0x0ab0, /* પ - ર */ 0x0ab2, 0x0ab3, /* લ - ળ */ 0x0ab5, 0x0ab9, /* વ - હ */ 0x0b05, 0x0b0c, /* ଅ - ଌ */ 0x0b0f, 0x0b10, /* ଏ - ଐ */ 0x0b13, 0x0b28, /* ଓ - ନ */ 0x0b2a, 0x0b30, /* ପ - ର */ 0x0b32, 0x0b33, /* ଲ - ଳ */ 0x0b36, 0x0b39, /* ଶ - ହ */ 0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */ 0x0b5f, 0x0b61, /* ୟ - ୡ */ 0x0b85, 0x0b8a, /* அ - ஊ */ 0x0b8e, 0x0b90, /* எ - ஐ */ 0x0b92, 0x0b95, /* ஒ - க */ 0x0b99, 0x0b9a, /* ங - ச */ 0x0b9e, 0x0b9f, /* ஞ - ட */ 0x0ba3, 0x0ba4, /* ண - த */ 0x0ba8, 0x0baa, /* ந - ப */ 0x0bae, 0x0bb5, /* ம - வ */ 0x0bb7, 0x0bb9, /* ஷ - ஹ */ 0x0c05, 0x0c0c, /* అ - ఌ */ 0x0c0e, 0x0c10, /* ఎ - ఐ */ 0x0c12, 0x0c28, /* ఒ - న */ 0x0c2a, 0x0c33, /* ప - ళ */ 0x0c35, 0x0c39, /* వ - హ */ 0x0c60, 0x0c61, /* ౠ - ౡ */ 0x0c85, 0x0c8c, /* ಅ - ಌ */ 0x0c8e, 0x0c90, /* ಎ - ಐ */ 0x0c92, 0x0ca8, /* ಒ - ನ */ 0x0caa, 0x0cb3, /* ಪ - ಳ */ 0x0cb5, 0x0cb9, /* ವ - ಹ */ 0x0ce0, 0x0ce1, /* ೠ - ೡ */ 0x0d05, 0x0d0c, /* അ - ഌ */ 0x0d0e, 0x0d10, /* എ - ഐ */ 0x0d12, 0x0d28, /* ഒ - ന */ 0x0d2a, 0x0d39, /* പ - ഹ */ 0x0d60, 0x0d61, /* ൠ - ൡ */ 0x0e01, 0x0e30, /* ก - ะ */ 0x0e32, 0x0e33, /* า - ำ */ 0x0e40, 0x0e46, /* เ - ๆ */ 0x0e5a, 0x0e5b, /* ๚ - ๛ */ 0x0e81, 0x0e82, /* ກ - ຂ */ 0x0e87, 0x0e88, /* ງ - ຈ */ 0x0e94, 0x0e97, /* ດ - ທ */ 0x0e99, 0x0e9f, /* ນ - ຟ */ 0x0ea1, 0x0ea3, /* ມ - ຣ */ 0x0eaa, 0x0eab, /* ສ - ຫ */ 0x0ead, 0x0eae, /* ອ - ຮ */ 0x0eb2, 0x0eb3, /* າ - ຳ */ 0x0ec0, 0x0ec4, /* ເ - ໄ */ 0x0edc, 0x0edd, /* ໜ - ໝ */ 0x0f18, 0x0f19, /* ༘ - ༙ */ 0x0f40, 0x0f47, /* ཀ - ཇ */ 0x0f49, 0x0f69, /* ཉ - ཀྵ */ 0x10d0, 0x10f6, /* ა - ჶ */ 0x1100, 0x1159, /* ᄀ - ᅙ */ 0x115f, 0x11a2, /* ᅟ - ᆢ */ 0x11a8, 0x11f9, /* ᆨ - ᇹ */ 0x1e00, 0x1e9b, /* Ḁ - ẛ */ 0x1f50, 0x1f57, /* ὐ - ὗ */ 0x1f80, 0x1fb4, /* ᾀ - ᾴ */ 0x1fb6, 0x1fbc, /* ᾶ - ᾼ */ 0x1fc2, 0x1fc4, /* ῂ - ῄ */ 0x1fc6, 0x1fcc, /* ῆ - ῌ */ 0x1fd0, 0x1fd3, /* ῐ - ΐ */ 0x1fd6, 0x1fdb, /* ῖ - Ί */ 0x1fe0, 0x1fec, /* ῠ - Ῥ */ 0x1ff2, 0x1ff4, /* ῲ - ῴ */ 0x1ff6, 0x1ffc, /* ῶ - ῼ */ 0x210a, 0x2113, /* ℊ - ℓ */ 0x2115, 0x211d, /* ℕ - ℝ */ 0x2120, 0x2122, /* ℠ - ™ */ 0x212a, 0x2131, /* K - ℱ */ 0x2133, 0x2138, /* ℳ - ℸ */ 0x3041, 0x3094, /* ぁ - ゔ */ 0x30a1, 0x30fa, /* ァ - ヺ */ 0x3105, 0x312c, /* ㄅ - ㄬ */ 0x3131, 0x318e, /* ㄱ - ㆎ */ 0x3192, 0x319f, /* ㆒ - ㆟ */ 0x3260, 0x327b, /* ㉠ - ㉻ */ 0x328a, 0x32b0, /* ㊊ - ㊰ */ 0x32d0, 0x32fe, /* ㋐ - ㋾ */ 0x3300, 0x3357, /* ㌀ - ㍗ */ 0x3371, 0x3376, /* ㍱ - ㍶ */ 0x337b, 0x3394, /* ㍻ - ㎔ */ 0x3399, 0x339e, /* ㎙ - ㎞ */ 0x33a9, 0x33ad, /* ㎩ - ㎭ */ 0x33b0, 0x33c1, /* ㎰ - ㏁ */ 0x33c3, 0x33c5, /* ㏃ - ㏅ */ 0x33c7, 0x33d7, /* ㏇ - ㏗ */ 0x33d9, 0x33dd, /* ㏙ - ㏝ */ 0x4e00, 0x9fff, /* 一 - 鿿 */ 0xac00, 0xd7a3, /* 가 - 힣 */ 0xf900, 0xfb06, /* 豈 - st */ 0xfb13, 0xfb17, /* ﬓ - ﬗ */ 0xfb1f, 0xfb28, /* ײַ - ﬨ */ 0xfb2a, 0xfb36, /* שׁ - זּ */ 0xfb38, 0xfb3c, /* טּ - לּ */ 0xfb40, 0xfb41, /* נּ - סּ */ 0xfb43, 0xfb44, /* ףּ - פּ */ 0xfb46, 0xfbb1, /* צּ - ﮱ */ 0xfbd3, 0xfd3d, /* ﯓ - ﴽ */ 0xfd50, 0xfd8f, /* ﵐ - ﶏ */ 0xfd92, 0xfdc7, /* ﶒ - ﷇ */ 0xfdf0, 0xfdf9, /* ﷰ - ﷹ */ 0xfe70, 0xfe72, /* ﹰ - ﹲ */ 0xfe76, 0xfefc, /* ﹶ - ﻼ */ 0xff66, 0xff6f, /* ヲ - ッ */ 0xff71, 0xff9d, /* ア - ン */ 0xffa0, 0xffbe, /* ᅠ - ᄒ */ 0xffc2, 0xffc7, /* ᅡ - ᅦ */ 0xffca, 0xffcf, /* ᅧ - ᅬ */ 0xffd2, 0xffd7, /* ᅭ - ᅲ */ 0xffda, 0xffdc, /* ᅳ - ᅵ */ }; /* * alpha singlets - * only covers ranges not in lower||upper */ static Rune _alpha1[] = { 0x00aa, /* ª */ 0x00b5, /* µ */ 0x00ba, /* º */ 0x03da, /* Ϛ */ 0x03dc, /* Ϝ */ 0x03de, /* Ϟ */ 0x03e0, /* Ϡ */ 0x06d5, /* ە */ 0x09b2, /* ল */ 0x0a5e, /* ਫ਼ */ 0x0a8d, /* ઍ */ 0x0ae0, /* ૠ */ 0x0b9c, /* ஜ */ 0x0cde, /* ೞ */ 0x0e4f, /* ๏ */ 0x0e84, /* ຄ */ 0x0e8a, /* ຊ */ 0x0e8d, /* ຍ */ 0x0ea5, /* ລ */ 0x0ea7, /* ວ */ 0x0eb0, /* ະ */ 0x0ebd, /* ຽ */ 0x1fbe, /* ι */ 0x207f, /* ⁿ */ 0x20a8, /* ₨ */ 0x2102, /* ℂ */ 0x2107, /* ℇ */ 0x2124, /* ℤ */ 0x2126, /* Ω */ 0x2128, /* ℨ */ 0xfb3e, /* מּ */ 0xfe74, /* ﹴ */ }; /* * space ranges */ static Rune _space2[] = { 0x0009, 0x000a, /* tab and newline */ 0x0020, 0x0020, /* space */ 0x00a0, 0x00a0, /*   */ 0x2000, 0x200b, /*   - ​ */ 0x2028, 0x2029, /* 
 - 
 */ 0x3000, 0x3000, /*   */ 0xfeff, 0xfeff, /*  */ }; /* * lower case ranges * 3rd col is conversion excess 500 */ static Rune _toupper2[] = { 0x0061, 0x007a, 468, /* a-z A-Z */ 0x00e0, 0x00f6, 468, /* à-ö À-Ö */ 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */ 0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */ 0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */ 0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */ 0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */ 0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */ 0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */ 0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */ 0x0430, 0x044f, 468, /* а-я А-Я */ 0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */ 0x045e, 0x045f, 420, /* ў-џ Ў-Џ */ 0x0561, 0x0586, 452, /* ա-ֆ Ա-Ֆ */ 0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */ 0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */ 0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */ 0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */ 0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */ 0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */ 0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */ 0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */ 0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */ 0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */ 0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */ 0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */ 0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */ 0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */ 0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */ 0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */ 0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */ 0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */ 0x2170, 0x217f, 484, /* ⅰ-ⅿ Ⅰ-Ⅿ */ 0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */ 0xff41, 0xff5a, 468, /* a-z A-Z */ }; /* * lower case singlets * 2nd col is conversion excess 500 */ static Rune _toupper1[] = { 0x00ff, 621, /* ÿ Ÿ */ 0x0101, 499, /* ā Ā */ 0x0103, 499, /* ă Ă */ 0x0105, 499, /* ą Ą */ 0x0107, 499, /* ć Ć */ 0x0109, 499, /* ĉ Ĉ */ 0x010b, 499, /* ċ Ċ */ 0x010d, 499, /* č Č */ 0x010f, 499, /* ď Ď */ 0x0111, 499, /* đ Đ */ 0x0113, 499, /* ē Ē */ 0x0115, 499, /* ĕ Ĕ */ 0x0117, 499, /* ė Ė */ 0x0119, 499, /* ę Ę */ 0x011b, 499, /* ě Ě */ 0x011d, 499, /* ĝ Ĝ */ 0x011f, 499, /* ğ Ğ */ 0x0121, 499, /* ġ Ġ */ 0x0123, 499, /* ģ Ģ */ 0x0125, 499, /* ĥ Ĥ */ 0x0127, 499, /* ħ Ħ */ 0x0129, 499, /* ĩ Ĩ */ 0x012b, 499, /* ī Ī */ 0x012d, 499, /* ĭ Ĭ */ 0x012f, 499, /* į Į */ 0x0131, 268, /* ı I */ 0x0133, 499, /* ij IJ */ 0x0135, 499, /* ĵ Ĵ */ 0x0137, 499, /* ķ Ķ */ 0x013a, 499, /* ĺ Ĺ */ 0x013c, 499, /* ļ Ļ */ 0x013e, 499, /* ľ Ľ */ 0x0140, 499, /* ŀ Ŀ */ 0x0142, 499, /* ł Ł */ 0x0144, 499, /* ń Ń */ 0x0146, 499, /* ņ Ņ */ 0x0148, 499, /* ň Ň */ 0x014b, 499, /* ŋ Ŋ */ 0x014d, 499, /* ō Ō */ 0x014f, 499, /* ŏ Ŏ */ 0x0151, 499, /* ő Ő */ 0x0153, 499, /* œ Œ */ 0x0155, 499, /* ŕ Ŕ */ 0x0157, 499, /* ŗ Ŗ */ 0x0159, 499, /* ř Ř */ 0x015b, 499, /* ś Ś */ 0x015d, 499, /* ŝ Ŝ */ 0x015f, 499, /* ş Ş */ 0x0161, 499, /* š Š */ 0x0163, 499, /* ţ Ţ */ 0x0165, 499, /* ť Ť */ 0x0167, 499, /* ŧ Ŧ */ 0x0169, 499, /* ũ Ũ */ 0x016b, 499, /* ū Ū */ 0x016d, 499, /* ŭ Ŭ */ 0x016f, 499, /* ů Ů */ 0x0171, 499, /* ű Ű */ 0x0173, 499, /* ų Ų */ 0x0175, 499, /* ŵ Ŵ */ 0x0177, 499, /* ŷ Ŷ */ 0x017a, 499, /* ź Ź */ 0x017c, 499, /* ż Ż */ 0x017e, 499, /* ž Ž */ 0x017f, 200, /* ſ S */ 0x0183, 499, /* ƃ Ƃ */ 0x0185, 499, /* ƅ Ƅ */ 0x0188, 499, /* ƈ Ƈ */ 0x018c, 499, /* ƌ Ƌ */ 0x0192, 499, /* ƒ Ƒ */ 0x0199, 499, /* ƙ Ƙ */ 0x01a1, 499, /* ơ Ơ */ 0x01a3, 499, /* ƣ Ƣ */ 0x01a5, 499, /* ƥ Ƥ */ 0x01a8, 499, /* ƨ Ƨ */ 0x01ad, 499, /* ƭ Ƭ */ 0x01b0, 499, /* ư Ư */ 0x01b4, 499, /* ƴ Ƴ */ 0x01b6, 499, /* ƶ Ƶ */ 0x01b9, 499, /* ƹ Ƹ */ 0x01bd, 499, /* ƽ Ƽ */ 0x01c5, 499, /* Dž DŽ */ 0x01c6, 498, /* dž DŽ */ 0x01c8, 499, /* Lj LJ */ 0x01c9, 498, /* lj LJ */ 0x01cb, 499, /* Nj NJ */ 0x01cc, 498, /* nj NJ */ 0x01ce, 499, /* ǎ Ǎ */ 0x01d0, 499, /* ǐ Ǐ */ 0x01d2, 499, /* ǒ Ǒ */ 0x01d4, 499, /* ǔ Ǔ */ 0x01d6, 499, /* ǖ Ǖ */ 0x01d8, 499, /* ǘ Ǘ */ 0x01da, 499, /* ǚ Ǚ */ 0x01dc, 499, /* ǜ Ǜ */ 0x01df, 499, /* ǟ Ǟ */ 0x01e1, 499, /* ǡ Ǡ */ 0x01e3, 499, /* ǣ Ǣ */ 0x01e5, 499, /* ǥ Ǥ */ 0x01e7, 499, /* ǧ Ǧ */ 0x01e9, 499, /* ǩ Ǩ */ 0x01eb, 499, /* ǫ Ǫ */ 0x01ed, 499, /* ǭ Ǭ */ 0x01ef, 499, /* ǯ Ǯ */ 0x01f2, 499, /* Dz DZ */ 0x01f3, 498, /* dz DZ */ 0x01f5, 499, /* ǵ Ǵ */ 0x01fb, 499, /* ǻ Ǻ */ 0x01fd, 499, /* ǽ Ǽ */ 0x01ff, 499, /* ǿ Ǿ */ 0x0201, 499, /* ȁ Ȁ */ 0x0203, 499, /* ȃ Ȃ */ 0x0205, 499, /* ȅ Ȅ */ 0x0207, 499, /* ȇ Ȇ */ 0x0209, 499, /* ȉ Ȉ */ 0x020b, 499, /* ȋ Ȋ */ 0x020d, 499, /* ȍ Ȍ */ 0x020f, 499, /* ȏ Ȏ */ 0x0211, 499, /* ȑ Ȑ */ 0x0213, 499, /* ȓ Ȓ */ 0x0215, 499, /* ȕ Ȕ */ 0x0217, 499, /* ȗ Ȗ */ 0x0253, 290, /* ɓ Ɓ */ 0x0254, 294, /* ɔ Ɔ */ 0x025b, 297, /* ɛ Ɛ */ 0x0260, 295, /* ɠ Ɠ */ 0x0263, 293, /* ɣ Ɣ */ 0x0268, 291, /* ɨ Ɨ */ 0x0269, 289, /* ɩ Ɩ */ 0x026f, 289, /* ɯ Ɯ */ 0x0272, 287, /* ɲ Ɲ */ 0x0283, 282, /* ʃ Ʃ */ 0x0288, 282, /* ʈ Ʈ */ 0x0292, 281, /* ʒ Ʒ */ 0x03ac, 462, /* ά Ά */ 0x03cc, 436, /* ό Ό */ 0x03d0, 438, /* ϐ Β */ 0x03d1, 443, /* ϑ Θ */ 0x03d5, 453, /* ϕ Φ */ 0x03d6, 446, /* ϖ Π */ 0x03e3, 499, /* ϣ Ϣ */ 0x03e5, 499, /* ϥ Ϥ */ 0x03e7, 499, /* ϧ Ϧ */ 0x03e9, 499, /* ϩ Ϩ */ 0x03eb, 499, /* ϫ Ϫ */ 0x03ed, 499, /* ϭ Ϭ */ 0x03ef, 499, /* ϯ Ϯ */ 0x03f0, 414, /* ϰ Κ */ 0x03f1, 420, /* ϱ Ρ */ 0x0461, 499, /* ѡ Ѡ */ 0x0463, 499, /* ѣ Ѣ */ 0x0465, 499, /* ѥ Ѥ */ 0x0467, 499, /* ѧ Ѧ */ 0x0469, 499, /* ѩ Ѩ */ 0x046b, 499, /* ѫ Ѫ */ 0x046d, 499, /* ѭ Ѭ */ 0x046f, 499, /* ѯ Ѯ */ 0x0471, 499, /* ѱ Ѱ */ 0x0473, 499, /* ѳ Ѳ */ 0x0475, 499, /* ѵ Ѵ */ 0x0477, 499, /* ѷ Ѷ */ 0x0479, 499, /* ѹ Ѹ */ 0x047b, 499, /* ѻ Ѻ */ 0x047d, 499, /* ѽ Ѽ */ 0x047f, 499, /* ѿ Ѿ */ 0x0481, 499, /* ҁ Ҁ */ 0x0491, 499, /* ґ Ґ */ 0x0493, 499, /* ғ Ғ */ 0x0495, 499, /* ҕ Ҕ */ 0x0497, 499, /* җ Җ */ 0x0499, 499, /* ҙ Ҙ */ 0x049b, 499, /* қ Қ */ 0x049d, 499, /* ҝ Ҝ */ 0x049f, 499, /* ҟ Ҟ */ 0x04a1, 499, /* ҡ Ҡ */ 0x04a3, 499, /* ң Ң */ 0x04a5, 499, /* ҥ Ҥ */ 0x04a7, 499, /* ҧ Ҧ */ 0x04a9, 499, /* ҩ Ҩ */ 0x04ab, 499, /* ҫ Ҫ */ 0x04ad, 499, /* ҭ Ҭ */ 0x04af, 499, /* ү Ү */ 0x04b1, 499, /* ұ Ұ */ 0x04b3, 499, /* ҳ Ҳ */ 0x04b5, 499, /* ҵ Ҵ */ 0x04b7, 499, /* ҷ Ҷ */ 0x04b9, 499, /* ҹ Ҹ */ 0x04bb, 499, /* һ Һ */ 0x04bd, 499, /* ҽ Ҽ */ 0x04bf, 499, /* ҿ Ҿ */ 0x04c2, 499, /* ӂ Ӂ */ 0x04c4, 499, /* ӄ Ӄ */ 0x04c8, 499, /* ӈ Ӈ */ 0x04cc, 499, /* ӌ Ӌ */ 0x04d1, 499, /* ӑ Ӑ */ 0x04d3, 499, /* ӓ Ӓ */ 0x04d5, 499, /* ӕ Ӕ */ 0x04d7, 499, /* ӗ Ӗ */ 0x04d9, 499, /* ә Ә */ 0x04db, 499, /* ӛ Ӛ */ 0x04dd, 499, /* ӝ Ӝ */ 0x04df, 499, /* ӟ Ӟ */ 0x04e1, 499, /* ӡ Ӡ */ 0x04e3, 499, /* ӣ Ӣ */ 0x04e5, 499, /* ӥ Ӥ */ 0x04e7, 499, /* ӧ Ӧ */ 0x04e9, 499, /* ө Ө */ 0x04eb, 499, /* ӫ Ӫ */ 0x04ef, 499, /* ӯ Ӯ */ 0x04f1, 499, /* ӱ Ӱ */ 0x04f3, 499, /* ӳ Ӳ */ 0x04f5, 499, /* ӵ Ӵ */ 0x04f9, 499, /* ӹ Ӹ */ 0x1e01, 499, /* ḁ Ḁ */ 0x1e03, 499, /* ḃ Ḃ */ 0x1e05, 499, /* ḅ Ḅ */ 0x1e07, 499, /* ḇ Ḇ */ 0x1e09, 499, /* ḉ Ḉ */ 0x1e0b, 499, /* ḋ Ḋ */ 0x1e0d, 499, /* ḍ Ḍ */ 0x1e0f, 499, /* ḏ Ḏ */ 0x1e11, 499, /* ḑ Ḑ */ 0x1e13, 499, /* ḓ Ḓ */ 0x1e15, 499, /* ḕ Ḕ */ 0x1e17, 499, /* ḗ Ḗ */ 0x1e19, 499, /* ḙ Ḙ */ 0x1e1b, 499, /* ḛ Ḛ */ 0x1e1d, 499, /* ḝ Ḝ */ 0x1e1f, 499, /* ḟ Ḟ */ 0x1e21, 499, /* ḡ Ḡ */ 0x1e23, 499, /* ḣ Ḣ */ 0x1e25, 499, /* ḥ Ḥ */ 0x1e27, 499, /* ḧ Ḧ */ 0x1e29, 499, /* ḩ Ḩ */ 0x1e2b, 499, /* ḫ Ḫ */ 0x1e2d, 499, /* ḭ Ḭ */ 0x1e2f, 499, /* ḯ Ḯ */ 0x1e31, 499, /* ḱ Ḱ */ 0x1e33, 499, /* ḳ Ḳ */ 0x1e35, 499, /* ḵ Ḵ */ 0x1e37, 499, /* ḷ Ḷ */ 0x1e39, 499, /* ḹ Ḹ */ 0x1e3b, 499, /* ḻ Ḻ */ 0x1e3d, 499, /* ḽ Ḽ */ 0x1e3f, 499, /* ḿ Ḿ */ 0x1e41, 499, /* ṁ Ṁ */ 0x1e43, 499, /* ṃ Ṃ */ 0x1e45, 499, /* ṅ Ṅ */ 0x1e47, 499, /* ṇ Ṇ */ 0x1e49, 499, /* ṉ Ṉ */ 0x1e4b, 499, /* ṋ Ṋ */ 0x1e4d, 499, /* ṍ Ṍ */ 0x1e4f, 499, /* ṏ Ṏ */ 0x1e51, 499, /* ṑ Ṑ */ 0x1e53, 499, /* ṓ Ṓ */ 0x1e55, 499, /* ṕ Ṕ */ 0x1e57, 499, /* ṗ Ṗ */ 0x1e59, 499, /* ṙ Ṙ */ 0x1e5b, 499, /* ṛ Ṛ */ 0x1e5d, 499, /* ṝ Ṝ */ 0x1e5f, 499, /* ṟ Ṟ */ 0x1e61, 499, /* ṡ Ṡ */ 0x1e63, 499, /* ṣ Ṣ */ 0x1e65, 499, /* ṥ Ṥ */ 0x1e67, 499, /* ṧ Ṧ */ 0x1e69, 499, /* ṩ Ṩ */ 0x1e6b, 499, /* ṫ Ṫ */ 0x1e6d, 499, /* ṭ Ṭ */ 0x1e6f, 499, /* ṯ Ṯ */ 0x1e71, 499, /* ṱ Ṱ */ 0x1e73, 499, /* ṳ Ṳ */ 0x1e75, 499, /* ṵ Ṵ */ 0x1e77, 499, /* ṷ Ṷ */ 0x1e79, 499, /* ṹ Ṹ */ 0x1e7b, 499, /* ṻ Ṻ */ 0x1e7d, 499, /* ṽ Ṽ */ 0x1e7f, 499, /* ṿ Ṿ */ 0x1e81, 499, /* ẁ Ẁ */ 0x1e83, 499, /* ẃ Ẃ */ 0x1e85, 499, /* ẅ Ẅ */ 0x1e87, 499, /* ẇ Ẇ */ 0x1e89, 499, /* ẉ Ẉ */ 0x1e8b, 499, /* ẋ Ẋ */ 0x1e8d, 499, /* ẍ Ẍ */ 0x1e8f, 499, /* ẏ Ẏ */ 0x1e91, 499, /* ẑ Ẑ */ 0x1e93, 499, /* ẓ Ẓ */ 0x1e95, 499, /* ẕ Ẕ */ 0x1ea1, 499, /* ạ Ạ */ 0x1ea3, 499, /* ả Ả */ 0x1ea5, 499, /* ấ Ấ */ 0x1ea7, 499, /* ầ Ầ */ 0x1ea9, 499, /* ẩ Ẩ */ 0x1eab, 499, /* ẫ Ẫ */ 0x1ead, 499, /* ậ Ậ */ 0x1eaf, 499, /* ắ Ắ */ 0x1eb1, 499, /* ằ Ằ */ 0x1eb3, 499, /* ẳ Ẳ */ 0x1eb5, 499, /* ẵ Ẵ */ 0x1eb7, 499, /* ặ Ặ */ 0x1eb9, 499, /* ẹ Ẹ */ 0x1ebb, 499, /* ẻ Ẻ */ 0x1ebd, 499, /* ẽ Ẽ */ 0x1ebf, 499, /* ế Ế */ 0x1ec1, 499, /* ề Ề */ 0x1ec3, 499, /* ể Ể */ 0x1ec5, 499, /* ễ Ễ */ 0x1ec7, 499, /* ệ Ệ */ 0x1ec9, 499, /* ỉ Ỉ */ 0x1ecb, 499, /* ị Ị */ 0x1ecd, 499, /* ọ Ọ */ 0x1ecf, 499, /* ỏ Ỏ */ 0x1ed1, 499, /* ố Ố */ 0x1ed3, 499, /* ồ Ồ */ 0x1ed5, 499, /* ổ Ổ */ 0x1ed7, 499, /* ỗ Ỗ */ 0x1ed9, 499, /* ộ Ộ */ 0x1edb, 499, /* ớ Ớ */ 0x1edd, 499, /* ờ Ờ */ 0x1edf, 499, /* ở Ở */ 0x1ee1, 499, /* ỡ Ỡ */ 0x1ee3, 499, /* ợ Ợ */ 0x1ee5, 499, /* ụ Ụ */ 0x1ee7, 499, /* ủ Ủ */ 0x1ee9, 499, /* ứ Ứ */ 0x1eeb, 499, /* ừ Ừ */ 0x1eed, 499, /* ử Ử */ 0x1eef, 499, /* ữ Ữ */ 0x1ef1, 499, /* ự Ự */ 0x1ef3, 499, /* ỳ Ỳ */ 0x1ef5, 499, /* ỵ Ỵ */ 0x1ef7, 499, /* ỷ Ỷ */ 0x1ef9, 499, /* ỹ Ỹ */ 0x1f51, 508, /* ὑ Ὑ */ 0x1f53, 508, /* ὓ Ὓ */ 0x1f55, 508, /* ὕ Ὕ */ 0x1f57, 508, /* ὗ Ὗ */ 0x1fb3, 509, /* ᾳ ᾼ */ 0x1fc3, 509, /* ῃ ῌ */ 0x1fe5, 507, /* ῥ Ῥ */ 0x1ff3, 509, /* ῳ ῼ */ }; /* * upper case ranges * 3rd col is conversion excess 500 */ static Rune _tolower2[] = { 0x0041, 0x005a, 532, /* A-Z a-z */ 0x00c0, 0x00d6, 532, /* À-Ö à-ö */ 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */ 0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */ 0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */ 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */ 0x0388, 0x038a, 537, /* Έ-Ί έ-ί */ 0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */ 0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */ 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */ 0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */ 0x040e, 0x040f, 580, /* Ў-Џ ў-џ */ 0x0410, 0x042f, 532, /* А-Я а-я */ 0x0531, 0x0556, 548, /* Ա-Ֆ ա-ֆ */ 0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */ 0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */ 0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */ 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */ 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */ 0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */ 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */ 0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */ 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */ 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */ 0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */ 0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */ 0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */ 0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */ 0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */ 0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */ 0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */ 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */ 0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */ 0x2160, 0x216f, 516, /* Ⅰ-Ⅿ ⅰ-ⅿ */ 0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */ 0xff21, 0xff3a, 532, /* A-Z a-z */ }; /* * upper case singlets * 2nd col is conversion excess 500 */ static Rune _tolower1[] = { 0x0100, 501, /* Ā ā */ 0x0102, 501, /* Ă ă */ 0x0104, 501, /* Ą ą */ 0x0106, 501, /* Ć ć */ 0x0108, 501, /* Ĉ ĉ */ 0x010a, 501, /* Ċ ċ */ 0x010c, 501, /* Č č */ 0x010e, 501, /* Ď ď */ 0x0110, 501, /* Đ đ */ 0x0112, 501, /* Ē ē */ 0x0114, 501, /* Ĕ ĕ */ 0x0116, 501, /* Ė ė */ 0x0118, 501, /* Ę ę */ 0x011a, 501, /* Ě ě */ 0x011c, 501, /* Ĝ ĝ */ 0x011e, 501, /* Ğ ğ */ 0x0120, 501, /* Ġ ġ */ 0x0122, 501, /* Ģ ģ */ 0x0124, 501, /* Ĥ ĥ */ 0x0126, 501, /* Ħ ħ */ 0x0128, 501, /* Ĩ ĩ */ 0x012a, 501, /* Ī ī */ 0x012c, 501, /* Ĭ ĭ */ 0x012e, 501, /* Į į */ 0x0130, 301, /* İ i */ 0x0132, 501, /* IJ ij */ 0x0134, 501, /* Ĵ ĵ */ 0x0136, 501, /* Ķ ķ */ 0x0139, 501, /* Ĺ ĺ */ 0x013b, 501, /* Ļ ļ */ 0x013d, 501, /* Ľ ľ */ 0x013f, 501, /* Ŀ ŀ */ 0x0141, 501, /* Ł ł */ 0x0143, 501, /* Ń ń */ 0x0145, 501, /* Ņ ņ */ 0x0147, 501, /* Ň ň */ 0x014a, 501, /* Ŋ ŋ */ 0x014c, 501, /* Ō ō */ 0x014e, 501, /* Ŏ ŏ */ 0x0150, 501, /* Ő ő */ 0x0152, 501, /* Œ œ */ 0x0154, 501, /* Ŕ ŕ */ 0x0156, 501, /* Ŗ ŗ */ 0x0158, 501, /* Ř ř */ 0x015a, 501, /* Ś ś */ 0x015c, 501, /* Ŝ ŝ */ 0x015e, 501, /* Ş ş */ 0x0160, 501, /* Š š */ 0x0162, 501, /* Ţ ţ */ 0x0164, 501, /* Ť ť */ 0x0166, 501, /* Ŧ ŧ */ 0x0168, 501, /* Ũ ũ */ 0x016a, 501, /* Ū ū */ 0x016c, 501, /* Ŭ ŭ */ 0x016e, 501, /* Ů ů */ 0x0170, 501, /* Ű ű */ 0x0172, 501, /* Ų ų */ 0x0174, 501, /* Ŵ ŵ */ 0x0176, 501, /* Ŷ ŷ */ 0x0178, 379, /* Ÿ ÿ */ 0x0179, 501, /* Ź ź */ 0x017b, 501, /* Ż ż */ 0x017d, 501, /* Ž ž */ 0x0181, 710, /* Ɓ ɓ */ 0x0182, 501, /* Ƃ ƃ */ 0x0184, 501, /* Ƅ ƅ */ 0x0186, 706, /* Ɔ ɔ */ 0x0187, 501, /* Ƈ ƈ */ 0x018b, 501, /* Ƌ ƌ */ 0x0190, 703, /* Ɛ ɛ */ 0x0191, 501, /* Ƒ ƒ */ 0x0193, 705, /* Ɠ ɠ */ 0x0194, 707, /* Ɣ ɣ */ 0x0196, 711, /* Ɩ ɩ */ 0x0197, 709, /* Ɨ ɨ */ 0x0198, 501, /* Ƙ ƙ */ 0x019c, 711, /* Ɯ ɯ */ 0x019d, 713, /* Ɲ ɲ */ 0x01a0, 501, /* Ơ ơ */ 0x01a2, 501, /* Ƣ ƣ */ 0x01a4, 501, /* Ƥ ƥ */ 0x01a7, 501, /* Ƨ ƨ */ 0x01a9, 718, /* Ʃ ʃ */ 0x01ac, 501, /* Ƭ ƭ */ 0x01ae, 718, /* Ʈ ʈ */ 0x01af, 501, /* Ư ư */ 0x01b3, 501, /* Ƴ ƴ */ 0x01b5, 501, /* Ƶ ƶ */ 0x01b7, 719, /* Ʒ ʒ */ 0x01b8, 501, /* Ƹ ƹ */ 0x01bc, 501, /* Ƽ ƽ */ 0x01c4, 502, /* DŽ dž */ 0x01c5, 501, /* Dž dž */ 0x01c7, 502, /* LJ lj */ 0x01c8, 501, /* Lj lj */ 0x01ca, 502, /* NJ nj */ 0x01cb, 501, /* Nj nj */ 0x01cd, 501, /* Ǎ ǎ */ 0x01cf, 501, /* Ǐ ǐ */ 0x01d1, 501, /* Ǒ ǒ */ 0x01d3, 501, /* Ǔ ǔ */ 0x01d5, 501, /* Ǖ ǖ */ 0x01d7, 501, /* Ǘ ǘ */ 0x01d9, 501, /* Ǚ ǚ */ 0x01db, 501, /* Ǜ ǜ */ 0x01de, 501, /* Ǟ ǟ */ 0x01e0, 501, /* Ǡ ǡ */ 0x01e2, 501, /* Ǣ ǣ */ 0x01e4, 501, /* Ǥ ǥ */ 0x01e6, 501, /* Ǧ ǧ */ 0x01e8, 501, /* Ǩ ǩ */ 0x01ea, 501, /* Ǫ ǫ */ 0x01ec, 501, /* Ǭ ǭ */ 0x01ee, 501, /* Ǯ ǯ */ 0x01f1, 502, /* DZ dz */ 0x01f2, 501, /* Dz dz */ 0x01f4, 501, /* Ǵ ǵ */ 0x01fa, 501, /* Ǻ ǻ */ 0x01fc, 501, /* Ǽ ǽ */ 0x01fe, 501, /* Ǿ ǿ */ 0x0200, 501, /* Ȁ ȁ */ 0x0202, 501, /* Ȃ ȃ */ 0x0204, 501, /* Ȅ ȅ */ 0x0206, 501, /* Ȇ ȇ */ 0x0208, 501, /* Ȉ ȉ */ 0x020a, 501, /* Ȋ ȋ */ 0x020c, 501, /* Ȍ ȍ */ 0x020e, 501, /* Ȏ ȏ */ 0x0210, 501, /* Ȑ ȑ */ 0x0212, 501, /* Ȓ ȓ */ 0x0214, 501, /* Ȕ ȕ */ 0x0216, 501, /* Ȗ ȗ */ 0x0386, 538, /* Ά ά */ 0x038c, 564, /* Ό ό */ 0x03e2, 501, /* Ϣ ϣ */ 0x03e4, 501, /* Ϥ ϥ */ 0x03e6, 501, /* Ϧ ϧ */ 0x03e8, 501, /* Ϩ ϩ */ 0x03ea, 501, /* Ϫ ϫ */ 0x03ec, 501, /* Ϭ ϭ */ 0x03ee, 501, /* Ϯ ϯ */ 0x0460, 501, /* Ѡ ѡ */ 0x0462, 501, /* Ѣ ѣ */ 0x0464, 501, /* Ѥ ѥ */ 0x0466, 501, /* Ѧ ѧ */ 0x0468, 501, /* Ѩ ѩ */ 0x046a, 501, /* Ѫ ѫ */ 0x046c, 501, /* Ѭ ѭ */ 0x046e, 501, /* Ѯ ѯ */ 0x0470, 501, /* Ѱ ѱ */ 0x0472, 501, /* Ѳ ѳ */ 0x0474, 501, /* Ѵ ѵ */ 0x0476, 501, /* Ѷ ѷ */ 0x0478, 501, /* Ѹ ѹ */ 0x047a, 501, /* Ѻ ѻ */ 0x047c, 501, /* Ѽ ѽ */ 0x047e, 501, /* Ѿ ѿ */ 0x0480, 501, /* Ҁ ҁ */ 0x0490, 501, /* Ґ ґ */ 0x0492, 501, /* Ғ ғ */ 0x0494, 501, /* Ҕ ҕ */ 0x0496, 501, /* Җ җ */ 0x0498, 501, /* Ҙ ҙ */ 0x049a, 501, /* Қ қ */ 0x049c, 501, /* Ҝ ҝ */ 0x049e, 501, /* Ҟ ҟ */ 0x04a0, 501, /* Ҡ ҡ */ 0x04a2, 501, /* Ң ң */ 0x04a4, 501, /* Ҥ ҥ */ 0x04a6, 501, /* Ҧ ҧ */ 0x04a8, 501, /* Ҩ ҩ */ 0x04aa, 501, /* Ҫ ҫ */ 0x04ac, 501, /* Ҭ ҭ */ 0x04ae, 501, /* Ү ү */ 0x04b0, 501, /* Ұ ұ */ 0x04b2, 501, /* Ҳ ҳ */ 0x04b4, 501, /* Ҵ ҵ */ 0x04b6, 501, /* Ҷ ҷ */ 0x04b8, 501, /* Ҹ ҹ */ 0x04ba, 501, /* Һ һ */ 0x04bc, 501, /* Ҽ ҽ */ 0x04be, 501, /* Ҿ ҿ */ 0x04c1, 501, /* Ӂ ӂ */ 0x04c3, 501, /* Ӄ ӄ */ 0x04c7, 501, /* Ӈ ӈ */ 0x04cb, 501, /* Ӌ ӌ */ 0x04d0, 501, /* Ӑ ӑ */ 0x04d2, 501, /* Ӓ ӓ */ 0x04d4, 501, /* Ӕ ӕ */ 0x04d6, 501, /* Ӗ ӗ */ 0x04d8, 501, /* Ә ә */ 0x04da, 501, /* Ӛ ӛ */ 0x04dc, 501, /* Ӝ ӝ */ 0x04de, 501, /* Ӟ ӟ */ 0x04e0, 501, /* Ӡ ӡ */ 0x04e2, 501, /* Ӣ ӣ */ 0x04e4, 501, /* Ӥ ӥ */ 0x04e6, 501, /* Ӧ ӧ */ 0x04e8, 501, /* Ө ө */ 0x04ea, 501, /* Ӫ ӫ */ 0x04ee, 501, /* Ӯ ӯ */ 0x04f0, 501, /* Ӱ ӱ */ 0x04f2, 501, /* Ӳ ӳ */ 0x04f4, 501, /* Ӵ ӵ */ 0x04f8, 501, /* Ӹ ӹ */ 0x1e00, 501, /* Ḁ ḁ */ 0x1e02, 501, /* Ḃ ḃ */ 0x1e04, 501, /* Ḅ ḅ */ 0x1e06, 501, /* Ḇ ḇ */ 0x1e08, 501, /* Ḉ ḉ */ 0x1e0a, 501, /* Ḋ ḋ */ 0x1e0c, 501, /* Ḍ ḍ */ 0x1e0e, 501, /* Ḏ ḏ */ 0x1e10, 501, /* Ḑ ḑ */ 0x1e12, 501, /* Ḓ ḓ */ 0x1e14, 501, /* Ḕ ḕ */ 0x1e16, 501, /* Ḗ ḗ */ 0x1e18, 501, /* Ḙ ḙ */ 0x1e1a, 501, /* Ḛ ḛ */ 0x1e1c, 501, /* Ḝ ḝ */ 0x1e1e, 501, /* Ḟ ḟ */ 0x1e20, 501, /* Ḡ ḡ */ 0x1e22, 501, /* Ḣ ḣ */ 0x1e24, 501, /* Ḥ ḥ */ 0x1e26, 501, /* Ḧ ḧ */ 0x1e28, 501, /* Ḩ ḩ */ 0x1e2a, 501, /* Ḫ ḫ */ 0x1e2c, 501, /* Ḭ ḭ */ 0x1e2e, 501, /* Ḯ ḯ */ 0x1e30, 501, /* Ḱ ḱ */ 0x1e32, 501, /* Ḳ ḳ */ 0x1e34, 501, /* Ḵ ḵ */ 0x1e36, 501, /* Ḷ ḷ */ 0x1e38, 501, /* Ḹ ḹ */ 0x1e3a, 501, /* Ḻ ḻ */ 0x1e3c, 501, /* Ḽ ḽ */ 0x1e3e, 501, /* Ḿ ḿ */ 0x1e40, 501, /* Ṁ ṁ */ 0x1e42, 501, /* Ṃ ṃ */ 0x1e44, 501, /* Ṅ ṅ */ 0x1e46, 501, /* Ṇ ṇ */ 0x1e48, 501, /* Ṉ ṉ */ 0x1e4a, 501, /* Ṋ ṋ */ 0x1e4c, 501, /* Ṍ ṍ */ 0x1e4e, 501, /* Ṏ ṏ */ 0x1e50, 501, /* Ṑ ṑ */ 0x1e52, 501, /* Ṓ ṓ */ 0x1e54, 501, /* Ṕ ṕ */ 0x1e56, 501, /* Ṗ ṗ */ 0x1e58, 501, /* Ṙ ṙ */ 0x1e5a, 501, /* Ṛ ṛ */ 0x1e5c, 501, /* Ṝ ṝ */ 0x1e5e, 501, /* Ṟ ṟ */ 0x1e60, 501, /* Ṡ ṡ */ 0x1e62, 501, /* Ṣ ṣ */ 0x1e64, 501, /* Ṥ ṥ */ 0x1e66, 501, /* Ṧ ṧ */ 0x1e68, 501, /* Ṩ ṩ */ 0x1e6a, 501, /* Ṫ ṫ */ 0x1e6c, 501, /* Ṭ ṭ */ 0x1e6e, 501, /* Ṯ ṯ */ 0x1e70, 501, /* Ṱ ṱ */ 0x1e72, 501, /* Ṳ ṳ */ 0x1e74, 501, /* Ṵ ṵ */ 0x1e76, 501, /* Ṷ ṷ */ 0x1e78, 501, /* Ṹ ṹ */ 0x1e7a, 501, /* Ṻ ṻ */ 0x1e7c, 501, /* Ṽ ṽ */ 0x1e7e, 501, /* Ṿ ṿ */ 0x1e80, 501, /* Ẁ ẁ */ 0x1e82, 501, /* Ẃ ẃ */ 0x1e84, 501, /* Ẅ ẅ */ 0x1e86, 501, /* Ẇ ẇ */ 0x1e88, 501, /* Ẉ ẉ */ 0x1e8a, 501, /* Ẋ ẋ */ 0x1e8c, 501, /* Ẍ ẍ */ 0x1e8e, 501, /* Ẏ ẏ */ 0x1e90, 501, /* Ẑ ẑ */ 0x1e92, 501, /* Ẓ ẓ */ 0x1e94, 501, /* Ẕ ẕ */ 0x1ea0, 501, /* Ạ ạ */ 0x1ea2, 501, /* Ả ả */ 0x1ea4, 501, /* Ấ ấ */ 0x1ea6, 501, /* Ầ ầ */ 0x1ea8, 501, /* Ẩ ẩ */ 0x1eaa, 501, /* Ẫ ẫ */ 0x1eac, 501, /* Ậ ậ */ 0x1eae, 501, /* Ắ ắ */ 0x1eb0, 501, /* Ằ ằ */ 0x1eb2, 501, /* Ẳ ẳ */ 0x1eb4, 501, /* Ẵ ẵ */ 0x1eb6, 501, /* Ặ ặ */ 0x1eb8, 501, /* Ẹ ẹ */ 0x1eba, 501, /* Ẻ ẻ */ 0x1ebc, 501, /* Ẽ ẽ */ 0x1ebe, 501, /* Ế ế */ 0x1ec0, 501, /* Ề ề */ 0x1ec2, 501, /* Ể ể */ 0x1ec4, 501, /* Ễ ễ */ 0x1ec6, 501, /* Ệ ệ */ 0x1ec8, 501, /* Ỉ ỉ */ 0x1eca, 501, /* Ị ị */ 0x1ecc, 501, /* Ọ ọ */ 0x1ece, 501, /* Ỏ ỏ */ 0x1ed0, 501, /* Ố ố */ 0x1ed2, 501, /* Ồ ồ */ 0x1ed4, 501, /* Ổ ổ */ 0x1ed6, 501, /* Ỗ ỗ */ 0x1ed8, 501, /* Ộ ộ */ 0x1eda, 501, /* Ớ ớ */ 0x1edc, 501, /* Ờ ờ */ 0x1ede, 501, /* Ở ở */ 0x1ee0, 501, /* Ỡ ỡ */ 0x1ee2, 501, /* Ợ ợ */ 0x1ee4, 501, /* Ụ ụ */ 0x1ee6, 501, /* Ủ ủ */ 0x1ee8, 501, /* Ứ ứ */ 0x1eea, 501, /* Ừ ừ */ 0x1eec, 501, /* Ử ử */ 0x1eee, 501, /* Ữ ữ */ 0x1ef0, 501, /* Ự ự */ 0x1ef2, 501, /* Ỳ ỳ */ 0x1ef4, 501, /* Ỵ ỵ */ 0x1ef6, 501, /* Ỷ ỷ */ 0x1ef8, 501, /* Ỹ ỹ */ 0x1f59, 492, /* Ὑ ὑ */ 0x1f5b, 492, /* Ὓ ὓ */ 0x1f5d, 492, /* Ὕ ὕ */ 0x1f5f, 492, /* Ὗ ὗ */ 0x1fbc, 491, /* ᾼ ᾳ */ 0x1fcc, 491, /* ῌ ῃ */ 0x1fec, 493, /* Ῥ ῥ */ 0x1ffc, 491, /* ῼ ῳ */ }; /* * title characters are those between * upper and lower case. ie DZ Dz dz */ static Rune _totitle1[] = { 0x01c4, 501, /* DŽ Dž */ 0x01c6, 499, /* dž Dž */ 0x01c7, 501, /* LJ Lj */ 0x01c9, 499, /* lj Lj */ 0x01ca, 501, /* NJ Nj */ 0x01cc, 499, /* nj Nj */ 0x01f1, 501, /* DZ Dz */ 0x01f3, 499, /* dz Dz */ }; #define bsearch xbsearch static Rune* bsearch(Rune c, Rune *t, int n, int ne) { Rune *p; int m; while(n > 1) { m = n/2; p = t + m*ne; if(c >= p[0]) { t = p; n = n-m; } else n = m; } if(n && c >= t[0]) return t; return 0; } Rune tolowerrune(Rune c) { Rune *p; p = bsearch(c, _tolower2, nelem(_tolower2)/3, 3); if(p && c >= p[0] && c <= p[1]) return c + p[2] - 500; p = bsearch(c, _tolower1, nelem(_tolower1)/2, 2); if(p && c == p[0]) return c + p[1] - 500; return c; } Rune toupperrune(Rune c) { Rune *p; p = bsearch(c, _toupper2, nelem(_toupper2)/3, 3); if(p && c >= p[0] && c <= p[1]) return c + p[2] - 500; p = bsearch(c, _toupper1, nelem(_toupper1)/2, 2); if(p && c == p[0]) return c + p[1] - 500; return c; } Rune totitlerune(Rune c) { Rune *p; p = bsearch(c, _totitle1, nelem(_totitle1)/2, 2); if(p && c == p[0]) return c + p[1] - 500; return c; } int islowerrune(Rune c) { Rune *p; p = bsearch(c, _toupper2, nelem(_toupper2)/3, 3); if(p && c >= p[0] && c <= p[1]) return 1; p = bsearch(c, _toupper1, nelem(_toupper1)/2, 2); if(p && c == p[0]) return 1; return 0; } int isupperrune(Rune c) { Rune *p; p = bsearch(c, _tolower2, nelem(_tolower2)/3, 3); if(p && c >= p[0] && c <= p[1]) return 1; p = bsearch(c, _tolower1, nelem(_tolower1)/2, 2); if(p && c == p[0]) return 1; return 0; } int isalpharune(Rune c) { Rune *p; if(isupperrune(c) || islowerrune(c)) return 1; p = bsearch(c, _alpha2, nelem(_alpha2)/2, 2); if(p && c >= p[0] && c <= p[1]) return 1; p = bsearch(c, _alpha1, nelem(_alpha1), 1); if(p && c == p[0]) return 1; return 0; } int istitlerune(Rune c) { return isupperrune(c) && islowerrune(c); } int isspacerune(Rune c) { Rune *p; p = bsearch(c, _space2, nelem(_space2)/2, 2); if(p && c >= p[0] && c <= p[1]) return 1; return 0; } drawterm-20110822.orig/libc/dirstat.c0000644000175000017500000000126011245145712016621 0ustar tinchotincho#include #include #include enum { DIRSIZE = STATFIXLEN + 16 * 4 /* enough for encoded stat buf + some reasonable strings */ }; Dir* dirstat(char *name) { Dir *d; uchar *buf; int n, nd, i; nd = DIRSIZE; for(i=0; i<2; i++){ /* should work by the second try */ d = malloc(sizeof(Dir) + BIT16SZ + nd); if(d == nil) return nil; buf = (uchar*)&d[1]; n = stat(name, buf, BIT16SZ+nd); if(n < BIT16SZ){ free(d); return nil; } nd = GBIT16((uchar*)buf); /* upper bound on size of Dir + strings */ if(nd <= n){ convM2D(buf, n, d, (char*)&d[1]); return d; } /* else sizeof(Dir)+BIT16SZ+nd is plenty */ free(d); } return nil; } drawterm-20110822.orig/libc/runesnprint.c0000644000175000017500000000033711245145712017542 0ustar tinchotincho#include #include #include "fmtdef.h" int runesnprint(Rune *buf, int len, char *fmt, ...) { int n; va_list args; va_start(args, fmt); n = runevsnprint(buf, len, fmt, args); va_end(args); return n; } drawterm-20110822.orig/libc/strecpy.c0000644000175000017500000000033711245145712016644 0ustar tinchotincho#include #include char* strecpy(char *to, char *e, char *from) { if(to >= e) return to; to = memccpy(to, from, '\0', e - to); if(to == nil){ to = e - 1; *to = '\0'; }else{ to--; } return to; } drawterm-20110822.orig/libc/runestrncmp.c0000644000175000017500000000037211245145712017532 0ustar tinchotincho#include #include int runestrncmp(Rune *s1, Rune *s2, long n) { Rune c1, c2; while(n > 0) { c1 = *s1++; c2 = *s2++; n--; if(c1 != c2) { if(c1 > c2) return 1; return -1; } if(c1 == 0) break; } return 0; } drawterm-20110822.orig/libc/utfnlen.c0000644000175000017500000000047511245145712016631 0ustar tinchotincho#include #include int utfnlen(char *s, long m) { int c; long n; Rune rune; char *es; es = s + m; for(n = 0; s < es; n++) { c = *(uchar*)s; if(c < Runeself){ if(c == '\0') break; s++; continue; } if(!fullrune(s, es-s)) break; s += chartorune(&rune, s); } return n; } drawterm-20110822.orig/libc/truerand.c0000644000175000017500000000046211245145712016776 0ustar tinchotincho#include #include ulong truerand(void) { ulong x; static int randfd = -1; if(randfd < 0) randfd = open("/dev/random", OREAD|OCEXEC); if(randfd < 0) sysfatal("can't open /dev/random"); if(read(randfd, &x, sizeof(x)) != sizeof(x)) sysfatal("can't read /dev/random"); return x; } drawterm-20110822.orig/libc/fmtvprint.c0000644000175000017500000000100711245145712017177 0ustar tinchotincho#include #include #include "fmtdef.h" /* * format a string into the output buffer * designed for formats which themselves call fmt, * but ignore any width flags */ int fmtvprint(Fmt *f, char *fmt, va_list args) { va_list va; int n; f->flags = 0; f->width = 0; f->prec = 0; VA_COPY(va,f->args); VA_END(f->args); VA_COPY(f->args,args); n = dofmt(f, fmt); f->flags = 0; f->width = 0; f->prec = 0; VA_END(f->args); VA_COPY(f->args,va); VA_END(va); if(n >= 0) return 0; return n; } drawterm-20110822.orig/libc/fmtfd.c0000644000175000017500000000103711245145712016251 0ustar tinchotincho#include #include #include #include "fmtdef.h" /* * public routine for final flush of a formatting buffer * to a file descriptor; returns total char count. */ int fmtfdflush(Fmt *f) { if(__fmtFdFlush(f) <= 0) return -1; return f->nfmt; } /* * initialize an output buffer for buffered printing */ int fmtfdinit(Fmt *f, int fd, char *buf, int size) { f->runes = 0; f->start = buf; f->to = buf; f->stop = buf + size; f->flush = __fmtFdFlush; f->farg = (void*)(uintptr_t)fd; f->nfmt = 0; return 0; } drawterm-20110822.orig/libc/nrand.c0000644000175000017500000000027711245145712016260 0ustar tinchotincho#include #include #define MASK 0x7fffffffL int nrand(int n) { long slop, v; if(n < 0) return n; slop = MASK % n; do v = lrand(); while(v <= slop); return v % n; } drawterm-20110822.orig/libc/strtod.c0000644000175000017500000002033111245145712016466 0ustar tinchotincho#include #include #include "fmtdef.h" static ulong umuldiv(ulong a, ulong b, ulong c) { double d; d = ((double)a * (double)b) / (double)c; if(d >= 4294967295.) d = 4294967295.; return (ulong)d; } /* * This routine will convert to arbitrary precision * floating point entirely in multi-precision fixed. * The answer is the closest floating point number to * the given decimal number. Exactly half way are * rounded ala ieee rules. * Method is to scale input decimal between .500 and .999... * with external power of 2, then binary search for the * closest mantissa to this decimal number. * Nmant is is the required precision. (53 for ieee dp) * Nbits is the max number of bits/word. (must be <= 28) * Prec is calculated - the number of words of fixed mantissa. */ enum { Nbits = 28, /* bits safely represented in a ulong */ Nmant = 53, /* bits of precision required */ Prec = (Nmant+Nbits+1)/Nbits, /* words of Nbits each to represent mantissa */ Sigbit = 1<<(Prec*Nbits-Nmant), /* first significant bit of Prec-th word */ Ndig = 1500, One = (ulong)(1<>1), Maxe = 310, Fsign = 1<<0, /* found - */ Fesign = 1<<1, /* found e- */ Fdpoint = 1<<2, /* found . */ S0 = 0, /* _ _S0 +S1 #S2 .S3 */ S1, /* _+ #S2 .S3 */ S2, /* _+# #S2 .S4 eS5 */ S3, /* _+. #S4 */ S4, /* _+#.# #S4 eS5 */ S5, /* _+#.#e +S6 #S7 */ S6, /* _+#.#e+ #S7 */ S7, /* _+#.#e+# #S7 */ }; static int xcmp(char*, char*); static int fpcmp(char*, ulong*); static void frnorm(ulong*); static void divascii(char*, int*, int*, int*); static void mulascii(char*, int*, int*, int*); typedef struct Tab Tab; struct Tab { int bp; int siz; char* cmp; }; #ifndef ERANGE #define ERANGE 12345 #endif double fmtstrtod(const char *as, char **aas) { int na, ex, dp, bp, c, i, flag, state; ulong low[Prec], hig[Prec], mid[Prec]; double d; char *s, a[Ndig]; flag = 0; /* Fsign, Fesign, Fdpoint */ na = 0; /* number of digits of a[] */ dp = 0; /* na of decimal point */ ex = 0; /* exonent */ state = S0; for(s=(char*)as;; s++) { c = *s; if(c >= '0' && c <= '9') { switch(state) { case S0: case S1: case S2: state = S2; break; case S3: case S4: state = S4; break; case S5: case S6: case S7: state = S7; ex = ex*10 + (c-'0'); continue; } if(na == 0 && c == '0') { dp--; continue; } if(na < Ndig-50) a[na++] = c; continue; } switch(c) { case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': if(state == S0) continue; break; case '-': if(state == S0) flag |= Fsign; else flag |= Fesign; case '+': if(state == S0) state = S1; else if(state == S5) state = S6; else break; /* syntax */ continue; case '.': flag |= Fdpoint; dp = na; if(state == S0 || state == S1) { state = S3; continue; } if(state == S2) { state = S4; continue; } break; case 'e': case 'E': if(state == S2 || state == S4) { state = S5; continue; } break; } break; } /* * clean up return char-pointer */ switch(state) { case S0: if(xcmp(s, "nan") == 0) { if(aas != nil) *aas = s+3; goto retnan; } case S1: if(xcmp(s, "infinity") == 0) { if(aas != nil) *aas = s+8; goto retinf; } if(xcmp(s, "inf") == 0) { if(aas != nil) *aas = s+3; goto retinf; } case S3: if(aas != nil) *aas = (char*)as; goto ret0; /* no digits found */ case S6: s--; /* back over +- */ case S5: s--; /* back over e */ break; } if(aas != nil) *aas = s; if(flag & Fdpoint) while(na > 0 && a[na-1] == '0') na--; if(na == 0) goto ret0; /* zero */ a[na] = 0; if(!(flag & Fdpoint)) dp = na; if(flag & Fesign) ex = -ex; dp += ex; if(dp < -Maxe){ errno = ERANGE; goto ret0; /* underflow by exp */ } else if(dp > +Maxe) goto retinf; /* overflow by exp */ /* * normalize the decimal ascii number * to range .[5-9][0-9]* e0 */ bp = 0; /* binary exponent */ while(dp > 0) divascii(a, &na, &dp, &bp); while(dp < 0 || a[0] < '5') mulascii(a, &na, &dp, &bp); /* close approx by naive conversion */ mid[0] = 0; mid[1] = 1; for(i=0; (c=a[i]); i++) { mid[0] = mid[0]*10 + (c-'0'); mid[1] = mid[1]*10; if(i >= 8) break; } low[0] = umuldiv(mid[0], One, mid[1]); hig[0] = umuldiv(mid[0]+1, One, mid[1]); for(i=1; i>= 1; } frnorm(mid); /* compare */ c = fpcmp(a, mid); if(c > 0) { c = 1; for(i=0; i= Sigbit/2) { mid[Prec-1] += Sigbit; frnorm(mid); } goto out; ret0: return 0; retnan: return __NaN(); retinf: /* * Unix strtod requires these. Plan 9 would return Inf(0) or Inf(-1). */ errno = ERANGE; if(flag & Fsign) return -HUGE_VAL; return HUGE_VAL; out: d = 0; for(i=0; i0; i--) { f[i] += c; c = f[i] >> Nbits; f[i] &= One-1; } f[0] += c; } static int fpcmp(char *a, ulong* f) { ulong tf[Prec]; int i, d, c; for(i=0; i> Nbits) + '0'; tf[0] &= One-1; /* compare next digit */ c = *a; if(c == 0) { if('0' < d) return -1; if(tf[0] != 0) goto cont; for(i=1; i d) return +1; if(c < d) return -1; a++; cont:; } } static void divby(char *a, int *na, int b) { int n, c; char *p; p = a; n = 0; while(n>>b == 0) { c = *a++; if(c == 0) { while(n) { c = n*10; if(c>>b) break; n = c; } goto xx; } n = n*10 + c-'0'; (*na)--; } for(;;) { c = n>>b; n -= c<>b; n -= c<= (int)(nelem(tab1))) d = (int)(nelem(tab1))-1; t = tab1 + d; b = t->bp; if(memcmp(a, t->cmp, t->siz) > 0) d--; *dp -= d; *bp += b; divby(a, na, b); } static void mulby(char *a, char *p, char *q, int b) { int n, c; n = 0; *p = 0; for(;;) { q--; if(q < a) break; c = *q - '0'; c = (c<= (int)(nelem(tab2))) d = (int)(nelem(tab2))-1; t = tab2 + d; b = t->bp; if(memcmp(a, t->cmp, t->siz) < 0) d--; p = a + *na; *bp -= b; *dp += d; *na += d; mulby(a, p+d, p, b); } static int xcmp(char *a, char *b) { int c1, c2; while((c1 = *b++)) { c2 = *a++; if(isupper(c2)) c2 = tolower(c2); if(c1 != c2) return 1; } return 0; } drawterm-20110822.orig/libc/runevseprint.c0000644000175000017500000000055211245145712017716 0ustar tinchotincho#include #include #include "fmtdef.h" Rune* runevseprint(Rune *buf, Rune *e, char *fmt, va_list args) { Fmt f; if(e <= buf) return nil; f.runes = 1; f.start = buf; f.to = buf; f.stop = e - 1; f.flush = 0; f.farg = nil; f.nfmt = 0; VA_COPY(f.args,args); dofmt(&f, fmt); VA_END(f.args); *(Rune*)f.to = '\0'; return (Rune*)f.to; } drawterm-20110822.orig/libc/fltfmt.c0000644000175000017500000001423611245145712016452 0ustar tinchotincho#include #include #include #include #include "fmtdef.h" enum { FDIGIT = 30, FDEFLT = 6, NSIGNIF = 17 }; /* * first few powers of 10, enough for about 1/2 of the * total space for doubles. */ static double pows10[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89, 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99, 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, }; #undef pow10 #define pow10(x) fmtpow10(x) static double pow10(int n) { double d; int neg; neg = 0; if(n < 0){ if(n < DBL_MIN_10_EXP){ return 0.; } neg = 1; n = -n; }else if(n > DBL_MAX_10_EXP){ return HUGE_VAL; } if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))) d = pows10[n]; else{ d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1]; for(;;){ n -= sizeof(pows10)/sizeof(pows10[0]) - 1; if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){ d *= pows10[n]; break; } d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1]; } } if(neg){ return 1./d; } return d; } static int xadd(char *a, int n, int v) { char *b; int c; if(n < 0 || n >= NSIGNIF) return 0; for(b = a+n; b >= a; b--) { c = *b + v; if(c <= '9') { *b = c; return 0; } *b = '0'; v = 1; } *a = '1'; /* overflow adding */ return 1; } static int xsub(char *a, int n, int v) { char *b; int c; for(b = a+n; b >= a; b--) { c = *b - v; if(c >= '0') { *b = c; return 0; } *b = '9'; v = 1; } *a = '9'; /* underflow subtracting */ return 1; } static void xdtoa(Fmt *fmt, char *s2, double f) { char s1[NSIGNIF+10]; double g, h; int e, d, i, n; int c1, c2, c3, c4, ucase, sign, chr, prec; prec = FDEFLT; if(fmt->flags & FmtPrec) prec = fmt->prec; if(prec > FDIGIT) prec = FDIGIT; if(__isNaN(f)) { strcpy(s2, "NaN"); return; } if(__isInf(f, 1)) { strcpy(s2, "+Inf"); return; } if(__isInf(f, -1)) { strcpy(s2, "-Inf"); return; } sign = 0; if(f < 0) { f = -f; sign++; } ucase = 0; chr = fmt->r; if(isupper(chr)) { ucase = 1; chr = tolower(chr); } e = 0; g = f; if(g != 0) { frexp(f, &e); e = e * .301029995664; if(e >= -150 && e <= +150) { d = 0; h = f; } else { d = e/2; h = f * pow10(-d); } g = h * pow10(d-e); while(g < 1) { e--; g = h * pow10(d-e); } while(g >= 10) { e++; g = h * pow10(d-e); } } /* * convert NSIGNIF digits and convert * back to get accuracy. */ for(i=0; i= NSIGNIF-2) { strcpy(s2, s1); d = e; s1[NSIGNIF-2] = '0'; s1[NSIGNIF-1] = '0'; sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); g = strtod(s1, nil); if(g == f) goto found; if(xadd(s1, NSIGNIF-3, 1)) { e++; sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); } g = strtod(s1, nil); if(g == f) goto found; strcpy(s1, s2); e = d; } /* * convert back so s1 gets exact answer */ for(;;) { sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1); g = strtod(s1, nil); if(f > g) { if(xadd(s1, NSIGNIF-1, 1)) e--; continue; } if(f < g) { if(xsub(s1, NSIGNIF-1, 1)) e++; continue; } break; } found: /* * sign */ d = 0; i = 0; if(sign) s2[d++] = '-'; else if(fmt->flags & FmtSign) s2[d++] = '+'; else if(fmt->flags & FmtSpace) s2[d++] = ' '; /* * copy into final place * c1 digits of leading '0' * c2 digits from conversion * c3 digits of trailing '0' * c4 digits after '.' */ c1 = 0; c2 = prec + 1; c3 = 0; c4 = prec; switch(chr) { default: if(xadd(s1, c2, 5)) e++; break; case 'g': /* * decide on 'e' of 'f' style convers */ if(xadd(s1, c2, 5)) e++; if(e >= -5 && e <= prec) { c1 = -e - 1; c4 = prec - e; chr = 'h'; // flag for 'f' style } break; case 'f': if(xadd(s1, c2+e, 5)) e++; c1 = -e; if(c1 > prec) c1 = c2; c2 += e; break; } /* * clean up c1 c2 and c3 */ if(c1 < 0) c1 = 0; if(c2 < 0) c2 = 0; if(c2 > NSIGNIF) { c3 = c2-NSIGNIF; c2 = NSIGNIF; } /* * copy digits */ while(c1 > 0) { if(c1+c2+c3 == c4) s2[d++] = '.'; s2[d++] = '0'; c1--; } while(c2 > 0) { if(c2+c3 == c4) s2[d++] = '.'; s2[d++] = s1[i++]; c2--; } while(c3 > 0) { if(c3 == c4) s2[d++] = '.'; s2[d++] = '0'; c3--; } /* * strip trailing '0' on g conv */ if(fmt->flags & FmtSharp) { if(0 == c4) s2[d++] = '.'; } else if(chr == 'g' || chr == 'h') { for(n=d-1; n>=0; n--) if(s2[n] != '0') break; for(i=n; i>=0; i--) if(s2[i] == '.') { d = n; if(i != n) d++; break; } } if(chr == 'e' || chr == 'g') { if(ucase) s2[d++] = 'E'; else s2[d++] = 'e'; c1 = e; if(c1 < 0) { s2[d++] = '-'; c1 = -c1; } else s2[d++] = '+'; if(c1 >= 100) { s2[d++] = c1/100 + '0'; c1 = c1%100; } s2[d++] = c1/10 + '0'; s2[d++] = c1%10 + '0'; } s2[d] = 0; } static int floatfmt(Fmt *fmt, double f) { char s[341]; /* precision+exponent+sign+'.'+null */ xdtoa(fmt, s, f); fmt->flags &= FmtWidth|FmtLeft; __fmtcpy(fmt, s, strlen(s), strlen(s)); return 0; } int __efgfmt(Fmt *f) { double d; d = va_arg(f->args, double); return floatfmt(f, d); } drawterm-20110822.orig/libc/runestrstr.c0000644000175000017500000000061511245145712017405 0ustar tinchotincho#include #include /* * Return pointer to first occurrence of s2 in s1, * 0 if none */ Rune* runestrstr(Rune *s1, Rune *s2) { Rune *p, *pa, *pb; int c0, c; c0 = *s2; if(c0 == 0) return s1; s2++; for(p=runestrchr(s1, c0); p; p=runestrchr(p+1, c0)) { pa = p; for(pb=s2;; pb++) { c = *pb; if(c == 0) return p; if(c != *++pa) break; } } return 0; } drawterm-20110822.orig/libc/smprint.c0000644000175000017500000000027411245145712016647 0ustar tinchotincho#include #include #include "fmtdef.h" char* smprint(char *fmt, ...) { va_list args; char *p; va_start(args, fmt); p = vsmprint(fmt, args); va_end(args); return p; } drawterm-20110822.orig/libc/convM2D.c0000644000175000017500000000261311245145712016422 0ustar tinchotincho#include #include #include int statcheck(uchar *buf, uint nbuf) { uchar *ebuf; int i; ebuf = buf + nbuf; if(nbuf < STATFIXLEN || nbuf != BIT16SZ + GBIT16(buf)) return -1; buf += STATFIXLEN - 4 * BIT16SZ; for(i = 0; i < 4; i++){ if(buf + BIT16SZ > ebuf) return -1; buf += BIT16SZ + GBIT16(buf); } if(buf != ebuf) return -1; return 0; } static char nullstring[] = ""; uint convM2D(uchar *buf, uint nbuf, Dir *d, char *strs) { uchar *p, *ebuf; char *sv[4]; int i, ns; if(nbuf < STATFIXLEN) return 0; p = buf; ebuf = buf + nbuf; p += BIT16SZ; /* ignore size */ d->type = GBIT16(p); p += BIT16SZ; d->dev = GBIT32(p); p += BIT32SZ; d->qid.type = GBIT8(p); p += BIT8SZ; d->qid.vers = GBIT32(p); p += BIT32SZ; d->qid.path = GBIT64(p); p += BIT64SZ; d->mode = GBIT32(p); p += BIT32SZ; d->atime = GBIT32(p); p += BIT32SZ; d->mtime = GBIT32(p); p += BIT32SZ; d->length = GBIT64(p); p += BIT64SZ; for(i = 0; i < 4; i++){ if(p + BIT16SZ > ebuf) return 0; ns = GBIT16(p); p += BIT16SZ; if(p + ns > ebuf) return 0; if(strs){ sv[i] = strs; memmove(strs, p, ns); strs += ns; *strs++ = '\0'; } p += ns; } if(strs){ d->name = sv[0]; d->uid = sv[1]; d->gid = sv[2]; d->muid = sv[3]; }else{ d->name = nullstring; d->uid = nullstring; d->gid = nullstring; d->muid = nullstring; } return p - buf; } drawterm-20110822.orig/libc/lnrand.c0000644000175000017500000000030211245145712016421 0ustar tinchotincho#include #include #define MASK 0x7fffffffL long lnrand(long n) { long slop, v; if(n < 0) return n; slop = MASK % n; do v = lrand(); while(v <= slop); return v % n; } drawterm-20110822.orig/libc/Makefile0000644000175000017500000000224511245145712016447 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libc.a OFILES=\ charstod.$O\ cleanname.$O\ convD2M.$O\ convM2D.$O\ convM2S.$O\ convS2M.$O\ crypt.$O\ dial.$O\ dirfstat.$O\ dirfwstat.$O\ dirmodefmt.$O\ dirstat.$O\ dirwstat.$O\ dofmt.$O\ dorfmt.$O\ encodefmt.$O\ fcallfmt.$O\ fltfmt.$O\ fmt.$O\ fmtfd.$O\ fmtfdflush.$O\ fmtlock.$O\ fmtprint.$O\ fmtquote.$O\ fmtrune.$O\ fmtstr.$O\ fmtvprint.$O\ fprint.$O\ getfields.$O\ getpid.$O\ lock.$O\ mallocz.$O\ nan64.$O\ netmkaddr.$O\ nsec.$O\ pow10.$O\ pushssl.$O\ pushtls.$O\ read9pmsg.$O\ readn.$O\ rune.$O\ runefmtstr.$O\ runeseprint.$O\ runesmprint.$O\ runesnprint.$O\ runesprint.$O\ runestrchr.$O\ runestrlen.$O\ runestrstr.$O\ runetype.$O\ runevseprint.$O\ runevsmprint.$O\ runevsnprint.$O\ seprint.$O\ smprint.$O\ snprint.$O\ sprint.$O\ strecpy.$O\ strtod.$O\ strtoll.$O\ sysfatal.$O\ time.$O\ tokenize.$O\ truerand.$O\ u16.$O\ u32.$O\ u64.$O\ utfecpy.$O\ utflen.$O\ utfnlen.$O\ utfrrune.$O\ utfrune.$O\ utfutf.$O\ vfprint.$O\ vseprint.$O\ vsmprint.$O\ vsnprint.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/libc/runefmtstr.c0000644000175000017500000000024411245145712017361 0ustar tinchotincho#include #include #include "fmtdef.h" Rune* runefmtstrflush(Fmt *f) { if(f->start == nil) return nil; *(Rune*)f->to = '\0'; return f->start; } drawterm-20110822.orig/libc/runestrncat.c0000644000175000017500000000032511245145712017520 0ustar tinchotincho#include #include Rune* runestrncat(Rune *s1, Rune *s2, long n) { Rune *os1; os1 = s1; s1 = runestrchr(s1, 0); while(*s1++ = *s2++) if(--n < 0) { s1[-1] = 0; break; } return os1; } drawterm-20110822.orig/libc/dirmodefmt.c0000644000175000017500000000110511245145712017277 0ustar tinchotincho#include #include #include static char *modes[] = { "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx", }; static void rwx(long m, char *s) { strncpy(s, modes[m], 3); } int dirmodefmt(Fmt *f) { static char buf[16]; ulong m; m = va_arg(f->args, ulong); if(m & DMDIR) buf[0]='d'; else if(m & DMAPPEND) buf[0]='a'; else if(m & DMAUTH) buf[0]='A'; else buf[0]='-'; if(m & DMEXCL) buf[1]='l'; else buf[1]='-'; rwx((m>>6)&7, buf+2); rwx((m>>3)&7, buf+5); rwx((m>>0)&7, buf+8); buf[11] = 0; return fmtstrcpy(f, buf); } drawterm-20110822.orig/libc/fmtprint.c0000644000175000017500000000077611245145712017025 0ustar tinchotincho#include #include #include "fmtdef.h" /* * format a string into the output buffer * designed for formats which themselves call fmt, * but ignore any width flags */ int fmtprint(Fmt *f, char *fmt, ...) { va_list va; int n; f->flags = 0; f->width = 0; f->prec = 0; VA_COPY(va, f->args); VA_END(f->args); va_start(f->args, fmt); n = dofmt(f, fmt); va_end(f->args); f->flags = 0; f->width = 0; f->prec = 0; VA_COPY(f->args,va); VA_END(va); if(n >= 0) return 0; return n; } drawterm-20110822.orig/libc/fmtquote.c0000644000175000017500000001123111245145712017012 0ustar tinchotincho#include #include #include "fmtdef.h" /* * How many bytes of output UTF will be produced by quoting (if necessary) this string? * How many runes? How much of the input will be consumed? * The parameter q is filled in by __quotesetup. * The string may be UTF or Runes (s or r). * Return count does not include NUL. * Terminate the scan at the first of: * NUL in input * count exceeded in input * count exceeded on output * *ninp is set to number of input bytes accepted. * nin may be <0 initially, to avoid checking input by count. */ void __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout) { int w; Rune c; q->quoted = 0; q->nbytesout = 0; q->nrunesout = 0; q->nbytesin = 0; q->nrunesin = 0; if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){ if(nout < 2) return; q->quoted = 1; q->nbytesout = 2; q->nrunesout = 2; } for(; nin!=0; nin--){ if(s) w = chartorune(&c, s); else{ c = *r; w = runelen(c); } if(c == '\0') break; if(runesout){ if(q->nrunesout+1 > nout) break; }else{ if(q->nbytesout+w > nout) break; } if((c <= L' ') || (c == L'\'') || (fmtdoquote!=0 && fmtdoquote(c))){ if(!q->quoted){ if(runesout){ if(1+q->nrunesout+1+1 > nout) /* no room for quotes */ break; }else{ if(1+q->nbytesout+w+1 > nout) /* no room for quotes */ break; } q->nrunesout += 2; /* include quotes */ q->nbytesout += 2; /* include quotes */ q->quoted = 1; } if(c == '\'') { if(runesout){ if(1+q->nrunesout+1 > nout) /* no room for quotes */ break; }else{ if(1+q->nbytesout+w > nout) /* no room for quotes */ break; } q->nbytesout++; q->nrunesout++; /* quotes reproduce as two characters */ } } /* advance input */ if(s) s += w; else r++; q->nbytesin += w; q->nrunesin++; /* advance output */ q->nbytesout += w; q->nrunesout++; } } static int qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f) { Rune r, *rm, *rme; char *t, *s, *m, *me; Rune *rt, *rs; ulong fl; int nc, w; m = sin; me = m + q->nbytesin; rm = rin; rme = rm + q->nrunesin; w = f->width; fl = f->flags; if(f->runes){ if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0) return -1; }else{ if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0) return -1; } t = (char*)f->to; s = (char*)f->stop; rt = (Rune*)f->to; rs = (Rune*)f->stop; if(f->runes) FMTRCHAR(f, rt, rs, '\''); else FMTRUNE(f, t, s, '\''); for(nc = q->nrunesin; nc > 0; nc--){ if(sin){ r = *(uchar*)m; if(r < Runeself) m++; else if((me - m) >= UTFmax || fullrune(m, me-m)) m += chartorune(&r, m); else break; }else{ if(rm >= rme) break; r = *(uchar*)rm++; } if(f->runes){ FMTRCHAR(f, rt, rs, r); if(r == '\'') FMTRCHAR(f, rt, rs, r); }else{ FMTRUNE(f, t, s, r); if(r == '\'') FMTRUNE(f, t, s, r); } } if(f->runes){ FMTRCHAR(f, rt, rs, '\''); USED(rs); f->nfmt += rt - (Rune *)f->to; f->to = rt; if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0) return -1; }else{ FMTRUNE(f, t, s, '\''); USED(s); f->nfmt += t - (char *)f->to; f->to = t; if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0) return -1; } return 0; } int __quotestrfmt(int runesin, Fmt *f) { int nin, outlen; Rune *r; char *s; Quoteinfo q; nin = -1; if(f->flags&FmtPrec) nin = f->prec; if(runesin){ r = va_arg(f->args, Rune *); s = nil; }else{ s = va_arg(f->args, char *); r = nil; } if(!s && !r) return __fmtcpy(f, (void*)"", 5, 5); if(f->flush) outlen = 0x7FFFFFFF; /* if we can flush, no output limit */ else if(f->runes) outlen = (Rune*)f->stop - (Rune*)f->to; else outlen = (char*)f->stop - (char*)f->to; __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes); //print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); if(runesin){ if(!q.quoted) return __fmtrcpy(f, r, q.nrunesin); return qstrfmt(nil, r, &q, f); } if(!q.quoted) return __fmtcpy(f, s, q.nrunesin, q.nbytesin); return qstrfmt(s, nil, &q, f); } int quotestrfmt(Fmt *f) { return __quotestrfmt(0, f); } int quoterunestrfmt(Fmt *f) { return __quotestrfmt(1, f); } void quotefmtinstall(void) { fmtinstall('q', quotestrfmt); fmtinstall('Q', quoterunestrfmt); } int __needsquotes(char *s, int *quotelenp) { Quoteinfo q; __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0); *quotelenp = q.nbytesout; return q.quoted; } int __runeneedsquotes(Rune *r, int *quotelenp) { Quoteinfo q; __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0); *quotelenp = q.nrunesout; return q.quoted; } drawterm-20110822.orig/libc/u64.c0000644000175000017500000000632211245145712015571 0ustar tinchotincho#include #include enum { INVAL= 255 }; static uchar t64d[256] = { INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, 62,INVAL,INVAL,INVAL, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL }; static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int dec64(uchar *out, int lim, char *in, int n) { ulong b24; uchar *start = out; uchar *e = out + lim; int i, c; b24 = 0; i = 0; while(n-- > 0){ c = t64d[*(uchar*)in++]; if(c == INVAL) continue; switch(i){ case 0: b24 = c<<18; break; case 1: b24 |= c<<12; break; case 2: b24 |= c<<6; break; case 3: if(out + 3 > e) goto exhausted; b24 |= c; *out++ = b24>>16; *out++ = b24>>8; *out++ = b24; i = -1; break; } i++; } switch(i){ case 2: if(out + 1 > e) goto exhausted; *out++ = b24>>16; break; case 3: if(out + 2 > e) goto exhausted; *out++ = b24>>16; *out++ = b24>>8; break; } exhausted: return out - start; } int enc64(char *out, int lim, uchar *in, int n) { int i; ulong b24; char *start = out; char *e = out + lim; for(i = n/3; i > 0; i--){ b24 = (*in++)<<16; b24 |= (*in++)<<8; b24 |= *in++; if(out + 4 >= e) goto exhausted; *out++ = t64e[(b24>>18)]; *out++ = t64e[(b24>>12)&0x3f]; *out++ = t64e[(b24>>6)&0x3f]; *out++ = t64e[(b24)&0x3f]; } switch(n%3){ case 2: b24 = (*in++)<<16; b24 |= (*in)<<8; if(out + 4 >= e) goto exhausted; *out++ = t64e[(b24>>18)]; *out++ = t64e[(b24>>12)&0x3f]; *out++ = t64e[(b24>>6)&0x3f]; *out++ = '='; break; case 1: b24 = (*in)<<16; if(out + 4 >= e) goto exhausted; *out++ = t64e[(b24>>18)]; *out++ = t64e[(b24>>12)&0x3f]; *out++ = '='; *out++ = '='; break; } exhausted: *out = 0; return out - start; } drawterm-20110822.orig/libc/nsec.c0000644000175000017500000000225411245145712016103 0ustar tinchotincho#include #include static uvlong order = (uvlong) 0x0001020304050607ULL; static void be2vlong(vlong *to, uchar *f) { uchar *t, *o; int i; t = (uchar*)to; o = (uchar*)ℴ for(i = 0; i < 8; i++) t[o[i]] = f[i]; } /* * After a fork with fd's copied, both fd's are pointing to * the same Chan structure. Since the offset is kept in the Chan * structure, the seek's and read's in the two processes can * compete at moving the offset around. Hence the retry loop. * * Since the bintime version doesn't need a seek, it doesn't * have the loop. */ vlong nsec(void) { char b[12+1]; static int f = -1; static int usebintime; int retries; vlong t; if(f < 0){ usebintime = 1; f = open("/dev/bintime", OREAD|OCEXEC); if(f < 0){ usebintime = 0; f = open("/dev/nsec", OREAD|OCEXEC); if(f < 0) return 0; } } if(usebintime){ if(read(f, b, sizeof(uvlong)) < 0) goto error; be2vlong(&t, (uchar*)b); return t; } else { for(retries = 0; retries < 100; retries++){ if(seek(f, 0, 0) >= 0 && read(f, b, sizeof(b)-1) >= 0){ b[sizeof(b)-1] = 0; return strtoll(b, 0, 0); } } } error: close(f); f = -1; return 0; } drawterm-20110822.orig/libc/rune.c0000644000175000017500000000440211245145712016121 0ustar tinchotincho#include #include enum { Bit1 = 7, Bitx = 6, Bit2 = 5, Bit3 = 4, Bit4 = 3, T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ Maskx = (1< T1 */ c = *(uchar*)str; if(c < Tx) { *rune = c; return 1; } /* * two character sequence * 0080-07FF => T2 Tx */ c1 = *(uchar*)(str+1) ^ Tx; if(c1 & Testx) goto bad; if(c < T3) { if(c < T2) goto bad; l = ((c << Bitx) | c1) & Rune2; if(l <= Rune1) goto bad; *rune = l; return 2; } /* * three character sequence * 0800-FFFF => T3 Tx Tx */ c2 = *(uchar*)(str+2) ^ Tx; if(c2 & Testx) goto bad; if(c < T4) { l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; if(l <= Rune2) goto bad; *rune = l; return 3; } /* * bad decoding */ bad: *rune = Bad; return 1; } int runetochar(char *str, Rune *rune) { long c; /* * one character sequence * 00000-0007F => 00-7F */ c = *rune; if(c <= Rune1) { str[0] = c; return 1; } /* * two character sequence * 0080-07FF => T2 Tx */ if(c <= Rune2) { str[0] = T2 | (c >> 1*Bitx); str[1] = Tx | (c & Maskx); return 2; } /* * three character sequence * 0800-FFFF => T3 Tx Tx */ str[0] = T3 | (c >> 2*Bitx); str[1] = Tx | ((c >> 1*Bitx) & Maskx); str[2] = Tx | (c & Maskx); return 3; } int runelen(long c) { Rune rune; char str[10]; rune = c; return runetochar(str, &rune); } int runenlen(Rune *r, int nrune) { int nb, c; nb = 0; while(nrune--) { c = *r++; if(c <= Rune1) nb++; else if(c <= Rune2) nb += 2; else nb += 3; } return nb; } int fullrune(char *str, int n) { int c; if(n > 0) { c = *(uchar*)str; if(c < Tx) return 1; if(n > 1) if(c < T3 || n > 2) return 1; } return 0; } drawterm-20110822.orig/libc/utf.h0000644000175000017500000000264211245145712015757 0ustar tinchotincho#ifndef _UTFH_ #define _UTFH_ 1 typedef unsigned short Rune; /* 16 bits */ enum { UTFmax = 3, /* maximum bytes per rune */ Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ Runeself = 0x80, /* rune and UTF sequences are the same (<) */ Runeerror = 0x80, /* decoding error in UTF */ }; /* * rune routines */ extern int runetochar(char*, Rune*); extern int chartorune(Rune*, char*); extern int runelen(long); extern int runenlen(Rune*, int); extern int fullrune(char*, int); extern int utflen(char*); extern int utfnlen(char*, long); extern char* utfrune(char*, long); extern char* utfrrune(char*, long); extern char* utfutf(char*, char*); extern char* utfecpy(char*, char*, char*); extern Rune* runestrcat(Rune*, Rune*); extern Rune* runestrchr(Rune*, Rune); extern int runestrcmp(Rune*, Rune*); extern Rune* runestrcpy(Rune*, Rune*); extern Rune* runestrncpy(Rune*, Rune*, long); extern Rune* runestrecpy(Rune*, Rune*, Rune*); extern Rune* runestrdup(Rune*); extern Rune* runestrncat(Rune*, Rune*, long); extern int runestrncmp(Rune*, Rune*, long); extern Rune* runestrrchr(Rune*, Rune); extern long runestrlen(Rune*); extern Rune* runestrstr(Rune*, Rune*); extern Rune tolowerrune(Rune); extern Rune totitlerune(Rune); extern Rune toupperrune(Rune); extern int isalpharune(Rune); extern int islowerrune(Rune); extern int isspacerune(Rune); extern int istitlerune(Rune); extern int isupperrune(Rune); #endif drawterm-20110822.orig/libc/runevsnprint.c0000644000175000017500000000056411245145712017732 0ustar tinchotincho#include #include #include "fmtdef.h" int runevsnprint(Rune *buf, int len, char *fmt, va_list args) { Fmt f; if(len <= 0) return -1; f.runes = 1; f.start = buf; f.to = buf; f.stop = buf + len - 1; f.flush = 0; f.farg = nil; f.nfmt = 0; VA_COPY(f.args,args); dofmt(&f, fmt); VA_END(f.args); *(Rune*)f.to = '\0'; return (Rune*)f.to - buf; } drawterm-20110822.orig/libc/cleanname.c0000644000175000017500000000225711245145712017101 0ustar tinchotincho#include #include /* * In place, rewrite name to compress multiple /, eliminate ., and process .. */ #define SEP(x) ((x)=='/' || (x) == 0) char* cleanname(char *name) { char *p, *q, *dotdot; int rooted; rooted = name[0] == '/'; /* * invariants: * p points at beginning of path element we're considering. * q points just past the last path element we wrote (no slash). * dotdot points just past the point where .. cannot backtrack * any further (no slash). */ p = q = dotdot = name+rooted; while(*p) { if(p[0] == '/') /* null element */ p++; else if(p[0] == '.' && SEP(p[1])) p += 1; /* don't count the separator in case it is nul */ else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) { p += 2; if(q > dotdot) { /* can backtrack */ while(--q > dotdot && *q != '/') ; } else if(!rooted) { /* /.. is / but ./../ is .. */ if(q != name) *q++ = '/'; *q++ = '.'; *q++ = '.'; dotdot = q; } } else { /* real path element */ if(q != name+rooted) *q++ = '/'; while((*q = *p) != '/' && *q != 0) p++, q++; } } if(q == name) /* empty string is really ``.'' */ *q++ = '.'; *q = '\0'; return name; } drawterm-20110822.orig/libc/dorfmt.c0000644000175000017500000000142711245145712016447 0ustar tinchotincho#include #include #include "fmtdef.h" /* format the output into f->to and return the number of characters fmted */ int dorfmt(Fmt *f, const Rune *fmt) { Rune *rt, *rs; int r; char *t, *s; int nfmt; nfmt = f->nfmt; for(;;){ if(f->runes){ rt = f->to; rs = f->stop; while((r = *fmt++) && r != '%'){ FMTRCHAR(f, rt, rs, r); } f->nfmt += rt - (Rune *)f->to; f->to = rt; if(!r) return f->nfmt - nfmt; f->stop = rs; }else{ t = f->to; s = f->stop; while((r = *fmt++) && r != '%'){ FMTRUNE(f, t, f->stop, r); } f->nfmt += t - (char *)f->to; f->to = t; if(!r) return f->nfmt - nfmt; f->stop = s; } fmt = __fmtdispatch(f, (Rune*)fmt, 1); if(fmt == nil) return -1; } return 0; /* not reached */ } drawterm-20110822.orig/libc/sysfatal.c0000644000175000017500000000073711245145712017005 0ustar tinchotincho#include #include static void _sysfatalimpl(char *fmt, va_list arg) { char buf[1024]; vseprint(buf, buf+sizeof(buf), fmt, arg); if(argv0) fprint(2, "%s: %s\n", argv0, buf); else fprint(2, "%s\n", buf); #undef write write(2, buf, strlen(buf)); write(2, "\n", 1); panic("sysfatal"); } void (*_sysfatal)(char *fmt, va_list arg) = _sysfatalimpl; void sysfatal(char *fmt, ...) { va_list arg; va_start(arg, fmt); (*_sysfatal)(fmt, arg); va_end(arg); } drawterm-20110822.orig/libc/getpid.c0000644000175000017500000000030611245145712016423 0ustar tinchotincho#include #include int getpid(void) { char b[20]; int f; memset(b, 0, sizeof(b)); f = open("#c/pid", 0); if(f >= 0) { read(f, b, sizeof(b)); close(f); } return atol(b); } drawterm-20110822.orig/libc/fmt.c0000644000175000017500000000656011245145712015745 0ustar tinchotincho#include #include #include "fmtdef.h" enum { Maxfmt = 64 }; typedef struct Convfmt Convfmt; struct Convfmt { int c; volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */ }; struct { /* lock by calling __fmtlock, __fmtunlock */ int nfmt; Convfmt fmt[Maxfmt]; } fmtalloc; static Convfmt knownfmt[] = { ' ', __flagfmt, '#', __flagfmt, '%', __percentfmt, '+', __flagfmt, ',', __flagfmt, '-', __flagfmt, 'C', __runefmt, /* Plan 9 addition */ 'E', __efgfmt, #ifndef PLAN9PORT 'F', __efgfmt, /* ANSI only */ #endif 'G', __efgfmt, #ifndef PLAN9PORT 'L', __flagfmt, /* ANSI only */ #endif 'S', __runesfmt, /* Plan 9 addition */ 'X', __ifmt, 'b', __ifmt, /* Plan 9 addition */ 'c', __charfmt, 'd', __ifmt, 'e', __efgfmt, 'f', __efgfmt, 'g', __efgfmt, 'h', __flagfmt, #ifndef PLAN9PORT 'i', __ifmt, /* ANSI only */ #endif 'l', __flagfmt, 'n', __countfmt, 'o', __ifmt, 'p', __ifmt, 'r', __errfmt, 's', __strfmt, #ifdef PLAN9PORT 'u', __flagfmt, #else 'u', __ifmt, #endif 'x', __ifmt, 0, 0, }; int (*fmtdoquote)(int); /* * __fmtlock() must be set */ static int __fmtinstall(int c, Fmts f) { Convfmt *p, *ep; if(c<=0 || c>=65536) return -1; if(!f) f = __badfmt; ep = &fmtalloc.fmt[fmtalloc.nfmt]; for(p=fmtalloc.fmt; pc == c) break; if(p == &fmtalloc.fmt[Maxfmt]) return -1; p->fmt = f; if(p == ep){ /* installing a new format character */ fmtalloc.nfmt++; p->c = c; } return 0; } int fmtinstall(int c, int (*f)(Fmt*)) { int ret; __fmtlock(); ret = __fmtinstall(c, f); __fmtunlock(); return ret; } static Fmts fmtfmt(int c) { Convfmt *p, *ep; ep = &fmtalloc.fmt[fmtalloc.nfmt]; for(p=fmtalloc.fmt; pc == c){ while(p->fmt == 0) /* loop until value is updated */ ; return p->fmt; } /* is this a predefined format char? */ __fmtlock(); for(p=knownfmt; p->c; p++) if(p->c == c){ __fmtinstall(p->c, p->fmt); __fmtunlock(); return p->fmt; } __fmtunlock(); return __badfmt; } void* __fmtdispatch(Fmt *f, void *fmt, int isrunes) { Rune rune, r; int i, n; f->flags = 0; f->width = f->prec = 0; for(;;){ if(isrunes){ r = *(Rune*)fmt; fmt = (Rune*)fmt + 1; }else{ fmt = (char*)fmt + chartorune(&rune, (char*)fmt); r = rune; } f->r = r; switch(r){ case '\0': return nil; case '.': f->flags |= FmtWidth|FmtPrec; continue; case '0': if(!(f->flags & FmtWidth)){ f->flags |= FmtZero; continue; } /* fall through */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': i = 0; while(r >= '0' && r <= '9'){ i = i * 10 + r - '0'; if(isrunes){ r = *(Rune*)fmt; fmt = (Rune*)fmt + 1; }else{ r = *(char*)fmt; fmt = (char*)fmt + 1; } } if(isrunes) fmt = (Rune*)fmt - 1; else fmt = (char*)fmt - 1; numflag: if(f->flags & FmtWidth){ f->flags |= FmtPrec; f->prec = i; }else{ f->flags |= FmtWidth; f->width = i; } continue; case '*': i = va_arg(f->args, int); if(i < 0){ /* * negative precision => * ignore the precision. */ if(f->flags & FmtPrec){ f->flags &= ~FmtPrec; f->prec = 0; continue; } i = -i; f->flags |= FmtLeft; } goto numflag; } n = (*fmtfmt(r))(f); if(n < 0) return nil; if(n == 0) return fmt; } } drawterm-20110822.orig/libc/utfdef.h0000644000175000017500000000051711245145712016435 0ustar tinchotincho#define uchar _utfuchar #define ushort _utfushort #define uint _utfuint #define ulong _utfulong #define vlong _utfvlong #define uvlong _utfuvlong typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; #define nelem(x) (sizeof(x)/sizeof((x)[0])) #define nil ((void*)0) drawterm-20110822.orig/libc/runevsmprint.c0000644000175000017500000000211711245145712017725 0ustar tinchotincho#include #include #include "fmtdef.h" static int runeFmtStrFlush(Fmt *f) { Rune *s; int n; if(f->start == nil) return 0; n = (uintptr)f->farg; n *= 2; s = (Rune*)f->start; f->start = realloc(s, sizeof(Rune)*n); if(f->start == nil){ f->farg = nil; f->to = nil; f->stop = nil; free(s); return 0; } f->farg = (void*)(uintptr)n; f->to = (Rune*)f->start + ((Rune*)f->to - s); f->stop = (Rune*)f->start + n - 1; return 1; } int runefmtstrinit(Fmt *f) { int n; memset(f, 0, sizeof *f); f->runes = 1; n = 32; f->start = malloc(sizeof(Rune)*n); if(f->start == nil) return -1; f->to = f->start; f->stop = (Rune*)f->start + n - 1; f->flush = runeFmtStrFlush; f->farg = (void*)(uintptr)n; f->nfmt = 0; return 0; } /* * print into an allocated string buffer */ Rune* runevsmprint(char *fmt, va_list args) { Fmt f; int n; if(runefmtstrinit(&f) < 0) return nil; VA_COPY(f.args,args); n = dofmt(&f, fmt); VA_END(f.args); if(f.start == nil) return nil; if(n < 0){ free(f.start); return nil; } *(Rune*)f.to = '\0'; return (Rune*)f.start; } drawterm-20110822.orig/libc/runestrcpy.c0000644000175000017500000000021211245145712017361 0ustar tinchotincho#include #include Rune* runestrcpy(Rune *s1, Rune *s2) { Rune *os1; os1 = s1; while(*s1++ = *s2++) ; return os1; } drawterm-20110822.orig/libc/print.c0000644000175000017500000000027011245145712016303 0ustar tinchotincho#include #include #include "fmtdef.h" int print(char *fmt, ...) { int n; va_list args; va_start(args, fmt); n = vfprint(1, fmt, args); va_end(args); return n; } drawterm-20110822.orig/libc/fprint.c0000644000175000017500000000030211245145712016445 0ustar tinchotincho#include #include #include "fmtdef.h" int fprint(int fd, char *fmt, ...) { int n; va_list args; va_start(args, fmt); n = vfprint(fd, fmt, args); va_end(args); return n; } drawterm-20110822.orig/libc/utfecpy.c0000644000175000017500000000043411245145712016630 0ustar tinchotincho#include #include char* utfecpy(char *to, char *e, char *from) { char *end; if(to >= e) return to; end = memccpy(to, from, '\0', e - to); if(end == nil){ end = e-1; while(end>to && (*--end&0xC0)==0x80) ; *end = '\0'; }else{ end--; } return end; } drawterm-20110822.orig/libc/vsnprint.c0000644000175000017500000000056011245145712017034 0ustar tinchotincho#include #include #include "fmtdef.h" int vsnprint(char *buf, int len, char *fmt, va_list args) { Fmt f; if(len <= 0) return -1; f.runes = 0; f.start = buf; f.to = buf; f.stop = buf + len - 1; f.flush = 0; f.farg = nil; f.nfmt = 0; VA_COPY(f.args,args); dofmt(&f, fmt); VA_END(f.args); *(char*)f.to = '\0'; return (char*)f.to - buf; } drawterm-20110822.orig/libc/seprint.c0000644000175000017500000000033011245145712016630 0ustar tinchotincho#include #include #include "fmtdef.h" char* seprint(char *buf, char *e, char *fmt, ...) { char *p; va_list args; va_start(args, fmt); p = vseprint(buf, e, fmt, args); va_end(args); return p; } drawterm-20110822.orig/libc/strtoll.c0000644000175000017500000000245011245145712016654 0ustar tinchotincho#include #include #define VLONG_MAX ((vlong)~(((uvlong)1)<<63)) #define VLONG_MIN ((vlong)(((uvlong)1)<<63)) vlong strtoll(const char *nptr, char **endptr, int base) { char *p; vlong n, nn, m; int c, ovfl, v, neg, ndig; p = (char*)nptr; neg = 0; n = 0; ndig = 0; ovfl = 0; /* * White space */ for(;; p++) { switch(*p) { case ' ': case '\t': case '\n': case '\f': case '\r': case '\v': continue; } break; } /* * Sign */ if(*p=='-' || *p=='+') if(*p++ == '-') neg = 1; /* * Base */ if(base==0){ base = 10; if(*p == '0') { base = 8; if(p[1]=='x' || p[1]=='X') { p += 2; base = 16; } } } else if(base==16 && *p=='0') { if(p[1]=='x' || p[1]=='X') p += 2; } else if(base<0 || 36= base) break; if(n > m) ovfl = 1; nn = n*base + v; if(nn < n) ovfl = 1; n = nn; } Return: if(ndig == 0) p = (char*)nptr; if(endptr) *endptr = p; if(ovfl){ if(neg) return VLONG_MIN; return VLONG_MAX; } if(neg) return -n; return n; } drawterm-20110822.orig/libc/fmtrune.c0000644000175000017500000000051011245145712016624 0ustar tinchotincho#include #include #include "fmtdef.h" int fmtrune(Fmt *f, int r) { Rune *rt; char *t; int n; if(f->runes){ rt = (Rune*)f->to; FMTRCHAR(f, rt, f->stop, r); f->to = rt; n = 1; }else{ t = (char*)f->to; FMTRUNE(f, t, f->stop, r); n = t - (char*)f->to; f->to = t; } f->nfmt += n; return 0; } drawterm-20110822.orig/libc/nan.h0000644000175000017500000000016211245145712015730 0ustar tinchotinchoextern double __NaN(void); extern double __Inf(int); extern int __isNaN(double); extern int __isInf(double, int); drawterm-20110822.orig/libc/utflen.c0000644000175000017500000000036211245145712016446 0ustar tinchotincho#include #include int utflen(char *s) { int c; long n; Rune rune; n = 0; for(;;) { c = *(uchar*)s; if(c < Runeself) { if(c == 0) return n; s++; } else s += chartorune(&rune, s); n++; } return 0; } drawterm-20110822.orig/libc/fmtstr.c0000644000175000017500000000024711245145712016472 0ustar tinchotincho#include #include #include "fmtdef.h" char* fmtstrflush(Fmt *f) { if(f->start == nil) return nil; *(char*)f->to = '\0'; return (char*)f->start; } drawterm-20110822.orig/libc/lrand.c0000644000175000017500000000212511245145712016250 0ustar tinchotincho#include #include /* * algorithm by * D. P. Mitchell & J. A. Reeds */ #define LEN 607 #define TAP 273 #define MASK 0x7fffffffL #define A 48271 #define M 2147483647 #define Q 44488 #define R 3399 #define NORM (1.0/(1.0+MASK)) static ulong rng_vec[LEN]; static ulong* rng_tap = rng_vec; static ulong* rng_feed = 0; static Lock lk; static void isrand(long seed) { long lo, hi, x; int i; rng_tap = rng_vec; rng_feed = rng_vec+LEN-TAP; seed = seed%M; if(seed < 0) seed += M; if(seed == 0) seed = 89482311; x = seed; /* * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1) */ for(i = -20; i < LEN; i++) { hi = x / Q; lo = x % Q; x = A*lo - R*hi; if(x < 0) x += M; if(i >= 0) rng_vec[i] = x; } } void srand(long seed) { lock(&lk); isrand(seed); unlock(&lk); } long lrand(void) { ulong x; lock(&lk); rng_tap--; if(rng_tap < rng_vec) { if(rng_feed == 0) { isrand(1); rng_tap--; } rng_tap += LEN; } rng_feed--; if(rng_feed < rng_vec) rng_feed += LEN; x = (*rng_feed + *rng_tap) & MASK; *rng_feed = x; unlock(&lk); return x; } drawterm-20110822.orig/libc/fmtfdflush.c0000644000175000017500000000051211245145712017310 0ustar tinchotincho#include #include #include #include "fmtdef.h" /* * generic routine for flushing a formatting buffer * to a file descriptor */ int __fmtFdFlush(Fmt *f) { int n; n = (char*)f->to - (char*)f->start; if(n && write((uintptr_t)f->farg, f->start, n) != n) return 0; f->to = f->start; return 1; } drawterm-20110822.orig/libc/convM2S.c0000644000175000017500000001155111245145712016442 0ustar tinchotincho#include #include #include static uchar* gstring(uchar *p, uchar *ep, char **s) { uint n; if(p+BIT16SZ > ep) return nil; n = GBIT16(p); p += BIT16SZ - 1; if(p+n+1 > ep) return nil; /* move it down, on top of count, to make room for '\0' */ memmove(p, p + 1, n); p[n] = '\0'; *s = (char*)p; p += n+1; return p; } static uchar* gqid(uchar *p, uchar *ep, Qid *q) { if(p+QIDSZ > ep) return nil; q->type = GBIT8(p); p += BIT8SZ; q->vers = GBIT32(p); p += BIT32SZ; q->path = GBIT64(p); p += BIT64SZ; return p; } /* * no syntactic checks. * three causes for error: * 1. message size field is incorrect * 2. input buffer too short for its own data (counts too long, etc.) * 3. too many names or qids * gqid() and gstring() return nil if they would reach beyond buffer. * main switch statement checks range and also can fall through * to test at end of routine. */ uint convM2S(uchar *ap, uint nap, Fcall *f) { uchar *p, *ep; uint i, size; p = ap; ep = p + nap; if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep) return 0; size = GBIT32(p); p += BIT32SZ; if(size < BIT32SZ+BIT8SZ+BIT16SZ) return 0; f->type = GBIT8(p); p += BIT8SZ; f->tag = GBIT16(p); p += BIT16SZ; switch(f->type) { default: return 0; case Tversion: if(p+BIT32SZ > ep) return 0; f->msize = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->version); break; case Tflush: if(p+BIT16SZ > ep) return 0; f->oldtag = GBIT16(p); p += BIT16SZ; break; case Tauth: if(p+BIT32SZ > ep) return 0; f->afid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->uname); if(p == nil) break; p = gstring(p, ep, &f->aname); if(p == nil) break; break; case Tattach: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; if(p+BIT32SZ > ep) return 0; f->afid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->uname); if(p == nil) break; p = gstring(p, ep, &f->aname); if(p == nil) break; break; case Twalk: if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->newfid = GBIT32(p); p += BIT32SZ; f->nwname = GBIT16(p); p += BIT16SZ; if(f->nwname > MAXWELEM) return 0; for(i=0; inwname; i++){ p = gstring(p, ep, &f->wname[i]); if(p == nil) break; } break; case Topen: if(p+BIT32SZ+BIT8SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->mode = GBIT8(p); p += BIT8SZ; break; case Tcreate: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->name); if(p == nil) break; if(p+BIT32SZ+BIT8SZ > ep) return 0; f->perm = GBIT32(p); p += BIT32SZ; f->mode = GBIT8(p); p += BIT8SZ; break; case Tread: if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->offset = GBIT64(p); p += BIT64SZ; f->count = GBIT32(p); p += BIT32SZ; break; case Twrite: if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->offset = GBIT64(p); p += BIT64SZ; f->count = GBIT32(p); p += BIT32SZ; if(p+f->count > ep) return 0; f->data = (char*)p; p += f->count; break; case Tclunk: case Tremove: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; break; case Tstat: if(p+BIT32SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; break; case Twstat: if(p+BIT32SZ+BIT16SZ > ep) return 0; f->fid = GBIT32(p); p += BIT32SZ; f->nstat = GBIT16(p); p += BIT16SZ; if(p+f->nstat > ep) return 0; f->stat = p; p += f->nstat; break; /* */ case Rversion: if(p+BIT32SZ > ep) return 0; f->msize = GBIT32(p); p += BIT32SZ; p = gstring(p, ep, &f->version); break; case Rerror: p = gstring(p, ep, &f->ename); break; case Rflush: break; case Rauth: p = gqid(p, ep, &f->aqid); if(p == nil) break; break; case Rattach: p = gqid(p, ep, &f->qid); if(p == nil) break; break; case Rwalk: if(p+BIT16SZ > ep) return 0; f->nwqid = GBIT16(p); p += BIT16SZ; if(f->nwqid > MAXWELEM) return 0; for(i=0; inwqid; i++){ p = gqid(p, ep, &f->wqid[i]); if(p == nil) break; } break; case Ropen: case Rcreate: p = gqid(p, ep, &f->qid); if(p == nil) break; if(p+BIT32SZ > ep) return 0; f->iounit = GBIT32(p); p += BIT32SZ; break; case Rread: if(p+BIT32SZ > ep) return 0; f->count = GBIT32(p); p += BIT32SZ; if(p+f->count > ep) return 0; f->data = (char*)p; p += f->count; break; case Rwrite: if(p+BIT32SZ > ep) return 0; f->count = GBIT32(p); p += BIT32SZ; break; case Rclunk: case Rremove: break; case Rstat: if(p+BIT16SZ > ep) return 0; f->nstat = GBIT16(p); p += BIT16SZ; if(p+f->nstat > ep) return 0; f->stat = p; p += f->nstat; break; case Rwstat: break; } if(p==nil || p>ep) return 0; if(ap+size == p) return size; return 0; } drawterm-20110822.orig/libc/strtod.h0000644000175000017500000000017011245145712016472 0ustar tinchotinchoextern double __NaN(void); extern double __Inf(int); extern double __isNaN(double); extern double __isInf(double, int); drawterm-20110822.orig/libc/convS2M.c0000644000175000017500000001162611245145712016445 0ustar tinchotincho#include #include #include static uchar* pstring(uchar *p, char *s) { uint n; if(s == nil){ PBIT16(p, 0); p += BIT16SZ; return p; } n = strlen(s); PBIT16(p, n); p += BIT16SZ; memmove(p, s, n); p += n; return p; } static uchar* pqid(uchar *p, Qid *q) { PBIT8(p, q->type); p += BIT8SZ; PBIT32(p, q->vers); p += BIT32SZ; PBIT64(p, q->path); p += BIT64SZ; return p; } static uint stringsz(char *s) { if(s == nil) return BIT16SZ; return BIT16SZ+strlen(s); } uint sizeS2M(Fcall *f) { uint n; int i; n = 0; n += BIT32SZ; /* size */ n += BIT8SZ; /* type */ n += BIT16SZ; /* tag */ switch(f->type) { default: return 0; case Tversion: n += BIT32SZ; n += stringsz(f->version); break; case Tflush: n += BIT16SZ; break; case Tauth: n += BIT32SZ; n += stringsz(f->uname); n += stringsz(f->aname); break; case Tattach: n += BIT32SZ; n += BIT32SZ; n += stringsz(f->uname); n += stringsz(f->aname); break; case Twalk: n += BIT32SZ; n += BIT32SZ; n += BIT16SZ; for(i=0; inwname; i++) n += stringsz(f->wname[i]); break; case Topen: n += BIT32SZ; n += BIT8SZ; break; case Tcreate: n += BIT32SZ; n += stringsz(f->name); n += BIT32SZ; n += BIT8SZ; break; case Tread: n += BIT32SZ; n += BIT64SZ; n += BIT32SZ; break; case Twrite: n += BIT32SZ; n += BIT64SZ; n += BIT32SZ; n += f->count; break; case Tclunk: case Tremove: n += BIT32SZ; break; case Tstat: n += BIT32SZ; break; case Twstat: n += BIT32SZ; n += BIT16SZ; n += f->nstat; break; /* */ case Rversion: n += BIT32SZ; n += stringsz(f->version); break; case Rerror: n += stringsz(f->ename); break; case Rflush: break; case Rauth: n += QIDSZ; break; case Rattach: n += QIDSZ; break; case Rwalk: n += BIT16SZ; n += f->nwqid*QIDSZ; break; case Ropen: case Rcreate: n += QIDSZ; n += BIT32SZ; break; case Rread: n += BIT32SZ; n += f->count; break; case Rwrite: n += BIT32SZ; break; case Rclunk: break; case Rremove: break; case Rstat: n += BIT16SZ; n += f->nstat; break; case Rwstat: break; } return n; } uint convS2M(Fcall *f, uchar *ap, uint nap) { uchar *p; uint i, size; size = sizeS2M(f); if(size == 0) return 0; if(size > nap) return 0; p = (uchar*)ap; PBIT32(p, size); p += BIT32SZ; PBIT8(p, f->type); p += BIT8SZ; PBIT16(p, f->tag); p += BIT16SZ; switch(f->type) { default: return 0; case Tversion: PBIT32(p, f->msize); p += BIT32SZ; p = pstring(p, f->version); break; case Tflush: PBIT16(p, f->oldtag); p += BIT16SZ; break; case Tauth: PBIT32(p, f->afid); p += BIT32SZ; p = pstring(p, f->uname); p = pstring(p, f->aname); break; case Tattach: PBIT32(p, f->fid); p += BIT32SZ; PBIT32(p, f->afid); p += BIT32SZ; p = pstring(p, f->uname); p = pstring(p, f->aname); break; case Twalk: PBIT32(p, f->fid); p += BIT32SZ; PBIT32(p, f->newfid); p += BIT32SZ; PBIT16(p, f->nwname); p += BIT16SZ; if(f->nwname > MAXWELEM) return 0; for(i=0; inwname; i++) p = pstring(p, f->wname[i]); break; case Topen: PBIT32(p, f->fid); p += BIT32SZ; PBIT8(p, f->mode); p += BIT8SZ; break; case Tcreate: PBIT32(p, f->fid); p += BIT32SZ; p = pstring(p, f->name); PBIT32(p, f->perm); p += BIT32SZ; PBIT8(p, f->mode); p += BIT8SZ; break; case Tread: PBIT32(p, f->fid); p += BIT32SZ; PBIT64(p, f->offset); p += BIT64SZ; PBIT32(p, f->count); p += BIT32SZ; break; case Twrite: PBIT32(p, f->fid); p += BIT32SZ; PBIT64(p, f->offset); p += BIT64SZ; PBIT32(p, f->count); p += BIT32SZ; memmove(p, f->data, f->count); p += f->count; break; case Tclunk: case Tremove: PBIT32(p, f->fid); p += BIT32SZ; break; case Tstat: PBIT32(p, f->fid); p += BIT32SZ; break; case Twstat: PBIT32(p, f->fid); p += BIT32SZ; PBIT16(p, f->nstat); p += BIT16SZ; memmove(p, f->stat, f->nstat); p += f->nstat; break; /* */ case Rversion: PBIT32(p, f->msize); p += BIT32SZ; p = pstring(p, f->version); break; case Rerror: p = pstring(p, f->ename); break; case Rflush: break; case Rauth: p = pqid(p, &f->aqid); break; case Rattach: p = pqid(p, &f->qid); break; case Rwalk: PBIT16(p, f->nwqid); p += BIT16SZ; if(f->nwqid > MAXWELEM) return 0; for(i=0; inwqid; i++) p = pqid(p, &f->wqid[i]); break; case Ropen: case Rcreate: p = pqid(p, &f->qid); PBIT32(p, f->iounit); p += BIT32SZ; break; case Rread: PBIT32(p, f->count); p += BIT32SZ; memmove(p, f->data, f->count); p += f->count; break; case Rwrite: PBIT32(p, f->count); p += BIT32SZ; break; case Rclunk: break; case Rremove: break; case Rstat: PBIT16(p, f->nstat); p += BIT16SZ; memmove(p, f->stat, f->nstat); p += f->nstat; break; case Rwstat: break; } if(size != p-ap) return 0; return size; } drawterm-20110822.orig/libc/runestrchr.c0000644000175000017500000000031711245145712017350 0ustar tinchotincho#include #include Rune* runestrchr(Rune *s, Rune c) { Rune c0 = c; Rune c1; if(c == 0) { while(*s++) ; return s-1; } while(c1 = *s++) if(c1 == c0) return s-1; return 0; } drawterm-20110822.orig/libc/runestrlen.c0000644000175000017500000000013611245145712017351 0ustar tinchotincho#include #include long runestrlen(Rune *s) { return runestrchr(s, 0) - s; } drawterm-20110822.orig/libc/fcallfmt.c0000644000175000017500000001315411245145712016744 0ustar tinchotincho#include #include #include static uint dumpsome(char*, char*, char*, long); static void fdirconv(char*, char*, Dir*); static char *qidtype(char*, uchar); #define QIDFMT "(%.16llux %lud %s)" int fcallfmt(Fmt *fmt) { Fcall *f; int fid, type, tag, i; char buf[512], tmp[200]; char *p, *e; Dir *d; Qid *q; e = buf+sizeof(buf); f = va_arg(fmt->args, Fcall*); type = f->type; fid = f->fid; tag = f->tag; switch(type){ case Tversion: /* 100 */ seprint(buf, e, "Tversion tag %ud msize %ud version '%s'", tag, f->msize, f->version); break; case Rversion: seprint(buf, e, "Rversion tag %ud msize %ud version '%s'", tag, f->msize, f->version); break; case Tauth: /* 102 */ seprint(buf, e, "Tauth tag %ud afid %d uname %s aname %s", tag, f->afid, f->uname, f->aname); break; case Rauth: seprint(buf, e, "Rauth tag %ud qid " QIDFMT, tag, f->aqid.path, f->aqid.vers, qidtype(tmp, f->aqid.type)); break; case Tattach: /* 104 */ seprint(buf, e, "Tattach tag %ud fid %d afid %d uname %s aname %s", tag, fid, f->afid, f->uname, f->aname); break; case Rattach: seprint(buf, e, "Rattach tag %ud qid " QIDFMT, tag, f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type)); break; case Rerror: /* 107; 106 (Terror) illegal */ seprint(buf, e, "Rerror tag %ud ename %s", tag, f->ename); break; case Tflush: /* 108 */ seprint(buf, e, "Tflush tag %ud oldtag %ud", tag, f->oldtag); break; case Rflush: seprint(buf, e, "Rflush tag %ud", tag); break; case Twalk: /* 110 */ p = seprint(buf, e, "Twalk tag %ud fid %d newfid %d nwname %d ", tag, fid, f->newfid, f->nwname); if(f->nwname <= MAXWELEM) for(i=0; inwname; i++) p = seprint(p, e, "%d:%s ", i, f->wname[i]); break; case Rwalk: p = seprint(buf, e, "Rwalk tag %ud nwqid %ud ", tag, f->nwqid); if(f->nwqid <= MAXWELEM) for(i=0; inwqid; i++){ q = &f->wqid[i]; p = seprint(p, e, "%d:" QIDFMT " ", i, q->path, q->vers, qidtype(tmp, q->type)); } break; case Topen: /* 112 */ seprint(buf, e, "Topen tag %ud fid %ud mode %d", tag, fid, f->mode); break; case Ropen: seprint(buf, e, "Ropen tag %ud qid " QIDFMT " iounit %ud ", tag, f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit); break; case Tcreate: /* 114 */ seprint(buf, e, "Tcreate tag %ud fid %ud name %s perm %M mode %d", tag, fid, f->name, (ulong)f->perm, f->mode); break; case Rcreate: seprint(buf, e, "Rcreate tag %ud qid " QIDFMT " iounit %ud ", tag, f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit); break; case Tread: /* 116 */ seprint(buf, e, "Tread tag %ud fid %d offset %lld count %ud", tag, fid, f->offset, f->count); break; case Rread: p = seprint(buf, e, "Rread tag %ud count %ud ", tag, f->count); dumpsome(p, e, f->data, f->count); break; case Twrite: /* 118 */ p = seprint(buf, e, "Twrite tag %ud fid %d offset %lld count %ud ", tag, fid, f->offset, f->count); dumpsome(p, e, f->data, f->count); break; case Rwrite: seprint(buf, e, "Rwrite tag %ud count %ud", tag, f->count); break; case Tclunk: /* 120 */ seprint(buf, e, "Tclunk tag %ud fid %ud", tag, fid); break; case Rclunk: seprint(buf, e, "Rclunk tag %ud", tag); break; case Tremove: /* 122 */ seprint(buf, e, "Tremove tag %ud fid %ud", tag, fid); break; case Rremove: seprint(buf, e, "Rremove tag %ud", tag); break; case Tstat: /* 124 */ seprint(buf, e, "Tstat tag %ud fid %ud", tag, fid); break; case Rstat: p = seprint(buf, e, "Rstat tag %ud ", tag); if(f->nstat > sizeof tmp) seprint(p, e, " stat(%d bytes)", f->nstat); else{ d = (Dir*)tmp; convM2D(f->stat, f->nstat, d, (char*)(d+1)); seprint(p, e, " stat "); fdirconv(p+6, e, d); } break; case Twstat: /* 126 */ p = seprint(buf, e, "Twstat tag %ud fid %ud", tag, fid); if(f->nstat > sizeof tmp) seprint(p, e, " stat(%d bytes)", f->nstat); else{ d = (Dir*)tmp; convM2D(f->stat, f->nstat, d, (char*)(d+1)); seprint(p, e, " stat "); fdirconv(p+6, e, d); } break; case Rwstat: seprint(buf, e, "Rwstat tag %ud", tag); break; default: seprint(buf, e, "unknown type %d", type); } return fmtstrcpy(fmt, buf); } static char* qidtype(char *s, uchar t) { char *p; p = s; if(t & QTDIR) *p++ = 'd'; if(t & QTAPPEND) *p++ = 'a'; if(t & QTEXCL) *p++ = 'l'; if(t & QTAUTH) *p++ = 'A'; *p = '\0'; return s; } int dirfmt(Fmt *fmt) { char buf[160]; fdirconv(buf, buf+sizeof buf, va_arg(fmt->args, Dir*)); return fmtstrcpy(fmt, buf); } static void fdirconv(char *buf, char *e, Dir *d) { char tmp[16]; seprint(buf, e, "'%s' '%s' '%s' '%s' " "q " QIDFMT " m %#luo " "at %ld mt %ld l %lld " "t %d d %d", d->name, d->uid, d->gid, d->muid, d->qid.path, d->qid.vers, qidtype(tmp, d->qid.type), d->mode, d->atime, d->mtime, d->length, d->type, d->dev); } /* * dump out count (or DUMPL, if count is bigger) bytes from * buf to ans, as a string if they are all printable, * else as a series of hex bytes */ #define DUMPL 64 static uint dumpsome(char *ans, char *e, char *buf, long count) { int i, printable; char *p; if(buf == nil){ seprint(ans, e, ""); return strlen(ans); } printable = 1; if(count > DUMPL) count = DUMPL; for(i=0; i127) printable = 0; p = ans; *p++ = '\''; if(printable){ if(count > e-p-2) count = e-p-2; memmove(p, buf, count); p += count; }else{ if(2*count > e-p-2) count = (e-p-2)/2; for(i=0; i0 && i%4==0) *p++ = ' '; sprint(p, "%2.2ux", buf[i]); p += 2; } } *p++ = '\''; *p = 0; return p - ans; } drawterm-20110822.orig/libc/dial.c0000644000175000017500000000716711245145712016074 0ustar tinchotincho#include #include typedef struct DS DS; static int call(char*, char*, DS*); static int csdial(DS*); static void _dial_string_parse(char*, DS*); enum { Maxstring = 128, Maxpath = 256, }; struct DS { /* dist string */ char buf[Maxstring]; char *netdir; char *proto; char *rem; /* other args */ char *local; char *dir; int *cfdp; }; /* * the dialstring is of the form '[/net/]proto!dest' */ int dial(char *dest, char *local, char *dir, int *cfdp) { DS ds; int rv; char err[ERRMAX], alterr[ERRMAX]; ds.local = local; ds.dir = dir; ds.cfdp = cfdp; _dial_string_parse(dest, &ds); if(ds.netdir) return csdial(&ds); ds.netdir = "/net"; rv = csdial(&ds); if(rv >= 0) return rv; err[0] = '\0'; errstr(err, sizeof err); if(strstr(err, "refused") != 0){ werrstr("%s", err); return rv; } ds.netdir = "/net.alt"; rv = csdial(&ds); if(rv >= 0) return rv; alterr[0] = 0; errstr(alterr, sizeof alterr); if(strstr(alterr, "translate") || strstr(alterr, "does not exist")) werrstr("%s", err); else werrstr("%s", alterr); return rv; } static int csdial(DS *ds) { int n, fd, rv; char *p, buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX]; /* * open connection server */ snprint(buf, sizeof(buf), "%s/cs", ds->netdir); fd = open(buf, ORDWR); if(fd < 0){ /* no connection server, don't translate */ snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto); return call(clone, ds->rem, ds); } /* * ask connection server to translate */ snprint(buf, sizeof(buf), "%s!%s", ds->proto, ds->rem); if(write(fd, buf, strlen(buf)) < 0){ close(fd); return -1; } /* * loop through each address from the connection server till * we get one that works. */ *besterr = 0; rv = -1; seek(fd, 0, 0); strcpy(err, "cs gave empty translation list"); while((n = read(fd, buf, sizeof(buf) - 1)) > 0){ buf[n] = 0; p = strchr(buf, ' '); if(p == 0) continue; *p++ = 0; rv = call(buf, p, ds); if(rv >= 0) break; err[0] = '\0'; errstr(err, sizeof err); if(strstr(err, "does not exist") == 0) strcpy(besterr, err); } close(fd); if(rv < 0 && *besterr) werrstr("%s", besterr); else werrstr("%s", err); return rv; } static int call(char *clone, char *dest, DS *ds) { int fd, cfd, n; char name[Maxpath], data[Maxpath], *p; cfd = open(clone, ORDWR); if(cfd < 0) return -1; /* get directory name */ n = read(cfd, name, sizeof(name)-1); if(n < 0){ close(cfd); return -1; } name[n] = 0; for(p = name; *p == ' '; p++) ; snprint(name, sizeof(name), "%ld", strtoul(p, 0, 0)); p = strrchr(clone, '/'); *p = 0; if(ds->dir) snprint(ds->dir, NETPATHLEN, "%s/%s", clone, name); snprint(data, sizeof(data), "%s/%s/data", clone, name); /* connect */ if(ds->local) snprint(name, sizeof(name), "connect %s %s", dest, ds->local); else snprint(name, sizeof(name), "connect %s", dest); if(write(cfd, name, strlen(name)) < 0){ close(cfd); return -1; } /* open data connection */ fd = open(data, ORDWR); if(fd < 0){ print("open %s: %r\n", data); close(cfd); return -1; } if(ds->cfdp) *ds->cfdp = cfd; else close(cfd); return fd; } /* * parse a dial string */ static void _dial_string_parse(char *str, DS *ds) { char *p, *p2; strncpy(ds->buf, str, Maxstring); ds->buf[Maxstring-1] = 0; p = strchr(ds->buf, '!'); if(p == 0) { ds->netdir = 0; ds->proto = "net"; ds->rem = ds->buf; } else { if(*ds->buf != '/' && *ds->buf != '#'){ ds->netdir = 0; ds->proto = ds->buf; } else { for(p2 = p; *p2 != '/'; p2--) ; *p2++ = 0; ds->netdir = ds->buf; ds->proto = p2; } *p = 0; ds->rem = p + 1; } } drawterm-20110822.orig/libc/utfrune.c0000644000175000017500000000062111245145712016637 0ustar tinchotincho#include #include char* utfrune(char *s, long c) { long c1; Rune r; int n; if(c < Runesync) /* not part of utf sequence */ return strchr(s, c); for(;;) { c1 = *(uchar*)s; if(c1 < Runeself) { /* one byte rune */ if(c1 == 0) return 0; if(c1 == c) return s; s++; continue; } n = chartorune(&r, s); if(r == c) return s; s += n; } return 0; } drawterm-20110822.orig/libc/pushssl.c0000644000175000017500000000161111245145712016650 0ustar tinchotincho#include #include /* * Since the SSL device uses decimal file descriptors to name channels, * it is impossible for a user-level file server to stand in for the kernel device. * Thus we hard-code #D rather than use /net/ssl. */ int pushssl(int fd, char *alg, char *secin, char *secout, int *cfd) { char buf[8]; char dname[64]; int n, data, ctl; ctl = open("#D/ssl/clone", ORDWR); if(ctl < 0) return -1; n = read(ctl, buf, sizeof(buf)-1); if(n < 0) goto error; buf[n] = 0; sprint(dname, "#D/ssl/%s/data", buf); data = open(dname, ORDWR); if(data < 0) goto error; if(fprint(ctl, "fd %d", fd) < 0 || fprint(ctl, "secretin %s", secin) < 0 || fprint(ctl, "secretout %s", secout) < 0 || fprint(ctl, "alg %s", alg) < 0){ close(data); goto error; } close(fd); if(cfd != 0) *cfd = ctl; else close(ctl); return data; error: close(ctl); return -1; } drawterm-20110822.orig/libc/runesmprint.c0000644000175000017500000000030411245145712017533 0ustar tinchotincho#include #include #include "fmtdef.h" Rune* runesmprint(char *fmt, ...) { va_list args; Rune *p; va_start(args, fmt); p = runevsmprint(fmt, args); va_end(args); return p; } drawterm-20110822.orig/libc/utfutf.c0000644000175000017500000000060711245145712016470 0ustar tinchotincho#include #include /* * Return pointer to first occurrence of s2 in s1, * 0 if none */ char* utfutf(char *s1, char *s2) { char *p; long f, n1, n2; Rune r; n1 = chartorune(&r, s2); f = r; if(f <= Runesync) /* represents self */ return strstr(s1, s2); n2 = strlen(s2); for(p=s1; (p=utfrune(p, f)); p+=n1) if(strncmp(p, s2, n2) == 0) return p; return 0; } drawterm-20110822.orig/win32-factotum.c0000644000175000017500000000035611245145712017025 0ustar tinchotincho#include #include #include #include #include #include #include "drawterm.h" #undef getenv char* getuser(void) { return getenv("USER"); } int dialfactotum(void) { return -1; } drawterm-20110822.orig/gui-win32/0000755000175000017500000000000011245145711015616 5ustar tinchotinchodrawterm-20110822.orig/gui-win32/cload.c0000644000175000017500000000027411245145711017047 0ustar tinchotincho#include #include #include #include int cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { return _cloadmemimage(i, r, data, ndata); } drawterm-20110822.orig/gui-win32/wstrtoutf.c0000644000175000017500000000063011245145711020042 0ustar tinchotincho#include #include int wstrutflen(Rune *s) { int n; for(n=0; *s; n+=runelen(*s),s++) ; return n; } int wstrtoutf(char *s, Rune *t, int n) { int i; char *s0; s0 = s; if(n <= 0) return wstrutflen(t)+1; while(*t) { if(n < UTFmax+1 && n < runelen(*t)+1) { *s = 0; return i+wstrutflen(t)+1; } i = runetochar(s, t); s += i; n -= i; t++; } *s = 0; return s-s0; } drawterm-20110822.orig/gui-win32/Makefile0000644000175000017500000000033411245145711017256 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libgui.a OFILES=\ alloc.$O\ cload.$O\ draw.$O\ load.$O\ screen.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/gui-win32/screen.c0000644000175000017500000002660511245145711017252 0ustar tinchotincho#define _WIN32_WINNT 0x0500 #include #undef Rectangle #define Rectangle _Rectangle #include "u.h" #include "lib.h" #include "kern/dat.h" #include "kern/fns.h" #include "error.h" #include "user.h" #include #include #include "screen.h" #include "keyboard.h" Memimage *gscreen; Screeninfo screen; extern int mousequeue; static int depth; static HINSTANCE inst; static HWND window; static HPALETTE palette; static LOGPALETTE *logpal; static Lock gdilock; static BITMAPINFO *bmi; static HCURSOR hcursor; static void winproc(void *); static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); static void paletteinit(void); static void bmiinit(void); static int readybit; static Rendez rend; Point ZP; static int isready(void*a) { return readybit; } void screeninit(void) { int fmt; int dx, dy; memimageinit(); if(depth == 0) depth = GetDeviceCaps(GetDC(NULL), BITSPIXEL); switch(depth){ case 32: screen.dibtype = DIB_RGB_COLORS; screen.depth = 32; fmt = XRGB32; break; case 24: screen.dibtype = DIB_RGB_COLORS; screen.depth = 24; fmt = RGB24; break; case 16: screen.dibtype = DIB_RGB_COLORS; screen.depth = 16; fmt = RGB15; /* [sic] */ break; case 8: default: screen.dibtype = DIB_PAL_COLORS; screen.depth = 8; depth = 8; fmt = CMAP8; break; } dx = GetDeviceCaps(GetDC(NULL), HORZRES); dy = GetDeviceCaps(GetDC(NULL), VERTRES); gscreen = allocmemimage(Rect(0,0,dx,dy), fmt); kproc("winscreen", winproc, 0); ksleep(&rend, isready, 0); } uchar* attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X) { *r = gscreen->r; *chan = gscreen->chan; *depth = gscreen->depth; *width = gscreen->width; *softscreen = 1; return gscreen->data->bdata; } void flushmemscreen(Rectangle r) { screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP, gscreen->width*sizeof(ulong)); // Sleep(100); } void screenload(Rectangle r, int depth, uchar *p, Point pt, int step) { int dx, dy, delx; HDC hdc; RECT winr; if(depth != gscreen->depth) panic("screenload: bad ldepth"); /* * Sometimes we do get rectangles that are off the * screen to the negative axes, for example, when * dragging around a window border in a Move operation. */ if(rectclip(&r, gscreen->r) == 0) return; if((step&3) != 0 || ((pt.x*depth)%32) != 0 || ((ulong)p&3) != 0) panic("screenload: bad params %d %d %ux", step, pt.x, p); dx = r.max.x - r.min.x; dy = r.max.y - r.min.y; if(dx <= 0 || dy <= 0) return; if(depth == 24) delx = r.min.x % 4; else delx = r.min.x & (31/depth); p += (r.min.y-pt.y)*step; p += ((r.min.x-delx-pt.x)*depth)>>3; if(GetWindowRect(window, &winr)==0) return; if(rectclip(&r, Rect(0, 0, winr.right-winr.left, winr.bottom-winr.top))==0) return; lock(&gdilock); hdc = GetDC(window); SelectPalette(hdc, palette, 0); RealizePalette(hdc); //FillRect(hdc,(void*)&r, GetStockObject(BLACK_BRUSH)); //GdiFlush(); //Sleep(100); bmi->bmiHeader.biWidth = (step*8)/depth; bmi->bmiHeader.biHeight = -dy; /* - => origin upper left */ StretchDIBits(hdc, r.min.x, r.min.y, dx, dy, delx, 0, dx, dy, p, bmi, screen.dibtype, SRCCOPY); ReleaseDC(window, hdc); GdiFlush(); unlock(&gdilock); } static void winproc(void *a) { WNDCLASS wc; MSG msg; inst = GetModuleHandle(NULL); paletteinit(); bmiinit(); terminit(); wc.style = 0; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = inst; wc.hIcon = LoadIcon(inst, NULL); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = L"9pmgraphics"; RegisterClass(&wc); window = CreateWindowEx( 0, /* extended style */ L"9pmgraphics", /* class */ L"drawterm screen", /* caption */ WS_OVERLAPPEDWINDOW, /* style */ CW_USEDEFAULT, /* init. x pos */ CW_USEDEFAULT, /* init. y pos */ CW_USEDEFAULT, /* init. x size */ CW_USEDEFAULT, /* init. y size */ NULL, /* parent window (actually owner window for overlapped)*/ NULL, /* menu handle */ inst, /* program handle */ NULL /* create parms */ ); if(window == nil) panic("can't make window\n"); ShowWindow(window, SW_SHOWDEFAULT); UpdateWindow(window); readybit = 1; wakeup(&rend); screen.reshaped = 0; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // MessageBox(0, "winproc", "exits", MB_OK); ExitProcess(0); } int col(int v, int n) { int i, c; c = 0; for(i = 0; i < 8; i += n) c |= v << (16-(n+i)); return c >> 8; } void paletteinit(void) { PALETTEENTRY *pal; int r, g, b, cr, cg, cb, v; int num, den; int i, j; logpal = mallocz(sizeof(LOGPALETTE) + 256*sizeof(PALETTEENTRY), 1); if(logpal == nil) panic("out of memory"); logpal->palVersion = 0x300; logpal->palNumEntries = 256; pal = logpal->palPalEntry; for(r=0,i=0; r<4; r++) { for(v=0; v<4; v++,i+=16){ for(g=0,j=v-r; g<4; g++) { for(b=0; b<4; b++,j++){ den=r; if(g>den) den=g; if(b>den) den=b; /* divide check -- pick grey shades */ if(den==0) cr=cg=cb=v*17; else{ num=17*(4*den+v); cr=r*num/den; cg=g*num/den; cb=b*num/den; } pal[i+(j&15)].peRed = cr; pal[i+(j&15)].peGreen = cg; pal[i+(j&15)].peBlue = cb; pal[i+(j&15)].peFlags = 0; } } } } palette = CreatePalette(logpal); } void getcolor(ulong i, ulong *r, ulong *g, ulong *b) { PALETTEENTRY *pal; pal = logpal->palPalEntry; *r = pal[i].peRed; *g = pal[i].peGreen; *b = pal[i].peBlue; } void bmiinit(void) { ushort *p; int i; bmi = mallocz(sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD), 1); if(bmi == 0) panic("out of memory"); bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi->bmiHeader.biWidth = 0; bmi->bmiHeader.biHeight = 0; /* - => origin upper left */ bmi->bmiHeader.biPlanes = 1; bmi->bmiHeader.biBitCount = depth; bmi->bmiHeader.biCompression = BI_RGB; bmi->bmiHeader.biSizeImage = 0; bmi->bmiHeader.biXPelsPerMeter = 0; bmi->bmiHeader.biYPelsPerMeter = 0; bmi->bmiHeader.biClrUsed = 0; bmi->bmiHeader.biClrImportant = 0; /* number of important colors: 0 means all */ p = (ushort*)bmi->bmiColors; for(i = 0; i < 256; i++) p[i] = i; } LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { PAINTSTRUCT paint; HDC hdc; LONG x, y, b; int i; Rectangle r; switch(msg) { case WM_CREATE: break; case WM_SETCURSOR: /* User set */ if(hcursor != NULL) { SetCursor(hcursor); return 1; } return DefWindowProc(hwnd, msg, wparam, lparam); case WM_MOUSEWHEEL: if ((int)(wparam & 0xFFFF0000)>0) b|=8; else b|=16; case WM_MOUSEMOVE: case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: x = LOWORD(lparam); y = HIWORD(lparam); b = 0; if(wparam & MK_LBUTTON) b = 1; if(wparam & MK_MBUTTON) b |= 2; if(wparam & MK_RBUTTON) { if(wparam & MK_SHIFT) b |= 2; else b |= 4; } lock(&mouse.lk); i = mouse.wi; if(mousequeue) { if(i == mouse.ri || mouse.lastb != b || mouse.trans) { mouse.wi = (i+1)%Mousequeue; if(mouse.wi == mouse.ri) mouse.ri = (mouse.ri+1)%Mousequeue; mouse.trans = mouse.lastb != b; } else { i = (i-1+Mousequeue)%Mousequeue; } } else { mouse.wi = (i+1)%Mousequeue; mouse.ri = i; } mouse.queue[i].xy.x = x; mouse.queue[i].xy.y = y; mouse.queue[i].buttons = b; mouse.queue[i].msec = ticks(); mouse.lastb = b; unlock(&mouse.lk); wakeup(&mouse.r); break; case WM_CHAR: /* repeat count is lparam & 0xf */ switch(wparam){ case '\n': wparam = '\r'; break; case '\r': wparam = '\n'; break; } kbdputc(kbdq, wparam); break; case WM_SYSKEYUP: break; case WM_SYSKEYDOWN: case WM_KEYDOWN: switch(wparam) { case VK_MENU: kbdputc(kbdq, Kalt); break; case VK_INSERT: kbdputc(kbdq, Kins); break; case VK_DELETE: // kbdputc(kbdq, Kdel); kbdputc(kbdq, 0x7f); // should have Kdel in keyboard.h break; case VK_UP: kbdputc(kbdq, Kup); break; case VK_DOWN: kbdputc(kbdq, Kdown); break; case VK_LEFT: kbdputc(kbdq, Kleft); break; case VK_RIGHT: kbdputc(kbdq, Kright); break; } break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PALETTECHANGED: if((HWND)wparam == hwnd) break; /* fall through */ case WM_QUERYNEWPALETTE: hdc = GetDC(hwnd); SelectPalette(hdc, palette, 0); if(RealizePalette(hdc) != 0) InvalidateRect(hwnd, nil, 0); ReleaseDC(hwnd, hdc); break; case WM_PAINT: hdc = BeginPaint(hwnd, &paint); r.min.x = paint.rcPaint.left; r.min.y = paint.rcPaint.top; r.max.x = paint.rcPaint.right; r.max.y = paint.rcPaint.bottom; flushmemscreen(r); EndPaint(hwnd, &paint); break; case WM_COMMAND: case WM_SETFOCUS: case WM_DEVMODECHANGE: case WM_WININICHANGE: case WM_INITMENU: default: return DefWindowProc(hwnd, msg, wparam, lparam); } return 0; } void mouseset(Point xy) { POINT pt; pt.x = xy.x; pt.y = xy.y; MapWindowPoints(window, 0, &pt, 1); SetCursorPos(pt.x, pt.y); } void setcursor(void) { HCURSOR nh; int x, y, h, w; uchar *sp, *cp; uchar *and, *xor; h = GetSystemMetrics(SM_CYCURSOR); w = (GetSystemMetrics(SM_CXCURSOR)+7)/8; and = mallocz(h*w, 1); memset(and, 0xff, h*w); xor = mallocz(h*w, 1); lock(&cursor.lk); for(y=0,sp=cursor.set,cp=cursor.clr; y<16; y++) { for(x=0; x<2; x++) { and[y*w+x] = ~(*sp|*cp); xor[y*w+x] = ~*sp & *cp; cp++; sp++; } } nh = CreateCursor(inst, -cursor.offset.x, -cursor.offset.y, GetSystemMetrics(SM_CXCURSOR), h, and, xor); if(nh != NULL) { SetCursor(nh); if(hcursor != NULL) DestroyCursor(hcursor); hcursor = nh; } unlock(&cursor.lk); free(and); free(xor); PostMessage(window, WM_SETCURSOR, (int)window, 0); } void cursorarrow(void) { if(hcursor != 0) { DestroyCursor(hcursor); hcursor = 0; } SetCursor(LoadCursor(0, IDC_ARROW)); PostMessage(window, WM_SETCURSOR, (int)window, 0); } void setcolor(ulong index, ulong red, ulong green, ulong blue) { } uchar* clipreadunicode(HANDLE h) { Rune *p; int n; uchar *q; p = GlobalLock(h); n = wstrutflen(p)+1; q = malloc(n); wstrtoutf(q, p, n); GlobalUnlock(h); return q; } uchar * clipreadutf(HANDLE h) { uchar *p; p = GlobalLock(h); p = strdup(p); GlobalUnlock(h); return p; } char* clipread(void) { HANDLE h; uchar *p; if(!OpenClipboard(window)) { oserror(); return strdup(""); } if((h = GetClipboardData(CF_UNICODETEXT))) p = clipreadunicode(h); else if((h = GetClipboardData(CF_TEXT))) p = clipreadutf(h); else { oserror(); p = strdup(""); } CloseClipboard(); return p; } int clipwrite(char *buf) { HANDLE h; char *p, *e; Rune *rp; int n = strlen(buf); if(!OpenClipboard(window)) { oserror(); return -1; } if(!EmptyClipboard()) { oserror(); CloseClipboard(); return -1; } h = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, (n+1)*sizeof(Rune)); if(h == NULL) panic("out of memory"); rp = GlobalLock(h); p = buf; e = p+n; while(p #include #include #include int loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { return _loadmemimage(i, r, data, ndata); } drawterm-20110822.orig/gui-win32/draw.c0000644000175000017500000000055511245145711016724 0ustar tinchotincho#include #include #include #include void memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op) { _memimagedraw(_memimagedrawsetup(dst, r, src, sp, mask, mp, op)); } ulong pixelbits(Memimage *m, Point p) { return _pixelbits(m, p); } void memimageinit(void) { _memimageinit(); } drawterm-20110822.orig/gui-win32/alloc.c0000644000175000017500000000043611245145711017057 0ustar tinchotincho#include #include #include #include Memimage* allocmemimage(Rectangle r, ulong chan) { return _allocmemimage(r, chan); } void freememimage(Memimage *i) { _freememimage(i); } void memfillcolor(Memimage *i, ulong val) { _memfillcolor(i, val); } drawterm-20110822.orig/exportfs/0000755000175000017500000000000011506541252015744 5ustar tinchotinchodrawterm-20110822.orig/exportfs/exportsrv.c0000644000175000017500000002545011506541252020172 0ustar tinchotincho#include #include #include #define Extern extern #include "exportfs.h" char Ebadfid[] = "Bad fid"; char Enotdir[] = "Not a directory"; char Edupfid[] = "Fid already in use"; char Eopen[] = "Fid already opened"; char Exmnt[] = "Cannot .. past mount point"; char Emip[] = "Mount in progress"; char Enopsmt[] = "Out of pseudo mount points"; char Enomem[] = "No memory"; char Eversion[] = "Bad 9P2000 version"; int iounit(int x) { return 8*8192+IOHDRSZ; } void* emallocz(ulong n) { void *v; v = mallocz(n, 1); if(v == nil) panic("out of memory"); return v; } void Xversion(Fsrpc *t) { Fcall rhdr; if(t->work.msize > messagesize) t->work.msize = messagesize; messagesize = t->work.msize; if(strncmp(t->work.version, "9P2000", 6) != 0){ reply(&t->work, &rhdr, Eversion); return; } rhdr.version = "9P2000"; rhdr.msize = t->work.msize; reply(&t->work, &rhdr, 0); t->busy = 0; } void Xauth(Fsrpc *t) { Fcall rhdr; reply(&t->work, &rhdr, "exportfs: authentication not required"); t->busy = 0; } void Xflush(Fsrpc *t) { Fsrpc *w, *e; Fcall rhdr; e = &Workq[Nr_workbufs]; for(w = Workq; w < e; w++) { if(w->work.tag == t->work.oldtag) { DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint); if(w->busy && w->pid) { w->flushtag = t->work.tag; DEBUG(DFD, "\tset flushtag %d\n", t->work.tag); // if(w->canint) // postnote(PNPROC, w->pid, "flush"); t->busy = 0; return; } } } reply(&t->work, &rhdr, 0); DEBUG(DFD, "\tflush reply\n"); t->busy = 0; } void Xattach(Fsrpc *t) { Fcall rhdr; Fid *f; f = newfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } if(srvfd >= 0){ /* if(psmpt == 0){ Nomount: reply(&t->work, &rhdr, Enopsmt); t->busy = 0; freefid(t->work.fid); return; } for(i=0; i= Npsmpt) goto Nomount; sprint(buf, "%d", i); f->f = file(psmpt, buf); if(f->f == nil) goto Nomount; sprint(buf, "/mnt/exportfs/%d", i); nfd = dup(srvfd, -1); if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){ errstr(buf, sizeof buf); reply(&t->work, &rhdr, buf); t->busy = 0; freefid(t->work.fid); close(nfd); return; } psmap[i] = 1; f->mid = i; */ }else{ f->f = root; f->f->ref++; } rhdr.qid = f->f->qid; reply(&t->work, &rhdr, 0); t->busy = 0; } Fid* clonefid(Fid *f, int new) { Fid *n; n = newfid(new); if(n == 0) { n = getfid(new); if(n == 0) fatal("inconsistent fids"); if(n->fid >= 0) close(n->fid); freefid(new); n = newfid(new); if(n == 0) fatal("inconsistent fids2"); } n->f = f->f; n->f->ref++; return n; } void Xwalk(Fsrpc *t) { char err[ERRMAX], *e; Fcall rhdr; Fid *f, *nf; File *wf; int i; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } nf = nil; if(t->work.newfid != t->work.fid){ nf = clonefid(f, t->work.newfid); f = nf; } rhdr.nwqid = 0; e = nil; for(i=0; iwork.nwname; i++){ if(i == MAXWELEM){ e = "Too many path elements"; break; } if(strcmp(t->work.wname[i], "..") == 0) { if(f->f->parent == nil) { e = Exmnt; break; } wf = f->f->parent; wf->ref++; goto Accept; } wf = file(f->f, t->work.wname[i]); if(wf == 0){ errstr(err, sizeof err); e = err; break; } Accept: freefile(f->f); rhdr.wqid[rhdr.nwqid++] = wf->qid; f->f = wf; continue; } if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname)) freefid(t->work.newfid); if(rhdr.nwqid > 0) e = nil; reply(&t->work, &rhdr, e); t->busy = 0; } void Xclunk(Fsrpc *t) { Fcall rhdr; Fid *f; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } if(f->fid >= 0) close(f->fid); freefid(t->work.fid); reply(&t->work, &rhdr, 0); t->busy = 0; } void Xstat(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; Dir *d; int s; uchar *statbuf; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } if(f->fid >= 0) d = dirfstat(f->fid); else { path = makepath(f->f, ""); d = dirstat(path); free(path); } if(d == nil) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } d->qid.path = f->f->qidt->uniqpath; s = sizeD2M(d); statbuf = emallocz(s); s = convD2M(d, statbuf, s); free(d); rhdr.nstat = s; rhdr.stat = statbuf; reply(&t->work, &rhdr, 0); free(statbuf); t->busy = 0; } static int getiounit(int fd) { int n; n = iounit(fd); if(n > messagesize-IOHDRSZ) n = messagesize-IOHDRSZ; return n; } void Xcreate(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; File *nf; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } path = makepath(f->f, t->work.name); f->fid = create(path, t->work.mode, t->work.perm); free(path); if(f->fid < 0) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } nf = file(f->f, t->work.name); if(nf == 0) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } f->mode = t->work.mode; freefile(f->f); f->f = nf; rhdr.qid = f->f->qid; rhdr.iounit = getiounit(f->fid); reply(&t->work, &rhdr, 0); t->busy = 0; } void Xremove(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } path = makepath(f->f, ""); DEBUG(DFD, "\tremove: %s\n", path); if(remove(path) < 0) { free(path); errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } free(path); f->f->inval = 1; if(f->fid >= 0) close(f->fid); freefid(t->work.fid); reply(&t->work, &rhdr, 0); t->busy = 0; } void Xwstat(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; int s; char *strings; Dir d; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } strings = emallocz(t->work.nstat); /* ample */ if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){ rerrstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; free(strings); return; } if(f->fid >= 0) s = dirfwstat(f->fid, &d); else { path = makepath(f->f, ""); s = dirwstat(path, &d); free(path); } if(s < 0) { rerrstr(err, sizeof err); reply(&t->work, &rhdr, err); } else { /* wstat may really be rename */ if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){ free(f->f->name); f->f->name = estrdup(d.name); } reply(&t->work, &rhdr, 0); } free(strings); t->busy = 0; } void slave(Fsrpc *f) { Proc *p; int pid; static int nproc; for(;;) { for(p = Proclist; p; p = p->next) { if(p->busy == 0) { f->pid = p->pid; p->busy = 1; pid = (uintptr)rendezvous((void*)(uintptr)p->pid, f); if(pid != p->pid) fatal("rendezvous sync fail"); return; } } if(++nproc > MAXPROC) fatal("too many procs"); pid = kproc("slave", blockingslave, nil); DEBUG(DFD, "slave pid %d\n", pid); if(pid == -1) fatal("kproc"); p = malloc(sizeof(Proc)); if(p == 0) fatal("out of memory"); p->busy = 0; p->pid = pid; p->next = Proclist; Proclist = p; DEBUG(DFD, "parent %d rendez\n", pid); rendezvous((void*)(uintptr)pid, p); DEBUG(DFD, "parent %d went\n", pid); } } void blockingslave(void *x) { Fsrpc *p; Fcall rhdr; Proc *m; int pid; USED(x); notify(flushaction); pid = getpid(); DEBUG(DFD, "blockingslave %d rendez\n", pid); m = (Proc*)rendezvous((void*)(uintptr)pid, 0); DEBUG(DFD, "blockingslave %d rendez got %p\n", pid, m); for(;;) { p = rendezvous((void*)(uintptr)pid, (void*)(uintptr)pid); if((uintptr)p == ~(uintptr)0) /* Interrupted */ continue; DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid); if(p->flushtag != NOTAG) goto flushme; switch(p->work.type) { case Tread: slaveread(p); break; case Twrite: slavewrite(p); break; case Topen: slaveopen(p); break; default: reply(&p->work, &rhdr, "exportfs: slave type error"); } if(p->flushtag != NOTAG) { flushme: p->work.type = Tflush; p->work.tag = p->flushtag; reply(&p->work, &rhdr, 0); } p->busy = 0; m->busy = 0; } } int openmount(int sfd) { werrstr("openmount not implemented"); return -1; } void slaveopen(Fsrpc *p) { char err[ERRMAX], *path; Fcall *work, rhdr; Fid *f; Dir *d; work = &p->work; f = getfid(work->fid); if(f == 0) { reply(work, &rhdr, Ebadfid); return; } if(f->fid >= 0) { close(f->fid); f->fid = -1; } path = makepath(f->f, ""); DEBUG(DFD, "\topen: %s %d\n", path, work->mode); p->canint = 1; if(p->flushtag != NOTAG){ free(path); return; } /* There is a race here I ignore because there are no locks */ f->fid = open(path, work->mode); free(path); p->canint = 0; if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) { Error: errstr(err, sizeof err); reply(work, &rhdr, err); return; } f->f->qid = d->qid; free(d); if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */ f->fid = openmount(f->fid); if(f->fid < 0) goto Error; } DEBUG(DFD, "\topen: fd %d\n", f->fid); f->mode = work->mode; rhdr.iounit = getiounit(f->fid); rhdr.qid = f->f->qid; reply(work, &rhdr, 0); } void slaveread(Fsrpc *p) { Fid *f; int n, r; Fcall *work, rhdr; char *data, err[ERRMAX]; work = &p->work; f = getfid(work->fid); if(f == 0) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; p->canint = 1; if(p->flushtag != NOTAG) return; data = malloc(n); if(data == nil) fatal(Enomem); /* can't just call pread, since directories must update the offset */ r = pread(f->fid, data, n, work->offset); p->canint = 0; if(r < 0) { free(data); errstr(err, sizeof err); reply(work, &rhdr, err); return; } DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r); rhdr.data = data; rhdr.count = r; reply(work, &rhdr, 0); free(data); } void slavewrite(Fsrpc *p) { char err[ERRMAX]; Fcall *work, rhdr; Fid *f; int n; work = &p->work; f = getfid(work->fid); if(f == 0) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; p->canint = 1; if(p->flushtag != NOTAG) return; n = pwrite(f->fid, work->data, n, work->offset); p->canint = 0; if(n < 0) { errstr(err, sizeof err); reply(work, &rhdr, err); return; } DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid); rhdr.count = n; reply(work, &rhdr, 0); } void reopen(Fid *f) { USED(f); fatal("reopen"); } void flushaction(void *a, char *cause) { USED(a); if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) { fprint(2, "exportsrv: note: %s\n", cause); exits("noted"); } if(strncmp(cause, "kill", 4) == 0) noted(NDFLT); noted(NCONT); } drawterm-20110822.orig/exportfs/exportfs.c0000644000175000017500000002033611506541252017766 0ustar tinchotincho/* * exportfs - Export a plan 9 name space across a network */ #include #include #include #include #include "drawterm.h" #define Extern #include "exportfs.h" /* #define QIDPATH ((1LL<<48)-1) */ #define QIDPATH ((((vlong)1)<<48)-1) vlong newqid = 0; void (*fcalls[256])(Fsrpc*); /* accounting and debugging counters */ int filecnt; int freecnt; int qidcnt; int qfreecnt; int ncollision; int netfd; int exportfs(int fd, int msgsz) { char buf[ERRMAX], ebuf[ERRMAX]; Fsrpc *r; int i, n; fcalls[Tversion] = Xversion; fcalls[Tauth] = Xauth; fcalls[Tflush] = Xflush; fcalls[Tattach] = Xattach; fcalls[Twalk] = Xwalk; fcalls[Topen] = slave; fcalls[Tcreate] = Xcreate; fcalls[Tclunk] = Xclunk; fcalls[Tread] = slave; fcalls[Twrite] = slave; fcalls[Tremove] = Xremove; fcalls[Tstat] = Xstat; fcalls[Twstat] = Xwstat; srvfd = -1; netfd = fd; //dbg = 1; strcpy(buf, "this is buf"); strcpy(ebuf, "this is ebuf"); DEBUG(DFD, "exportfs: started\n"); // rfork(RFNOTEG); messagesize = msgsz; if(messagesize == 0){ messagesize = iounit(netfd); if(messagesize == 0) messagesize = 8*8192+IOHDRSZ; } Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); // for(i=0; ibuf, messagesize); if(n <= 0) fatal("eof: n=%d %r", n); if(convM2S(r->buf, n, &r->work) == 0){ iprint("convM2S %d byte message\n", n); for(i=0; ibuf[i]); if(i%16 == 15) iprint("\n"); } if(i%16) iprint("\n"); fatal("convM2S format error"); } if(0) iprint("<- %F\n", &r->work); DEBUG(DFD, "%F\n", &r->work); (fcalls[r->work.type])(r); } } void reply(Fcall *r, Fcall *t, char *err) { uchar *data; int m, n; t->tag = r->tag; t->fid = r->fid; if(err) { t->type = Rerror; t->ename = err; } else t->type = r->type + 1; if(0) iprint("-> %F\n", t); DEBUG(DFD, "\t%F\n", t); data = malloc(messagesize); /* not mallocz; no need to clear */ if(data == nil) fatal(Enomem); n = convS2M(t, data, messagesize); if((m=write(netfd, data, n))!=n){ iprint("wrote %d got %d (%r)\n", n, m); fatal("write"); } free(data); } Fid * getfid(int nr) { Fid *f; for(f = fidhash(nr); f; f = f->next) if(f->nr == nr) return f; return 0; } int freefid(int nr) { Fid *f, **l; char buf[128]; l = &fidhash(nr); for(f = *l; f; f = f->next) { if(f->nr == nr) { if(f->mid) { sprint(buf, "/mnt/exportfs/%d", f->mid); unmount(0, buf); psmap[f->mid] = 0; } if(f->f) { freefile(f->f); f->f = nil; } *l = f->next; f->next = fidfree; fidfree = f; return 1; } l = &f->next; } return 0; } Fid * newfid(int nr) { Fid *new, **l; int i; l = &fidhash(nr); for(new = *l; new; new = new->next) if(new->nr == nr) return 0; if(fidfree == 0) { fidfree = emallocz(sizeof(Fid) * Fidchunk); for(i = 0; i < Fidchunk-1; i++) fidfree[i].next = &fidfree[i+1]; fidfree[Fidchunk-1].next = 0; } new = fidfree; fidfree = new->next; memset(new, 0, sizeof(Fid)); new->next = *l; *l = new; new->nr = nr; new->fid = -1; new->mid = 0; return new; } Fsrpc * getsbuf(void) { static int ap; int look, rounds; Fsrpc *wb; int small_instead_of_fast = 1; if(small_instead_of_fast) ap = 0; /* so we always start looking at the beginning and reuse buffers */ for(rounds = 0; rounds < 10; rounds++) { for(look = 0; look < Nr_workbufs; look++) { if(++ap == Nr_workbufs) ap = 0; if(Workq[ap].busy == 0) break; } if(look == Nr_workbufs){ sleep(10 * rounds); continue; } wb = &Workq[ap]; wb->pid = 0; wb->canint = 0; wb->flushtag = NOTAG; wb->busy = 1; if(wb->buf == nil) /* allocate buffers dynamically to keep size down */ wb->buf = emallocz(messagesize); return wb; } fatal("No more work buffers"); return nil; } void freefile(File *f) { File *parent, *child; Loop: f->ref--; if(f->ref > 0) return; freecnt++; if(f->ref < 0) abort(); DEBUG(DFD, "free %s\n", f->name); /* delete from parent */ parent = f->parent; if(parent->child == f) parent->child = f->childlist; else{ for(child=parent->child; child->childlist!=f; child=child->childlist) if(child->childlist == nil) fatal("bad child list"); child->childlist = f->childlist; } freeqid(f->qidt); free(f->name); f->name = nil; free(f); f = parent; if(f != nil) goto Loop; } File * file(File *parent, char *name) { Dir *dir; char *path; File *f; DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); path = makepath(parent, name); dir = dirstat(path); free(path); if(dir == nil) return nil; for(f = parent->child; f; f = f->childlist) if(strcmp(name, f->name) == 0) break; if(f == nil){ f = emallocz(sizeof(File)); f->name = estrdup(name); f->parent = parent; f->childlist = parent->child; parent->child = f; parent->ref++; f->ref = 0; filecnt++; } f->ref++; f->qid.type = dir->qid.type; f->qid.vers = dir->qid.vers; f->qidt = uniqueqid(dir); f->qid.path = f->qidt->uniqpath; f->inval = 0; free(dir); return f; } void initroot(void) { Dir *dir; root = emallocz(sizeof(File)); root->name = estrdup("."); dir = dirstat(root->name); if(dir == nil) fatal("root stat"); root->ref = 1; root->qid.vers = dir->qid.vers; root->qidt = uniqueqid(dir); root->qid.path = root->qidt->uniqpath; root->qid.type = QTDIR; free(dir); psmpt = emallocz(sizeof(File)); psmpt->name = estrdup("/"); dir = dirstat(psmpt->name); if(dir == nil) return; psmpt->ref = 1; psmpt->qid.vers = dir->qid.vers; psmpt->qidt = uniqueqid(dir); psmpt->qid.path = psmpt->qidt->uniqpath; free(dir); psmpt = file(psmpt, "mnt"); if(psmpt == 0) return; psmpt = file(psmpt, "exportfs"); } char* makepath(File *p, char *name) { int i, n; char *c, *s, *path, *seg[256]; seg[0] = name; n = strlen(name)+2; for(i = 1; i < 256 && p; i++, p = p->parent){ seg[i] = p->name; n += strlen(p->name)+1; } path = malloc(n); if(path == nil) fatal("out of memory"); s = path; while(i--) { for(c = seg[i]; *c; c++) *s++ = *c; *s++ = '/'; } while(s[-1] == '/') s--; *s = '\0'; return path; } int qidhash(vlong path) { int h, n; h = 0; for(n=0; n<64; n+=Nqidbits){ h ^= path; path >>= Nqidbits; } return h & (Nqidtab-1); } void freeqid(Qidtab *q) { ulong h; Qidtab *l; q->ref--; if(q->ref > 0) return; qfreecnt++; h = qidhash(q->path); if(qidtab[h] == q) qidtab[h] = q->next; else{ for(l=qidtab[h]; l->next!=q; l=l->next) if(l->next == nil) fatal("bad qid list"); l->next = q->next; } free(q); } Qidtab* qidlookup(Dir *d) { ulong h; Qidtab *q; h = qidhash(d->qid.path); for(q=qidtab[h]; q!=nil; q=q->next) if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) return q; return nil; } int qidexists(vlong path) { int h; Qidtab *q; for(h=0; hnext) if(q->uniqpath == path) return 1; return 0; } Qidtab* uniqueqid(Dir *d) { ulong h; vlong path; Qidtab *q; q = qidlookup(d); if(q != nil){ q->ref++; return q; } path = d->qid.path; while(qidexists(path)){ DEBUG(DFD, "collision on %s\n", d->name); /* collision: find a new one */ ncollision++; path &= QIDPATH; ++newqid; if(newqid >= (1<<16)){ DEBUG(DFD, "collision wraparound\n"); newqid = 1; } path |= newqid<<48; DEBUG(DFD, "assign qid %.16llux\n", path); } q = mallocz(sizeof(Qidtab), 1); if(q == nil) fatal("no memory for qid table"); qidcnt++; q->ref = 1; q->type = d->type; q->dev = d->dev; q->path = d->qid.path; q->uniqpath = path; h = qidhash(d->qid.path); q->next = qidtab[h]; qidtab[h] = q; return q; } void fatal(char *s, ...) { char buf[ERRMAX]; va_list arg; if (s) { va_start(arg, s); vsnprint(buf, ERRMAX, s, arg); va_end(arg); } /* Clear away the slave children */ // for(m = Proclist; m; m = m->next) // postnote(PNPROC, m->pid, "kill"); DEBUG(DFD, "%s\n", buf); if (s) sysfatal(buf); else sysfatal(""); } drawterm-20110822.orig/exportfs/Makefile0000644000175000017500000000031011245145711017376 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libexportfs.a OFILES=\ exportfs.$O\ exportsrv.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/exportfs/exportfs.h0000644000175000017500000000526211245145711017774 0ustar tinchotincho/* * exportfs.h - definitions for exporting file server */ #define DEBUG if(!dbg){}else fprint #define DFD 2 #define fidhash(s) fhash[s%FHASHSIZE] #define Proc Exproc typedef struct Fsrpc Fsrpc; typedef struct Fid Fid; typedef struct File File; typedef struct Proc Proc; typedef struct Qidtab Qidtab; struct Fsrpc { int busy; /* Work buffer has pending rpc to service */ int pid; /* Pid of slave process executing the rpc */ int canint; /* Interrupt gate */ int flushtag; /* Tag on which to reply to flush */ Fcall work; /* Plan 9 incoming Fcall */ uchar *buf; /* Data buffer */ }; struct Fid { int fid; /* system fd for i/o */ File *f; /* File attached to this fid */ int mode; int nr; /* fid number */ int mid; /* Mount id */ Fid *next; /* hash link */ }; struct File { char *name; int ref; Qid qid; Qidtab *qidt; int inval; File *parent; File *child; File *childlist; }; struct Proc { int pid; int busy; Proc *next; }; struct Qidtab { int ref; int type; int dev; vlong path; vlong uniqpath; Qidtab *next; }; enum { MAXPROC = 50, FHASHSIZE = 64, Nr_workbufs = 50, Fidchunk = 1000, Npsmpt = 32, Nqidbits = 5, Nqidtab = (1<= sizeof buf){ print("warning: skipping long line in secstore factotum file\n"); continue; } memmove(buf, p, ep-p); buf[ep-p] = 0; nf = tokenize(buf, f, nelem(f)); if(nf == 0 || strcmp(f[0], "key") != 0) continue; pass = nil; haveproto = havedom = 0; user = nil; for(i=1; i #include #include #include /* deprecated. This is the mechanism that put entries in /sys/lib/httpd.rewrite and passwords on the authserver in /sys/lib/httppasswords, which was awkward to administer. Instead, use local .httplogin files, which are implemented in sys/src/cmd/ip/httpd/authorize.c */ int httpauth(char *name, char *password) { int afd; Ticketreq tr; Ticket t; char key[DESKEYLEN]; char buf[512]; afd = authdial(nil, nil); if(afd < 0) return -1; /* send ticket request to AS */ memset(&tr, 0, sizeof(tr)); strcpy(tr.uid, name); tr.type = AuthHttp; convTR2M(&tr, buf); if(write(afd, buf, TICKREQLEN) != TICKREQLEN){ close(afd); return -1; } if(_asrdresp(afd, buf, TICKETLEN) < 0){ close(afd); return -1; } close(afd); /* * use password and try to decrypt the * ticket. If it doesn't work we've got a bad password, * give up. */ passtokey(key, password); convM2T(buf, &t, key); if(t.num != AuthHr || strcmp(t.cuid, tr.uid)) return -1; return 0; } drawterm-20110822.orig/libauth/auth_getuserpasswd.c0000644000175000017500000000252111245145712021610 0ustar tinchotincho#include #include #include #include "authlocal.h" enum { ARgiveup = 100, }; static int dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) { int ret; for(;;){ if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) return ret; if(getkey == 0) return ARgiveup; /* don't know how */ if((*getkey)(rpc->arg) < 0) return ARgiveup; /* user punted */ } } UserPasswd* auth_getuserpasswd(AuthGetkey *getkey, char *fmt, ...) { AuthRpc *rpc; char *f[3], *p, *params; int fd; va_list arg; UserPasswd *up; up = nil; rpc = nil; params = nil; fd = open("/mnt/factotum/rpc", ORDWR); if(fd < 0) goto out; rpc = auth_allocrpc(fd); if(rpc == nil) goto out; quotefmtinstall(); /* just in case */ va_start(arg, fmt); params = vsmprint(fmt, arg); va_end(arg); if(params == nil) goto out; if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok || dorpc(rpc, "read", nil, 0, getkey) != ARok) goto out; rpc->arg[rpc->narg] = '\0'; if(tokenize(rpc->arg, f, 2) != 2){ werrstr("bad answer from factotum"); goto out; } up = malloc(sizeof(*up)+rpc->narg+1); if(up == nil) goto out; p = (char*)&up[1]; strcpy(p, f[0]); up->user = p; p += strlen(p)+1; strcpy(p, f[1]); up->passwd = p; out: free(params); auth_freerpc(rpc); close(fd); return up; } drawterm-20110822.orig/libauth/auth_attr.c0000644000175000017500000000033111245145712017657 0ustar tinchotincho#include #include #include #include #include "authlocal.h" Attr* auth_attr(AuthRpc *rpc) { if(auth_rpc(rpc, "attr", nil, 0) != ARok) return nil; return _parseattr(rpc->arg); } drawterm-20110822.orig/libauth/attr.c0000644000175000017500000000545111245145712016646 0ustar tinchotincho#include #include #include int _attrfmt(Fmt *fmt) { char *b, buf[1024], *ebuf; Attr *a; ebuf = buf+sizeof buf; b = buf; strcpy(buf, " "); for(a=va_arg(fmt->args, Attr*); a; a=a->next){ if(a->name == nil) continue; switch(a->type){ case AttrQuery: b = seprint(b, ebuf, " %q?", a->name); break; case AttrNameval: b = seprint(b, ebuf, " %q=%q", a->name, a->val); break; case AttrDefault: b = seprint(b, ebuf, " %q:=%q", a->name, a->val); break; } } return fmtstrcpy(fmt, buf+1); } Attr* _copyattr(Attr *a) { Attr **la, *na; na = nil; la = &na; for(; a; a=a->next){ *la = _mkattr(a->type, a->name, a->val, nil); setmalloctag(*la, getcallerpc(&a)); la = &(*la)->next; } *la = nil; return na; } Attr* _delattr(Attr *a, char *name) { Attr *fa; Attr **la; for(la=&a; *la; ){ if(strcmp((*la)->name, name) == 0){ fa = *la; *la = (*la)->next; fa->next = nil; _freeattr(fa); }else la=&(*la)->next; } return a; } Attr* _findattr(Attr *a, char *n) { for(; a; a=a->next) if(strcmp(a->name, n) == 0 && a->type != AttrQuery) return a; return nil; } void _freeattr(Attr *a) { Attr *anext; for(; a; a=anext){ anext = a->next; free(a->name); free(a->val); a->name = (void*)~0; a->val = (void*)~0; a->next = (void*)~0; free(a); } } Attr* _mkattr(int type, char *name, char *val, Attr *next) { Attr *a; a = malloc(sizeof(*a)); if(a==nil) sysfatal("_mkattr malloc: %r"); a->type = type; a->name = strdup(name); a->val = strdup(val); if(a->name==nil || a->val==nil) sysfatal("_mkattr malloc: %r"); a->next = next; setmalloctag(a, getcallerpc(&type)); return a; } static Attr* cleanattr(Attr *a) { Attr *fa; Attr **la; for(la=&a; *la; ){ if((*la)->type==AttrQuery && _findattr(a, (*la)->name)){ fa = *la; *la = (*la)->next; fa->next = nil; _freeattr(fa); }else la=&(*la)->next; } return a; } Attr* _parseattr(char *s) { char *p, *t, *tok[256]; int i, ntok, type; Attr *a; s = strdup(s); if(s == nil) sysfatal("_parseattr strdup: %r"); ntok = tokenize(s, tok, nelem(tok)); a = nil; for(i=ntok-1; i>=0; i--){ t = tok[i]; if((p = strchr(t, '='))){ *p++ = '\0'; // if(p-2 >= t && p[-2] == ':'){ // p[-2] = '\0'; // type = AttrDefault; // }else type = AttrNameval; a = _mkattr(type, t, p, a); setmalloctag(a, getcallerpc(&s)); } else if(t[strlen(t)-1] == '?'){ t[strlen(t)-1] = '\0'; a = _mkattr(AttrQuery, t, "", a); setmalloctag(a, getcallerpc(&s)); }else{ /* really a syntax error, but better to provide some indication */ a = _mkattr(AttrNameval, t, "", a); setmalloctag(a, getcallerpc(&s)); } } free(s); return cleanattr(a); } char* _strfindattr(Attr *a, char *n) { a = _findattr(a, n); if(a == nil) return nil; return a->val; } drawterm-20110822.orig/libauth/authlocal.h0000644000175000017500000000012711245145712017650 0ustar tinchotinchoextern AuthInfo* _fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params); drawterm-20110822.orig/libauth/Makefile0000644000175000017500000000046211245145712017165 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libauth.a OFILES=\ attr.$O\ auth_attr.$O\ auth_challenge.$O\ auth_getuserpasswd.$O\ auth_proxy.$O\ auth_respond.$O\ auth_rpc.$O\ auth_userpasswd.$O\ default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/libauth/auth_respond.c0000644000175000017500000000261211245145712020363 0ustar tinchotincho#include #include #include #include #include "authlocal.h" enum { ARgiveup = 100, }; static int dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) { int ret; for(;;){ if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) return ret; if(getkey == 0) return ARgiveup; /* don't know how */ if((*getkey)(rpc->arg) < 0) return ARgiveup; /* user punted */ } } int auth_respond(void *chal, uint nchal, char *user, uint nuser, void *resp, uint nresp, AuthGetkey *getkey, char *fmt, ...) { char *p, *s; va_list arg; int afd; AuthRpc *rpc; Attr *a; if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) return -1; if((rpc = auth_allocrpc(afd)) == nil){ close(afd); return -1; } quotefmtinstall(); /* just in case */ va_start(arg, fmt); p = vsmprint(fmt, arg); va_end(arg); if(p==nil || dorpc(rpc, "start", p, strlen(p), getkey) != ARok || dorpc(rpc, "write", chal, nchal, getkey) != ARok || dorpc(rpc, "read", nil, 0, getkey) != ARok){ free(p); close(afd); auth_freerpc(rpc); return -1; } free(p); if(rpc->narg < nresp) nresp = rpc->narg; memmove(resp, rpc->arg, nresp); if((a = auth_attr(rpc)) != nil && (s = _strfindattr(a, "user")) != nil && strlen(s) < nuser) strcpy(user, s); else if(nuser > 0) user[0] = '\0'; _freeattr(a); close(afd); auth_freerpc(rpc); return nresp; } drawterm-20110822.orig/libauth/auth_challenge.c0000644000175000017500000000367011245145712020640 0ustar tinchotincho#include #include #include #include #include "authlocal.h" Chalstate* auth_challenge(char *fmt, ...) { char *p; va_list arg; Chalstate *c; quotefmtinstall(); /* just in case */ va_start(arg, fmt); p = vsmprint(fmt, arg); va_end(arg); if(p == nil) return nil; c = mallocz(sizeof(*c), 1); if(c == nil){ free(p); return nil; } if((c->afd = open("/mnt/factotum/rpc", ORDWR)) < 0){ Error: auth_freechal(c); free(p); return nil; } if((c->rpc=auth_allocrpc(c->afd)) == nil || auth_rpc(c->rpc, "start", p, strlen(p)) != ARok || auth_rpc(c->rpc, "read", nil, 0) != ARok) goto Error; if(c->rpc->narg > sizeof(c->chal)-1){ werrstr("buffer too small for challenge"); goto Error; } memmove(c->chal, c->rpc->arg, c->rpc->narg); c->nchal = c->rpc->narg; free(p); return c; } AuthInfo* auth_response(Chalstate *c) { int ret; AuthInfo *ai; ai = nil; if(c->afd < 0){ werrstr("auth_response: connection not open"); return nil; } if(c->resp == nil){ werrstr("auth_response: nil response"); return nil; } if(c->nresp == 0){ werrstr("auth_response: unspecified response length"); return nil; } if(c->user){ if(auth_rpc(c->rpc, "write", c->user, strlen(c->user)) != ARok){ /* * if this fails we're out of phase with factotum. * give up. */ goto Out; } } if(auth_rpc(c->rpc, "write", c->resp, c->nresp) != ARok){ /* * don't close the connection -- maybe we'll try again. */ return nil; } switch(ret = auth_rpc(c->rpc, "read", nil, 0)){ case ARok: default: werrstr("factotum protocol botch %d %s", ret, c->rpc->ibuf); break; case ARdone: ai = auth_getinfo(c->rpc); break; } Out: close(c->afd); auth_freerpc(c->rpc); c->afd = -1; c->rpc = nil; return ai; } void auth_freechal(Chalstate *c) { if(c == nil) return; if(c->afd >= 0) close(c->afd); if(c->rpc != nil) auth_freerpc(c->rpc); memset(c, 0xBB, sizeof(*c)); free(c); } drawterm-20110822.orig/libauth/auth_proxy.c0000644000175000017500000000703611245145712020077 0ustar tinchotincho#include #include #include #include #include "authlocal.h" enum { ARgiveup = 100, }; static uchar* gstring(uchar *p, uchar *ep, char **s) { uint n; if(p == nil) return nil; if(p+BIT16SZ > ep) return nil; n = GBIT16(p); p += BIT16SZ; if(p+n > ep) return nil; *s = malloc(n+1); memmove((*s), p, n); (*s)[n] = '\0'; p += n; return p; } static uchar* gcarray(uchar *p, uchar *ep, uchar **s, int *np) { uint n; if(p == nil) return nil; if(p+BIT16SZ > ep) return nil; n = GBIT16(p); p += BIT16SZ; if(p+n > ep) return nil; *s = malloc(n); if(*s == nil) return nil; memmove((*s), p, n); *np = n; p += n; return p; } void auth_freeAI(AuthInfo *ai) { if(ai == nil) return; free(ai->cuid); free(ai->suid); free(ai->cap); free(ai->secret); free(ai); } static uchar* convM2AI(uchar *p, int n, AuthInfo **aip) { uchar *e = p+n; AuthInfo *ai; ai = mallocz(sizeof(*ai), 1); if(ai == nil) return nil; p = gstring(p, e, &ai->cuid); p = gstring(p, e, &ai->suid); p = gstring(p, e, &ai->cap); p = gcarray(p, e, &ai->secret, &ai->nsecret); if(p == nil) auth_freeAI(ai); else *aip = ai; return p; } AuthInfo* auth_getinfo(AuthRpc *rpc) { AuthInfo *a; if(auth_rpc(rpc, "authinfo", nil, 0) != ARok) return nil; a = nil; if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){ werrstr("bad auth info from factotum"); return nil; } return a; } static int dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) { int ret; for(;;){ if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) return ret; if(getkey == 0) return ARgiveup; /* don't know how */ if((*getkey)(rpc->arg) < 0) return ARgiveup; /* user punted */ } } /* * this just proxies what the factotum tells it to. */ AuthInfo* fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params) { char *buf; int m, n, ret; AuthInfo *a; char oerr[ERRMAX]; rerrstr(oerr, sizeof oerr); werrstr("UNKNOWN AUTH ERROR"); if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){ werrstr("fauth_proxy start: %r"); return nil; } buf = malloc(AuthRpcMax); if(buf == nil) return nil; for(;;){ switch(dorpc(rpc, "read", nil, 0, getkey)){ case ARdone: free(buf); a = auth_getinfo(rpc); errstr(oerr, sizeof oerr); /* no error, restore whatever was there */ return a; case ARok: if(write(fd, rpc->arg, rpc->narg) != rpc->narg){ werrstr("auth_proxy write fd: %r"); goto Error; } break; case ARphase: n = 0; memset(buf, 0, AuthRpcMax); while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){ if(atoi(rpc->arg) > AuthRpcMax) break; m = read(fd, buf+n, atoi(rpc->arg)-n); if(m <= 0){ if(m == 0) werrstr("auth_proxy short read: %s", buf); goto Error; } n += m; } if(ret != ARok){ werrstr("auth_proxy rpc write: %s: %r", buf); goto Error; } break; default: werrstr("auth_proxy rpc: %r"); goto Error; } } Error: free(buf); return nil; } AuthInfo* auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...) { int afd; char *p; va_list arg; AuthInfo *ai; AuthRpc *rpc; quotefmtinstall(); /* just in case */ va_start(arg, fmt); p = vsmprint(fmt, arg); va_end(arg); afd = open("/mnt/factotum/rpc", ORDWR); if(afd < 0){ werrstr("opening /mnt/factotum/rpc: %r"); free(p); return nil; } rpc = auth_allocrpc(afd); if(rpc == nil){ free(p); return nil; } ai = fauth_proxy(fd, rpc, getkey, p); free(p); auth_freerpc(rpc); close(afd); return ai; } drawterm-20110822.orig/libauth/auth_userpasswd.c0000644000175000017500000000211111245145712021103 0ustar tinchotincho#include #include #include #include #include "authlocal.h" /* * compute the proper response. We encrypt the ascii of * challenge number, with trailing binary zero fill. * This process was derived empirically. * this was copied from inet's guard. */ static void netresp(char *key, long chal, char *answer) { uchar buf[8]; memset(buf, 0, 8); sprint((char *)buf, "%lud", chal); if(encrypt(key, buf, 8) < 0) abort(); chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]; sprint(answer, "%.8lux", chal); } AuthInfo* auth_userpasswd(char *user, char *passwd) { char key[DESKEYLEN], resp[16]; AuthInfo *ai; Chalstate *ch; /* * Probably we should have a factotum protocol * to check a raw password. For now, we use * p9cr, which is simplest to speak. */ if((ch = auth_challenge("user=%q proto=p9cr role=server", user)) == nil) return nil; passtokey(key, passwd); netresp(key, atol(ch->chal), resp); memset(key, 0, sizeof key); ch->resp = resp; ch->nresp = strlen(resp); ai = auth_response(ch); auth_freechal(ch); return ai; } drawterm-20110822.orig/libauth/auth_rpc.c0000644000175000017500000000402011245145712017470 0ustar tinchotincho#include #include #include #include "authlocal.h" static struct { char *verb; int val; } tab[] = { "ok", ARok, "done", ARdone, "error", ARerror, "needkey", ARneedkey, "badkey", ARbadkey, "phase", ARphase, "toosmall", ARtoosmall, "error", ARerror, }; static int classify(char *buf, uint n, AuthRpc *rpc) { int i, len; for(i=0; i= len && memcmp(buf, tab[i].verb, len) == 0 && (n==len || buf[len]==' ')){ if(n==len){ rpc->narg = 0; rpc->arg = ""; }else{ rpc->narg = n - (len+1); rpc->arg = (char*)buf+len+1; } return tab[i].val; } } werrstr("malformed rpc response: %s", buf); return ARrpcfailure; } AuthRpc* auth_allocrpc(int afd) { AuthRpc *rpc; rpc = mallocz(sizeof(*rpc), 1); if(rpc == nil) return nil; rpc->afd = afd; return rpc; } void auth_freerpc(AuthRpc *rpc) { free(rpc); } uint auth_rpc(AuthRpc *rpc, char *verb, void *a, int na) { int l, n, type; char *f[4]; l = strlen(verb); if(na+l+1 > AuthRpcMax){ werrstr("rpc too big"); return ARtoobig; } memmove(rpc->obuf, verb, l); rpc->obuf[l] = ' '; memmove(rpc->obuf+l+1, a, na); if((n=write(rpc->afd, rpc->obuf, l+1+na)) != l+1+na){ if(n >= 0) werrstr("auth_rpc short write"); return ARrpcfailure; } if((n=read(rpc->afd, rpc->ibuf, AuthRpcMax)) < 0) return ARrpcfailure; rpc->ibuf[n] = '\0'; /* * Set error string for good default behavior. */ switch(type = classify(rpc->ibuf, n, rpc)){ default: werrstr("unknown rpc type %d (bug in auth_rpc.c)", type); break; case ARok: break; case ARrpcfailure: break; case ARerror: if(rpc->narg == 0) werrstr("unspecified rpc error"); else werrstr("%s", rpc->arg); break; case ARneedkey: werrstr("needkey %s", rpc->arg); break; case ARbadkey: if(getfields(rpc->arg, f, nelem(f), 0, "\n") < 2) werrstr("badkey %s", rpc->arg); else werrstr("badkey %s", f[1]); break; case ARphase: werrstr("phase error %s", rpc->arg); break; } return type; } drawterm-20110822.orig/libsec/0000755000175000017500000000000011510255052015326 5ustar tinchotinchodrawterm-20110822.orig/libsec/desCBC.c0000644000175000017500000000206711245145712016570 0ustar tinchotincho#include "os.h" #include #include // Because of the way that non multiple of 8 // buffers are handled, the decryptor must // be fed buffers of the same size as the // encryptor // If the length is not a multiple of 8, I encrypt // the overflow to be compatible with lacy's cryptlib void desCBCencrypt(uchar *p, int len, DESstate *s) { uchar *p2, *ip, *eip; for(; len >= 8; len -= 8){ p2 = p; ip = s->ivec; for(eip = ip+8; ip < eip; ) *p2++ ^= *ip++; block_cipher(s->expanded, p, 0); memmove(s->ivec, p, 8); p += 8; } if(len > 0){ ip = s->ivec; block_cipher(s->expanded, ip, 0); for(eip = ip+len; ip < eip; ) *p++ ^= *ip++; } } void desCBCdecrypt(uchar *p, int len, DESstate *s) { uchar *ip, *eip, *tp; uchar tmp[8]; for(; len >= 8; len -= 8){ memmove(tmp, p, 8); block_cipher(s->expanded, p, 1); tp = tmp; ip = s->ivec; for(eip = ip+8; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } if(len > 0){ ip = s->ivec; block_cipher(s->expanded, ip, 0); for(eip = ip+len; ip < eip; ) *p++ ^= *ip++; } } drawterm-20110822.orig/libsec/hmac.c0000644000175000017500000000221711245145712016412 0ustar tinchotincho#include "os.h" #include /* rfc2104 */ static DigestState* hmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s, DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen) { int i; uchar pad[65], innerdigest[256]; if(xlen > sizeof(innerdigest)) return nil; if(klen>64) return nil; /* first time through */ if(s == nil){ for(i=0; i<64; i++) pad[i] = 0x36; pad[64] = 0; for(i=0; i /* * these routines use the 64bit format for * DES keys. */ void setupDESstate(DESstate *s, uchar key[8], uchar *ivec) { memset(s, 0, sizeof(*s)); memmove(s->key, key, sizeof(s->key)); des_key_setup(key, s->expanded); if(ivec) memmove(s->ivec, ivec, 8); s->setup = 0xdeadbeef; } void setupDES3state(DES3state *s, uchar key[3][8], uchar *ivec) { memset(s, 0, sizeof(*s)); memmove(s->key, key, sizeof(s->key)); des_key_setup(key[0], s->expanded[0]); des_key_setup(key[1], s->expanded[1]); des_key_setup(key[2], s->expanded[2]); if(ivec) memmove(s->ivec, ivec, 8); s->setup = 0xdeadbeef; } drawterm-20110822.orig/libsec/md5pickle.c0000644000175000017500000000122111245145712017351 0ustar tinchotincho#include "os.h" #include char* md5pickle(MD5state *s) { char *p; int m, n; m = 4*9+4*((s->blen+3)/3); p = malloc(m); if(p == nil) return p; n = sprint(p, "%8.8ux %8.8ux %8.8ux %8.8ux ", s->state[0], s->state[1], s->state[2], s->state[3]); enc64(p+n, m-n, s->buf, s->blen); return p; } MD5state* md5unpickle(char *p) { MD5state *s; s = malloc(sizeof(*s)); if(s == nil) return nil; s->state[0] = strtoul(p, &p, 16); s->state[1] = strtoul(p, &p, 16); s->state[2] = strtoul(p, &p, 16); s->state[3] = strtoul(p, &p, 16); s->blen = dec64(s->buf, sizeof(s->buf), p, strlen(p)); s->malloced = 1; s->seeded = 1; return s; } drawterm-20110822.orig/libsec/eggen.c0000644000175000017500000000063511245145712016571 0ustar tinchotincho#include "os.h" #include #include EGpriv* eggen(int nlen, int rounds) { EGpub *pub; EGpriv *priv; priv = egprivalloc(); pub = &priv->pub; pub->p = mpnew(0); pub->alpha = mpnew(0); pub->key = mpnew(0); priv->secret = mpnew(0); gensafeprime(pub->p, pub->alpha, nlen, rounds); mprand(nlen-1, genrandom, priv->secret); mpexp(pub->alpha, priv->secret, pub->p, pub->key); return priv; } drawterm-20110822.orig/libsec/x509.c0000644000175000017500000014207511245145712016216 0ustar tinchotincho#include #include #include #include typedef DigestState*(*DigestFun)(uchar*,ulong,uchar*,DigestState*); /* ANSI offsetof, backwards. */ #define OFFSETOF(a, b) offsetof(b, a) /*=============================================================*/ /* general ASN1 declarations and parsing * * For now, this is used only for extracting the key from an * X509 certificate, so the entire collection is hidden. But * someday we should probably make the functions visible and * give them their own man page. */ typedef struct Elem Elem; typedef struct Tag Tag; typedef struct Value Value; typedef struct Bytes Bytes; typedef struct Ints Ints; typedef struct Bits Bits; typedef struct Elist Elist; /* tag classes */ #define Universal 0 #define Context 0x80 /* universal tags */ #define BOOLEAN 1 #define INTEGER 2 #define BIT_STRING 3 #define OCTET_STRING 4 #define NULLTAG 5 #define OBJECT_ID 6 #define ObjectDescriptor 7 #define EXTERNAL 8 #define REAL 9 #define ENUMERATED 10 #define EMBEDDED_PDV 11 #define SEQUENCE 16 /* also SEQUENCE OF */ #define SETOF 17 /* also SETOF OF */ #define NumericString 18 #define PrintableString 19 #define TeletexString 20 #define VideotexString 21 #define IA5String 22 #define UTCTime 23 #define GeneralizedTime 24 #define GraphicString 25 #define VisibleString 26 #define GeneralString 27 #define UniversalString 28 #define BMPString 30 struct Bytes { int len; uchar data[1]; }; struct Ints { int len; int data[1]; }; struct Bits { int len; /* number of bytes */ int unusedbits; /* unused bits in last byte */ uchar data[1]; /* most-significant bit first */ }; struct Tag { int class; int num; }; enum { VBool, VInt, VOctets, VBigInt, VReal, VOther, VBitString, VNull, VEOC, VObjId, VString, VSeq, VSet }; struct Value { int tag; /* VBool, etc. */ union { int boolval; int intval; Bytes* octetsval; Bytes* bigintval; Bytes* realval; /* undecoded; hardly ever used */ Bytes* otherval; Bits* bitstringval; Ints* objidval; char* stringval; Elist* seqval; Elist* setval; } u; /* (Don't use anonymous unions, for ease of porting) */ }; struct Elem { Tag tag; Value val; }; struct Elist { Elist* tl; Elem hd; }; /* decoding errors */ enum { ASN_OK, ASN_ESHORT, ASN_ETOOBIG, ASN_EVALLEN, ASN_ECONSTR, ASN_EPRIM, ASN_EINVAL, ASN_EUNIMPL }; /* here are the functions to consider making extern someday */ static Bytes* newbytes(int len); static Bytes* makebytes(uchar* buf, int len); static void freebytes(Bytes* b); static Bytes* catbytes(Bytes* b1, Bytes* b2); static Ints* newints(int len); static Ints* makeints(int* buf, int len); static void freeints(Ints* b); static Bits* newbits(int len); static Bits* makebits(uchar* buf, int len, int unusedbits); static void freebits(Bits* b); static Elist* mkel(Elem e, Elist* tail); static void freeelist(Elist* el); static int elistlen(Elist* el); static int is_seq(Elem* pe, Elist** pseq); static int is_set(Elem* pe, Elist** pset); static int is_int(Elem* pe, int* pint); static int is_bigint(Elem* pe, Bytes** pbigint); static int is_bitstring(Elem* pe, Bits** pbits); static int is_octetstring(Elem* pe, Bytes** poctets); static int is_oid(Elem* pe, Ints** poid); static int is_string(Elem* pe, char** pstring); static int is_time(Elem* pe, char** ptime); static int decode(uchar* a, int alen, Elem* pelem); static int decode_seq(uchar* a, int alen, Elist** pelist); static int decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval); static int encode(Elem e, Bytes** pbytes); static int oid_lookup(Ints* o, Ints** tab); static void freevalfields(Value* v); static mpint *asn1mpint(Elem *e); #define TAG_MASK 0x1F #define CONSTR_MASK 0x20 #define CLASS_MASK 0xC0 #define MAXOBJIDLEN 20 static int ber_decode(uchar** pp, uchar* pend, Elem* pelem); static int tag_decode(uchar** pp, uchar* pend, Tag* ptag, int* pisconstr); static int length_decode(uchar** pp, uchar* pend, int* plength); static int value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value* pval); static int int_decode(uchar** pp, uchar* pend, int count, int unsgned, int* pint); static int uint7_decode(uchar** pp, uchar* pend, int* pint); static int octet_decode(uchar** pp, uchar* pend, int length, int isconstr, Bytes** pbytes); static int seq_decode(uchar** pp, uchar* pend, int length, int isconstr, Elist** pelist); static int enc(uchar** pp, Elem e, int lenonly); static int val_enc(uchar** pp, Elem e, int *pconstr, int lenonly); static void uint7_enc(uchar** pp, int num, int lenonly); static void int_enc(uchar** pp, int num, int unsgned, int lenonly); static void * emalloc(int n) { void *p; if(n==0) n=1; p = malloc(n); if(p == nil){ exits("out of memory"); } memset(p, 0, n); return p; } static char* estrdup(char *s) { char *d, *d0; if(!s) return 0; d = d0 = emalloc(strlen(s)+1); while(*d++ = *s++) ; return d0; } /* * Decode a[0..len] as a BER encoding of an ASN1 type. * The return value is one of ASN_OK, etc. * Depending on the error, the returned elem may or may not * be nil. */ static int decode(uchar* a, int alen, Elem* pelem) { uchar* p = a; return ber_decode(&p, &a[alen], pelem); } /* * Like decode, but continue decoding after first element * of array ends. */ static int decode_seq(uchar* a, int alen, Elist** pelist) { uchar* p = a; return seq_decode(&p, &a[alen], -1, 1, pelist); } /* * Decode the whole array as a BER encoding of an ASN1 value, * (i.e., the part after the tag and length). * Assume the value is encoded as universal tag "kind". * The constr arg is 1 if the value is constructed, 0 if primitive. * If there's an error, the return string will contain the error. * Depending on the error, the returned value may or may not * be nil. */ static int decode_value(uchar* a, int alen, int kind, int isconstr, Value* pval) { uchar* p = a; return value_decode(&p, &a[alen], alen, kind, isconstr, pval); } /* * All of the following decoding routines take arguments: * uchar **pp; * uchar *pend; * Where parsing is supposed to start at **pp, and when parsing * is done, *pp is updated to point at next char to be parsed. * The pend pointer is just past end of string; an error should * be returned parsing hasn't finished by then. * * The returned int is ASN_OK if all went fine, else ASN_ESHORT, etc. * The remaining argument(s) are pointers to where parsed entity goes. */ /* Decode an ASN1 'Elem' (tag, length, value) */ static int ber_decode(uchar** pp, uchar* pend, Elem* pelem) { int err; int isconstr; int length; Tag tag; Value val; err = tag_decode(pp, pend, &tag, &isconstr); if(err == ASN_OK) { err = length_decode(pp, pend, &length); if(err == ASN_OK) { if(tag.class == Universal) err = value_decode(pp, pend, length, tag.num, isconstr, &val); else err = value_decode(pp, pend, length, OCTET_STRING, 0, &val); if(err == ASN_OK) { pelem->tag = tag; pelem->val = val; } } } return err; } /* Decode a tag field */ static int tag_decode(uchar** pp, uchar* pend, Tag* ptag, int* pisconstr) { int err; int v; uchar* p; err = ASN_OK; p = *pp; if(pend-p >= 2) { v = *p++; ptag->class = v&CLASS_MASK; if(v&CONSTR_MASK) *pisconstr = 1; else *pisconstr = 0; v &= TAG_MASK; if(v == TAG_MASK) err = uint7_decode(&p, pend, &v); ptag->num = v; } else err = ASN_ESHORT; *pp = p; return err; } /* Decode a length field */ static int length_decode(uchar** pp, uchar* pend, int* plength) { int err; int num; int v; uchar* p; err = ASN_OK; num = 0; p = *pp; if(p < pend) { v = *p++; if(v&0x80) err = int_decode(&p, pend, v&0x7F, 1, &num); else if(v == 0x80) num = -1; else num = v; } else err = ASN_ESHORT; *pp = p; *plength = num; return err; } /* Decode a value field */ static int value_decode(uchar** pp, uchar* pend, int length, int kind, int isconstr, Value* pval) { int err; Bytes* va; int num; int bitsunused; int subids[MAXOBJIDLEN]; int isubid; Elist* vl; uchar* p; uchar* pe; err = ASN_OK; p = *pp; if(length == -1) { /* "indefinite" length spec */ if(!isconstr) err = ASN_EINVAL; } else if(p + length > pend) err = ASN_EVALLEN; if(err != ASN_OK) return err; switch(kind) { case 0: /* marker for end of indefinite constructions */ if(length == 0) pval->tag = VNull; else err = ASN_EINVAL; break; case BOOLEAN: if(isconstr) err = ASN_ECONSTR; else if(length != 1) err = ASN_EVALLEN; else { pval->tag = VBool; pval->u.boolval = (*p++ != 0); } break; case INTEGER: case ENUMERATED: if(isconstr) err = ASN_ECONSTR; else if(length <= 4) { err = int_decode(&p, pend, length, 0, &num); if(err == ASN_OK) { pval->tag = VInt; pval->u.intval = num; } } else { pval->tag = VBigInt; pval->u.bigintval = makebytes(p, length); p += length; } break; case BIT_STRING: pval->tag = VBitString; if(isconstr) { if(length == -1 && p + 2 <= pend && *p == 0 && *(p+1) ==0) { pval->u.bitstringval = makebits(0, 0, 0); p += 2; } else /* TODO: recurse and concat results */ err = ASN_EUNIMPL; } else { if(length < 2) { if(length == 1 && *p == 0) { pval->u.bitstringval = makebits(0, 0, 0); p++; } else err = ASN_EINVAL; } else { bitsunused = *p; if(bitsunused > 7) err = ASN_EINVAL; else if(length > 0x0FFFFFFF) err = ASN_ETOOBIG; else { pval->u.bitstringval = makebits(p+1, length-1, bitsunused); p += length; } } } break; case OCTET_STRING: case ObjectDescriptor: err = octet_decode(&p, pend, length, isconstr, &va); if(err == ASN_OK) { pval->tag = VOctets; pval->u.octetsval = va; } break; case NULLTAG: if(isconstr) err = ASN_ECONSTR; else if(length != 0) err = ASN_EVALLEN; else pval->tag = VNull; break; case OBJECT_ID: if(isconstr) err = ASN_ECONSTR; else if(length == 0) err = ASN_EVALLEN; else { isubid = 0; pe = p+length; while(p < pe && isubid < MAXOBJIDLEN) { err = uint7_decode(&p, pend, &num); if(err != ASN_OK) break; if(isubid == 0) { subids[isubid++] = num / 40; subids[isubid++] = num % 40; } else subids[isubid++] = num; } if(err == ASN_OK) { if(p != pe) err = ASN_EVALLEN; else { pval->tag = VObjId; pval->u.objidval = makeints(subids, isubid); } } } break; case EXTERNAL: case EMBEDDED_PDV: /* TODO: parse this internally */ if(p+length > pend) err = ASN_EVALLEN; else { pval->tag = VOther; pval->u.otherval = makebytes(p, length); p += length; } break; case REAL: /* Let the application decode */ if(isconstr) err = ASN_ECONSTR; else if(p+length > pend) err = ASN_EVALLEN; else { pval->tag = VReal; pval->u.realval = makebytes(p, length); p += length; } break; case SEQUENCE: err = seq_decode(&p, pend, length, isconstr, &vl); if(err == ASN_OK) { pval->tag = VSeq ; pval->u.seqval = vl; } break; case SETOF: err = seq_decode(&p, pend, length, isconstr, &vl); if(err == ASN_OK) { pval->tag = VSet; pval->u.setval = vl; } break; case NumericString: case PrintableString: case TeletexString: case VideotexString: case IA5String: case UTCTime: case GeneralizedTime: case GraphicString: case VisibleString: case GeneralString: case UniversalString: case BMPString: /* TODO: figure out when character set conversion is necessary */ err = octet_decode(&p, pend, length, isconstr, &va); if(err == ASN_OK) { pval->tag = VString; pval->u.stringval = (char*)emalloc(va->len+1); memmove(pval->u.stringval, va->data, va->len); pval->u.stringval[va->len] = 0; free(va); } break; default: if(p+length > pend) err = ASN_EVALLEN; else { pval->tag = VOther; pval->u.otherval = makebytes(p, length); p += length; } break; } *pp = p; return err; } /* * Decode an int in format where count bytes are * concatenated to form value. * Although ASN1 allows any size integer, we return * an error if the result doesn't fit in a 32-bit int. * If unsgned is not set, make sure to propagate sign bit. */ static int int_decode(uchar** pp, uchar* pend, int count, int unsgned, int* pint) { int err; int num; uchar* p; p = *pp; err = ASN_OK; num = 0; if(p+count <= pend) { if((count > 4) || (unsgned && count == 4 && (*p&0x80))) err = ASN_ETOOBIG; else { if(!unsgned && count > 0 && count < 4 && (*p&0x80)) num = -1; // set all bits, initially while(count--) num = (num << 8)|(*p++); } } else err = ASN_ESHORT; *pint = num; *pp = p; return err; } /* * Decode an unsigned int in format where each * byte except last has high bit set, and remaining * seven bits of each byte are concatenated to form value. * Although ASN1 allows any size integer, we return * an error if the result doesn't fit in a 32 bit int. */ static int uint7_decode(uchar** pp, uchar* pend, int* pint) { int err; int num; int more; int v; uchar* p; p = *pp; err = ASN_OK; num = 0; more = 1; while(more && p < pend) { v = *p++; if(num&0x7F000000) { err = ASN_ETOOBIG; break; } num <<= 7; more = v&0x80; num |= (v&0x7F); } if(p == pend) err = ASN_ESHORT; *pint = num; *pp = p; return err; } /* * Decode an octet string, recursively if isconstr. * We've already checked that length==-1 implies isconstr==1, * and otherwise that specified length fits within (*pp..pend) */ static int octet_decode(uchar** pp, uchar* pend, int length, int isconstr, Bytes** pbytes) { int err; uchar* p; Bytes* ans; Bytes* newans; uchar* pstart; uchar* pold; Elem elem; err = ASN_OK; p = *pp; ans = nil; if(length >= 0 && !isconstr) { ans = makebytes(p, length); p += length; } else { /* constructed, either definite or indefinite length */ pstart = p; for(;;) { if(length >= 0 && p >= pstart + length) { if(p != pstart + length) err = ASN_EVALLEN; break; } pold = p; err = ber_decode(&p, pend, &elem); if(err != ASN_OK) break; switch(elem.val.tag) { case VOctets: newans = catbytes(ans, elem.val.u.octetsval); freebytes(ans); ans = newans; break; case VEOC: if(length != -1) { p = pold; err = ASN_EINVAL; } goto cloop_done; default: p = pold; err = ASN_EINVAL; goto cloop_done; } } cloop_done: ; } *pp = p; *pbytes = ans; return err; } /* * Decode a sequence or set. * We've already checked that length==-1 implies isconstr==1, * and otherwise that specified length fits within (*p..pend) */ static int seq_decode(uchar** pp, uchar* pend, int length, int isconstr, Elist** pelist) { int err; uchar* p; uchar* pstart; uchar* pold; Elist* ans; Elem elem; Elist* lve; Elist* lveold; err = ASN_OK; ans = nil; p = *pp; if(!isconstr) err = ASN_EPRIM; else { /* constructed, either definite or indefinite length */ lve = nil; pstart = p; for(;;) { if(length >= 0 && p >= pstart + length) { if(p != pstart + length) err = ASN_EVALLEN; break; } pold = p; err = ber_decode(&p, pend, &elem); if(err != ASN_OK) break; if(elem.val.tag == VEOC) { if(length != -1) { p = pold; err = ASN_EINVAL; } break; } else lve = mkel(elem, lve); } if(err == ASN_OK) { /* reverse back to original order */ while(lve != nil) { lveold = lve; lve = lve->tl; lveold->tl = ans; ans = lveold; } } } *pp = p; *pelist = ans; return err; } /* * Encode e by BER rules, putting answer in *pbytes. * This is done by first calling enc with lenonly==1 * to get the length of the needed buffer, * then allocating the buffer and using enc again to fill it up. */ static int encode(Elem e, Bytes** pbytes) { uchar* p; Bytes* ans; int err; uchar uc; p = &uc; err = enc(&p, e, 1); if(err == ASN_OK) { ans = newbytes(p-&uc); p = ans->data; err = enc(&p, e, 0); *pbytes = ans; } return err; } /* * The various enc functions take a pointer to a pointer * into a buffer, and encode their entity starting there, * updating the pointer afterwards. * If lenonly is 1, only the pointer update is done, * allowing enc to be called first to calculate the needed * buffer length. * If lenonly is 0, it is assumed that the answer will fit. */ static int enc(uchar** pp, Elem e, int lenonly) { int err; int vlen; int constr; Tag tag; int v; int ilen; uchar* p; uchar* psave; p = *pp; err = val_enc(&p, e, &constr, 1); if(err != ASN_OK) return err; vlen = p - *pp; p = *pp; tag = e.tag; v = tag.class|constr; if(tag.num < 31) { if(!lenonly) *p = (v|tag.num); p++; } else { if(!lenonly) *p = (v|31); p++; if(tag.num < 0) return ASN_EINVAL; uint7_enc(&p, tag.num, lenonly); } if(vlen < 0x80) { if(!lenonly) *p = vlen; p++; } else { psave = p; int_enc(&p, vlen, 1, 1); ilen = p-psave; p = psave; if(!lenonly) { *p++ = (0x80 | ilen); int_enc(&p, vlen, 1, 0); } else p += 1 + ilen; } if(!lenonly) val_enc(&p, e, &constr, 0); else p += vlen; *pp = p; return err; } static int val_enc(uchar** pp, Elem e, int *pconstr, int lenonly) { int err; uchar* p; int kind; int cl; int v; Bytes* bb = nil; Bits* bits; Ints* oid; int k; Elist* el; char* s; p = *pp; err = ASN_OK; kind = e.tag.num; cl = e.tag.class; *pconstr = 0; if(cl != Universal) { switch(e.val.tag) { case VBool: kind = BOOLEAN; break; case VInt: kind = INTEGER; break; case VBigInt: kind = INTEGER; break; case VOctets: kind = OCTET_STRING; break; case VReal: kind = REAL; break; case VOther: kind = OCTET_STRING; break; case VBitString: kind = BIT_STRING; break; case VNull: kind = NULLTAG; break; case VObjId: kind = OBJECT_ID; break; case VString: kind = UniversalString; break; case VSeq: kind = SEQUENCE; break; case VSet: kind = SETOF; break; } } switch(kind) { case BOOLEAN: if(is_int(&e, &v)) { if(v != 0) v = 255; int_enc(&p, v, 1, lenonly); } else err = ASN_EINVAL; break; case INTEGER: case ENUMERATED: if(is_int(&e, &v)) int_enc(&p, v, 0, lenonly); else { if(is_bigint(&e, &bb)) { if(!lenonly) memmove(p, bb->data, bb->len); p += bb->len; } else err = ASN_EINVAL; } break; case BIT_STRING: if(is_bitstring(&e, &bits)) { if(bits->len == 0) { if(!lenonly) *p = 0; p++; } else { v = bits->unusedbits; if(v < 0 || v > 7) err = ASN_EINVAL; else { if(!lenonly) { *p = v; memmove(p+1, bits->data, bits->len); } p += 1 + bits->len; } } } else err = ASN_EINVAL; break; case OCTET_STRING: case ObjectDescriptor: case EXTERNAL: case REAL: case EMBEDDED_PDV: bb = nil; switch(e.val.tag) { case VOctets: bb = e.val.u.octetsval; break; case VReal: bb = e.val.u.realval; break; case VOther: bb = e.val.u.otherval; break; } if(bb != nil) { if(!lenonly) memmove(p, bb->data, bb->len); p += bb->len; } else err = ASN_EINVAL; break; case NULLTAG: break; case OBJECT_ID: if(is_oid(&e, &oid)) { for(k = 0; k < oid->len; k++) { v = oid->data[k]; if(k == 0) { v *= 40; if(oid->len > 1) v += oid->data[++k]; } uint7_enc(&p, v, lenonly); } } else err = ASN_EINVAL; break; case SEQUENCE: case SETOF: el = nil; if(e.val.tag == VSeq) el = e.val.u.seqval; else if(e.val.tag == VSet) el = e.val.u.setval; else err = ASN_EINVAL; if(el != nil) { *pconstr = CONSTR_MASK; for(; el != nil; el = el->tl) { err = enc(&p, el->hd, lenonly); if(err != ASN_OK) break; } } break; case NumericString: case PrintableString: case TeletexString: case VideotexString: case IA5String: case UTCTime: case GeneralizedTime: case GraphicString: case VisibleString: case GeneralString: case UniversalString: case BMPString: if(e.val.tag == VString) { s = e.val.u.stringval; if(s != nil) { v = strlen(s); if(!lenonly) memmove(p, s, v); p += v; } } else err = ASN_EINVAL; break; default: err = ASN_EINVAL; } *pp = p; return err; } /* * Encode num as unsigned 7 bit values with top bit 1 on all bytes * except last, only putting in bytes if !lenonly. */ static void uint7_enc(uchar** pp, int num, int lenonly) { int n; int v; int k; uchar* p; p = *pp; n = 1; v = num >> 7; while(v > 0) { v >>= 7; n++; } if(lenonly) p += n; else { for(k = (n - 1)*7; k > 0; k -= 7) *p++= ((num >> k)|0x80); *p++ = (num&0x7F); } *pp = p; } /* * Encode num as unsigned or signed integer, * only putting in bytes if !lenonly. * Encoding is length followed by bytes to concatenate. */ static void int_enc(uchar** pp, int num, int unsgned, int lenonly) { int v; int n; int prevv; int k; uchar* p; p = *pp; v = num; if(v < 0) v = -(v + 1); n = 1; prevv = v; v >>= 8; while(v > 0) { prevv = v; v >>= 8; n++; } if(!unsgned && (prevv&0x80)) n++; if(lenonly) p += n; else { for(k = (n - 1)*8; k >= 0; k -= 8) *p++ = (num >> k); } *pp = p; } static int ints_eq(Ints* a, Ints* b) { int alen; int i; alen = a->len; if(alen != b->len) return 0; for(i = 0; i < alen; i++) if(a->data[i] != b->data[i]) return 0; return 1; } /* * Look up o in tab (which must have nil entry to terminate). * Return index of matching entry, or -1 if none. */ static int oid_lookup(Ints* o, Ints** tab) { int i; for(i = 0; tab[i] != nil; i++) if(ints_eq(o, tab[i])) return i; return -1; } /* * Return true if *pe is a SEQUENCE, and set *pseq to * the value of the sequence if so. */ static int is_seq(Elem* pe, Elist** pseq) { if(pe->tag.class == Universal && pe->tag.num == SEQUENCE && pe->val.tag == VSeq) { *pseq = pe->val.u.seqval; return 1; } return 0; } static int is_set(Elem* pe, Elist** pset) { if(pe->tag.class == Universal && pe->tag.num == SETOF && pe->val.tag == VSet) { *pset = pe->val.u.setval; return 1; } return 0; } static int is_int(Elem* pe, int* pint) { if(pe->tag.class == Universal) { if(pe->tag.num == INTEGER && pe->val.tag == VInt) { *pint = pe->val.u.intval; return 1; } else if(pe->tag.num == BOOLEAN && pe->val.tag == VBool) { *pint = pe->val.u.boolval; return 1; } } return 0; } /* * for convience, all VInt's are readable via this routine, * as well as all VBigInt's */ static int is_bigint(Elem* pe, Bytes** pbigint) { int v, n, i; if(pe->tag.class == Universal && pe->tag.num == INTEGER) { if(pe->val.tag == VBigInt) *pbigint = pe->val.u.bigintval; else if(pe->val.tag == VInt){ v = pe->val.u.intval; for(n = 1; n < 4; n++) if((1 << (8 * n)) > v) break; *pbigint = newbytes(n); for(i = 0; i < n; i++) (*pbigint)->data[i] = (v >> ((n - 1 - i) * 8)); }else return 0; return 1; } return 0; } static int is_bitstring(Elem* pe, Bits** pbits) { if(pe->tag.class == Universal && pe->tag.num == BIT_STRING && pe->val.tag == VBitString) { *pbits = pe->val.u.bitstringval; return 1; } return 0; } static int is_octetstring(Elem* pe, Bytes** poctets) { if(pe->tag.class == Universal && pe->tag.num == OCTET_STRING && pe->val.tag == VOctets) { *poctets = pe->val.u.octetsval; return 1; } return 0; } static int is_oid(Elem* pe, Ints** poid) { if(pe->tag.class == Universal && pe->tag.num == OBJECT_ID && pe->val.tag == VObjId) { *poid = pe->val.u.objidval; return 1; } return 0; } static int is_string(Elem* pe, char** pstring) { if(pe->tag.class == Universal) { switch(pe->tag.num) { case NumericString: case PrintableString: case TeletexString: case VideotexString: case IA5String: case GraphicString: case VisibleString: case GeneralString: case UniversalString: case BMPString: if(pe->val.tag == VString) { *pstring = pe->val.u.stringval; return 1; } } } return 0; } static int is_time(Elem* pe, char** ptime) { if(pe->tag.class == Universal && (pe->tag.num == UTCTime || pe->tag.num == GeneralizedTime) && pe->val.tag == VString) { *ptime = pe->val.u.stringval; return 1; } return 0; } /* * malloc and return a new Bytes structure capable of * holding len bytes. (len >= 0) */ static Bytes* newbytes(int len) { Bytes* ans; ans = (Bytes*)emalloc(OFFSETOF(data[0], Bytes) + len); ans->len = len; return ans; } /* * newbytes(len), with data initialized from buf */ static Bytes* makebytes(uchar* buf, int len) { Bytes* ans; ans = newbytes(len); memmove(ans->data, buf, len); return ans; } static void freebytes(Bytes* b) { if(b != nil) free(b); } /* * Make a new Bytes, containing bytes of b1 followed by those of b2. * Either b1 or b2 or both can be nil. */ static Bytes* catbytes(Bytes* b1, Bytes* b2) { Bytes* ans; int n; if(b1 == nil) { if(b2 == nil) ans = newbytes(0); else ans = makebytes(b2->data, b2->len); } else if(b2 == nil) { ans = makebytes(b1->data, b1->len); } else { n = b1->len + b2->len; ans = newbytes(n); ans->len = n; memmove(ans->data, b1->data, b1->len); memmove(ans->data+b1->len, b2->data, b2->len); } return ans; } /* len is number of ints */ static Ints* newints(int len) { Ints* ans; ans = (Ints*)emalloc(OFFSETOF(data[0], Ints) + len*sizeof(int)); ans->len = len; return ans; } static Ints* makeints(int* buf, int len) { Ints* ans; ans = newints(len); if(len > 0) memmove(ans->data, buf, len*sizeof(int)); return ans; } static void freeints(Ints* b) { if(b != nil) free(b); } /* len is number of bytes */ static Bits* newbits(int len) { Bits* ans; ans = (Bits*)emalloc(OFFSETOF(data[0], Bits) + len); ans->len = len; ans->unusedbits = 0; return ans; } static Bits* makebits(uchar* buf, int len, int unusedbits) { Bits* ans; ans = newbits(len); memmove(ans->data, buf, len); ans->unusedbits = unusedbits; return ans; } static void freebits(Bits* b) { if(b != nil) free(b); } static Elist* mkel(Elem e, Elist* tail) { Elist* el; el = (Elist*)emalloc(sizeof(Elist)); el->hd = e; el->tl = tail; return el; } static int elistlen(Elist* el) { int ans = 0; while(el != nil) { ans++; el = el->tl; } return ans; } /* Frees elist, but not fields inside values of constituent elems */ static void freeelist(Elist* el) { Elist* next; while(el != nil) { next = el->tl; free(el); el = next; } } /* free any allocated structures inside v (recursively freeing Elists) */ static void freevalfields(Value* v) { Elist* el; Elist* l; if(v == nil) return; switch(v->tag) { case VOctets: freebytes(v->u.octetsval); break; case VBigInt: freebytes(v->u.bigintval); break; case VReal: freebytes(v->u.realval); break; case VOther: freebytes(v->u.otherval); break; case VBitString: freebits(v->u.bitstringval); break; case VObjId: freeints(v->u.objidval); break; case VString: if (v->u.stringval) free(v->u.stringval); break; case VSeq: el = v->u.seqval; for(l = el; l != nil; l = l->tl) freevalfields(&l->hd.val); if (el) freeelist(el); break; case VSet: el = v->u.setval; for(l = el; l != nil; l = l->tl) freevalfields(&l->hd.val); if (el) freeelist(el); break; } } /* end of general ASN1 functions */ /*=============================================================*/ /* * Decode and parse an X.509 Certificate, defined by this ASN1: * Certificate ::= SEQUENCE { * certificateInfo CertificateInfo, * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING } * * CertificateInfo ::= SEQUENCE { * version [0] INTEGER DEFAULT v1 (0), * serialNumber INTEGER, * signature AlgorithmIdentifier, * issuer Name, * validity Validity, * subject Name, * subjectPublicKeyInfo SubjectPublicKeyInfo } * (version v2 has two more fields, optional unique identifiers for * issuer and subject; since we ignore these anyway, we won't parse them) * * Validity ::= SEQUENCE { * notBefore UTCTime, * notAfter UTCTime } * * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFER, * parameters ANY DEFINED BY ALGORITHM OPTIONAL } * * Name ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= SETOF SIZE(1..MAX) OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type OBJECT IDENTIFER, * value DirectoryString } * (selected attributes have these Object Ids: * commonName {2 5 4 3} * countryName {2 5 4 6} * localityName {2 5 4 7} * stateOrProvinceName {2 5 4 8} * organizationName {2 5 4 10} * organizationalUnitName {2 5 4 11} * ) * * DirectoryString ::= CHOICE { * teletexString TeletexString, * printableString PrintableString, * universalString UniversalString } * * See rfc1423, rfc2437 for AlgorithmIdentifier, subjectPublicKeyInfo, signature. * * Not yet implemented: * CertificateRevocationList ::= SIGNED SEQUENCE{ * signature AlgorithmIdentifier, * issuer Name, * lastUpdate UTCTime, * nextUpdate UTCTime, * revokedCertificates * SEQUENCE OF CRLEntry OPTIONAL} * CRLEntry ::= SEQUENCE{ * userCertificate SerialNumber, * revocationDate UTCTime} */ typedef struct CertX509 { int serial; char* issuer; char* validity_start; char* validity_end; char* subject; int publickey_alg; Bytes* publickey; int signature_alg; Bytes* signature; } CertX509; /* Algorithm object-ids */ enum { ALG_rsaEncryption, ALG_md2WithRSAEncryption, ALG_md4WithRSAEncryption, ALG_md5WithRSAEncryption, ALG_sha1WithRSAEncryption, ALG_md5, NUMALGS }; typedef struct Ints7 { int len; int data[7]; } Ints7; static Ints7 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 }; static Ints7 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 }; static Ints7 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 }; static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 }; static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 }; static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 }; static Ints *alg_oid_tab[NUMALGS+1] = { (Ints*)&oid_rsaEncryption, (Ints*)&oid_md2WithRSAEncryption, (Ints*)&oid_md4WithRSAEncryption, (Ints*)&oid_md5WithRSAEncryption, (Ints*)&oid_sha1WithRSAEncryption, (Ints*)&oid_md5, nil }; static DigestFun digestalg[NUMALGS+1] = { md5, md5, md5, md5, sha1, md5, nil }; static void freecert(CertX509* c) { if (!c) return; if(c->issuer != nil) free(c->issuer); if(c->validity_start != nil) free(c->validity_start); if(c->validity_end != nil) free(c->validity_end); if(c->subject != nil) free(c->subject); freebytes(c->publickey); freebytes(c->signature); } /* * Parse the Name ASN1 type. * The sequence of RelativeDistinguishedName's gives a sort of pathname, * from most general to most specific. Each element of the path can be * one or more (but usually just one) attribute-value pair, such as * countryName="US". * We'll just form a "postal-style" address string by concatenating the elements * from most specific to least specific, separated by commas. * Return name-as-string (which must be freed by caller). */ static char* parse_name(Elem* e) { Elist* el; Elem* es; Elist* esetl; Elem* eat; Elist* eatl; char* s; enum { MAXPARTS = 100 }; char* parts[MAXPARTS]; int i; int plen; char* ans = nil; if(!is_seq(e, &el)) goto errret; i = 0; plen = 0; while(el != nil) { es = &el->hd; if(!is_set(es, &esetl)) goto errret; while(esetl != nil) { eat = &esetl->hd; if(!is_seq(eat, &eatl) || elistlen(eatl) != 2) goto errret; if(!is_string(&eatl->tl->hd, &s) || i>=MAXPARTS) goto errret; parts[i++] = s; plen += strlen(s) + 2; /* room for ", " after */ esetl = esetl->tl; } el = el->tl; } if(i > 0) { ans = (char*)emalloc(plen); *ans = '\0'; while(--i >= 0) { s = parts[i]; strcat(ans, s); if(i > 0) strcat(ans, ", "); } } errret: return ans; } /* * Parse an AlgorithmIdentifer ASN1 type. * Look up the oid in oid_tab and return one of OID_rsaEncryption, etc.., * or -1 if not found. * For now, ignore parameters, since none of our algorithms need them. */ static int parse_alg(Elem* e) { Elist* el; Ints* oid; if(!is_seq(e, &el) || el == nil || !is_oid(&el->hd, &oid)) return -1; return oid_lookup(oid, alg_oid_tab); } static CertX509* decode_cert(Bytes* a) { int ok = 0; int n; CertX509* c = nil; Elem ecert; Elem* ecertinfo; Elem* esigalg; Elem* esig; Elem* eserial; Elem* eissuer; Elem* evalidity; Elem* esubj; Elem* epubkey; Elist* el; Elist* elcert = nil; Elist* elcertinfo = nil; Elist* elvalidity = nil; Elist* elpubkey = nil; Bits* bits = nil; Bytes* b; Elem* e; if(decode(a->data, a->len, &ecert) != ASN_OK) goto errret; c = (CertX509*)emalloc(sizeof(CertX509)); c->serial = -1; c->issuer = nil; c->validity_start = nil; c->validity_end = nil; c->subject = nil; c->publickey_alg = -1; c->publickey = nil; c->signature_alg = -1; c->signature = nil; /* Certificate */ if(!is_seq(&ecert, &elcert) || elistlen(elcert) !=3) goto errret; ecertinfo = &elcert->hd; el = elcert->tl; esigalg = &el->hd; c->signature_alg = parse_alg(esigalg); el = el->tl; esig = &el->hd; /* Certificate Info */ if(!is_seq(ecertinfo, &elcertinfo)) goto errret; n = elistlen(elcertinfo); if(n < 6) goto errret; eserial =&elcertinfo->hd; el = elcertinfo->tl; /* check for optional version, marked by explicit context tag 0 */ if(eserial->tag.class == Context && eserial->tag.num == 0) { eserial = &el->hd; if(n < 7) goto errret; el = el->tl; } if(parse_alg(&el->hd) != c->signature_alg) goto errret; el = el->tl; eissuer = &el->hd; el = el->tl; evalidity = &el->hd; el = el->tl; esubj = &el->hd; el = el->tl; epubkey = &el->hd; if(!is_int(eserial, &c->serial)) { if(!is_bigint(eserial, &b)) goto errret; c->serial = -1; /* else we have to change cert struct */ } c->issuer = parse_name(eissuer); if(c->issuer == nil) goto errret; /* Validity */ if(!is_seq(evalidity, &elvalidity)) goto errret; if(elistlen(elvalidity) != 2) goto errret; e = &elvalidity->hd; if(!is_time(e, &c->validity_start)) goto errret; e->val.u.stringval = nil; /* string ownership transfer */ e = &elvalidity->tl->hd; if(!is_time(e, &c->validity_end)) goto errret; e->val.u.stringval = nil; /* string ownership transfer */ /* resume CertificateInfo */ c->subject = parse_name(esubj); if(c->subject == nil) goto errret; /* SubjectPublicKeyInfo */ if(!is_seq(epubkey, &elpubkey)) goto errret; if(elistlen(elpubkey) != 2) goto errret; c->publickey_alg = parse_alg(&elpubkey->hd); if(c->publickey_alg < 0) goto errret; if(!is_bitstring(&elpubkey->tl->hd, &bits)) goto errret; if(bits->unusedbits != 0) goto errret; c->publickey = makebytes(bits->data, bits->len); /*resume Certificate */ if(c->signature_alg < 0) goto errret; if(!is_bitstring(esig, &bits)) goto errret; c->signature = makebytes(bits->data, bits->len); ok = 1; errret: freevalfields(&ecert.val); /* recurses through lists, too */ if(!ok){ freecert(c); c = nil; } return c; } /* * RSAPublickKey :: SEQUENCE { * modulus INTEGER, * publicExponent INTEGER * } */ static RSApub* decode_rsapubkey(Bytes* a) { Elem e; Elist *el; mpint *mp; RSApub* key; key = rsapuballoc(); if(decode(a->data, a->len, &e) != ASN_OK) goto errret; if(!is_seq(&e, &el) || elistlen(el) != 2) goto errret; key->n = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->ek = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; return key; errret: rsapubfree(key); return nil; } /* * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER -- (inverse of q) mod p } */ static RSApriv* decode_rsaprivkey(Bytes* a) { int version; Elem e; Elist *el; mpint *mp; RSApriv* key; key = rsaprivalloc(); if(decode(a->data, a->len, &e) != ASN_OK) goto errret; if(!is_seq(&e, &el) || elistlen(el) != 9) goto errret; if(!is_int(&el->hd, &version) || version != 0) goto errret; el = el->tl; key->pub.n = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->pub.ek = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->dk = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->q = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->p = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->kq = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->kp = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; el = el->tl; key->c2 = mp = asn1mpint(&el->hd); if(mp == nil) goto errret; return key; errret: rsaprivfree(key); return nil; } static mpint* asn1mpint(Elem *e) { Bytes *b; mpint *mp; int v; if(is_int(e, &v)) return itomp(v, nil); if(is_bigint(e, &b)) { mp = betomp(b->data, b->len, nil); freebytes(b); return mp; } return nil; } static mpint* pkcs1pad(Bytes *b, mpint *modulus) { int n = (mpsignif(modulus)+7)/8; int pm1, i; uchar *p; mpint *mp; pm1 = n - 1 - b->len; p = (uchar*)emalloc(n); p[0] = 0; p[1] = 1; for(i = 2; i < pm1; i++) p[i] = 0xFF; p[pm1] = 0; memcpy(&p[pm1+1], b->data, b->len); mp = betomp(p, n, nil); free(p); return mp; } RSApriv* asn1toRSApriv(uchar *kd, int kn) { Bytes *b; RSApriv *key; b = makebytes(kd, kn); key = decode_rsaprivkey(b); freebytes(b); return key; } /* * digest(CertificateInfo) * Our ASN.1 library doesn't return pointers into the original * data array, so we need to do a little hand decoding. */ static void digest_certinfo(Bytes *cert, DigestFun digestfun, uchar *digest) { uchar *info, *p, *pend; ulong infolen; int isconstr, length; Tag tag; Elem elem; p = cert->data; pend = cert->data + cert->len; if(tag_decode(&p, pend, &tag, &isconstr) != ASN_OK || tag.class != Universal || tag.num != SEQUENCE || length_decode(&p, pend, &length) != ASN_OK || p+length > pend) return; info = p; if(ber_decode(&p, pend, &elem) != ASN_OK || elem.tag.num != SEQUENCE) return; infolen = p - info; (*digestfun)(info, infolen, digest, nil); } static char* verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg) { Elem e; Elist *el; Bytes *digest; uchar *pkcs1buf, *buf; int buflen; mpint *pkcs1; /* see 9.2.1 of rfc2437 */ pkcs1 = betomp(signature->data, signature->len, nil); mpexp(pkcs1, pk->ek, pk->n, pkcs1); buflen = mptobe(pkcs1, nil, 0, &pkcs1buf); buf = pkcs1buf; if(buflen < 4 || buf[0] != 1) return "expected 1"; buf++; while(buf[0] == 0xff) buf++; if(buf[0] != 0) return "expected 0"; buf++; buflen -= buf-pkcs1buf; if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 || !is_octetstring(&el->tl->hd, &digest)) return "signature parse error"; *psigalg = &el->hd; if(memcmp(digest->data, edigest, digest->len) == 0) return nil; return "digests did not match"; } RSApub* X509toRSApub(uchar *cert, int ncert, char *name, int nname) { char *e; Bytes *b; CertX509 *c; RSApub *pk; b = makebytes(cert, ncert); c = decode_cert(b); freebytes(b); if(c == nil) return nil; if(name != nil && c->subject != nil){ e = strchr(c->subject, ','); if(e != nil) *e = 0; // take just CN part of Distinguished Name strncpy(name, c->subject, nname); } pk = decode_rsapubkey(c->publickey); freecert(c); return pk; } char* X509verify(uchar *cert, int ncert, RSApub *pk) { char *e; Bytes *b; CertX509 *c; uchar digest[SHA1dlen]; Elem *sigalg; b = makebytes(cert, ncert); c = decode_cert(b); if(c != nil) digest_certinfo(b, digestalg[c->signature_alg], digest); freebytes(b); if(c == nil) return "cannot decode cert"; e = verify_signature(c->signature, pk, digest, &sigalg); freecert(c); return e; } /* ------- Elem constructors ---------- */ static Elem Null(void) { Elem e; e.tag.class = Universal; e.tag.num = NULLTAG; e.val.tag = VNull; return e; } static Elem mkint(int j) { Elem e; e.tag.class = Universal; e.tag.num = INTEGER; e.val.tag = VInt; e.val.u.intval = j; return e; } static Elem mkbigint(mpint *p) { Elem e; uchar *buf; int buflen; e.tag.class = Universal; e.tag.num = INTEGER; e.val.tag = VBigInt; buflen = mptobe(p, nil, 0, &buf); e.val.u.bigintval = makebytes(buf, buflen); free(buf); return e; } static Elem mkstring(char *s) { Elem e; e.tag.class = Universal; e.tag.num = IA5String; e.val.tag = VString; e.val.u.stringval = estrdup(s); return e; } static Elem mkoctet(uchar *buf, int buflen) { Elem e; e.tag.class = Universal; e.tag.num = OCTET_STRING; e.val.tag = VOctets; e.val.u.octetsval = makebytes(buf, buflen); return e; } static Elem mkbits(uchar *buf, int buflen) { Elem e; e.tag.class = Universal; e.tag.num = BIT_STRING; e.val.tag = VBitString; e.val.u.bitstringval = makebits(buf, buflen, 0); return e; } static Elem mkutc(long t) { Elem e; char utc[50]; Tm *tm = gmtime(t); e.tag.class = Universal; e.tag.num = UTCTime; e.val.tag = VString; snprint(utc, 50, "%.2d%.2d%.2d%.2d%.2d%.2dZ", tm->year % 100, tm->mon+1, tm->mday, tm->hour, tm->min, tm->sec); e.val.u.stringval = estrdup(utc); return e; } static Elem mkoid(Ints *oid) { Elem e; e.tag.class = Universal; e.tag.num = OBJECT_ID; e.val.tag = VObjId; e.val.u.objidval = makeints(oid->data, oid->len); return e; } static Elem mkseq(Elist *el) { Elem e; e.tag.class = Universal; e.tag.num = SEQUENCE; e.val.tag = VSeq; e.val.u.seqval = el; return e; } static Elem mkset(Elist *el) { Elem e; e.tag.class = Universal; e.tag.num = SETOF; e.val.tag = VSet; e.val.u.setval = el; return e; } static Elem mkalg(int alg) { return mkseq(mkel(mkoid(alg_oid_tab[alg]), mkel(Null(), nil))); } typedef struct Ints7pref { int len; int data[7]; char prefix[4]; } Ints7pref; Ints7pref DN_oid[] = { {4, 2, 5, 4, 6, 0, 0, 0, "C="}, {4, 2, 5, 4, 8, 0, 0, 0, "ST="}, {4, 2, 5, 4, 7, 0, 0, 0, "L="}, {4, 2, 5, 4, 10, 0, 0, 0, "O="}, {4, 2, 5, 4, 11, 0, 0, 0, "OU="}, {4, 2, 5, 4, 3, 0, 0, 0, "CN="}, {7, 1,2,840,113549,1,9,1, "E="}, }; static Elem mkname(Ints7pref *oid, char *subj) { return mkset(mkel(mkseq(mkel(mkoid((Ints*)oid), mkel(mkstring(subj), nil))), nil)); } static Elem mkDN(char *dn) { int i, j, nf; char *f[20], *prefix, *d2 = estrdup(dn); Elist* el = nil; nf = tokenize(d2, f, nelem(f)); for(i=nf-1; i>=0; i--){ for(j=0; jn),mkel(mkint(mptoi(pk->ek)),nil))); if(encode(pubkey, &pkbytes) != ASN_OK) goto errret; freevalfields(&pubkey.val); pubkey = mkseq( mkel(mkalg(ALG_rsaEncryption), mkel(mkbits(pkbytes->data, pkbytes->len), nil))); freebytes(pkbytes); validity = mkseq( mkel(mkutc(valid[0]), mkel(mkutc(valid[1]), nil))); certinfo = mkseq( mkel(mkint(serial), mkel(mkalg(ALG_md5WithRSAEncryption), mkel(issuer, mkel(validity, mkel(subject, mkel(pubkey, nil))))))); if(encode(certinfo, &certinfobytes) != ASN_OK) goto errret; md5(certinfobytes->data, certinfobytes->len, digest, 0); freebytes(certinfobytes); sig = mkseq( mkel(mkalg(ALG_md5), mkel(mkoctet(digest, MD5dlen), nil))); if(encode(sig, &sigbytes) != ASN_OK) goto errret; pkcs1 = pkcs1pad(sigbytes, pk->n); freebytes(sigbytes); rsadecrypt(priv, pkcs1, pkcs1); buflen = mptobe(pkcs1, nil, 0, &buf); mpfree(pkcs1); e = mkseq( mkel(certinfo, mkel(mkalg(ALG_md5WithRSAEncryption), mkel(mkbits(buf, buflen), nil)))); free(buf); if(encode(e, &certbytes) != ASN_OK) goto errret; if(certlen) *certlen = certbytes->len; cert = certbytes->data; errret: freevalfields(&e.val); return cert; } uchar* X509req(RSApriv *priv, char *subj, int *certlen) { /* RFC 2314, PKCS #10 Certification Request Syntax */ int version = 0; uchar *cert = nil; RSApub *pk = rsaprivtopub(priv); Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes; Elem e, certinfo, subject, pubkey, sig; uchar digest[MD5dlen], *buf; int buflen; mpint *pkcs1; e.val.tag = VInt; /* so freevalfields at errret is no-op */ subject = mkDN(subj); pubkey = mkseq(mkel(mkbigint(pk->n),mkel(mkint(mptoi(pk->ek)),nil))); if(encode(pubkey, &pkbytes) != ASN_OK) goto errret; freevalfields(&pubkey.val); pubkey = mkseq( mkel(mkalg(ALG_rsaEncryption), mkel(mkbits(pkbytes->data, pkbytes->len), nil))); freebytes(pkbytes); certinfo = mkseq( mkel(mkint(version), mkel(subject, mkel(pubkey, nil)))); if(encode(certinfo, &certinfobytes) != ASN_OK) goto errret; md5(certinfobytes->data, certinfobytes->len, digest, 0); freebytes(certinfobytes); sig = mkseq( mkel(mkalg(ALG_md5), mkel(mkoctet(digest, MD5dlen), nil))); if(encode(sig, &sigbytes) != ASN_OK) goto errret; pkcs1 = pkcs1pad(sigbytes, pk->n); freebytes(sigbytes); rsadecrypt(priv, pkcs1, pkcs1); buflen = mptobe(pkcs1, nil, 0, &buf); mpfree(pkcs1); e = mkseq( mkel(certinfo, mkel(mkalg(ALG_md5), mkel(mkbits(buf, buflen), nil)))); free(buf); if(encode(e, &certbytes) != ASN_OK) goto errret; if(certlen) *certlen = certbytes->len; cert = certbytes->data; errret: freevalfields(&e.val); return cert; } static char* tagdump(Tag tag) { if(tag.class != Universal) return smprint("class%d,num%d", tag.class, tag.num); switch(tag.num){ case BOOLEAN: return "BOOLEAN"; break; case INTEGER: return "INTEGER"; break; case BIT_STRING: return "BIT STRING"; break; case OCTET_STRING: return "OCTET STRING"; break; case NULLTAG: return "NULLTAG"; break; case OBJECT_ID: return "OID"; break; case ObjectDescriptor: return "OBJECT_DES"; break; case EXTERNAL: return "EXTERNAL"; break; case REAL: return "REAL"; break; case ENUMERATED: return "ENUMERATED"; break; case EMBEDDED_PDV: return "EMBEDDED PDV"; break; case SEQUENCE: return "SEQUENCE"; break; case SETOF: return "SETOF"; break; case NumericString: return "NumericString"; break; case PrintableString: return "PrintableString"; break; case TeletexString: return "TeletexString"; break; case VideotexString: return "VideotexString"; break; case IA5String: return "IA5String"; break; case UTCTime: return "UTCTime"; break; case GeneralizedTime: return "GeneralizedTime"; break; case GraphicString: return "GraphicString"; break; case VisibleString: return "VisibleString"; break; case GeneralString: return "GeneralString"; break; case UniversalString: return "UniversalString"; break; case BMPString: return "BMPString"; break; default: return smprint("Universal,num%d", tag.num); } } static void edump(Elem e) { Value v; Elist *el; int i; print("%s{", tagdump(e.tag)); v = e.val; switch(v.tag){ case VBool: print("Bool %d",v.u.boolval); break; case VInt: print("Int %d",v.u.intval); break; case VOctets: print("Octets[%d] %.2x%.2x...",v.u.octetsval->len,v.u.octetsval->data[0],v.u.octetsval->data[1]); break; case VBigInt: print("BigInt[%d] %.2x%.2x...",v.u.bigintval->len,v.u.bigintval->data[0],v.u.bigintval->data[1]); break; case VReal: print("Real..."); break; case VOther: print("Other..."); break; case VBitString: print("BitString..."); break; case VNull: print("Null"); break; case VEOC: print("EOC..."); break; case VObjId: print("ObjId"); for(i = 0; ilen; i++) print(" %d", v.u.objidval->data[i]); break; case VString: print("String \"%s\"",v.u.stringval); break; case VSeq: print("Seq\n"); for(el = v.u.seqval; el!=nil; el = el->tl) edump(el->hd); break; case VSet: print("Set\n"); for(el = v.u.setval; el!=nil; el = el->tl) edump(el->hd); break; } print("}\n"); } void asn1dump(uchar *der, int len) { Elem e; if(decode(der, len, &e) != ASN_OK){ print("didn't parse\n"); exits("didn't parse"); } edump(e); } void X509dump(uchar *cert, int ncert) { char *e; Bytes *b; CertX509 *c; RSApub *pk; uchar digest[SHA1dlen]; Elem *sigalg; print("begin X509dump\n"); b = makebytes(cert, ncert); c = decode_cert(b); if(c != nil) digest_certinfo(b, digestalg[c->signature_alg], digest); freebytes(b); if(c == nil){ print("cannot decode cert"); return; } print("serial %d\n", c->serial); print("issuer %s\n", c->issuer); print("validity %s %s\n", c->validity_start, c->validity_end); print("subject %s\n", c->subject); pk = decode_rsapubkey(c->publickey); print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n); print("sigalg=%d digest=%.*H\n", c->signature_alg, MD5dlen, digest); e = verify_signature(c->signature, pk, digest, &sigalg); if(e==nil){ e = "nil (meaning ok)"; print("sigalg=\n"); if(sigalg) edump(*sigalg); } print("self-signed verify_signature returns: %s\n", e); rsapubfree(pk); freecert(c); print("end X509dump\n"); } drawterm-20110822.orig/libsec/egencrypt.c0000644000175000017500000000144611245145712017505 0ustar tinchotincho#include "os.h" #include #include mpint* egencrypt(EGpub *pub, mpint *in, mpint *out) { mpint *m, *k, *gamma, *delta, *pm1; mpint *p = pub->p, *alpha = pub->alpha; int plen = mpsignif(p); int shift = ((plen+Dbits)/Dbits)*Dbits; // in libcrypt version, (int)(LENGTH(pub->p)*sizeof(NumType)*CHARBITS); if(out == nil) out = mpnew(0); pm1 = mpnew(0); m = mpnew(0); gamma = mpnew(0); delta = mpnew(0); mpmod(in, p, m); while(1){ k = mprand(plen, genrandom, nil); if((mpcmp(mpone, k) <= 0) && (mpcmp(k, pm1) < 0)) break; } mpexp(alpha, k, p, gamma); mpexp(pub->key, k, p, delta); mpmul(m, delta, delta); mpmod(delta, p, delta); mpleft(gamma, shift, out); mpadd(delta, out, out); mpfree(pm1); mpfree(m); mpfree(k); mpfree(gamma); mpfree(delta); return out; } drawterm-20110822.orig/libsec/dsaverify.c0000644000175000017500000000161511245145712017477 0ustar tinchotincho#include "os.h" #include #include int dsaverify(DSApub *pub, DSAsig *sig, mpint *m) { int rv = -1; mpint *u1, *u2, *v, *sinv; if(sig->r->sign < 0 || mpcmp(sig->r, pub->q) >= 0) return rv; if(sig->s->sign < 0 || mpcmp(sig->s, pub->q) >= 0) return rv; u1 = mpnew(0); u2 = mpnew(0); v = mpnew(0); sinv = mpnew(0); // find (s**-1) mod q, make sure it exists mpextendedgcd(sig->s, pub->q, u1, sinv, v); if(mpcmp(u1, mpone) != 0) goto out; // u1 = (sinv * m) mod q, u2 = (r * sinv) mod q mpmul(sinv, m, u1); mpmod(u1, pub->q, u1); mpmul(sig->r, sinv, u2); mpmod(u2, pub->q, u2); // v = (((alpha**u1)*(key**u2)) mod p) mod q mpexp(pub->alpha, u1, pub->p, sinv); mpexp(pub->key, u2, pub->p, v); mpmul(sinv, v, v); mpmod(v, pub->p, v); mpmod(v, pub->q, v); if(mpcmp(v, sig->r) == 0) rv = 0; out: mpfree(v); mpfree(u1); mpfree(u2); mpfree(sinv); return rv; } drawterm-20110822.orig/libsec/rsagen.c0000644000175000017500000000265311245145712016765 0ustar tinchotincho#include "os.h" #include #include static void genrand(mpint *p, int n) { mpdigit x; // generate n random bits with high set mpbits(p, n); genrandom((uchar*)p->p, (n+7)/8); p->top = (n+Dbits-1)/Dbits; x = 1; x <<= ((n-1)%Dbits); p->p[p->top-1] &= (x-1); p->p[p->top-1] |= x; } RSApriv* rsagen(int nlen, int elen, int rounds) { mpint *p, *q, *e, *d, *phi, *n, *t1, *t2, *kp, *kq, *c2; RSApriv *rsa; p = mpnew(nlen/2); q = mpnew(nlen/2); n = mpnew(nlen); e = mpnew(elen); d = mpnew(0); phi = mpnew(nlen); // create the prime factors and euclid's function genstrongprime(p, nlen/2, rounds); genstrongprime(q, nlen - mpsignif(p) + 1, rounds); mpmul(p, q, n); mpsub(p, mpone, e); mpsub(q, mpone, d); mpmul(e, d, phi); // find an e relatively prime to phi t1 = mpnew(0); t2 = mpnew(0); genrand(e, elen); for(;;){ mpextendedgcd(e, phi, d, t1, t2); if(mpcmp(d, mpone) == 0) break; mpadd(mpone, e, e); } mpfree(t1); mpfree(t2); // d = e**-1 mod phi mpinvert(e, phi, d); // compute chinese remainder coefficient c2 = mpnew(0); mpinvert(p, q, c2); // for crt a**k mod p == (a**(k mod p-1)) mod p kq = mpnew(0); kp = mpnew(0); mpsub(p, mpone, phi); mpmod(d, phi, kp); mpsub(q, mpone, phi); mpmod(d, phi, kq); rsa = rsaprivalloc(); rsa->pub.ek = e; rsa->pub.n = n; rsa->dk = d; rsa->kp = kp; rsa->kq = kq; rsa->p = p; rsa->q = q; rsa->c2 = c2; mpfree(phi); return rsa; } drawterm-20110822.orig/libsec/des3ECB.c0000644000175000017500000000162511245145712016654 0ustar tinchotincho#include "os.h" #include #include // I wasn't sure what to do when the buffer was not // a multiple of 8. I did what lacy's cryptolib did // to be compatible, but it looks dangerous to me // since its encrypting plain text with the key. -- presotto void des3ECBencrypt(uchar *p, int len, DES3state *s) { int i; uchar tmp[8]; for(; len >= 8; len -= 8){ triple_block_cipher(s->expanded, p, DES3EDE); p += 8; } if(len > 0){ for (i=0; i<8; i++) tmp[i] = i; triple_block_cipher(s->expanded, tmp, DES3EDE); for (i = 0; i < len; i++) p[i] ^= tmp[i]; } } void des3ECBdecrypt(uchar *p, int len, DES3state *s) { int i; uchar tmp[8]; for(; len >= 8; len -= 8){ triple_block_cipher(s->expanded, p, DES3DED); p += 8; } if(len > 0){ for (i=0; i<8; i++) tmp[i] = i; triple_block_cipher(s->expanded, tmp, DES3EDE); for (i = 0; i < len; i++) p[i] ^= tmp[i]; } } drawterm-20110822.orig/libsec/primetest.c0000644000175000017500000000466611245145712017530 0ustar tinchotincho#include "os.h" #include #include void main(void) { mpint *z = mpnew(0); mpint *p = mpnew(0); mpint *q = mpnew(0); mpint *nine = mpnew(0); fmtinstall('B', mpconv); strtomp("2492491", nil, 16, z); // 38347921 = x*y = (2**28-9)/7, // an example of 3**(n-1)=1 mod n strtomp("15662C00E811", nil, 16, p);// 23528569104401, a prime uitomp(9, nine); if(probably_prime(z, 5) == 1) fprint(2, "tricked primality test\n"); if(probably_prime(nine, 5) == 1) fprint(2, "9 passed primality test!\n"); if(probably_prime(p, 25) == 1) fprint(2, "ok\n"); DSAprimes(q, p, nil); print("q=%B\np=%B\n", q, p); exits(0); } // example output, checked with Maple: // seed EB7B6E35F7CD37B511D96C67D6688CC4DD440E1E // q=E0F0EF284E10796C5A2A511E94748BA03C795C13 // = 1284186945063585093695748280224501481698995297299 // p=C41CFBE4D4846F67A3DF7DE9921A49D3B42DC33728427AB159CEC8CBBDB12B5F0C244F1A734AEB9840804EA3C25036AD1B61AFF3ABBC247CD4B384224567A863A6F020E7EE9795554BCD08ABAD7321AF27E1E92E3DB1C6E7E94FAAE590AE9C48F96D93D178E809401ABE8A534A1EC44359733475A36A70C7B425125062B1142D // = 137715385439333164327584575331308277462546592976152006175830654712456008630139443747529133857837818585400418619916530061955288983751958831927807888408309879880101870216437711393638413509484569804814373511469405934988856674935304074081350525593807908358867354528898618574659752879015380013845760006721861915693 // r=DF310F4E54A5FEC5D86D3E14863921E834113E060F90052AD332B3241CEF2497EFA0303D6344F7C819691A0F9C4A773815AF8EAECFB7EC1D98F039F17A32A7E887D97251A927D093F44A55577F4D70444AEBD06B9B45695EC23962B175F266895C67D21C4656848614D888A4 // = 107239359478548771267308764204625458348785444483302647285245969203446101233421655396874997253111222983406676955642093641709149748793954493558324738441197139556917622937892491175016280660608595599724194374948056515856812347094848443460715881455884639869144172708 // g=2F1C308DC46B9A44B52DF7DACCE1208CCEF72F69C743ADD4D2327173444ED6E65E074694246E07F9FD4AE26E0FDDD9F54F813C40CB9BCD4338EA6F242AB94CD410E676C290368A16B1A3594877437E516C53A6EEE5493A038A017E955E218E7819734E3E2A6E0BAE08B14258F8C03CC1B30E0DDADFCF7CEDF0727684D3D255F1 // = 33081848392740465806285326014906437543653045153885419334085917570615301913274531387168723847139029827598735376746057461417880810924280288611116213062512408829164220104555543445909528701551198146080221790002337033997295756585193926863581671466708482411159477816144226847280417522524922667065714073338662508017 drawterm-20110822.orig/libsec/md5block.c0000644000175000017500000001162711245145712017207 0ustar tinchotincho#include "os.h" #include /* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ /* * Rotate ammounts used in the algorithm */ enum { S11= 7, S12= 12, S13= 17, S14= 22, S21= 5, S22= 9, S23= 14, S24= 20, S31= 4, S32= 11, S33= 16, S34= 23, S41= 6, S42= 10, S43= 15, S44= 21, }; static u32int md5tab[] = { /* round 1 */ /*[0]*/ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, /* round 2 */ /*[16]*/0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, /* round 3 */ /*[32]*/0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, /* round 4 */ /*[48]*/0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static void decode(u32int*, uchar*, ulong); extern void _md5block(uchar *p, ulong len, u32int *s); void _md5block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, sh; u32int *t; uchar *end; u32int x[16]; for(end = p+len; p < end; p += 64){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; decode(x, p, 64); t = md5tab; sh = 0; for(; sh != 16; t += 4){ a += ((c ^ d) & b) ^ d; a += x[sh] + t[0]; a = (a << S11) | (a >> (32 - S11)); a += b; d += ((b ^ c) & a) ^ c; d += x[sh + 1] + t[1]; d = (d << S12) | (d >> (32 - S12)); d += a; c += ((a ^ b) & d) ^ b; c += x[sh + 2] + t[2]; c = (c << S13) | (c >> (32 - S13)); c += d; b += ((d ^ a) & c) ^ a; b += x[sh + 3] + t[3]; b = (b << S14) | (b >> (32 - S14)); b += c; sh += 4; } sh = 1; for(; sh != 1+20*4; t += 4){ a += ((b ^ c) & d) ^ c; a += x[sh & 0xf] + t[0]; a = (a << S21) | (a >> (32 - S21)); a += b; d += ((a ^ b) & c) ^ b; d += x[(sh + 5) & 0xf] + t[1]; d = (d << S22) | (d >> (32 - S22)); d += a; c += ((d ^ a) & b) ^ a; c += x[(sh + 10) & 0xf] + t[2]; c = (c << S23) | (c >> (32 - S23)); c += d; b += ((c ^ d) & a) ^ d; b += x[(sh + 15) & 0xf] + t[3]; b = (b << S24) | (b >> (32 - S24)); b += c; sh += 20; } sh = 5; for(; sh != 5+12*4; t += 4){ a += b ^ c ^ d; a += x[sh & 0xf] + t[0]; a = (a << S31) | (a >> (32 - S31)); a += b; d += a ^ b ^ c; d += x[(sh + 3) & 0xf] + t[1]; d = (d << S32) | (d >> (32 - S32)); d += a; c += d ^ a ^ b; c += x[(sh + 6) & 0xf] + t[2]; c = (c << S33) | (c >> (32 - S33)); c += d; b += c ^ d ^ a; b += x[(sh + 9) & 0xf] + t[3]; b = (b << S34) | (b >> (32 - S34)); b += c; sh += 12; } sh = 0; for(; sh != 28*4; t += 4){ a += c ^ (b | ~d); a += x[sh & 0xf] + t[0]; a = (a << S41) | (a >> (32 - S41)); a += b; d += b ^ (a | ~c); d += x[(sh + 7) & 0xf] + t[1]; d = (d << S42) | (d >> (32 - S42)); d += a; c += a ^ (d | ~b); c += x[(sh + 14) & 0xf] + t[2]; c = (c << S43) | (c >> (32 - S43)); c += d; b += d ^ (c | ~a); b += x[(sh + 21) & 0xf] + t[3]; b = (b << S44) | (b >> (32 - S44)); b += c; sh += 28; } s[0] += a; s[1] += b; s[2] += c; s[3] += d; } } /* * decodes input (uchar) into output (u32int). Assumes len is * a multiple of 4. */ static void decode(u32int *output, uchar *input, ulong len) { uchar *e; for(e = input+len; input < e; input += 4) *output++ = input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24); } drawterm-20110822.orig/libsec/rsatest.c0000644000175000017500000000210711245145712017165 0ustar tinchotincho#include "os.h" #include #include #include void main(void) { RSApriv *rsa; Biobuf b; char *p; int n; mpint *clr, *enc, *clr2; uchar buf[4096]; uchar *e; vlong start; fmtinstall('B', mpconv); rsa = rsagen(1024, 16, 0); if(rsa == nil) sysfatal("rsagen"); Binit(&b, 0, OREAD); clr = mpnew(0); clr2 = mpnew(0); enc = mpnew(0); strtomp("123456789abcdef123456789abcdef123456789abcdef123456789abcdef", nil, 16, clr); rsaencrypt(&rsa->pub, clr, enc); start = nsec(); for(n = 0; n < 10; n++) rsadecrypt(rsa, enc, clr); print("%lld\n", nsec()-start); start = nsec(); for(n = 0; n < 10; n++) mpexp(enc, rsa->dk, rsa->pub.n, clr2); print("%lld\n", nsec()-start); if(mpcmp(clr, clr2) != 0) print("%B != %B\n", clr, clr2); print("> "); while(p = Brdline(&b, '\n')){ n = Blinelen(&b); letomp((uchar*)p, n, clr); print("clr %B\n", clr); rsaencrypt(&rsa->pub, clr, enc); print("enc %B\n", enc); rsadecrypt(rsa, enc, clr); print("clr %B\n", clr); n = mptole(clr, buf, sizeof(buf), nil); write(1, buf, n); print("> "); } } drawterm-20110822.orig/libsec/aes.c0000644000175000017500000017522111245145712016260 0ustar tinchotincho/* * this code is derived from the following source, * and modified to fit into the plan 9 libsec interface. * most of the changes are confined to the top section, * with the exception of converting Te4 and Td4 into u8 rather than u32 arrays. * * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include typedef uchar u8; typedef u32int u32; #define FULL_UNROLL static const u32 Td0[256]; static const u32 Td1[256]; static const u32 Td2[256]; static const u32 Td3[256]; static const u8 Te4[256]; static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); #ifdef NOT static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); #endif static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); static void rijndaelEncrypt(const u32int rk[], int Nr, const uchar pt[16], uchar ct[16]); static void rijndaelDecrypt(const u32int rk[], int Nr, const uchar ct[16], uchar pt[16]); void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec) { memset(s, 0, sizeof(*s)); if(keybytes > AESmaxkey) keybytes = AESmaxkey; memmove(s->key, key, keybytes); s->keybytes = keybytes; s->rounds = rijndaelKeySetup(s->ekey, s->dkey, s->key, keybytes * 8); if(ivec != nil) memmove(s->ivec, ivec, AESbsize); if(keybytes==16 || keybytes==24 || keybytes==32) s->setup = 0xcafebabe; // else rijndaelKeySetup was invalid } // Define by analogy with desCBCencrypt; AES modes are not standardized yet. // Because of the way that non-multiple-of-16 buffers are handled, // the decryptor must be fed buffers of the same size as the encryptor. void aesCBCencrypt(uchar *p, int len, AESstate *s) { uchar *p2, *ip, *eip; uchar q[AESbsize]; for(; len >= AESbsize; len -= AESbsize){ p2 = p; ip = s->ivec; for(eip = ip+AESbsize; ip < eip; ) *p2++ ^= *ip++; rijndaelEncrypt(s->ekey, s->rounds, p, q); memmove(s->ivec, q, AESbsize); memmove(p, q, AESbsize); p += AESbsize; } if(len > 0){ ip = s->ivec; rijndaelEncrypt(s->ekey, s->rounds, ip, q); memmove(s->ivec, q, AESbsize); for(eip = ip+len; ip < eip; ) *p++ ^= *ip++; } } void aesCBCdecrypt(uchar *p, int len, AESstate *s) { uchar *ip, *eip, *tp; uchar tmp[AESbsize], q[AESbsize]; for(; len >= AESbsize; len -= AESbsize){ memmove(tmp, p, AESbsize); rijndaelDecrypt(s->dkey, s->rounds, p, q); memmove(p, q, AESbsize); tp = tmp; ip = s->ivec; for(eip = ip+AESbsize; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } if(len > 0){ ip = s->ivec; rijndaelEncrypt(s->ekey, s->rounds, ip, q); memmove(s->ivec, q, AESbsize); for(eip = ip+len; ip < eip; ) *p++ ^= *ip++; } } /* * this function has been changed for plan 9. * Expand the cipher key into the encryption and decryption key schedules. * * @return the number of rounds for the given cipher key size. */ static int rijndaelKeySetup(u32 erk[/*4*(Nr + 1)*/], u32 drk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int Nr, i; /* expand the cipher key: */ Nr = rijndaelKeySetupEnc(erk, cipherKey, keyBits); /* * invert the order of the round keys and * apply the inverse MixColumn transform to all round keys but the first and the last */ drk[0 ] = erk[4*Nr ]; drk[1 ] = erk[4*Nr + 1]; drk[2 ] = erk[4*Nr + 2]; drk[3 ] = erk[4*Nr + 3]; drk[4*Nr ] = erk[0 ]; drk[4*Nr + 1] = erk[1 ]; drk[4*Nr + 2] = erk[2 ]; drk[4*Nr + 3] = erk[3 ]; erk += 4 * Nr; for (i = 1; i < Nr; i++) { drk += 4; erk -= 4; drk[0] = Td0[Te4[(erk[0] >> 24) ]] ^ Td1[Te4[(erk[0] >> 16) & 0xff]] ^ Td2[Te4[(erk[0] >> 8) & 0xff]] ^ Td3[Te4[(erk[0] ) & 0xff]]; drk[1] = Td0[Te4[(erk[1] >> 24) ]] ^ Td1[Te4[(erk[1] >> 16) & 0xff]] ^ Td2[Te4[(erk[1] >> 8) & 0xff]] ^ Td3[Te4[(erk[1] ) & 0xff]]; drk[2] = Td0[Te4[(erk[2] >> 24) ]] ^ Td1[Te4[(erk[2] >> 16) & 0xff]] ^ Td2[Te4[(erk[2] >> 8) & 0xff]] ^ Td3[Te4[(erk[2] ) & 0xff]]; drk[3] = Td0[Te4[(erk[3] >> 24) ]] ^ Td1[Te4[(erk[3] >> 16) & 0xff]] ^ Td2[Te4[(erk[3] >> 8) & 0xff]] ^ Td3[Te4[(erk[3] ) & 0xff]]; } return Nr; } /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Te4[x] = S [x] Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x] */ static const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; static const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; static const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; static const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; static const u8 Te4[256] = { 0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U, 0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U, 0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U, 0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U, 0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU, 0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U, 0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU, 0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U, 0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U, 0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U, 0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU, 0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU, 0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U, 0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U, 0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U, 0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U, 0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U, 0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U, 0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U, 0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU, 0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU, 0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U, 0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U, 0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U, 0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U, 0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU, 0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU, 0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU, 0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U, 0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU, 0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U, 0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U, }; static const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; static const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; static const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; static const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; static const u8 Td4[256] = { 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; static const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) #ifdef _MSC_VER #define GETU32(p) SWAP(*((u32 *)(p))) #define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } #else #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) #define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } #endif /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int i = 0; u32 temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); if (keyBits == 128) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te4[(temp >> 16) & 0xff] << 24) ^ (Te4[(temp >> 8) & 0xff] << 16) ^ (Te4[(temp ) & 0xff] << 8) ^ (Te4[(temp >> 24) ] ) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { return 10; } rk += 4; } } rk[4] = GETU32(cipherKey + 16); rk[5] = GETU32(cipherKey + 20); if (keyBits == 192) { for (;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] << 24) ^ (Te4[(temp >> 8) & 0xff] << 16) ^ (Te4[(temp ) & 0xff] << 8) ^ (Te4[(temp >> 24) ] ) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if (++i == 8) { return 12; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } rk[6] = GETU32(cipherKey + 24); rk[7] = GETU32(cipherKey + 28); if (keyBits == 256) { for (;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] << 24) ^ (Te4[(temp >> 8) & 0xff] << 16) ^ (Te4[(temp ) & 0xff] << 8) ^ (Te4[(temp >> 24) ] ) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if (++i == 7) { return 14; } temp = rk[11]; rk[12] = rk[ 4] ^ (Te4[(temp >> 24) ] << 24) ^ (Te4[(temp >> 16) & 0xff] << 16) ^ (Te4[(temp >> 8) & 0xff] << 8) ^ (Te4[(temp ) & 0xff] ); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ #ifdef NOTUSED static int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int Nr, i, j; u32 temp; /* expand the cipher key: */ Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te4[(rk[0] >> 24) ]] ^ Td1[Te4[(rk[0] >> 16) & 0xff]] ^ Td2[Te4[(rk[0] >> 8) & 0xff]] ^ Td3[Te4[(rk[0] ) & 0xff]]; rk[1] = Td0[Te4[(rk[1] >> 24) ]] ^ Td1[Te4[(rk[1] >> 16) & 0xff]] ^ Td2[Te4[(rk[1] >> 8) & 0xff]] ^ Td3[Te4[(rk[1] ) & 0xff]]; rk[2] = Td0[Te4[(rk[2] >> 24) ]] ^ Td1[Te4[(rk[2] >> 16) & 0xff]] ^ Td2[Te4[(rk[2] >> 8) & 0xff]] ^ Td3[Te4[(rk[2] ) & 0xff]]; rk[3] = Td0[Te4[(rk[3] >> 24) ]] ^ Td1[Te4[(rk[3] >> 16) & 0xff]] ^ Td2[Te4[(rk[3] >> 8) & 0xff]] ^ Td3[Te4[(rk[3] ) & 0xff]]; } return Nr; } #endif static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[4]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[5]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[6]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Te0[(t0 >> 24) ] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[(t3 ) & 0xff] ^ rk[0]; s1 = Te0[(t1 >> 24) ] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[(t0 ) & 0xff] ^ rk[1]; s2 = Te0[(t2 >> 24) ] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[(t1 ) & 0xff] ^ rk[2]; s3 = Te0[(t3 >> 24) ] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[(t2 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] << 24) ^ (Te4[(t1 >> 16) & 0xff] << 16) ^ (Te4[(t2 >> 8) & 0xff] << 8) ^ (Te4[(t3 ) & 0xff] ) ^ rk[0]; PUTU32(ct , s0); s1 = (Te4[(t1 >> 24) ] << 24) ^ (Te4[(t2 >> 16) & 0xff] << 16) ^ (Te4[(t3 >> 8) & 0xff] << 8) ^ (Te4[(t0 ) & 0xff] ) ^ rk[1]; PUTU32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] << 24) ^ (Te4[(t3 >> 16) & 0xff] << 16) ^ (Te4[(t0 >> 8) & 0xff] << 8) ^ (Te4[(t1 ) & 0xff] ) ^ rk[2]; PUTU32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] << 24) ^ (Te4[(t0 >> 16) & 0xff] << 16) ^ (Te4[(t1 >> 8) & 0xff] << 8) ^ (Te4[(t2 ) & 0xff] ) ^ rk[3]; PUTU32(ct + 12, s3); } static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; /* round 3: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; /* round 4: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; /* round 5: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; /* round 6: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; /* round 7: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; /* round 8: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; /* round 9: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; /* round 11: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; /* round 13: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[4]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[5]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[6]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Td0[(t0 >> 24) ] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[(t1 ) & 0xff] ^ rk[0]; s1 = Td0[(t1 >> 24) ] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[(t2 ) & 0xff] ^ rk[1]; s2 = Td0[(t2 >> 24) ] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[(t3 ) & 0xff] ^ rk[2]; s3 = Td0[(t3 >> 24) ] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[(t0 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Td4[(t0 >> 24) ] << 24) ^ (Td4[(t3 >> 16) & 0xff] << 16) ^ (Td4[(t2 >> 8) & 0xff] << 8) ^ (Td4[(t1 ) & 0xff] ) ^ rk[0]; PUTU32(pt , s0); s1 = (Td4[(t1 >> 24) ] << 24) ^ (Td4[(t0 >> 16) & 0xff] << 16) ^ (Td4[(t3 >> 8) & 0xff] << 8) ^ (Td4[(t2 ) & 0xff] ) ^ rk[1]; PUTU32(pt + 4, s1); s2 = (Td4[(t2 >> 24) ] << 24) ^ (Td4[(t1 >> 16) & 0xff] << 16) ^ (Td4[(t0 >> 8) & 0xff] << 8) ^ (Td4[(t3 ) & 0xff] ) ^ rk[2]; PUTU32(pt + 8, s2); s3 = (Td4[(t3 >> 24) ] << 24) ^ (Td4[(t2 >> 16) & 0xff] << 16) ^ (Td4[(t1 >> 8) & 0xff] << 8) ^ (Td4[(t0 ) & 0xff] ) ^ rk[3]; PUTU32(pt + 12, s3); } #ifdef INTERMEDIATE_VALUE_KAT static void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { int r; u32 s0, s1, s2, s3, t0, t1, t2, t3; /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(block ) ^ rk[0]; s1 = GETU32(block + 4) ^ rk[1]; s2 = GETU32(block + 8) ^ rk[2]; s3 = GETU32(block + 12) ^ rk[3]; rk += 4; /* * Nr - 1 full rounds: */ for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[0]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[1]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[2]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; rk += 4; } /* * apply last round and * map cipher state to byte array block: */ if (rounds == Nr) { t0 = (Te4[(s0 >> 24) ] << 24) ^ (Te4[(s1 >> 16) & 0xff] << 16) ^ (Te4[(s2 >> 8) & 0xff] << 8) ^ (Te4[(s3 ) & 0xff] ) ^ rk[0]; t1 = (Te4[(s1 >> 24) ] << 24) ^ (Te4[(s2 >> 16) & 0xff] << 16) ^ (Te4[(s3 >> 8) & 0xff] << 8) ^ (Te4[(s0 ) & 0xff] ) ^ rk[1]; t2 = (Te4[(s2 >> 24) ] << 24) ^ (Te4[(s3 >> 16) & 0xff] << 16) ^ (Te4[(s0 >> 8) & 0xff] << 8) ^ (Te4[(s1 ) & 0xff] ) ^ rk[2]; t3 = (Te4[(s3 >> 24) ] << 24) ^ (Te4[(s0 >> 16) & 0xff] << 16) ^ (Te4[(s1 >> 8) & 0xff] << 8) ^ (Te4[(s2 ) & 0xff] ) ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; } PUTU32(block , s0); PUTU32(block + 4, s1); PUTU32(block + 8, s2); PUTU32(block + 12, s3); } static void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { int r; u32 s0, s1, s2, s3, t0, t1, t2, t3; /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(block ) ^ rk[0]; s1 = GETU32(block + 4) ^ rk[1]; s2 = GETU32(block + 8) ^ rk[2]; s3 = GETU32(block + 12) ^ rk[3]; rk += 4; /* * Nr - 1 full rounds: */ for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[0]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[1]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[2]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; rk += 4; } /* * complete the last round and * map cipher state to byte array block: */ t0 = (Td4[(s0 >> 24) ] << 24) ^ (Td4[(s3 >> 16) & 0xff] << 16) ^ (Td4[(s2 >> 8) & 0xff] << 8) ^ (Td4[(s1 ) & 0xff] ); t1 = (Td4[(s1 >> 24) ] << 24) ^ (Td4[(s0 >> 16) & 0xff] << 16) ^ (Td4[(s3 >> 8) & 0xff] << 8) ^ (Td4[(s2 ) & 0xff] ); t2 = (Td4[(s2 >> 24) ] << 24) ^ (Td4[(s1 >> 16) & 0xff] << 16) ^ (Td4[(s0 >> 8) & 0xff] << 8) ^ (Td4[(s3 ) & 0xff] ); t3 = (Td4[(s3 >> 24) ] << 24) ^ (Td4[(s2 >> 16) & 0xff] << 16) ^ (Td4[(s1 >> 8) & 0xff] << 8) ^ (Td4[(s0 ) & 0xff] ); if (rounds == Nr) { t0 ^= rk[0]; t1 ^= rk[1]; t2 ^= rk[2]; t3 ^= rk[3]; } PUTU32(block , t0); PUTU32(block + 4, t1); PUTU32(block + 8, t2); PUTU32(block + 12, t3); } #endif /* INTERMEDIATE_VALUE_KAT */ drawterm-20110822.orig/libsec/dsasign.c0000644000175000017500000000164611245145712017137 0ustar tinchotincho#include "os.h" #include #include DSAsig* dsasign(DSApriv *priv, mpint *m) { DSApub *pub = &priv->pub; DSAsig *sig; mpint *qm1, *k, *kinv, *r, *s; mpint *q = pub->q, *p = pub->p, *alpha = pub->alpha; int qlen = mpsignif(q); qm1 = mpnew(0); kinv = mpnew(0); r = mpnew(0); s = mpnew(0); k = mpnew(0); mpsub(pub->q, mpone, qm1); // find a k that has an inverse mod q while(1){ mprand(qlen, genrandom, k); if((mpcmp(mpone, k) > 0) || (mpcmp(k, qm1) >= 0)) continue; mpextendedgcd(k, q, r, kinv, s); if(mpcmp(r, mpone) != 0) continue; break; } // make kinv positive mpmod(kinv, qm1, kinv); // r = ((alpha**k) mod p) mod q mpexp(alpha, k, p, r); mpmod(r, q, r); // s = (kinv*(m + ar)) mod q mpmul(r, priv->secret, s); mpadd(s, m, s); mpmul(s, kinv, s); mpmod(s, q, s); sig = dsasigalloc(); sig->r = r; sig->s = s; mpfree(qm1); mpfree(k); mpfree(kinv); return sig; } drawterm-20110822.orig/libsec/nfastrand.c0000644000175000017500000000050711245145712017462 0ustar tinchotincho#include #include #include #define Maxrand ((1UL<<31)-1) ulong nfastrand(ulong n) { ulong m, r; /* * set m to the maximum multiple of n <= 2^31-1 * so we want a random number < m. */ if(n > Maxrand) abort(); m = Maxrand - Maxrand % n; while((r = fastrand()) >= m) ; return r%n; } drawterm-20110822.orig/libsec/des.c0000644000175000017500000004213011245145712016253 0ustar tinchotincho#include "os.h" #include /* * integrated sbox & p perm */ static u32int spbox[] = { 0x00808200,0x00000000,0x00008000,0x00808202,0x00808002,0x00008202,0x00000002,0x00008000, 0x00000200,0x00808200,0x00808202,0x00000200,0x00800202,0x00808002,0x00800000,0x00000002, 0x00000202,0x00800200,0x00800200,0x00008200,0x00008200,0x00808000,0x00808000,0x00800202, 0x00008002,0x00800002,0x00800002,0x00008002,0x00000000,0x00000202,0x00008202,0x00800000, 0x00008000,0x00808202,0x00000002,0x00808000,0x00808200,0x00800000,0x00800000,0x00000200, 0x00808002,0x00008000,0x00008200,0x00800002,0x00000200,0x00000002,0x00800202,0x00008202, 0x00808202,0x00008002,0x00808000,0x00800202,0x00800002,0x00000202,0x00008202,0x00808200, 0x00000202,0x00800200,0x00800200,0x00000000,0x00008002,0x00008200,0x00000000,0x00808002, 0x40084010,0x40004000,0x00004000,0x00084010,0x00080000,0x00000010,0x40080010,0x40004010, 0x40000010,0x40084010,0x40084000,0x40000000,0x40004000,0x00080000,0x00000010,0x40080010, 0x00084000,0x00080010,0x40004010,0x00000000,0x40000000,0x00004000,0x00084010,0x40080000, 0x00080010,0x40000010,0x00000000,0x00084000,0x00004010,0x40084000,0x40080000,0x00004010, 0x00000000,0x00084010,0x40080010,0x00080000,0x40004010,0x40080000,0x40084000,0x00004000, 0x40080000,0x40004000,0x00000010,0x40084010,0x00084010,0x00000010,0x00004000,0x40000000, 0x00004010,0x40084000,0x00080000,0x40000010,0x00080010,0x40004010,0x40000010,0x00080010, 0x00084000,0x00000000,0x40004000,0x00004010,0x40000000,0x40080010,0x40084010,0x00084000, 0x00000104,0x04010100,0x00000000,0x04010004,0x04000100,0x00000000,0x00010104,0x04000100, 0x00010004,0x04000004,0x04000004,0x00010000,0x04010104,0x00010004,0x04010000,0x00000104, 0x04000000,0x00000004,0x04010100,0x00000100,0x00010100,0x04010000,0x04010004,0x00010104, 0x04000104,0x00010100,0x00010000,0x04000104,0x00000004,0x04010104,0x00000100,0x04000000, 0x04010100,0x04000000,0x00010004,0x00000104,0x00010000,0x04010100,0x04000100,0x00000000, 0x00000100,0x00010004,0x04010104,0x04000100,0x04000004,0x00000100,0x00000000,0x04010004, 0x04000104,0x00010000,0x04000000,0x04010104,0x00000004,0x00010104,0x00010100,0x04000004, 0x04010000,0x04000104,0x00000104,0x04010000,0x00010104,0x00000004,0x04010004,0x00010100, 0x80401000,0x80001040,0x80001040,0x00000040,0x00401040,0x80400040,0x80400000,0x80001000, 0x00000000,0x00401000,0x00401000,0x80401040,0x80000040,0x00000000,0x00400040,0x80400000, 0x80000000,0x00001000,0x00400000,0x80401000,0x00000040,0x00400000,0x80001000,0x00001040, 0x80400040,0x80000000,0x00001040,0x00400040,0x00001000,0x00401040,0x80401040,0x80000040, 0x00400040,0x80400000,0x00401000,0x80401040,0x80000040,0x00000000,0x00000000,0x00401000, 0x00001040,0x00400040,0x80400040,0x80000000,0x80401000,0x80001040,0x80001040,0x00000040, 0x80401040,0x80000040,0x80000000,0x00001000,0x80400000,0x80001000,0x00401040,0x80400040, 0x80001000,0x00001040,0x00400000,0x80401000,0x00000040,0x00400000,0x00001000,0x00401040, 0x00000080,0x01040080,0x01040000,0x21000080,0x00040000,0x00000080,0x20000000,0x01040000, 0x20040080,0x00040000,0x01000080,0x20040080,0x21000080,0x21040000,0x00040080,0x20000000, 0x01000000,0x20040000,0x20040000,0x00000000,0x20000080,0x21040080,0x21040080,0x01000080, 0x21040000,0x20000080,0x00000000,0x21000000,0x01040080,0x01000000,0x21000000,0x00040080, 0x00040000,0x21000080,0x00000080,0x01000000,0x20000000,0x01040000,0x21000080,0x20040080, 0x01000080,0x20000000,0x21040000,0x01040080,0x20040080,0x00000080,0x01000000,0x21040000, 0x21040080,0x00040080,0x21000000,0x21040080,0x01040000,0x00000000,0x20040000,0x21000000, 0x00040080,0x01000080,0x20000080,0x00040000,0x00000000,0x20040000,0x01040080,0x20000080, 0x10000008,0x10200000,0x00002000,0x10202008,0x10200000,0x00000008,0x10202008,0x00200000, 0x10002000,0x00202008,0x00200000,0x10000008,0x00200008,0x10002000,0x10000000,0x00002008, 0x00000000,0x00200008,0x10002008,0x00002000,0x00202000,0x10002008,0x00000008,0x10200008, 0x10200008,0x00000000,0x00202008,0x10202000,0x00002008,0x00202000,0x10202000,0x10000000, 0x10002000,0x00000008,0x10200008,0x00202000,0x10202008,0x00200000,0x00002008,0x10000008, 0x00200000,0x10002000,0x10000000,0x00002008,0x10000008,0x10202008,0x00202000,0x10200000, 0x00202008,0x10202000,0x00000000,0x10200008,0x00000008,0x00002000,0x10200000,0x00202008, 0x00002000,0x00200008,0x10002008,0x00000000,0x10202000,0x10000000,0x00200008,0x10002008, 0x00100000,0x02100001,0x02000401,0x00000000,0x00000400,0x02000401,0x00100401,0x02100400, 0x02100401,0x00100000,0x00000000,0x02000001,0x00000001,0x02000000,0x02100001,0x00000401, 0x02000400,0x00100401,0x00100001,0x02000400,0x02000001,0x02100000,0x02100400,0x00100001, 0x02100000,0x00000400,0x00000401,0x02100401,0x00100400,0x00000001,0x02000000,0x00100400, 0x02000000,0x00100400,0x00100000,0x02000401,0x02000401,0x02100001,0x02100001,0x00000001, 0x00100001,0x02000000,0x02000400,0x00100000,0x02100400,0x00000401,0x00100401,0x02100400, 0x00000401,0x02000001,0x02100401,0x02100000,0x00100400,0x00000000,0x00000001,0x02100401, 0x00000000,0x00100401,0x02100000,0x00000400,0x02000001,0x02000400,0x00000400,0x00100001, 0x08000820,0x00000800,0x00020000,0x08020820,0x08000000,0x08000820,0x00000020,0x08000000, 0x00020020,0x08020000,0x08020820,0x00020800,0x08020800,0x00020820,0x00000800,0x00000020, 0x08020000,0x08000020,0x08000800,0x00000820,0x00020800,0x00020020,0x08020020,0x08020800, 0x00000820,0x00000000,0x00000000,0x08020020,0x08000020,0x08000800,0x00020820,0x00020000, 0x00020820,0x00020000,0x08020800,0x00000800,0x00000020,0x08020020,0x00000800,0x00020820, 0x08000800,0x00000020,0x08000020,0x08020000,0x08020020,0x08000000,0x00020000,0x08000820, 0x00000000,0x08020820,0x00020020,0x08000020,0x08020000,0x08000800,0x08000820,0x00000000, 0x08020820,0x00020800,0x00020800,0x00000820,0x00000820,0x00020020,0x08000000,0x08020800, }; /* * for manual index calculation * #define fetch(box, i, sh) (*((u32int*)((uchar*)spbox + (box << 8) + ((i >> (sh)) & 0xfc)))) */ #define fetch(box, i, sh) ((spbox+(box << 6))[((i >> (sh + 2)) & 0x3f)]) /* * DES electronic codebook encryption of one block */ void block_cipher(ulong key[32], uchar text[8], int decrypting) { u32int right, left, v0, v1; int i, keystep; /* * initial permutation */ v0 = text[0] | ((u32int)text[2]<<8) | ((u32int)text[4]<<16) | ((u32int)text[6]<<24); left = text[1] | ((u32int)text[3]<<8) | ((u32int)text[5]<<16) | ((u32int)text[7]<<24); right = (left & 0xaaaaaaaa) | ((v0 >> 1) & 0x55555555); left = ((left << 1) & 0xaaaaaaaa) | (v0 & 0x55555555); left = ((left << 6) & 0x33003300) | (left & 0xcc33cc33) | ((left >> 6) & 0x00cc00cc); left = ((left << 12) & 0x0f0f0000) | (left & 0xf0f00f0f) | ((left >> 12) & 0x0000f0f0); right = ((right << 6) & 0x33003300) | (right & 0xcc33cc33) | ((right >> 6) & 0x00cc00cc); right = ((right << 12) & 0x0f0f0000) | (right & 0xf0f00f0f) | ((right >> 12) & 0x0000f0f0); if (decrypting) { keystep = -2; key = key + 32 - 2; } else keystep = 2; for (i = 0; i < 8; i++) { v0 = key[0]; v0 ^= (right >> 1) | (right << 31); left ^= fetch(0, v0, 24) ^ fetch(2, v0, 16) ^ fetch(4, v0, 8) ^ fetch(6, v0, 0); v1 = key[1]; v1 ^= (right << 3) | (right >> 29); left ^= fetch(1, v1, 24) ^ fetch(3, v1, 16) ^ fetch(5, v1, 8) ^ fetch(7, v1, 0); key += keystep; v0 = key[0]; v0 ^= (left >> 1) | (left << 31); right ^= fetch(0, v0, 24) ^ fetch(2, v0, 16) ^ fetch(4, v0, 8) ^ fetch(6, v0, 0); v1 = key[1]; v1 ^= (left << 3) | (left >> 29); right ^= fetch(1, v1, 24) ^ fetch(3, v1, 16) ^ fetch(5, v1, 8) ^ fetch(7, v1, 0); key += keystep; } /* * final permutation, inverse initial permutation */ v0 = ((left << 1) & 0xaaaaaaaa) | (right & 0x55555555); v1 = (left & 0xaaaaaaaa) | ((right >> 1) & 0x55555555); v1 = ((v1 << 6) & 0x33003300) | (v1 & 0xcc33cc33) | ((v1 >> 6) & 0x00cc00cc); v1 = ((v1 << 12) & 0x0f0f0000) | (v1 & 0xf0f00f0f) | ((v1 >> 12) & 0x0000f0f0); v0 = ((v0 << 6) & 0x33003300) | (v0 & 0xcc33cc33) | ((v0 >> 6) & 0x00cc00cc); v0 = ((v0 << 12) & 0x0f0f0000) | (v0 & 0xf0f00f0f) | ((v0 >> 12) & 0x0000f0f0); text[0] = v0; text[2] = v0 >> 8; text[4] = v0 >> 16; text[6] = v0 >> 24; text[1] = v1; text[3] = v1 >> 8; text[5] = v1 >> 16; text[7] = v1 >> 24; } /* * triple DES electronic codebook encryption of one block */ void triple_block_cipher(ulong expanded_key[3][32], uchar text[8], int ende) { ulong *key; u32int right, left, v0, v1; int i, j, keystep; /* * initial permutation */ v0 = text[0] | ((u32int)text[2]<<8) | ((u32int)text[4]<<16) | ((u32int)text[6]<<24); left = text[1] | ((u32int)text[3]<<8) | ((u32int)text[5]<<16) | ((u32int)text[7]<<24); right = (left & 0xaaaaaaaa) | ((v0 >> 1) & 0x55555555); left = ((left << 1) & 0xaaaaaaaa) | (v0 & 0x55555555); left = ((left << 6) & 0x33003300) | (left & 0xcc33cc33) | ((left >> 6) & 0x00cc00cc); left = ((left << 12) & 0x0f0f0000) | (left & 0xf0f00f0f) | ((left >> 12) & 0x0000f0f0); right = ((right << 6) & 0x33003300) | (right & 0xcc33cc33) | ((right >> 6) & 0x00cc00cc); right = ((right << 12) & 0x0f0f0000) | (right & 0xf0f00f0f) | ((right >> 12) & 0x0000f0f0); for(j = 0; j < 3; j++){ if((ende & 1) == DES3D) { key = &expanded_key[2-j][32-2]; keystep = -2; } else { key = &expanded_key[j][0]; keystep = 2; } ende >>= 1; for (i = 0; i < 8; i++) { v0 = key[0]; v0 ^= (right >> 1) | (right << 31); left ^= fetch(0, v0, 24) ^ fetch(2, v0, 16) ^ fetch(4, v0, 8) ^ fetch(6, v0, 0); v1 = key[1]; v1 ^= (right << 3) | (right >> 29); left ^= fetch(1, v1, 24) ^ fetch(3, v1, 16) ^ fetch(5, v1, 8) ^ fetch(7, v1, 0); key += keystep; v0 = key[0]; v0 ^= (left >> 1) | (left << 31); right ^= fetch(0, v0, 24) ^ fetch(2, v0, 16) ^ fetch(4, v0, 8) ^ fetch(6, v0, 0); v1 = key[1]; v1 ^= (left << 3) | (left >> 29); right ^= fetch(1, v1, 24) ^ fetch(3, v1, 16) ^ fetch(5, v1, 8) ^ fetch(7, v1, 0); key += keystep; } v0 = left; left = right; right = v0; } /* * final permutation, inverse initial permutation * left and right are swapped here */ v0 = ((right << 1) & 0xaaaaaaaa) | (left & 0x55555555); v1 = (right & 0xaaaaaaaa) | ((left >> 1) & 0x55555555); v1 = ((v1 << 6) & 0x33003300) | (v1 & 0xcc33cc33) | ((v1 >> 6) & 0x00cc00cc); v1 = ((v1 << 12) & 0x0f0f0000) | (v1 & 0xf0f00f0f) | ((v1 >> 12) & 0x0000f0f0); v0 = ((v0 << 6) & 0x33003300) | (v0 & 0xcc33cc33) | ((v0 >> 6) & 0x00cc00cc); v0 = ((v0 << 12) & 0x0f0f0000) | (v0 & 0xf0f00f0f) | ((v0 >> 12) & 0x0000f0f0); text[0] = v0; text[2] = v0 >> 8; text[4] = v0 >> 16; text[6] = v0 >> 24; text[1] = v1; text[3] = v1 >> 8; text[5] = v1 >> 16; text[7] = v1 >> 24; } /* * key compression permutation, 4 bits at a time */ static u32int comptab[] = { 0x000000,0x010000,0x000008,0x010008,0x000080,0x010080,0x000088,0x010088, 0x000000,0x010000,0x000008,0x010008,0x000080,0x010080,0x000088,0x010088, 0x000000,0x100000,0x000800,0x100800,0x000000,0x100000,0x000800,0x100800, 0x002000,0x102000,0x002800,0x102800,0x002000,0x102000,0x002800,0x102800, 0x000000,0x000004,0x000400,0x000404,0x000000,0x000004,0x000400,0x000404, 0x400000,0x400004,0x400400,0x400404,0x400000,0x400004,0x400400,0x400404, 0x000000,0x000020,0x008000,0x008020,0x800000,0x800020,0x808000,0x808020, 0x000002,0x000022,0x008002,0x008022,0x800002,0x800022,0x808002,0x808022, 0x000000,0x000200,0x200000,0x200200,0x001000,0x001200,0x201000,0x201200, 0x000000,0x000200,0x200000,0x200200,0x001000,0x001200,0x201000,0x201200, 0x000000,0x000040,0x000010,0x000050,0x004000,0x004040,0x004010,0x004050, 0x040000,0x040040,0x040010,0x040050,0x044000,0x044040,0x044010,0x044050, 0x000000,0x000100,0x020000,0x020100,0x000001,0x000101,0x020001,0x020101, 0x080000,0x080100,0x0a0000,0x0a0100,0x080001,0x080101,0x0a0001,0x0a0101, 0x000000,0x000100,0x040000,0x040100,0x000000,0x000100,0x040000,0x040100, 0x000040,0x000140,0x040040,0x040140,0x000040,0x000140,0x040040,0x040140, 0x000000,0x400000,0x008000,0x408000,0x000008,0x400008,0x008008,0x408008, 0x000400,0x400400,0x008400,0x408400,0x000408,0x400408,0x008408,0x408408, 0x000000,0x001000,0x080000,0x081000,0x000020,0x001020,0x080020,0x081020, 0x004000,0x005000,0x084000,0x085000,0x004020,0x005020,0x084020,0x085020, 0x000000,0x000800,0x000000,0x000800,0x000010,0x000810,0x000010,0x000810, 0x800000,0x800800,0x800000,0x800800,0x800010,0x800810,0x800010,0x800810, 0x000000,0x010000,0x000200,0x010200,0x000000,0x010000,0x000200,0x010200, 0x100000,0x110000,0x100200,0x110200,0x100000,0x110000,0x100200,0x110200, 0x000000,0x000004,0x000000,0x000004,0x000080,0x000084,0x000080,0x000084, 0x002000,0x002004,0x002000,0x002004,0x002080,0x002084,0x002080,0x002084, 0x000000,0x000001,0x200000,0x200001,0x020000,0x020001,0x220000,0x220001, 0x000002,0x000003,0x200002,0x200003,0x020002,0x020003,0x220002,0x220003, }; static int keysh[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, }; static void keycompperm(u32int left, u32int right, ulong *ek) { u32int v0, v1; int i; for(i = 0; i < 16; i++){ left = (left << keysh[i]) | (left >> (28 - keysh[i])); left &= 0xfffffff0; right = (right << keysh[i]) | (right >> (28 - keysh[i])); right &= 0xfffffff0; v0 = comptab[6 * (1 << 4) + ((left >> (32-4)) & 0xf)] | comptab[5 * (1 << 4) + ((left >> (32-8)) & 0xf)] | comptab[4 * (1 << 4) + ((left >> (32-12)) & 0xf)] | comptab[3 * (1 << 4) + ((left >> (32-16)) & 0xf)] | comptab[2 * (1 << 4) + ((left >> (32-20)) & 0xf)] | comptab[1 * (1 << 4) + ((left >> (32-24)) & 0xf)] | comptab[0 * (1 << 4) + ((left >> (32-28)) & 0xf)]; v1 = comptab[13 * (1 << 4) + ((right >> (32-4)) & 0xf)] | comptab[12 * (1 << 4) + ((right >> (32-8)) & 0xf)] | comptab[11 * (1 << 4) + ((right >> (32-12)) & 0xf)] | comptab[10 * (1 << 4) + ((right >> (32-16)) & 0xf)] | comptab[9 * (1 << 4) + ((right >> (32-20)) & 0xf)] | comptab[8 * (1 << 4) + ((right >> (32-24)) & 0xf)] | comptab[7 * (1 << 4) + ((right >> (32-28)) & 0xf)]; ek[0] = (((v0 >> (24-6)) & 0x3f) << 26) | (((v0 >> (24-18)) & 0x3f) << 18) | (((v1 >> (24-6)) & 0x3f) << 10) | (((v1 >> (24-18)) & 0x3f) << 2); ek[1] = (((v0 >> (24-12)) & 0x3f) << 26) | (((v0 >> (24-24)) & 0x3f) << 18) | (((v1 >> (24-12)) & 0x3f) << 10) | (((v1 >> (24-24)) & 0x3f) << 2); ek += 2; } } void des_key_setup(uchar key[8], ulong *ek) { u32int left, right, v0, v1; v0 = key[0] | ((u32int)key[2] << 8) | ((u32int)key[4] << 16) | ((u32int)key[6] << 24); v1 = key[1] | ((u32int)key[3] << 8) | ((u32int)key[5] << 16) | ((u32int)key[7] << 24); left = ((v0 >> 1) & 0x40404040) | ((v0 >> 2) & 0x10101010) | ((v0 >> 3) & 0x04040404) | ((v0 >> 4) & 0x01010101) | ((v1 >> 0) & 0x80808080) | ((v1 >> 1) & 0x20202020) | ((v1 >> 2) & 0x08080808) | ((v1 >> 3) & 0x02020202); right = ((v0 >> 1) & 0x04040404) | ((v0 << 2) & 0x10101010) | ((v0 << 5) & 0x40404040) | ((v1 << 0) & 0x08080808) | ((v1 << 3) & 0x20202020) | ((v1 << 6) & 0x80808080); left = ((left << 6) & 0x33003300) | (left & 0xcc33cc33) | ((left >> 6) & 0x00cc00cc); v0 = ((left << 12) & 0x0f0f0000) | (left & 0xf0f00f0f) | ((left >> 12) & 0x0000f0f0); right = ((right << 6) & 0x33003300) | (right & 0xcc33cc33) | ((right >> 6) & 0x00cc00cc); v1 = ((right << 12) & 0x0f0f0000) | (right & 0xf0f00f0f) | ((right >> 12) & 0x0000f0f0); left = v0 & 0xfffffff0; right = (v1 & 0xffffff00) | ((v0 << 4) & 0xf0); keycompperm(left, right, ek); } static uchar parity[128] = { 0x01, 0x02, 0x04, 0x07, 0x08, 0x0b, 0x0d, 0x0e, 0x10, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 0x1f, 0x20, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x2f, 0x31, 0x32, 0x34, 0x37, 0x38, 0x3b, 0x3d, 0x3e, 0x40, 0x43, 0x45, 0x46, 0x49, 0x4a, 0x4c, 0x4f, 0x51, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, 0x5e, 0x61, 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x6e, 0x70, 0x73, 0x75, 0x76, 0x79, 0x7a, 0x7c, 0x7f, 0x80, 0x83, 0x85, 0x86, 0x89, 0x8a, 0x8c, 0x8f, 0x91, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d, 0x9e, 0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xae, 0xb0, 0xb3, 0xb5, 0xb6, 0xb9, 0xba, 0xbc, 0xbf, 0xc1, 0xc2, 0xc4, 0xc7, 0xc8, 0xcb, 0xcd, 0xce, 0xd0, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc, 0xdf, 0xe0, 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xef, 0xf1, 0xf2, 0xf4, 0xf7, 0xf8, 0xfb, 0xfd, 0xfe, }; /* * convert a 7 byte key to an 8 byte one */ void des56to64(uchar *k56, uchar *k64) { u32int hi, lo; hi = ((u32int)k56[0]<<24)|((u32int)k56[1]<<16)|((u32int)k56[2]<<8)|k56[3]; lo = ((u32int)k56[4]<<24)|((u32int)k56[5]<<16)|((u32int)k56[6]<<8); k64[0] = parity[(hi>>25)&0x7f]; k64[1] = parity[(hi>>18)&0x7f]; k64[2] = parity[(hi>>11)&0x7f]; k64[3] = parity[(hi>>4)&0x7f]; k64[4] = parity[((hi<<3)|(lo>>29))&0x7f]; k64[5] = parity[(lo>>22)&0x7f]; k64[6] = parity[(lo>>15)&0x7f]; k64[7] = parity[(lo>>8)&0x7f]; } /* * convert an 8 byte key to a 7 byte one */ void des64to56(uchar *k64, uchar *k56) { u32int hi, lo; hi = (((u32int)k64[0]&0xfe)<<24)|(((u32int)k64[1]&0xfe)<<17)|(((u32int)k64[2]&0xfe)<<10) |((k64[3]&0xfe)<<3)|(k64[4]>>4); lo = (((u32int)k64[4]&0xfe)<<28)|(((u32int)k64[5]&0xfe)<<21)|(((u32int)k64[6]&0xfe)<<14) |(((u32int)k64[7]&0xfe)<<7); k56[0] = hi>>24; k56[1] = hi>>16; k56[2] = hi>>8; k56[3] = hi>>0; k56[4] = lo>>24; k56[5] = lo>>16; k56[6] = lo>>8; } void key_setup(uchar key[7], ulong *ek) { uchar k64[8]; des56to64(key, k64); des_key_setup(k64, ek); } drawterm-20110822.orig/libsec/os.h0000644000175000017500000000004111245145712016121 0ustar tinchotincho#include #include drawterm-20110822.orig/libsec/egtest.c0000644000175000017500000000121711245145712016774 0ustar tinchotincho#include "os.h" #include #include void main(void) { EGpriv *sk; mpint *m, *gamma, *delta, *in, *out; int plen, shift; fmtinstall('B', mpconv); sk = egprivalloc(); sk->pub.p = uitomp(2357, nil); sk->pub.alpha = uitomp(2, nil); sk->pub.key = uitomp(1185, nil); sk->secret = uitomp(1751, nil); m = uitomp(2035, nil); plen = mpsignif(sk->pub.p)+1; shift = ((plen+Dbits-1)/Dbits)*Dbits; gamma = uitomp(1430, nil); delta = uitomp(697, nil); out = mpnew(0); in = mpnew(0); mpleft(gamma, shift, in); mpadd(delta, in, in); egdecrypt(sk, in, out); if(mpcmp(m, out) != 0) print("decrypt failed to recover message\n"); } drawterm-20110822.orig/libsec/smallprimes.c0000644000175000017500000001530311245145712020032 0ustar tinchotincho#include "os.h" ulong smallprimes[1000] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, }; drawterm-20110822.orig/libsec/thumb.c0000644000175000017500000000354311245145712016624 0ustar tinchotincho#include #include #include #include #include #include enum{ ThumbTab = 1<<10 }; static void * emalloc(int n) { void *p; if(n==0) n=1; p = malloc(n); if(p == nil){ exits("out of memory"); } memset(p, 0, n); return p; } void freeThumbprints(Thumbprint *table) { Thumbprint *hd, *p, *q; for(hd = table; hd < table+ThumbTab; hd++){ for(p = hd->next; p; p = q){ q = p->next; free(p); } } free(table); } int okThumbprint(uchar *sum, Thumbprint *table) { Thumbprint *p; int i = ((sum[0]<<8) + sum[1]) & (ThumbTab-1); for(p = table[i].next; p; p = p->next) if(memcmp(sum, p->sha1, SHA1dlen) == 0) return 1; return 0; } static void loadThumbprints(char *file, Thumbprint *table, Thumbprint *crltab) { Thumbprint *entry; Biobuf *bin; char *line, *field[50]; uchar sum[SHA1dlen]; int i; bin = Bopen(file, OREAD); if(bin == nil) return; for(; (line = Brdstr(bin, '\n', 1)) != 0; free(line)){ if(tokenize(line, field, nelem(field)) < 2) continue; if(strcmp(field[0], "#include") == 0){ loadThumbprints(field[1], table, crltab); continue; } if(strcmp(field[0], "x509") != 0 || strncmp(field[1], "sha1=", strlen("sha1=")) != 0) continue; field[1] += strlen("sha1="); dec16(sum, sizeof(sum), field[1], strlen(field[1])); if(crltab && okThumbprint(sum, crltab)) continue; entry = (Thumbprint*)emalloc(sizeof(*entry)); memcpy(entry->sha1, sum, SHA1dlen); i = ((sum[0]<<8) + sum[1]) & (ThumbTab-1); entry->next = table[i].next; table[i].next = entry; } Bterm(bin); } Thumbprint * initThumbprints(char *ok, char *crl) { Thumbprint *table, *crltab = nil; if(crl){ crltab = emalloc(ThumbTab * sizeof(*table)); loadThumbprints(crl, crltab, nil); } table = emalloc(ThumbTab * sizeof(*table)); loadThumbprints(ok, table, crltab); free(crltab); return table; } drawterm-20110822.orig/libsec/smallprimetest.c0000644000175000017500000021176011245145712020554 0ustar tinchotincho#include "os.h" #include #include static ulong smallprimes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, 100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, 100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, 100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, 100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, 100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, 100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, 100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, 100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, 101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, 101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, 101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, 101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, 101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, 101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, 101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, 101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, 101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, 102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, 102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, 102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, 102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, 102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, 102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, 102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, 102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, 102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, 103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, 103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, 103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, 103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, 103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, 103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, 103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, 103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, 104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, 104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, 104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, 104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, 104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, 104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, }; // return 1 if p is divisable by sp, 0 otherwise static int divides(mpint *dividend, ulong divisor) { mpdigit d[2], q; int i; d[1] = 0; for(i = dividend->top-1; i >= 0; i--){ d[0] = dividend->p[i]; mpdigdiv(d, divisor, &q); d[1] = d[0] - divisor*q; } return d[1] == 0; } // return -1 if p is divisable by one of the small primes, 0 otherwise int smallprimetest(mpint *p) { int i; ulong sp; for(i = 0; i < nelem(smallprimes); i++){ sp = smallprimes[i]; if(p->top == 1 && p->p[0] <= sp) break; if(divides(p, sp)) return -1; } return 0; } drawterm-20110822.orig/libsec/dsaalloc.c0000644000175000017500000000154011245145712017262 0ustar tinchotincho#include "os.h" #include #include DSApub* dsapuballoc(void) { DSApub *dsa; dsa = mallocz(sizeof(*dsa), 1); if(dsa == nil) sysfatal("dsapuballoc"); return dsa; } void dsapubfree(DSApub *dsa) { if(dsa == nil) return; mpfree(dsa->p); mpfree(dsa->q); mpfree(dsa->alpha); mpfree(dsa->key); } DSApriv* dsaprivalloc(void) { DSApriv *dsa; dsa = mallocz(sizeof(*dsa), 1); if(dsa == nil) sysfatal("dsaprivalloc"); return dsa; } void dsaprivfree(DSApriv *dsa) { if(dsa == nil) return; mpfree(dsa->pub.p); mpfree(dsa->pub.q); mpfree(dsa->pub.alpha); mpfree(dsa->pub.key); mpfree(dsa->secret); } DSAsig* dsasigalloc(void) { DSAsig *dsa; dsa = mallocz(sizeof(*dsa), 1); if(dsa == nil) sysfatal("dsasigalloc"); return dsa; } void dsasigfree(DSAsig *dsa) { if(dsa == nil) return; mpfree(dsa->r); mpfree(dsa->s); } drawterm-20110822.orig/libsec/egsign.c0000644000175000017500000000144711245145712016762 0ustar tinchotincho#include "os.h" #include #include EGsig* egsign(EGpriv *priv, mpint *m) { EGpub *pub = &priv->pub; EGsig *sig; mpint *pm1, *k, *kinv, *r, *s; mpint *p = pub->p, *alpha = pub->alpha; int plen = mpsignif(p); pm1 = mpnew(0); kinv = mpnew(0); r = mpnew(0); s = mpnew(0); k = mpnew(0); mpsub(p, mpone, pm1); while(1){ mprand(plen, genrandom, k); if((mpcmp(mpone, k) > 0) || (mpcmp(k, pm1) >= 0)) continue; mpextendedgcd(k, pm1, r, kinv, s); if(mpcmp(r, mpone) != 0) continue; break; } mpmod(kinv, pm1, kinv); // make kinv positive mpexp(alpha, k, p, r); mpmul(priv->secret, r, s); mpmod(s, pm1, s); mpsub(m, s, s); mpmul(kinv, s, s); mpmod(s, pm1, s); sig = egsigalloc(); sig->r = r; sig->s = s; mpfree(pm1); mpfree(k); mpfree(kinv); return sig; } drawterm-20110822.orig/libsec/desECB.c0000644000175000017500000000153511245145712016571 0ustar tinchotincho#include "os.h" #include #include // I wasn't sure what to do when the buffer was not // a multiple of 8. I did what lacy's cryptolib did // to be compatible, but it looks dangerous to me // since its encrypting plain text with the key. -- presotto void desECBencrypt(uchar *p, int len, DESstate *s) { int i; uchar tmp[8]; for(; len >= 8; len -= 8){ block_cipher(s->expanded, p, 0); p += 8; } if(len > 0){ for (i=0; i<8; i++) tmp[i] = i; block_cipher(s->expanded, tmp, 0); for (i = 0; i < len; i++) p[i] ^= tmp[i]; } } void desECBdecrypt(uchar *p, int len, DESstate *s) { int i; uchar tmp[8]; for(; len >= 8; len -= 8){ block_cipher(s->expanded, p, 1); p += 8; } if(len > 0){ for (i=0; i<8; i++) tmp[i] = i; block_cipher(s->expanded, tmp, 0); for (i = 0; i < len; i++) p[i] ^= tmp[i]; } } drawterm-20110822.orig/libsec/gensafeprime.c0000644000175000017500000000134511245145712020150 0ustar tinchotincho#include "os.h" #include #include // find a prime p of length n and a generator alpha of Z^*_p // Alg 4.86 Menezes et al () Handbook, p.164 void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy) { mpint *q, *b; q = mpnew(n-1); while(1){ genprime(q, n-1, accuracy); mpleft(q, 1, p); mpadd(p, mpone, p); // p = 2*q+1 if(probably_prime(p, accuracy)) break; } // now find a generator alpha of the multiplicative // group Z*_p of order p-1=2q b = mpnew(0); while(1){ mprand(n, genrandom, alpha); mpmod(alpha, p, alpha); mpmul(alpha, alpha, b); mpmod(b, p, b); if(mpcmp(b, mpone) == 0) continue; mpexp(alpha, q, p, b); if(mpcmp(b, mpone) != 0) break; } mpfree(b); mpfree(q); } drawterm-20110822.orig/libsec/sha1pickle.c0000644000175000017500000000131511245145712017524 0ustar tinchotincho#include "os.h" #include char* sha1pickle(SHA1state *s) { char *p; int m, n; m = 5*9+4*((s->blen+3)/3); p = malloc(m); if(p == nil) return p; n = sprint(p, "%8.8ux %8.8ux %8.8ux %8.8ux %8.8ux ", s->state[0], s->state[1], s->state[2], s->state[3], s->state[4]); enc64(p+n, m-n, s->buf, s->blen); return p; } SHA1state* sha1unpickle(char *p) { SHA1state *s; s = malloc(sizeof(*s)); if(s == nil) return nil; s->state[0] = strtoul(p, &p, 16); s->state[1] = strtoul(p, &p, 16); s->state[2] = strtoul(p, &p, 16); s->state[3] = strtoul(p, &p, 16); s->state[4] = strtoul(p, &p, 16); s->blen = dec64(s->buf, sizeof(s->buf), p, strlen(p)); s->malloced = 1; s->seeded = 1; return s; } drawterm-20110822.orig/libsec/rsaencrypt.c0000644000175000017500000000030011245145712017663 0ustar tinchotincho#include "os.h" #include #include mpint* rsaencrypt(RSApub *rsa, mpint *in, mpint *out) { if(out == nil) out = mpnew(0); mpexp(in, rsa->ek, rsa->n, out); return out; } drawterm-20110822.orig/libsec/egalloc.c0000644000175000017500000000141211245145712017104 0ustar tinchotincho#include "os.h" #include #include EGpub* egpuballoc(void) { EGpub *eg; eg = mallocz(sizeof(*eg), 1); if(eg == nil) sysfatal("egpuballoc"); return eg; } void egpubfree(EGpub *eg) { if(eg == nil) return; mpfree(eg->p); mpfree(eg->alpha); mpfree(eg->key); } EGpriv* egprivalloc(void) { EGpriv *eg; eg = mallocz(sizeof(*eg), 1); if(eg == nil) sysfatal("egprivalloc"); return eg; } void egprivfree(EGpriv *eg) { if(eg == nil) return; mpfree(eg->pub.p); mpfree(eg->pub.alpha); mpfree(eg->pub.key); mpfree(eg->secret); } EGsig* egsigalloc(void) { EGsig *eg; eg = mallocz(sizeof(*eg), 1); if(eg == nil) sysfatal("egsigalloc"); return eg; } void egsigfree(EGsig *eg) { if(eg == nil) return; mpfree(eg->r); mpfree(eg->s); } drawterm-20110822.orig/libsec/egdecrypt.c0000644000175000017500000000106411245145712017467 0ustar tinchotincho#include "os.h" #include #include mpint* egdecrypt(EGpriv *priv, mpint *in, mpint *out) { EGpub *pub = &priv->pub; mpint *gamma, *delta; mpint *p = pub->p; int plen = mpsignif(p)+1; int shift = ((plen+Dbits-1)/Dbits)*Dbits; if(out == nil) out = mpnew(0); gamma = mpnew(0); delta = mpnew(0); mpright(in, shift, gamma); mpleft(gamma, shift, delta); mpsub(in, delta, delta); mpexp(gamma, priv->secret, p, out); mpinvert(out, p, gamma); mpmul(gamma, delta, out); mpmod(out, p, out); mpfree(gamma); mpfree(delta); return out; } drawterm-20110822.orig/libsec/Makefile0000644000175000017500000000140311245145712016772 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libsec.a OFILES=\ aes.$O\ blowfish.$O\ decodepem.$O\ des.$O\ des3CBC.$O\ des3ECB.$O\ desCBC.$O\ desECB.$O\ desmodes.$O\ dsaalloc.$O\ dsagen.$O\ dsaprimes.$O\ dsaprivtopub.$O\ dsasign.$O\ dsaverify.$O\ egalloc.$O\ egdecrypt.$O\ egencrypt.$O\ eggen.$O\ egprivtopub.$O\ egsign.$O\ egverify.$O\ fastrand.$O\ genprime.$O\ genrandom.$O\ gensafeprime.$O\ genstrongprime.$O\ hmac.$O\ md4.$O\ md5.$O\ md5pickle.$O\ nfastrand.$O\ prng.$O\ probably_prime.$O\ rc4.$O\ rsaalloc.$O\ rsadecrypt.$O\ rsaencrypt.$O\ rsafill.$O\ rsagen.$O\ rsaprivtopub.$O\ sha1.$O\ sha1pickle.$O\ smallprimes.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/libsec/dsaprimes.c0000644000175000017500000000353111245145712017471 0ustar tinchotincho#include "os.h" #include #include // NIST algorithm for generating DSA primes // Menezes et al (1997) Handbook of Applied Cryptography, p.151 // q is a 160-bit prime; p is a 1024-bit prime; q divides p-1 // arithmetic on unsigned ints mod 2**160, represented // as 20-byte, little-endian uchar array static void Hrand(uchar *s) { ulong *u = (ulong*)s; *u++ = fastrand(); *u++ = fastrand(); *u++ = fastrand(); *u++ = fastrand(); *u = fastrand(); } static void Hincr(uchar *s) { int i; for(i=0; i<20; i++) if(++s[i]!=0) break; } // this can run for quite a while; be patient void DSAprimes(mpint *q, mpint *p, uchar seed[SHA1dlen]) { int i, j, k, n = 6, b = 63; uchar s[SHA1dlen], Hs[SHA1dlen], Hs1[SHA1dlen], sj[SHA1dlen], sjk[SHA1dlen]; mpint *two1023, *mb, *Vk, *W, *X, *q2; two1023 = mpnew(1024); mpleft(mpone, 1023, two1023); mb = mpnew(0); mpleft(mpone, b, mb); W = mpnew(1024); Vk = mpnew(1024); X = mpnew(0); q2 = mpnew(0); forever: do{ Hrand(s); memcpy(sj, s, 20); sha1(s, 20, Hs, 0); Hincr(sj); sha1(sj, 20, Hs1, 0); for(i=0; i<20; i++) Hs[i] ^= Hs1[i]; Hs[0] |= 1; Hs[19] |= 0x80; letomp(Hs, 20, q); }while(!probably_prime(q, 18)); if(seed != nil) // allow skeptics to confirm computation memmove(seed, s, SHA1dlen); i = 0; j = 2; Hincr(sj); mpleft(q, 1, q2); while(i<4096){ memcpy(sjk, sj, 20); for(k=0; k <= n; k++){ sha1(sjk, 20, Hs, 0); letomp(Hs, 20, Vk); if(k == n) mpmod(Vk, mb, Vk); mpleft(Vk, 160*k, Vk); mpadd(W, Vk, W); Hincr(sjk); } mpadd(W, two1023, X); mpmod(X, q2, W); mpsub(W, mpone, W); mpsub(X, W, p); if(mpcmp(p, two1023)>=0 && probably_prime(p, 5)) goto done; i += 1; j += n+1; for(k=0; k #include RSApub* rsaprivtopub(RSApriv *priv) { RSApub *pub; pub = rsapuballoc(); if(pub == nil) return nil; pub->n = mpcopy(priv->pub.n); pub->ek = mpcopy(priv->pub.ek); return pub; } drawterm-20110822.orig/libsec/genrandom.c0000644000175000017500000000222311245145712017451 0ustar tinchotincho#include "os.h" #include #include typedef struct State{ QLock lock; int seeded; uvlong seed; DES3state des3; } State; static State x917state; static void X917(uchar *rand, int nrand) { int i, m, n8; uvlong I, x; /* 1. Compute intermediate value I = Ek(time). */ I = nsec(); triple_block_cipher(x917state.des3.expanded, (uchar*)&I, 0); /* two-key EDE */ /* 2. x[i] = Ek(I^seed); seed = Ek(x[i]^I); */ m = (nrand+7)/8; for(i=0; i8) ? 8 : nrand; memcpy(rand, (uchar*)&x, n8); rand += 8; nrand -= 8; x ^= I; triple_block_cipher(x917state.des3.expanded, (uchar*)&x, 0); x917state.seed = x; } } static void X917init(void) { int n; uchar mix[128]; uchar key3[3][8]; ulong *ulp; ulp = (ulong*)key3; for(n = 0; n < sizeof(key3)/sizeof(ulong); n++) ulp[n] = truerand(); setupDES3state(&x917state.des3, key3, nil); X917(mix, sizeof mix); x917state.seeded = 1; } void genrandom(uchar *p, int n) { qlock(&x917state.lock); if(x917state.seeded == 0) X917init(); X917(p, n); qunlock(&x917state.lock); } drawterm-20110822.orig/libsec/rsadecrypt.c0000644000175000017500000000135511245145712017664 0ustar tinchotincho#include "os.h" #include #include // decrypt rsa using garner's algorithm for the chinese remainder theorem // seminumerical algorithms, knuth, pp 253-254 // applied cryptography, menezes et al, pg 612 mpint* rsadecrypt(RSApriv *rsa, mpint *in, mpint *out) { mpint *v1, *v2; if(out == nil) out = mpnew(0); // convert in to modular representation v1 = mpnew(0); mpmod(in, rsa->p, v1); v2 = mpnew(0); mpmod(in, rsa->q, v2); // exponentiate the modular rep mpexp(v1, rsa->kp, rsa->p, v1); mpexp(v2, rsa->kq, rsa->q, v2); // out = v1 + p*((v2-v1)*c2 mod q) mpsub(v2, v1, v2); mpmul(v2, rsa->c2, v2); mpmod(v2, rsa->q, v2); mpmul(v2, rsa->p, out); mpadd(v1, out, out); mpfree(v1); mpfree(v2); return out; } drawterm-20110822.orig/libsec/genprime.c0000644000175000017500000000102711245145712017306 0ustar tinchotincho#include "os.h" #include #include // generate a probable prime. accuracy is the miller-rabin interations void genprime(mpint *p, int n, int accuracy) { mpdigit x; // generate n random bits with high and low bits set mpbits(p, n); genrandom((uchar*)p->p, (n+7)/8); p->top = (n+Dbits-1)/Dbits; x = 1; x <<= ((n-1)%Dbits); p->p[p->top-1] &= (x-1); p->p[p->top-1] |= x; p->p[0] |= 1; // keep icrementing till it looks prime for(;;){ if(probably_prime(p, accuracy)) break; mpadd(p, mptwo, p); } } drawterm-20110822.orig/libsec/rsaalloc.c0000644000175000017500000000122111245145712017274 0ustar tinchotincho#include "os.h" #include #include RSApub* rsapuballoc(void) { RSApub *rsa; rsa = mallocz(sizeof(*rsa), 1); if(rsa == nil) sysfatal("rsapuballoc"); return rsa; } void rsapubfree(RSApub *rsa) { if(rsa == nil) return; mpfree(rsa->ek); mpfree(rsa->n); free(rsa); } RSApriv* rsaprivalloc(void) { RSApriv *rsa; rsa = mallocz(sizeof(*rsa), 1); if(rsa == nil) sysfatal("rsaprivalloc"); return rsa; } void rsaprivfree(RSApriv *rsa) { if(rsa == nil) return; mpfree(rsa->pub.ek); mpfree(rsa->pub.n); mpfree(rsa->dk); mpfree(rsa->p); mpfree(rsa->q); mpfree(rsa->kp); mpfree(rsa->kq); mpfree(rsa->c2); free(rsa); } drawterm-20110822.orig/libsec/md5.c0000644000175000017500000000626611245145712016177 0ustar tinchotincho#include "os.h" #include /* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ static void encode(uchar*, u32int*, ulong); extern void _md5block(uchar*, ulong, u32int*); MD5state* md5(uchar *p, ulong len, uchar *digest, MD5state *s) { u32int x[16]; uchar buf[128]; int i; uchar *e; if(s == nil){ s = malloc(sizeof(*s)); if(s == nil) return nil; memset(s, 0, sizeof(*s)); s->malloced = 1; } if(s->seeded == 0){ /* seed the state, these constants would look nicer big-endian */ s->state[0] = 0x67452301; s->state[1] = 0xefcdab89; s->state[2] = 0x98badcfe; s->state[3] = 0x10325476; s->seeded = 1; } /* fill out the partial 64 byte block from previous calls */ if(s->blen){ i = 64 - s->blen; if(len < i) i = len; memmove(s->buf + s->blen, p, i); len -= i; s->blen += i; p += i; if(s->blen == 64){ _md5block(s->buf, s->blen, s->state); s->len += s->blen; s->blen = 0; } } /* do 64 byte blocks */ i = len & ~0x3f; if(i){ _md5block(p, i, s->state); s->len += i; len -= i; p += i; } /* save the left overs if not last call */ if(digest == 0){ if(len){ memmove(s->buf, p, len); s->blen += len; } return s; } /* * this is the last time through, pad what's left with 0x80, * 0's, and the input count to create a multiple of 64 bytes */ if(s->blen){ p = s->buf; len = s->blen; } else { memmove(buf, p, len); p = buf; } s->len += len; e = p + len; if(len < 56) i = 56 - len; else i = 120 - len; memset(e, 0, i); *e = 0x80; len += i; /* append the count */ x[0] = s->len<<3; x[1] = s->len>>29; encode(p+len, x, 8); /* digest the last part */ _md5block(p, len+8, s->state); s->len += len; /* return result and free state */ encode(digest, s->state, MD5dlen); if(s->malloced == 1) free(s); return nil; } /* * encodes input (u32int) into output (uchar). Assumes len is * a multiple of 4. */ static void encode(uchar *output, u32int *input, ulong len) { u32int x; uchar *e; for(e = output + len; output < e;) { x = *input++; *output++ = x; *output++ = x >> 8; *output++ = x >> 16; *output++ = x >> 24; } } drawterm-20110822.orig/libsec/egprivtopub.c0000644000175000017500000000042111245145712020043 0ustar tinchotincho#include "os.h" #include #include EGpub* egprivtopub(EGpriv *priv) { EGpub *pub; pub = egpuballoc(); if(pub == nil) return nil; pub->p = mpcopy(priv->pub.p); pub->alpha = mpcopy(priv->pub.alpha); pub->key = mpcopy(priv->pub.key); return pub; } drawterm-20110822.orig/libsec/md4.c0000644000175000017500000001024411245145712016165 0ustar tinchotincho#include "os.h" #include /* * This MD4 is implemented from the description in Stinson's Cryptography, * theory and practice. -- presotto */ /* * Rotate ammounts used in the algorithm */ enum { S11= 3, S12= 7, S13= 11, S14= 19, S21= 3, S22= 5, S23= 9, S24= 13, S31= 3, S32= 9, S33= 11, S34= 15, }; typedef struct MD4Table MD4Table; struct MD4Table { uchar x; /* index into data block */ uchar rot; /* amount to rotate left by */ }; static MD4Table tab[] = { /* round 1 */ /*[0]*/ { 0, S11}, { 1, S12}, { 2, S13}, { 3, S14}, { 4, S11}, { 5, S12}, { 6, S13}, { 7, S14}, { 8, S11}, { 9, S12}, { 10, S13}, { 11, S14}, { 12, S11}, { 13, S12}, { 14, S13}, { 15, S14}, /* round 2 */ /*[16]*/{ 0, S21}, { 4, S22}, { 8, S23}, { 12, S24}, { 1, S21}, { 5, S22}, { 9, S23}, { 13, S24}, { 2, S21}, { 6, S22}, { 10, S23}, { 14, S24}, { 3, S21}, { 7, S22}, { 11, S23}, { 15, S24}, /* round 3 */ /*[32]*/{ 0, S31}, { 8, S32}, { 4, S33}, { 12, S34}, { 2, S31}, { 10, S32}, { 6, S33}, { 14, S34}, { 1, S31}, { 9, S32}, { 5, S33}, { 13, S34}, { 3, S31}, { 11, S32}, { 7, S33}, { 15, S34}, }; static void encode(uchar*, u32int*, ulong); static void decode(u32int*, uchar*, ulong); static void md4block(uchar *p, ulong len, MD4state *s) { int i; u32int a, b, c, d, tmp; MD4Table *t; uchar *end; u32int x[16]; for(end = p+len; p < end; p += 64){ a = s->state[0]; b = s->state[1]; c = s->state[2]; d = s->state[3]; decode(x, p, 64); for(i = 0; i < 48; i++){ t = tab + i; switch(i>>4){ case 0: a += (b & c) | (~b & d); break; case 1: a += ((b & c) | (b & d) | (c & d)) + 0x5A827999; break; case 2: a += (b ^ c ^ d) + 0x6ED9EBA1; break; } a += x[t->x]; a = (a << t->rot) | (a >> (32 - t->rot)); /* rotate variables */ tmp = d; d = c; c = b; b = a; a = tmp; } s->state[0] += a; s->state[1] += b; s->state[2] += c; s->state[3] += d; s->len += 64; } } MD4state* md4(uchar *p, ulong len, uchar *digest, MD4state *s) { u32int x[16]; uchar buf[128]; int i; uchar *e; if(s == nil){ s = malloc(sizeof(*s)); if(s == nil) return nil; memset(s, 0, sizeof(*s)); s->malloced = 1; } if(s->seeded == 0){ /* seed the state, these constants would look nicer big-endian */ s->state[0] = 0x67452301; s->state[1] = 0xefcdab89; s->state[2] = 0x98badcfe; s->state[3] = 0x10325476; s->seeded = 1; } /* fill out the partial 64 byte block from previous calls */ if(s->blen){ i = 64 - s->blen; if(len < i) i = len; memmove(s->buf + s->blen, p, i); len -= i; s->blen += i; p += i; if(s->blen == 64){ md4block(s->buf, s->blen, s); s->blen = 0; } } /* do 64 byte blocks */ i = len & ~0x3f; if(i){ md4block(p, i, s); len -= i; p += i; } /* save the left overs if not last call */ if(digest == 0){ if(len){ memmove(s->buf, p, len); s->blen += len; } return s; } /* * this is the last time through, pad what's left with 0x80, * 0's, and the input count to create a multiple of 64 bytes */ if(s->blen){ p = s->buf; len = s->blen; } else { memmove(buf, p, len); p = buf; } s->len += len; e = p + len; if(len < 56) i = 56 - len; else i = 120 - len; memset(e, 0, i); *e = 0x80; len += i; /* append the count */ x[0] = s->len<<3; x[1] = s->len>>29; encode(p+len, x, 8); /* digest the last part */ md4block(p, len+8, s); /* return result and free state */ encode(digest, s->state, MD4dlen); if(s->malloced == 1) free(s); return nil; } /* * encodes input (u32int) into output (uchar). Assumes len is * a multiple of 4. */ static void encode(uchar *output, u32int *input, ulong len) { u32int x; uchar *e; for(e = output + len; output < e;) { x = *input++; *output++ = x; *output++ = x >> 8; *output++ = x >> 16; *output++ = x >> 24; } } /* * decodes input (uchar) into output (u32int). Assumes len is * a multiple of 4. */ static void decode(u32int *output, uchar *input, ulong len) { uchar *e; for(e = input+len; input < e; input += 4) *output++ = input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24); } drawterm-20110822.orig/libsec/probably_prime.c0000644000175000017500000000303711245145712020511 0ustar tinchotincho#include "os.h" #include #include // Miller-Rabin probabilistic primality testing // Knuth (1981) Seminumerical Algorithms, p.379 // Menezes et al () Handbook, p.39 // 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep int probably_prime(mpint *n, int nrep) { int j, k, rep, nbits, isprime = 1; mpint *nm1, *q, *x, *y, *r; if(n->sign < 0) sysfatal("negative prime candidate"); if(nrep <= 0) nrep = 18; k = mptoi(n); if(k == 2) // 2 is prime return 1; if(k < 2) // 1 is not prime return 0; if((n->p[0] & 1) == 0) // even is not prime return 0; // test against small prime numbers if(smallprimetest(n) < 0) return 0; // fermat test, 2^n mod n == 2 if p is prime x = uitomp(2, nil); y = mpnew(0); mpexp(x, n, n, y); k = mptoi(y); if(k != 2){ mpfree(x); mpfree(y); return 0; } nbits = mpsignif(n); nm1 = mpnew(nbits); mpsub(n, mpone, nm1); // nm1 = n - 1 */ k = mplowbits0(nm1); q = mpnew(0); mpright(nm1, k, q); // q = (n-1)/2**k for(rep = 0; rep < nrep; rep++){ // x = random in [2, n-2] r = mprand(nbits, prng, nil); mpmod(r, nm1, x); mpfree(r); if(mpcmp(x, mpone) <= 0) continue; // y = x**q mod n mpexp(x, q, n, y); if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0) goto done; for(j = 1; j < k; j++){ mpmul(y, y, x); mpmod(x, n, y); // y = y*y mod n if(mpcmp(y, nm1) == 0) goto done; if(mpcmp(y, mpone) == 0){ isprime = 0; goto done; } } isprime = 0; } done: mpfree(y); mpfree(x); mpfree(q); mpfree(nm1); return isprime; } drawterm-20110822.orig/libsec/blowfish.c0000644000175000017500000004633411245145712017327 0ustar tinchotincho#include "os.h" #include #include // Blowfish block cipher. See: // Lecture Notes in Computer Science 809 // Fast Software Encryption // Cambridge Security Workshop, Cambridge, England (1993) static u32int sbox[1024]; static u32int pbox[BFrounds+2]; static void bfencrypt(u32int *, BFstate *); static void bfdecrypt(u32int *, BFstate *); void setupBFstate(BFstate *s, uchar key[], int keybytes, uchar *ivec) { int i, j; u32int n, buf[2]; memset(s, 0, sizeof(*s)); memset(buf, 0, sizeof buf); if (keybytes > sizeof(s->key)) keybytes = sizeof(s->key); memmove(s->key, key, keybytes); if (ivec != nil) memmove(s->ivec, ivec, sizeof(s->ivec)); else memset(s->ivec, 0, sizeof(s->ivec)); memmove(s->pbox, pbox, sizeof(pbox)); memmove(s->sbox, sbox, sizeof(sbox)); if (keybytes > 4*(BFrounds + 2)) keybytes = 4*(BFrounds + 2); for(i=j=0; i < BFrounds+2; i++) { n = key[j]; j = (j+1) % keybytes; n <<= 8; n |= key[j]; j = (j+1) % keybytes; n <<= 8; n |= key[j]; j = (j+1) % keybytes; n <<= 8; n |= key[j]; j = (j+1) % keybytes; s->pbox[i] ^= n; } for(i=0; i < BFrounds+2; i += 2) { bfencrypt(buf, s); s->pbox[i] = buf[0]; s->pbox[i+1] = buf[1]; } for(i=0; i < 1024; i += 2) { bfencrypt(buf, s); s->sbox[i] = buf[0]; s->sbox[i+1] = buf[1]; } s->setup = 0xcafebabe; } void bfCBCencrypt(uchar *buf, int n, BFstate *s) { int i; uchar *p; u32int bo[2], bi[2], b; assert((n & 7) == 0); bo[0] = s->ivec[0] | ((u32int) s->ivec[1]<<8) | ((u32int)s->ivec[2]<<16) | ((u32int)s->ivec[3]<<24); bo[1] = s->ivec[4] | ((u32int) s->ivec[5]<<8) | ((u32int)s->ivec[6]<<16) | ((u32int)s->ivec[7]<<24); for(i=0; i < n; i += 8, buf += 8) { bi[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24); bi[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24); bi[0] ^= bo[0]; bi[1] ^= bo[1]; bfencrypt(bi, s); bo[0] = bi[0]; bo[1] = bi[1]; p = buf; b = bo[0]; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p++ = b; b = bo[1]; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p = b; } s->ivec[7] = bo[1] >> 24; s->ivec[6] = bo[1] >> 16; s->ivec[5] = bo[1] >> 8; s->ivec[4] = bo[1]; s->ivec[3] = bo[0] >> 24; s->ivec[2] = bo[0] >> 16; s->ivec[1] = bo[0] >> 8; s->ivec[0] = bo[0]; return; } void bfCBCdecrypt(uchar *buf, int n, BFstate *s) { int i; uchar *p; u32int b, bo[2], bi[2], xr[2]; assert((n & 7) == 0); bo[0] = s->ivec[0] | ((u32int) s->ivec[1]<<8) | ((u32int)s->ivec[2]<<16) | ((u32int)s->ivec[3]<<24); bo[1] = s->ivec[4] | ((u32int) s->ivec[5]<<8) | ((u32int)s->ivec[6]<<16) | ((u32int)s->ivec[7]<<24); for(i=0; i < n; i += 8, buf += 8) { bi[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24); bi[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24); xr[0] = bi[0]; xr[1] = bi[1]; bfdecrypt(bi, s); bo[0] ^= bi[0]; bo[1] ^= bi[1]; p = buf; b = bo[0]; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p++ = b; b = bo[1]; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p++ = b; b >>= 8; *p = b; bo[0] = xr[0]; bo[1] = xr[1]; } s->ivec[7] = bo[1] >> 24; s->ivec[6] = bo[1] >> 16; s->ivec[5] = bo[1] >> 8; s->ivec[4] = bo[1]; s->ivec[3] = bo[0] >> 24; s->ivec[2] = bo[0] >> 16; s->ivec[1] = bo[0] >> 8; s->ivec[0] = bo[0]; return; } void bfECBencrypt(uchar *buf, int n, BFstate *s) { int i; u32int b[2]; for(i=0; i < n; i += 8, buf += 8) { b[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24); b[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24); bfencrypt(b, s); buf[7] = b[1] >> 24; buf[6] = b[1] >> 16; buf[5] = b[1] >> 8; buf[4] = b[1]; buf[3] = b[0] >> 24; buf[2] = b[0] >> 16; buf[1] = b[0] >> 8; buf[0] = b[0]; } return; } void bfECBdecrypt(uchar *buf, int n, BFstate *s) { int i; u32int b[2]; for(i=0; i < n; i += 8, buf += 8) { b[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24); b[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24); bfdecrypt(b, s); buf[7] = b[1] >> 24; buf[6] = b[1] >> 16; buf[5] = b[1] >> 8; buf[4] = b[1]; buf[3] = b[0] >> 24; buf[2] = b[0] >> 16; buf[1] = b[0] >> 8; buf[0] = b[0]; } return; } static void bfencrypt(u32int *b, BFstate *s) { int i; u32int l, r; u32int *pb, *sb; l = b[0]; r = b[1]; pb = s->pbox; sb = s->sbox; l ^= pb[0]; for(i=1; i<16; i += 2) { r ^= pb[i]; r ^= ( (sb[ (uchar) (l>>24)] + sb[256 + ((uchar) (l>>16))]) ^ sb[512 + ((uchar) (l>>8))]) + sb[768 +((uchar) l)]; l ^= pb[i+1]; l ^= ( (sb[ (uchar) (r>>24)] + sb[256 + ((uchar) (r>>16))]) ^ sb[512 + ((uchar) (r>>8))]) + sb[768 +((uchar) r)]; } r ^= pb[BFrounds+1]; /* sic */ b[0] = r; b[1] = l; return; } static void bfdecrypt(u32int *b, BFstate *s) { int i; u32int l, r; u32int *pb, *sb; l = b[0]; r = b[1]; pb = s->pbox; sb = s->sbox; l ^= pb[BFrounds+1]; for(i=16; i > 0; i -= 2) { r ^= pb[i]; r ^= ( (sb[ (uchar) (l>>24)] + sb[256 + ((uchar) (l>>16))]) ^ sb[512 + ((uchar) (l>>8))]) + sb[768 +((uchar) l)]; l ^= pb[i-1]; l ^= ( (sb[ (uchar) (r>>24)] + sb[256 + ((uchar) (r>>16))]) ^ sb[512 + ((uchar) (r>>8))]) + sb[768 +((uchar) r)]; } r ^= pb[0]; /* sic */ b[0] = r; b[1] = l; return; } static u32int pbox[BFrounds+2] = { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b }; static u32int sbox[1024] = { 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L, 0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L, 0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, 0x858efc16L, 0x636920d8L, 0x71574e69L, 0xa458fea3L, 0xf4933d7eL, 0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL, 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L, 0xc5d1b023L, 0x286085f0L, 0xca417918L, 0xb8db38efL, 0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, 0xb01e8a3eL, 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, 0x55605c60L, 0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L, 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL, 0xa15486afL, 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL, 0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, 0x9b87931eL, 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, 0x28958677L, 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L, 0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L, 0xef845d5dL, 0xe98575b1L, 0xdc262302L, 0xeb651b88L, 0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, 0x83f44239L, 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, 0x9e1f9b5eL, 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L, 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L, 0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L, 0xa1f1651dL, 0x39af0176L, 0x66ca593eL, 0x82430e88L, 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, 0x3b8b5ebeL, 0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L, 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL, 0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL, 0x075372c9L, 0x80991b7bL, 0x25d479d8L, 0xf6e8def7L, 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, 0x04c006baL, 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L, 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL, 0x6dfc511fL, 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L, 0xbee3d004L, 0xde334afdL, 0x660f2807L, 0x192e4bb3L, 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, 0xb9d3fbdbL, 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L, 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L, 0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, 0xad0552abL, 0x323db5faL, 0xfd238760L, 0x53317b48L, 0x3e00df82L, 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, 0xdf1769dbL, 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L, 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L, 0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL, 0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, 0x4bfb9790L, 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, 0xcee4c6e8L, 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L, 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L, 0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L, 0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, 0x900df01cL, 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, 0xb3a8c1adL, 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L, 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L, 0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L, 0x165fa266L, 0x80957705L, 0x93cc7314L, 0x211a1477L, 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, 0xfb9d35cfL, 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L, 0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL, 0x2464369bL, 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL, 0x78c14389L, 0xd95a537fL, 0x207d5ba2L, 0x02e5b9c5L, 0x83260376L, 0x6295cfa9L, 0x11c81968L, 0x4e734a41L, 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L, 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L, 0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L, 0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, 0xc5855664L, 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, 0x6e85076aL, 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L, 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L, 0xecaa8c71L, 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L, 0x193602a5L, 0x75094c29L, 0xa0591340L, 0xe4183a3eL, 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, 0x99f73fd6L, 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L, 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL, 0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L, 0x687f3584L, 0x52a0e286L, 0xb79c5305L, 0xaa500737L, 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, 0x5716f2b8L, 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL, 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL, 0xd19113f9L, 0x7ca92ff6L, 0x94324773L, 0x22f54701L, 0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, 0x9af3dda7L, 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, 0xa4751e41L, 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L, 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL, 0x2cb81290L, 0x24977c79L, 0x5679b072L, 0xbcaf89afL, 0xde9a771fL, 0xd9930810L, 0xb38bae12L, 0xdccf3f2eL, 0x5512721fL, 0x2e6b7124L, 0x501adde6L, 0x9f84cd87L, 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL, 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L, 0xef1c1847L, 0x3215d908L, 0xdd433b37L, 0x24c2ba16L, 0x12a14d43L, 0x2a65c451L, 0x50940002L, 0x133ae4ddL, 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, 0x5f11199bL, 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L, 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL, 0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L, 0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, 0x99e71d0fL, 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, 0x9c10b36aL, 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L, 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L, 0x5223a708L, 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L, 0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, 0x018cff28L, 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, 0x68ab9802L, 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L, 0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L, 0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL, 0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, 0xcbaade14L, 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, 0xb2f3846eL, 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L, 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L, 0x9b540b19L, 0x875fa099L, 0x95f7997eL, 0x623d7da8L, 0xf837889aL, 0x97e32d77L, 0x11ed935fL, 0x16681281L, 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, 0x7858ba99L, 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L, 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L, 0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L, 0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, 0x203e13e0L, 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, 0xfacb4fd0L, 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L, 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L, 0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L, 0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, 0x5692b285L, 0x095bbf00L, 0xad19489dL, 0x1462b174L, 0x23820e00L, 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L, 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL, 0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, 0xce77326eL, 0xa6078084L, 0x19f8509eL, 0xe8efd855L, 0x61d99735L, 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, 0x800bcadcL, 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L, 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L, 0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L, 0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, 0xdb83adf7L, 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, 0x94692934L, 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L, 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL, 0x1e39f62eL, 0x97244546L, 0x14214f74L, 0xbf8b8840L, 0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, 0x66a02f45L, 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, 0x31cb8504L, 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL, 0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL, 0x68dc1462L, 0xd7486900L, 0x680ec0a4L, 0x27a18deeL, 0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, 0x7af4d6b6L, 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, 0x406b2a42L, 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL, 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L, 0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL, 0xfb0af54eL, 0xd8feb397L, 0x454056acL, 0xba489527L, 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, 0xd096954bL, 0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L, 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL, 0xfdf8e802L, 0x04272f70L, 0x80bb155cL, 0x05282ce3L, 0x95c11548L, 0xe4c66d22L, 0x48c1133fL, 0xc70f86dcL, 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, 0x5d886e17L, 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L, 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL, 0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, 0xcad18115L, 0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, 0xeebeb922L, 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, 0x2da2f728L, 0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L, 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL, 0x0a476341L, 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L, 0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, 0xdb6e6b0dL, 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, 0xdcd0e804L, 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL, 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L, 0xbb132f88L, 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL, 0x37392eb3L, 0xcc115979L, 0x8026e297L, 0xf42e312dL, 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, 0x782ef11cL, 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L, 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L, 0x44421659L, 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL, 0x64af674eL, 0xda86a85fL, 0xbebfe988L, 0x64e4c3feL, 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, 0x6003604dL, 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL, 0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL, 0x77a057beL, 0xbde8ae24L, 0x55464299L, 0xbf582e61L, 0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, 0x8789bdc2L, 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, 0x46fcd9b9L, 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L, 0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL, 0xb90bace1L, 0xbb8205d0L, 0x11a86248L, 0x7574a99eL, 0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, 0xc4324633L, 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, 0x1d6efe10L, 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L, 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L, 0x50115e01L, 0xa70683faL, 0xa002b5c4L, 0x0de6d027L, 0x9af88c27L, 0x773f8641L, 0xc3604c06L, 0x61a806b5L, 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, 0x30dc7d62L, 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L, 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L, 0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L, 0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, 0xd39eb8fcL, 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, 0x4dad0fc4L, 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL, 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L, 0xd79a3234L, 0x92638212L, 0x670efa8eL, 0x406000e0L, 0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, 0x5ac52d1bL, 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, 0x99bc9bbeL, 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL, 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L, 0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L, 0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, 0x4cd04dc6L, 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, 0xbe5ee304L, 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L, 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L, 0x83c061baL, 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L, 0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, 0xef5562e9L, 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, 0x77fa0a59L, 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L, 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L, 0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L, 0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, 0x5a88f54cL, 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, 0xed93fa9bL, 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L, 0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL, 0x15056dd4L, 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL, 0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, 0xa93a072aL, 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, 0x26dcf319L, 0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL, 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL, 0x4de81751L, 0x3830dc8eL, 0x379d5862L, 0x9320f991L, 0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, 0x774fbe32L, 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, 0x6413e680L, 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L, 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL, 0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL, 0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, 0xbcb4cdd5L, 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, 0xbf3c6f47L, 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L, 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL, 0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L, 0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, 0xce6ea048L, 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, 0x277227f8L, 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL, 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L, 0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L, 0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, 0xd50ada38L, 0x0339c32aL, 0xc6913667L, 0x8df9317cL, 0xe0b12b4fL, 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL, 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L, 0xfae59361L, 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L, 0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, 0xcb03a442L, 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, 0x3278e964L, 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL, 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L, 0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL, 0xe54cda54L, 0x1edad891L, 0xce6279cfL, 0xcd3e7e6fL, 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, 0xf6fb2299L, 0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L, 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL, 0xde966292L, 0x81b949d0L, 0x4c50901bL, 0x71c65614L, 0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, 0xc3f27b9aL, 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, 0x35bdd2f6L, 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL, 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L, 0xba38209cL, 0xf746ce76L, 0x77afa1c5L, 0x20756060L, 0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, 0x4cf9aa7eL, 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, 0xd6ebe1f9L, 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL, 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L, }; drawterm-20110822.orig/libsec/genstrongprime.c0000644000175000017500000000201711245145712020543 0ustar tinchotincho#include "os.h" #include #include // Gordon's algorithm for generating a strong prime // Menezes et al () Handbook, p.150 void genstrongprime(mpint *p, int n, int accuracy) { mpint *s, *t, *r, *i; if(n < 64) n = 64; s = mpnew(n/2); genprime(s, (n/2)-16, accuracy); t = mpnew(n/2); genprime(t, n-mpsignif(s)-32, accuracy); // first r = 2it + 1 that's prime i = mpnew(16); r = mpnew(0); itomp(0x8000, i); mpleft(t, 1, t); // 2t mpmul(i, t, r); // 2it mpadd(r, mpone, r); // 2it + 1 for(;;){ if(probably_prime(r, 18)) break; mpadd(r, t, r); // r += 2t } // p0 = 2(s**(r-2) mod r)s - 1 itomp(2, p); mpsub(r, p, p); mpexp(s, p, r, p); mpmul(s, p, p); mpleft(p, 1, p); mpsub(p, mpone, p); // first p = p0 + 2irs that's prime itomp(0x8000, i); mpleft(r, 1, r); // 2r mpmul(r, s, r); // 2rs mpmul(r, i, i); // 2irs mpadd(p, i, p); // p0 + 2irs for(;;){ if(probably_prime(p, accuracy)) break; mpadd(p, r, p); // p += 2rs } mpfree(i); mpfree(s); mpfree(r); mpfree(t); } drawterm-20110822.orig/libsec/rsafill.c0000644000175000017500000000212011245145712017127 0ustar tinchotincho#include "os.h" #include #include RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q) { mpint *c2, *kq, *kp, *x; RSApriv *rsa; // make sure we're not being hoodwinked if(!probably_prime(p, 10) || !probably_prime(q, 10)){ werrstr("rsafill: p or q not prime"); return nil; } x = mpnew(0); mpmul(p, q, x); if(mpcmp(n, x) != 0){ werrstr("rsafill: n != p*q"); mpfree(x); return nil; } c2 = mpnew(0); mpsub(p, mpone, c2); mpsub(q, mpone, x); mpmul(c2, x, x); mpmul(e, d, c2); mpmod(c2, x, x); if(mpcmp(x, mpone) != 0){ werrstr("rsafill: e*d != 1 mod (p-1)*(q-1)"); mpfree(x); mpfree(c2); return nil; } // compute chinese remainder coefficient mpinvert(p, q, c2); // for crt a**k mod p == (a**(k mod p-1)) mod p kq = mpnew(0); kp = mpnew(0); mpsub(p, mpone, x); mpmod(d, x, kp); mpsub(q, mpone, x); mpmod(d, x, kq); rsa = rsaprivalloc(); rsa->pub.ek = mpcopy(e); rsa->pub.n = mpcopy(n); rsa->dk = mpcopy(d); rsa->kp = kp; rsa->kq = kq; rsa->p = mpcopy(p); rsa->q = mpcopy(q); rsa->c2 = c2; mpfree(x); return rsa; } drawterm-20110822.orig/libsec/sha1block.c0000644000175000017500000001110111245145712017341 0ustar tinchotincho#include "os.h" void _sha1block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, e, x; uchar *end; u32int *wp, *wend; u32int w[80]; /* at this point, we have a multiple of 64 bytes */ for(end = p+len; p < end;){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; e = s[4]; wend = w + 15; for(wp = w; wp < wend; wp += 5){ wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); wp[1] = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7]; d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); wp[2] = (p[8]<<24) | (p[9]<<16) | (p[10]<<8) | p[11]; c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); wp[3] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); wp[4] = (p[16]<<24) | (p[17]<<16) | (p[18]<<8) | p[19]; a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); p += 20; } wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); wp += 5; p += 4; wend = w + 40; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x6ed9eba1 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x6ed9eba1 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x6ed9eba1 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x6ed9eba1 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x6ed9eba1 + (c^d^e); c = (c<<30)|(c>>2); } wend = w + 60; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x8f1bbcdc + ((b&c)|((b|c)&d)); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x8f1bbcdc + ((a&b)|((a|b)&c)); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x8f1bbcdc + ((e&a)|((e|a)&b)); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x8f1bbcdc + ((d&e)|((d|e)&a)); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x8f1bbcdc + ((c&d)|((c|d)&e)); c = (c<<30)|(c>>2); } wend = w + 80; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0xca62c1d6 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0xca62c1d6 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0xca62c1d6 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0xca62c1d6 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0xca62c1d6 + (c^d^e); c = (c<<30)|(c>>2); } /* save state */ s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; } } drawterm-20110822.orig/libsec/tlshand.c0000644000175000017500000015124411510255052017136 0ustar tinchotincho#include #include #include #include #include #include // The main groups of functions are: // client/server - main handshake protocol definition // message functions - formating handshake messages // cipher choices - catalog of digest and encrypt algorithms // security functions - PKCS#1, sslHMAC, session keygen // general utility functions - malloc, serialization // The handshake protocol builds on the TLS/SSL3 record layer protocol, // which is implemented in kernel device #a. See also /lib/rfc/rfc2246. enum { TLSFinishedLen = 12, SSL3FinishedLen = MD5dlen+SHA1dlen, MaxKeyData = 104, // amount of secret we may need MaxChunk = 1<<14, RandomSize = 32, SidSize = 32, MasterSecretSize = 48, AQueue = 0, AFlush = 1, }; typedef struct TlsSec TlsSec; typedef struct Bytes{ int len; uchar data[1]; // [len] } Bytes; typedef struct Ints{ int len; int data[1]; // [len] } Ints; typedef struct Algs{ char *enc; char *digest; int nsecret; int tlsid; int ok; } Algs; typedef struct Finished{ uchar verify[SSL3FinishedLen]; int n; } Finished; typedef struct TlsConnection{ TlsSec *sec; // security management goo int hand, ctl; // record layer file descriptors int erred; // set when tlsError called int (*trace)(char*fmt, ...); // for debugging int version; // protocol we are speaking int verset; // version has been set int ver2hi; // server got a version 2 hello int isClient; // is this the client or server? Bytes *sid; // SessionID Bytes *cert; // only last - no chain Lock statelk; int state; // must be set using setstate // input buffer for handshake messages uchar buf[MaxChunk+2048]; uchar *rp, *ep; uchar crandom[RandomSize]; // client random uchar srandom[RandomSize]; // server random int clientVersion; // version in ClientHello char *digest; // name of digest algorithm to use char *enc; // name of encryption algorithm to use int nsecret; // amount of secret data to init keys // for finished messages MD5state hsmd5; // handshake hash SHAstate hssha1; // handshake hash Finished finished; } TlsConnection; typedef struct Msg{ int tag; union { struct { int version; uchar random[RandomSize]; Bytes* sid; Ints* ciphers; Bytes* compressors; } clientHello; struct { int version; uchar random[RandomSize]; Bytes* sid; int cipher; int compressor; } serverHello; struct { int ncert; Bytes **certs; } certificate; struct { Bytes *types; int nca; Bytes **cas; } certificateRequest; struct { Bytes *key; } clientKeyExchange; Finished finished; } u; } Msg; typedef struct TlsSec{ char *server; // name of remote; nil for server int ok; // <0 killed; ==0 in progress; >0 reusable RSApub *rsapub; AuthRpc *rpc; // factotum for rsa private key uchar sec[MasterSecretSize]; // master secret uchar crandom[RandomSize]; // client random uchar srandom[RandomSize]; // server random int clientVers; // version in ClientHello int vers; // final version // byte generation and handshake checksum void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int, uchar*, int); void (*setFinished)(TlsSec*, MD5state, SHAstate, uchar*, int); int nfin; } TlsSec; enum { TLSVersion = 0x0301, SSL3Version = 0x0300, ProtocolVersion = 0x0301, // maximum version we speak MinProtoVersion = 0x0300, // limits on version we accept MaxProtoVersion = 0x03ff, }; // handshake type enum { HHelloRequest, HClientHello, HServerHello, HSSL2ClientHello = 9, /* local convention; see devtls.c */ HCertificate = 11, HServerKeyExchange, HCertificateRequest, HServerHelloDone, HCertificateVerify, HClientKeyExchange, HFinished = 20, HMax }; // alerts enum { ECloseNotify = 0, EUnexpectedMessage = 10, EBadRecordMac = 20, EDecryptionFailed = 21, ERecordOverflow = 22, EDecompressionFailure = 30, EHandshakeFailure = 40, ENoCertificate = 41, EBadCertificate = 42, EUnsupportedCertificate = 43, ECertificateRevoked = 44, ECertificateExpired = 45, ECertificateUnknown = 46, EIllegalParameter = 47, EUnknownCa = 48, EAccessDenied = 49, EDecodeError = 50, EDecryptError = 51, EExportRestriction = 60, EProtocolVersion = 70, EInsufficientSecurity = 71, EInternalError = 80, EUserCanceled = 90, ENoRenegotiation = 100, EMax = 256 }; // cipher suites enum { TLS_NULL_WITH_NULL_NULL = 0x0000, TLS_RSA_WITH_NULL_MD5 = 0x0001, TLS_RSA_WITH_NULL_SHA = 0x0002, TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003, TLS_RSA_WITH_RC4_128_MD5 = 0x0004, TLS_RSA_WITH_RC4_128_SHA = 0x0005, TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0X0006, TLS_RSA_WITH_IDEA_CBC_SHA = 0X0007, TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0X0008, TLS_RSA_WITH_DES_CBC_SHA = 0X0009, TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0X000A, TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0X000B, TLS_DH_DSS_WITH_DES_CBC_SHA = 0X000C, TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0X000D, TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0X000E, TLS_DH_RSA_WITH_DES_CBC_SHA = 0X000F, TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0X0010, TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0X0011, TLS_DHE_DSS_WITH_DES_CBC_SHA = 0X0012, TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0X0013, // ZZZ must be implemented for tls1.0 compliance TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0X0014, TLS_DHE_RSA_WITH_DES_CBC_SHA = 0X0015, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0X0016, TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017, TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018, TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0X0019, TLS_DH_anon_WITH_DES_CBC_SHA = 0X001A, TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0X001B, TLS_RSA_WITH_AES_128_CBC_SHA = 0X002f, // aes, aka rijndael with 128 bit blocks TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0X0030, TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0X0031, TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0X0032, TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0X0033, TLS_DH_anon_WITH_AES_128_CBC_SHA = 0X0034, TLS_RSA_WITH_AES_256_CBC_SHA = 0X0035, TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0X0036, TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0X0037, TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0X0038, TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0X0039, TLS_DH_anon_WITH_AES_256_CBC_SHA = 0X003A, CipherMax }; // compression methods enum { CompressionNull = 0, CompressionMax }; static Algs cipherAlgs[] = { {"rc4_128", "md5", 2 * (16 + MD5dlen), TLS_RSA_WITH_RC4_128_MD5}, {"rc4_128", "sha1", 2 * (16 + SHA1dlen), TLS_RSA_WITH_RC4_128_SHA}, {"3des_ede_cbc","sha1",2*(4*8+SHA1dlen), TLS_RSA_WITH_3DES_EDE_CBC_SHA}, }; static uchar compressors[] = { CompressionNull, }; static TlsConnection *tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...)); static TlsConnection *tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ...)); static void msgClear(Msg *m); static char* msgPrint(char *buf, int n, Msg *m); static int msgRecv(TlsConnection *c, Msg *m); static int msgSend(TlsConnection *c, Msg *m, int act); static void tlsError(TlsConnection *c, int err, char *msg, ...); #pragma varargck argpos tlsError 3 static int setVersion(TlsConnection *c, int version); static int finishedMatch(TlsConnection *c, Finished *f); static void tlsConnectionFree(TlsConnection *c); static int setAlgs(TlsConnection *c, int a); static int okCipher(Ints *cv); static int okCompression(Bytes *cv); static int initCiphers(void); static Ints* makeciphers(void); static TlsSec* tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uchar *ssid, int *nssid, uchar *srandom); static int tlsSecSecrets(TlsSec *sec, int vers, uchar *epm, int nepm, uchar *kd, int nkd); static TlsSec* tlsSecInitc(int cvers, uchar *crandom); static int tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd); static int tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient); static void tlsSecOk(TlsSec *sec); static void tlsSecKill(TlsSec *sec); static void tlsSecClose(TlsSec *sec); static void setMasterSecret(TlsSec *sec, Bytes *pm); static void serverMasterSecret(TlsSec *sec, uchar *epm, int nepm); static void setSecrets(TlsSec *sec, uchar *kd, int nkd); static int clientMasterSecret(TlsSec *sec, RSApub *pub, uchar **epm, int *nepm); static Bytes *pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype); static Bytes *pkcs1_decrypt(TlsSec *sec, uchar *epm, int nepm); static void tlsSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient); static void sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient); static void sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1); static int setVers(TlsSec *sec, int version); static AuthRpc* factotum_rsa_open(uchar *cert, int certlen); static mpint* factotum_rsa_decrypt(AuthRpc *rpc, mpint *cipher); static void factotum_rsa_close(AuthRpc*rpc); static void* emalloc(int); static void* erealloc(void*, int); static void put32(uchar *p, u32int); static void put24(uchar *p, int); static void put16(uchar *p, int); static u32int get32(uchar *p); static int get24(uchar *p); static int get16(uchar *p); static Bytes* newbytes(int len); static Bytes* makebytes(uchar* buf, int len); static void freebytes(Bytes* b); static Ints* newints(int len); static Ints* makeints(int* buf, int len); static void freeints(Ints* b); //================= client/server ======================== // push TLS onto fd, returning new (application) file descriptor // or -1 if error. int tlsServer(int fd, TLSconn *conn) { char buf[8]; char dname[64]; int n, data, ctl, hand; TlsConnection *tls; if(conn == nil) return -1; ctl = open("#a/tls/clone", ORDWR); if(ctl < 0) return -1; n = read(ctl, buf, sizeof(buf)-1); if(n < 0){ close(ctl); return -1; } buf[n] = 0; sprint(conn->dir, "#a/tls/%s", buf); sprint(dname, "#a/tls/%s/hand", buf); hand = open(dname, ORDWR); if(hand < 0){ close(ctl); return -1; } fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion); tls = tlsServer2(ctl, hand, conn->cert, conn->certlen, conn->trace); sprint(dname, "#a/tls/%s/data", buf); data = open(dname, ORDWR); close(fd); close(hand); close(ctl); if(data < 0){ return -1; } if(tls == nil){ close(data); return -1; } if(conn->cert) free(conn->cert); conn->cert = 0; // client certificates are not yet implemented conn->certlen = 0; conn->sessionIDlen = tls->sid->len; conn->sessionID = emalloc(conn->sessionIDlen); memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen); tlsConnectionFree(tls); return data; } // push TLS onto fd, returning new (application) file descriptor // or -1 if error. int tlsClient(int fd, TLSconn *conn) { char buf[8]; char dname[64]; int n, data, ctl, hand; TlsConnection *tls; if(!conn) return -1; ctl = open("#a/tls/clone", ORDWR); if(ctl < 0) return -1; n = read(ctl, buf, sizeof(buf)-1); if(n < 0){ close(ctl); return -1; } buf[n] = 0; sprint(conn->dir, "#a/tls/%s", buf); sprint(dname, "#a/tls/%s/hand", buf); hand = open(dname, ORDWR); if(hand < 0){ close(ctl); return -1; } sprint(dname, "#a/tls/%s/data", buf); data = open(dname, ORDWR); if(data < 0) return -1; fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion); tls = tlsClient2(ctl, hand, conn->sessionID, conn->sessionIDlen, conn->trace); close(fd); close(hand); close(ctl); if(tls == nil){ close(data); return -1; } conn->certlen = tls->cert->len; conn->cert = emalloc(conn->certlen); memcpy(conn->cert, tls->cert->data, conn->certlen); conn->sessionIDlen = tls->sid->len; conn->sessionID = emalloc(conn->sessionIDlen); memcpy(conn->sessionID, tls->sid->data, conn->sessionIDlen); tlsConnectionFree(tls); return data; } static TlsConnection * tlsServer2(int ctl, int hand, uchar *cert, int ncert, int (*trace)(char*fmt, ...)) { TlsConnection *c; Msg m; Bytes *csid; uchar sid[SidSize], kd[MaxKeyData]; char *secrets; int cipher, compressor, nsid, rv; if(trace) trace("tlsServer2\n"); if(!initCiphers()) return nil; c = emalloc(sizeof(TlsConnection)); c->ctl = ctl; c->hand = hand; c->trace = trace; c->version = ProtocolVersion; memset(&m, 0, sizeof(m)); if(!msgRecv(c, &m)){ if(trace) trace("initial msgRecv failed\n"); goto Err; } if(m.tag != HClientHello) { tlsError(c, EUnexpectedMessage, "expected a client hello"); goto Err; } c->clientVersion = m.u.clientHello.version; if(trace) trace("ClientHello version %x\n", c->clientVersion); if(setVersion(c, m.u.clientHello.version) < 0) { tlsError(c, EIllegalParameter, "incompatible version"); goto Err; } memmove(c->crandom, m.u.clientHello.random, RandomSize); cipher = okCipher(m.u.clientHello.ciphers); if(cipher < 0) { // reply with EInsufficientSecurity if we know that's the case if(cipher == -2) tlsError(c, EInsufficientSecurity, "cipher suites too weak"); else tlsError(c, EHandshakeFailure, "no matching cipher suite"); goto Err; } if(!setAlgs(c, cipher)){ tlsError(c, EHandshakeFailure, "no matching cipher suite"); goto Err; } compressor = okCompression(m.u.clientHello.compressors); if(compressor < 0) { tlsError(c, EHandshakeFailure, "no matching compressor"); goto Err; } csid = m.u.clientHello.sid; if(trace) trace(" cipher %d, compressor %d, csidlen %d\n", cipher, compressor, csid->len); c->sec = tlsSecInits(c->clientVersion, csid->data, csid->len, c->crandom, sid, &nsid, c->srandom); if(c->sec == nil){ tlsError(c, EHandshakeFailure, "can't initialize security: %r"); goto Err; } c->sec->rpc = factotum_rsa_open(cert, ncert); if(c->sec->rpc == nil){ tlsError(c, EHandshakeFailure, "factotum_rsa_open: %r"); goto Err; } c->sec->rsapub = X509toRSApub(cert, ncert, nil, 0); msgClear(&m); m.tag = HServerHello; m.u.serverHello.version = c->version; memmove(m.u.serverHello.random, c->srandom, RandomSize); m.u.serverHello.cipher = cipher; m.u.serverHello.compressor = compressor; c->sid = makebytes(sid, nsid); m.u.serverHello.sid = makebytes(c->sid->data, c->sid->len); if(!msgSend(c, &m, AQueue)) goto Err; msgClear(&m); m.tag = HCertificate; m.u.certificate.ncert = 1; m.u.certificate.certs = emalloc(m.u.certificate.ncert * sizeof(Bytes)); m.u.certificate.certs[0] = makebytes(cert, ncert); if(!msgSend(c, &m, AQueue)) goto Err; msgClear(&m); m.tag = HServerHelloDone; if(!msgSend(c, &m, AFlush)) goto Err; msgClear(&m); if(!msgRecv(c, &m)) goto Err; if(m.tag != HClientKeyExchange) { tlsError(c, EUnexpectedMessage, "expected a client key exchange"); goto Err; } if(tlsSecSecrets(c->sec, c->version, m.u.clientKeyExchange.key->data, m.u.clientKeyExchange.key->len, kd, c->nsecret) < 0){ tlsError(c, EHandshakeFailure, "couldn't set secrets: %r"); goto Err; } if(trace) trace("tls secrets\n"); secrets = (char*)emalloc(2*c->nsecret); enc64(secrets, 2*c->nsecret, kd, c->nsecret); rv = fprint(c->ctl, "secret %s %s 0 %s", c->digest, c->enc, secrets); memset(secrets, 0, 2*c->nsecret); free(secrets); memset(kd, 0, c->nsecret); if(rv < 0){ tlsError(c, EHandshakeFailure, "can't set keys: %r"); goto Err; } msgClear(&m); /* no CertificateVerify; skip to Finished */ if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 1) < 0){ tlsError(c, EInternalError, "can't set finished: %r"); goto Err; } if(!msgRecv(c, &m)) goto Err; if(m.tag != HFinished) { tlsError(c, EUnexpectedMessage, "expected a finished"); goto Err; } if(!finishedMatch(c, &m.u.finished)) { tlsError(c, EHandshakeFailure, "finished verification failed"); goto Err; } msgClear(&m); /* change cipher spec */ if(fprint(c->ctl, "changecipher") < 0){ tlsError(c, EInternalError, "can't enable cipher: %r"); goto Err; } if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 0) < 0){ tlsError(c, EInternalError, "can't set finished: %r"); goto Err; } m.tag = HFinished; m.u.finished = c->finished; if(!msgSend(c, &m, AFlush)) goto Err; msgClear(&m); if(trace) trace("tls finished\n"); if(fprint(c->ctl, "opened") < 0) goto Err; tlsSecOk(c->sec); return c; Err: msgClear(&m); tlsConnectionFree(c); return 0; } static TlsConnection * tlsClient2(int ctl, int hand, uchar *csid, int ncsid, int (*trace)(char*fmt, ...)) { TlsConnection *c; Msg m; uchar kd[MaxKeyData], *epm; char *secrets; int creq, nepm, rv; if(!initCiphers()) return nil; epm = nil; c = emalloc(sizeof(TlsConnection)); c->version = ProtocolVersion; c->ctl = ctl; c->hand = hand; c->trace = trace; c->isClient = 1; c->clientVersion = c->version; c->sec = tlsSecInitc(c->clientVersion, c->crandom); if(c->sec == nil) goto Err; /* client hello */ memset(&m, 0, sizeof(m)); m.tag = HClientHello; m.u.clientHello.version = c->clientVersion; memmove(m.u.clientHello.random, c->crandom, RandomSize); m.u.clientHello.sid = makebytes(csid, ncsid); m.u.clientHello.ciphers = makeciphers(); m.u.clientHello.compressors = makebytes(compressors,sizeof(compressors)); if(!msgSend(c, &m, AFlush)) goto Err; msgClear(&m); /* server hello */ if(!msgRecv(c, &m)) goto Err; if(m.tag != HServerHello) { tlsError(c, EUnexpectedMessage, "expected a server hello"); goto Err; } if(setVersion(c, m.u.serverHello.version) < 0) { tlsError(c, EIllegalParameter, "incompatible version %r"); goto Err; } memmove(c->srandom, m.u.serverHello.random, RandomSize); c->sid = makebytes(m.u.serverHello.sid->data, m.u.serverHello.sid->len); if(c->sid->len != 0 && c->sid->len != SidSize) { tlsError(c, EIllegalParameter, "invalid server session identifier"); goto Err; } if(!setAlgs(c, m.u.serverHello.cipher)) { tlsError(c, EIllegalParameter, "invalid cipher suite"); goto Err; } if(m.u.serverHello.compressor != CompressionNull) { tlsError(c, EIllegalParameter, "invalid compression"); goto Err; } msgClear(&m); /* certificate */ if(!msgRecv(c, &m) || m.tag != HCertificate) { tlsError(c, EUnexpectedMessage, "expected a certificate"); goto Err; } if(m.u.certificate.ncert < 1) { tlsError(c, EIllegalParameter, "runt certificate"); goto Err; } c->cert = makebytes(m.u.certificate.certs[0]->data, m.u.certificate.certs[0]->len); msgClear(&m); /* server key exchange (optional) */ if(!msgRecv(c, &m)) goto Err; if(m.tag == HServerKeyExchange) { tlsError(c, EUnexpectedMessage, "got an server key exchange"); goto Err; // If implementing this later, watch out for rollback attack // described in Wagner Schneier 1996, section 4.4. } /* certificate request (optional) */ creq = 0; if(m.tag == HCertificateRequest) { creq = 1; msgClear(&m); if(!msgRecv(c, &m)) goto Err; } if(m.tag != HServerHelloDone) { tlsError(c, EUnexpectedMessage, "expected a server hello done"); goto Err; } msgClear(&m); if(tlsSecSecretc(c->sec, c->sid->data, c->sid->len, c->srandom, c->cert->data, c->cert->len, c->version, &epm, &nepm, kd, c->nsecret) < 0){ tlsError(c, EBadCertificate, "invalid x509/rsa certificate"); goto Err; } secrets = (char*)emalloc(2*c->nsecret); enc64(secrets, 2*c->nsecret, kd, c->nsecret); rv = fprint(c->ctl, "secret %s %s 1 %s", c->digest, c->enc, secrets); memset(secrets, 0, 2*c->nsecret); free(secrets); memset(kd, 0, c->nsecret); if(rv < 0){ tlsError(c, EHandshakeFailure, "can't set keys: %r"); goto Err; } if(creq) { /* send a zero length certificate */ m.tag = HCertificate; if(!msgSend(c, &m, AFlush)) goto Err; msgClear(&m); } /* client key exchange */ m.tag = HClientKeyExchange; m.u.clientKeyExchange.key = makebytes(epm, nepm); free(epm); epm = nil; if(m.u.clientKeyExchange.key == nil) { tlsError(c, EHandshakeFailure, "can't set secret: %r"); goto Err; } if(!msgSend(c, &m, AFlush)) goto Err; msgClear(&m); /* change cipher spec */ if(fprint(c->ctl, "changecipher") < 0){ tlsError(c, EInternalError, "can't enable cipher: %r"); goto Err; } // Cipherchange must occur immediately before Finished to avoid // potential hole; see section 4.3 of Wagner Schneier 1996. if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 1) < 0){ tlsError(c, EInternalError, "can't set finished 1: %r"); goto Err; } m.tag = HFinished; m.u.finished = c->finished; if(!msgSend(c, &m, AFlush)) { fprint(2, "tlsClient nepm=%d\n", nepm); tlsError(c, EInternalError, "can't flush after client Finished: %r"); goto Err; } msgClear(&m); if(tlsSecFinished(c->sec, c->hsmd5, c->hssha1, c->finished.verify, c->finished.n, 0) < 0){ fprint(2, "tlsClient nepm=%d\n", nepm); tlsError(c, EInternalError, "can't set finished 0: %r"); goto Err; } if(!msgRecv(c, &m)) { fprint(2, "tlsClient nepm=%d\n", nepm); tlsError(c, EInternalError, "can't read server Finished: %r"); goto Err; } if(m.tag != HFinished) { fprint(2, "tlsClient nepm=%d\n", nepm); tlsError(c, EUnexpectedMessage, "expected a Finished msg from server"); goto Err; } if(!finishedMatch(c, &m.u.finished)) { tlsError(c, EHandshakeFailure, "finished verification failed"); goto Err; } msgClear(&m); if(fprint(c->ctl, "opened") < 0){ if(trace) trace("unable to do final open: %r\n"); goto Err; } tlsSecOk(c->sec); return c; Err: free(epm); msgClear(&m); tlsConnectionFree(c); return 0; } //================= message functions ======================== static uchar sendbuf[9000], *sendp; static int msgSend(TlsConnection *c, Msg *m, int act) { uchar *p; // sendp = start of new message; p = write pointer int nn, n, i; if(sendp == nil) sendp = sendbuf; p = sendp; if(c->trace) c->trace("send %s", msgPrint((char*)p, (sizeof sendbuf) - (p-sendbuf), m)); p[0] = m->tag; // header - fill in size later p += 4; switch(m->tag) { default: tlsError(c, EInternalError, "can't encode a %d", m->tag); goto Err; case HClientHello: // version put16(p, m->u.clientHello.version); p += 2; // random memmove(p, m->u.clientHello.random, RandomSize); p += RandomSize; // sid n = m->u.clientHello.sid->len; assert(n < 256); p[0] = n; memmove(p+1, m->u.clientHello.sid->data, n); p += n+1; n = m->u.clientHello.ciphers->len; assert(n > 0 && n < 200); put16(p, n*2); p += 2; for(i=0; iu.clientHello.ciphers->data[i]); p += 2; } n = m->u.clientHello.compressors->len; assert(n > 0); p[0] = n; memmove(p+1, m->u.clientHello.compressors->data, n); p += n+1; break; case HServerHello: put16(p, m->u.serverHello.version); p += 2; // random memmove(p, m->u.serverHello.random, RandomSize); p += RandomSize; // sid n = m->u.serverHello.sid->len; assert(n < 256); p[0] = n; memmove(p+1, m->u.serverHello.sid->data, n); p += n+1; put16(p, m->u.serverHello.cipher); p += 2; p[0] = m->u.serverHello.compressor; p += 1; break; case HServerHelloDone: break; case HCertificate: nn = 0; for(i = 0; i < m->u.certificate.ncert; i++) nn += 3 + m->u.certificate.certs[i]->len; if(p + 3 + nn - sendbuf > sizeof(sendbuf)) { tlsError(c, EInternalError, "output buffer too small for certificate"); goto Err; } put24(p, nn); p += 3; for(i = 0; i < m->u.certificate.ncert; i++){ put24(p, m->u.certificate.certs[i]->len); p += 3; memmove(p, m->u.certificate.certs[i]->data, m->u.certificate.certs[i]->len); p += m->u.certificate.certs[i]->len; } break; case HClientKeyExchange: n = m->u.clientKeyExchange.key->len; if(c->version != SSL3Version){ put16(p, n); p += 2; } memmove(p, m->u.clientKeyExchange.key->data, n); p += n; break; case HFinished: memmove(p, m->u.finished.verify, m->u.finished.n); p += m->u.finished.n; break; } // go back and fill in size n = p-sendp; assert(p <= sendbuf+sizeof(sendbuf)); put24(sendp+1, n-4); // remember hash of Handshake messages if(m->tag != HHelloRequest) { md5(sendp, n, 0, &c->hsmd5); sha1(sendp, n, 0, &c->hssha1); } sendp = p; if(act == AFlush){ sendp = sendbuf; if(write(c->hand, sendbuf, p-sendbuf) < 0){ fprint(2, "write error: %r\n"); goto Err; } } msgClear(m); return 1; Err: msgClear(m); return 0; } static uchar* tlsReadN(TlsConnection *c, int n) { uchar *p; int nn, nr; nn = c->ep - c->rp; if(nn < n){ if(c->rp != c->buf){ memmove(c->buf, c->rp, nn); c->rp = c->buf; c->ep = &c->buf[nn]; } for(; nn < n; nn += nr) { nr = read(c->hand, &c->rp[nn], n - nn); if(nr <= 0) return nil; c->ep += nr; } } p = c->rp; c->rp += n; return p; } static int msgRecv(TlsConnection *c, Msg *m) { uchar *p; int type, n, nn, i, nsid, nrandom, nciph; for(;;) { p = tlsReadN(c, 4); if(p == nil) return 0; type = p[0]; n = get24(p+1); if(type != HHelloRequest) break; if(n != 0) { tlsError(c, EDecodeError, "invalid hello request during handshake"); return 0; } } if(n > sizeof(c->buf)) { tlsError(c, EDecodeError, "handshake message too long %d %d", n, sizeof(c->buf)); return 0; } if(type == HSSL2ClientHello){ /* Cope with an SSL3 ClientHello expressed in SSL2 record format. This is sent by some clients that we must interoperate with, such as Java's JSSE and Microsoft's Internet Explorer. */ p = tlsReadN(c, n); if(p == nil) return 0; md5(p, n, 0, &c->hsmd5); sha1(p, n, 0, &c->hssha1); m->tag = HClientHello; if(n < 22) goto Short; m->u.clientHello.version = get16(p+1); p += 3; n -= 3; nn = get16(p); /* cipher_spec_len */ nsid = get16(p + 2); nrandom = get16(p + 4); p += 6; n -= 6; if(nsid != 0 /* no sid's, since shouldn't restart using ssl2 header */ || nrandom < 16 || nn % 3) goto Err; if(c->trace && (n - nrandom != nn)) c->trace("n-nrandom!=nn: n=%d nrandom=%d nn=%d\n", n, nrandom, nn); /* ignore ssl2 ciphers and look for {0x00, ssl3 cipher} */ nciph = 0; for(i = 0; i < nn; i += 3) if(p[i] == 0) nciph++; m->u.clientHello.ciphers = newints(nciph); nciph = 0; for(i = 0; i < nn; i += 3) if(p[i] == 0) m->u.clientHello.ciphers->data[nciph++] = get16(&p[i + 1]); p += nn; m->u.clientHello.sid = makebytes(nil, 0); if(nrandom > RandomSize) nrandom = RandomSize; memset(m->u.clientHello.random, 0, RandomSize - nrandom); memmove(&m->u.clientHello.random[RandomSize - nrandom], p, nrandom); m->u.clientHello.compressors = newbytes(1); m->u.clientHello.compressors->data[0] = CompressionNull; goto Ok; } md5(p, 4, 0, &c->hsmd5); sha1(p, 4, 0, &c->hssha1); p = tlsReadN(c, n); if(p == nil) return 0; md5(p, n, 0, &c->hsmd5); sha1(p, n, 0, &c->hssha1); m->tag = type; switch(type) { default: tlsError(c, EUnexpectedMessage, "can't decode a %d", type); goto Err; case HClientHello: if(n < 2) goto Short; m->u.clientHello.version = get16(p); p += 2; n -= 2; if(n < RandomSize) goto Short; memmove(m->u.clientHello.random, p, RandomSize); p += RandomSize; n -= RandomSize; if(n < 1 || n < p[0]+1) goto Short; m->u.clientHello.sid = makebytes(p+1, p[0]); p += m->u.clientHello.sid->len+1; n -= m->u.clientHello.sid->len+1; if(n < 2) goto Short; nn = get16(p); p += 2; n -= 2; if((nn & 1) || n < nn || nn < 2) goto Short; m->u.clientHello.ciphers = newints(nn >> 1); for(i = 0; i < nn; i += 2) m->u.clientHello.ciphers->data[i >> 1] = get16(&p[i]); p += nn; n -= nn; if(n < 1 || n < p[0]+1 || p[0] == 0) goto Short; nn = p[0]; m->u.clientHello.compressors = newbytes(nn); memmove(m->u.clientHello.compressors->data, p+1, nn); n -= nn + 1; break; case HServerHello: if(n < 2) goto Short; m->u.serverHello.version = get16(p); p += 2; n -= 2; if(n < RandomSize) goto Short; memmove(m->u.serverHello.random, p, RandomSize); p += RandomSize; n -= RandomSize; if(n < 1 || n < p[0]+1) goto Short; m->u.serverHello.sid = makebytes(p+1, p[0]); p += m->u.serverHello.sid->len+1; n -= m->u.serverHello.sid->len+1; if(n < 3) goto Short; m->u.serverHello.cipher = get16(p); m->u.serverHello.compressor = p[2]; n -= 3; break; case HCertificate: if(n < 3) goto Short; nn = get24(p); p += 3; n -= 3; if(n != nn) goto Short; /* certs */ i = 0; while(n > 0) { if(n < 3) goto Short; nn = get24(p); p += 3; n -= 3; if(nn > n) goto Short; m->u.certificate.ncert = i+1; m->u.certificate.certs = erealloc(m->u.certificate.certs, (i+1)*sizeof(Bytes)); m->u.certificate.certs[i] = makebytes(p, nn); p += nn; n -= nn; i++; } break; case HCertificateRequest: if(n < 2) goto Short; nn = get16(p); p += 2; n -= 2; if(nn < 1 || nn > n) goto Short; m->u.certificateRequest.types = makebytes(p, nn); nn = get24(p); p += 3; n -= 3; if(nn == 0 || n != nn) goto Short; /* cas */ i = 0; while(n > 0) { if(n < 2) goto Short; nn = get16(p); p += 2; n -= 2; if(nn < 1 || nn > n) goto Short; m->u.certificateRequest.nca = i+1; m->u.certificateRequest.cas = erealloc(m->u.certificateRequest.cas, (i+1)*sizeof(Bytes)); m->u.certificateRequest.cas[i] = makebytes(p, nn); p += nn; n -= nn; i++; } break; case HServerHelloDone: break; case HClientKeyExchange: /* * this message depends upon the encryption selected * assume rsa. */ if(c->version == SSL3Version) nn = n; else{ if(n < 2) goto Short; nn = get16(p); p += 2; n -= 2; } if(n < nn) goto Short; m->u.clientKeyExchange.key = makebytes(p, nn); n -= nn; break; case HFinished: m->u.finished.n = c->finished.n; if(n < m->u.finished.n) goto Short; memmove(m->u.finished.verify, p, m->u.finished.n); n -= m->u.finished.n; break; } if(type != HClientHello && n != 0) goto Short; Ok: if(c->trace){ char buf[8000]; c->trace("recv %s", msgPrint(buf, sizeof buf, m)); } return 1; Short: tlsError(c, EDecodeError, "handshake message has invalid length"); Err: msgClear(m); return 0; } static void msgClear(Msg *m) { int i; switch(m->tag) { default: sysfatal("msgClear: unknown message type: %d", m->tag); case HHelloRequest: break; case HClientHello: freebytes(m->u.clientHello.sid); freeints(m->u.clientHello.ciphers); freebytes(m->u.clientHello.compressors); break; case HServerHello: freebytes(m->u.clientHello.sid); break; case HCertificate: for(i=0; iu.certificate.ncert; i++) freebytes(m->u.certificate.certs[i]); free(m->u.certificate.certs); break; case HCertificateRequest: freebytes(m->u.certificateRequest.types); for(i=0; iu.certificateRequest.nca; i++) freebytes(m->u.certificateRequest.cas[i]); free(m->u.certificateRequest.cas); break; case HServerHelloDone: break; case HClientKeyExchange: freebytes(m->u.clientKeyExchange.key); break; case HFinished: break; } memset(m, 0, sizeof(Msg)); } static char * bytesPrint(char *bs, char *be, char *s0, Bytes *b, char *s1) { int i; if(s0) bs = seprint(bs, be, "%s", s0); bs = seprint(bs, be, "["); if(b == nil) bs = seprint(bs, be, "nil"); else for(i=0; ilen; i++) bs = seprint(bs, be, "%.2x ", b->data[i]); bs = seprint(bs, be, "]"); if(s1) bs = seprint(bs, be, "%s", s1); return bs; } static char * intsPrint(char *bs, char *be, char *s0, Ints *b, char *s1) { int i; if(s0) bs = seprint(bs, be, "%s", s0); bs = seprint(bs, be, "["); if(b == nil) bs = seprint(bs, be, "nil"); else for(i=0; ilen; i++) bs = seprint(bs, be, "%x ", b->data[i]); bs = seprint(bs, be, "]"); if(s1) bs = seprint(bs, be, "%s", s1); return bs; } static char* msgPrint(char *buf, int n, Msg *m) { int i; char *bs = buf, *be = buf+n; switch(m->tag) { default: bs = seprint(bs, be, "unknown %d\n", m->tag); break; case HClientHello: bs = seprint(bs, be, "ClientHello\n"); bs = seprint(bs, be, "\tversion: %.4x\n", m->u.clientHello.version); bs = seprint(bs, be, "\trandom: "); for(i=0; iu.clientHello.random[i]); bs = seprint(bs, be, "\n"); bs = bytesPrint(bs, be, "\tsid: ", m->u.clientHello.sid, "\n"); bs = intsPrint(bs, be, "\tciphers: ", m->u.clientHello.ciphers, "\n"); bs = bytesPrint(bs, be, "\tcompressors: ", m->u.clientHello.compressors, "\n"); break; case HServerHello: bs = seprint(bs, be, "ServerHello\n"); bs = seprint(bs, be, "\tversion: %.4x\n", m->u.serverHello.version); bs = seprint(bs, be, "\trandom: "); for(i=0; iu.serverHello.random[i]); bs = seprint(bs, be, "\n"); bs = bytesPrint(bs, be, "\tsid: ", m->u.serverHello.sid, "\n"); bs = seprint(bs, be, "\tcipher: %.4x\n", m->u.serverHello.cipher); bs = seprint(bs, be, "\tcompressor: %.2x\n", m->u.serverHello.compressor); break; case HCertificate: bs = seprint(bs, be, "Certificate\n"); for(i=0; iu.certificate.ncert; i++) bs = bytesPrint(bs, be, "\t", m->u.certificate.certs[i], "\n"); break; case HCertificateRequest: bs = seprint(bs, be, "CertificateRequest\n"); bs = bytesPrint(bs, be, "\ttypes: ", m->u.certificateRequest.types, "\n"); bs = seprint(bs, be, "\tcertificateauthorities\n"); for(i=0; iu.certificateRequest.nca; i++) bs = bytesPrint(bs, be, "\t\t", m->u.certificateRequest.cas[i], "\n"); break; case HServerHelloDone: bs = seprint(bs, be, "ServerHelloDone\n"); break; case HClientKeyExchange: bs = seprint(bs, be, "HClientKeyExchange\n"); bs = bytesPrint(bs, be, "\tkey: ", m->u.clientKeyExchange.key, "\n"); break; case HFinished: bs = seprint(bs, be, "HFinished\n"); for(i=0; iu.finished.n; i++) bs = seprint(bs, be, "%.2x", m->u.finished.verify[i]); bs = seprint(bs, be, "\n"); break; } USED(bs); return buf; } static void tlsError(TlsConnection *c, int err, char *fmt, ...) { char msg[512]; va_list arg; va_start(arg, fmt); vseprint(msg, msg+sizeof(msg), fmt, arg); va_end(arg); if(c->trace) c->trace("tlsError: %s\n", msg); else if(c->erred) fprint(2, "double error: %r, %s", msg); else werrstr("tls: local %s", msg); c->erred = 1; fprint(c->ctl, "alert %d", err); } // commit to specific version number static int setVersion(TlsConnection *c, int version) { if(c->verset || version > MaxProtoVersion || version < MinProtoVersion) return -1; if(version > c->version) version = c->version; if(version == SSL3Version) { c->version = version; c->finished.n = SSL3FinishedLen; }else if(version == TLSVersion){ c->version = version; c->finished.n = TLSFinishedLen; }else return -1; c->verset = 1; return fprint(c->ctl, "version 0x%x", version); } // confirm that received Finished message matches the expected value static int finishedMatch(TlsConnection *c, Finished *f) { return memcmp(f->verify, c->finished.verify, f->n) == 0; } // free memory associated with TlsConnection struct // (but don't close the TLS channel itself) static void tlsConnectionFree(TlsConnection *c) { tlsSecClose(c->sec); freebytes(c->sid); freebytes(c->cert); memset(c, 0, sizeof(c)); free(c); } //================= cipher choices ======================== static int weakCipher[CipherMax] = { 1, /* TLS_NULL_WITH_NULL_NULL */ 1, /* TLS_RSA_WITH_NULL_MD5 */ 1, /* TLS_RSA_WITH_NULL_SHA */ 1, /* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */ 0, /* TLS_RSA_WITH_RC4_128_MD5 */ 0, /* TLS_RSA_WITH_RC4_128_SHA */ 1, /* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */ 0, /* TLS_RSA_WITH_IDEA_CBC_SHA */ 1, /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA */ 0, /* TLS_RSA_WITH_DES_CBC_SHA */ 0, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */ 1, /* TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA */ 0, /* TLS_DH_DSS_WITH_DES_CBC_SHA */ 0, /* TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA */ 1, /* TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */ 0, /* TLS_DH_RSA_WITH_DES_CBC_SHA */ 0, /* TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA */ 1, /* TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA */ 0, /* TLS_DHE_DSS_WITH_DES_CBC_SHA */ 0, /* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */ 1, /* TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA */ 0, /* TLS_DHE_RSA_WITH_DES_CBC_SHA */ 0, /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */ 1, /* TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 */ 1, /* TLS_DH_anon_WITH_RC4_128_MD5 */ 1, /* TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA */ 1, /* TLS_DH_anon_WITH_DES_CBC_SHA */ 1, /* TLS_DH_anon_WITH_3DES_EDE_CBC_SHA */ }; static int setAlgs(TlsConnection *c, int a) { int i; for(i = 0; i < nelem(cipherAlgs); i++){ if(cipherAlgs[i].tlsid == a){ c->enc = cipherAlgs[i].enc; c->digest = cipherAlgs[i].digest; c->nsecret = cipherAlgs[i].nsecret; if(c->nsecret > MaxKeyData) return 0; return 1; } } return 0; } static int okCipher(Ints *cv) { int weak, i, j, c; weak = 1; for(i = 0; i < cv->len; i++) { c = cv->data[i]; if(c >= CipherMax) weak = 0; else weak &= weakCipher[c]; for(j = 0; j < nelem(cipherAlgs); j++) if(cipherAlgs[j].ok && cipherAlgs[j].tlsid == c) return c; } if(weak) return -2; return -1; } static int okCompression(Bytes *cv) { int i, j, c; for(i = 0; i < cv->len; i++) { c = cv->data[i]; for(j = 0; j < nelem(compressors); j++) { if(compressors[j] == c) return c; } } return -1; } static Lock ciphLock; static int nciphers; static int initCiphers(void) { enum {MaxAlgF = 1024, MaxAlgs = 10}; char s[MaxAlgF], *flds[MaxAlgs]; int i, j, n, ok; lock(&ciphLock); if(nciphers){ unlock(&ciphLock); return nciphers; } j = open("#a/tls/encalgs", OREAD); if(j < 0){ werrstr("can't open #a/tls/encalgs: %r"); return 0; } n = read(j, s, MaxAlgF-1); close(j); if(n <= 0){ werrstr("nothing in #a/tls/encalgs: %r"); return 0; } s[n] = 0; n = getfields(s, flds, MaxAlgs, 1, " \t\r\n"); for(i = 0; i < nelem(cipherAlgs); i++){ ok = 0; for(j = 0; j < n; j++){ if(strcmp(cipherAlgs[i].enc, flds[j]) == 0){ ok = 1; break; } } cipherAlgs[i].ok = ok; } j = open("#a/tls/hashalgs", OREAD); if(j < 0){ werrstr("can't open #a/tls/hashalgs: %r"); return 0; } n = read(j, s, MaxAlgF-1); close(j); if(n <= 0){ werrstr("nothing in #a/tls/hashalgs: %r"); return 0; } s[n] = 0; n = getfields(s, flds, MaxAlgs, 1, " \t\r\n"); for(i = 0; i < nelem(cipherAlgs); i++){ ok = 0; for(j = 0; j < n; j++){ if(strcmp(cipherAlgs[i].digest, flds[j]) == 0){ ok = 1; break; } } cipherAlgs[i].ok &= ok; if(cipherAlgs[i].ok) nciphers++; } unlock(&ciphLock); return nciphers; } static Ints* makeciphers(void) { Ints *is; int i, j; is = newints(nciphers); j = 0; for(i = 0; i < nelem(cipherAlgs); i++){ if(cipherAlgs[i].ok) is->data[j++] = cipherAlgs[i].tlsid; } return is; } //================= security functions ======================== // given X.509 certificate, set up connection to factotum // for using corresponding private key static AuthRpc* factotum_rsa_open(uchar *cert, int certlen) { int afd; char *s; mpint *pub = nil; RSApub *rsapub; AuthRpc *rpc; // start talking to factotum if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) return nil; if((rpc = auth_allocrpc(afd)) == nil){ close(afd); return nil; } s = "proto=rsa service=tls role=client"; if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){ factotum_rsa_close(rpc); return nil; } // roll factotum keyring around to match certificate rsapub = X509toRSApub(cert, certlen, nil, 0); while(1){ if(auth_rpc(rpc, "read", nil, 0) != ARok){ factotum_rsa_close(rpc); rpc = nil; goto done; } pub = strtomp(rpc->arg, nil, 16, nil); assert(pub != nil); if(mpcmp(pub,rsapub->n) == 0) break; } done: mpfree(pub); rsapubfree(rsapub); return rpc; } static mpint* factotum_rsa_decrypt(AuthRpc *rpc, mpint *cipher) { char *p; int rv; if((p = mptoa(cipher, 16, nil, 0)) == nil) return nil; rv = auth_rpc(rpc, "write", p, strlen(p)); free(p); if(rv != ARok || auth_rpc(rpc, "read", nil, 0) != ARok) return nil; mpfree(cipher); return strtomp(rpc->arg, nil, 16, nil); } static void factotum_rsa_close(AuthRpc*rpc) { if(!rpc) return; close(rpc->afd); auth_freerpc(rpc); } static void tlsPmd5(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed0, int nseed0, uchar *seed1, int nseed1) { uchar ai[MD5dlen], tmp[MD5dlen]; int i, n; MD5state *s; // generate a1 s = hmac_md5(label, nlabel, key, nkey, nil, nil); s = hmac_md5(seed0, nseed0, key, nkey, nil, s); hmac_md5(seed1, nseed1, key, nkey, ai, s); while(nbuf > 0) { s = hmac_md5(ai, MD5dlen, key, nkey, nil, nil); s = hmac_md5(label, nlabel, key, nkey, nil, s); s = hmac_md5(seed0, nseed0, key, nkey, nil, s); hmac_md5(seed1, nseed1, key, nkey, tmp, s); n = MD5dlen; if(n > nbuf) n = nbuf; for(i = 0; i < n; i++) buf[i] ^= tmp[i]; buf += n; nbuf -= n; hmac_md5(ai, MD5dlen, key, nkey, tmp, nil); memmove(ai, tmp, MD5dlen); } } static void tlsPsha1(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed0, int nseed0, uchar *seed1, int nseed1) { uchar ai[SHA1dlen], tmp[SHA1dlen]; int i, n; SHAstate *s; // generate a1 s = hmac_sha1(label, nlabel, key, nkey, nil, nil); s = hmac_sha1(seed0, nseed0, key, nkey, nil, s); hmac_sha1(seed1, nseed1, key, nkey, ai, s); while(nbuf > 0) { s = hmac_sha1(ai, SHA1dlen, key, nkey, nil, nil); s = hmac_sha1(label, nlabel, key, nkey, nil, s); s = hmac_sha1(seed0, nseed0, key, nkey, nil, s); hmac_sha1(seed1, nseed1, key, nkey, tmp, s); n = SHA1dlen; if(n > nbuf) n = nbuf; for(i = 0; i < n; i++) buf[i] ^= tmp[i]; buf += n; nbuf -= n; hmac_sha1(ai, SHA1dlen, key, nkey, tmp, nil); memmove(ai, tmp, SHA1dlen); } } // fill buf with md5(args)^sha1(args) static void tlsPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) { int i; int nlabel = strlen(label); int n = (nkey + 1) >> 1; for(i = 0; i < nbuf; i++) buf[i] = 0; tlsPmd5(buf, nbuf, key, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); tlsPsha1(buf, nbuf, key+nkey-n, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); } /* * for setting server session id's */ static Lock sidLock; static long maxSid = 1; /* the keys are verified to have the same public components * and to function correctly with pkcs 1 encryption and decryption. */ static TlsSec* tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uchar *ssid, int *nssid, uchar *srandom) { TlsSec *sec = emalloc(sizeof(*sec)); USED(csid); USED(ncsid); // ignore csid for now memmove(sec->crandom, crandom, RandomSize); sec->clientVers = cvers; put32(sec->srandom, time(0)); genrandom(sec->srandom+4, RandomSize-4); memmove(srandom, sec->srandom, RandomSize); /* * make up a unique sid: use our pid, and and incrementing id * can signal no sid by setting nssid to 0. */ memset(ssid, 0, SidSize); put32(ssid, getpid()); lock(&sidLock); put32(ssid+4, maxSid++); unlock(&sidLock); *nssid = SidSize; return sec; } static int tlsSecSecrets(TlsSec *sec, int vers, uchar *epm, int nepm, uchar *kd, int nkd) { if(epm != nil){ if(setVers(sec, vers) < 0) goto Err; serverMasterSecret(sec, epm, nepm); }else if(sec->vers != vers){ werrstr("mismatched session versions"); goto Err; } setSecrets(sec, kd, nkd); return 0; Err: sec->ok = -1; return -1; } static TlsSec* tlsSecInitc(int cvers, uchar *crandom) { TlsSec *sec = emalloc(sizeof(*sec)); sec->clientVers = cvers; put32(sec->crandom, time(0)); genrandom(sec->crandom+4, RandomSize-4); memmove(crandom, sec->crandom, RandomSize); return sec; } static int tlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd) { RSApub *pub; pub = nil; USED(sid); USED(nsid); memmove(sec->srandom, srandom, RandomSize); if(setVers(sec, vers) < 0) goto Err; pub = X509toRSApub(cert, ncert, nil, 0); if(pub == nil){ werrstr("invalid x509/rsa certificate"); goto Err; } if(clientMasterSecret(sec, pub, epm, nepm) < 0) goto Err; rsapubfree(pub); setSecrets(sec, kd, nkd); return 0; Err: if(pub != nil) rsapubfree(pub); sec->ok = -1; return -1; } static int tlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient) { if(sec->nfin != nfin){ sec->ok = -1; werrstr("invalid finished exchange"); return -1; } md5.malloced = 0; sha1.malloced = 0; (*sec->setFinished)(sec, md5, sha1, fin, isclient); return 1; } static void tlsSecOk(TlsSec *sec) { if(sec->ok == 0) sec->ok = 1; } static void tlsSecKill(TlsSec *sec) { if(!sec) return; factotum_rsa_close(sec->rpc); sec->ok = -1; } static void tlsSecClose(TlsSec *sec) { if(!sec) return; factotum_rsa_close(sec->rpc); free(sec->server); free(sec); } static int setVers(TlsSec *sec, int v) { if(v == SSL3Version){ sec->setFinished = sslSetFinished; sec->nfin = SSL3FinishedLen; sec->prf = sslPRF; }else if(v == TLSVersion){ sec->setFinished = tlsSetFinished; sec->nfin = TLSFinishedLen; sec->prf = tlsPRF; }else{ werrstr("invalid version"); return -1; } sec->vers = v; return 0; } /* * generate secret keys from the master secret. * * different crypto selections will require different amounts * of key expansion and use of key expansion data, * but it's all generated using the same function. */ static void setSecrets(TlsSec *sec, uchar *kd, int nkd) { (*sec->prf)(kd, nkd, sec->sec, MasterSecretSize, "key expansion", sec->srandom, RandomSize, sec->crandom, RandomSize); } /* * set the master secret from the pre-master secret. */ static void setMasterSecret(TlsSec *sec, Bytes *pm) { (*sec->prf)(sec->sec, MasterSecretSize, pm->data, MasterSecretSize, "master secret", sec->crandom, RandomSize, sec->srandom, RandomSize); } static void serverMasterSecret(TlsSec *sec, uchar *epm, int nepm) { Bytes *pm; pm = pkcs1_decrypt(sec, epm, nepm); // if the client messed up, just continue as if everything is ok, // to prevent attacks to check for correctly formatted messages. // Hence the fprint(2,) can't be replaced by tlsError(), which sends an Alert msg to the client. if(sec->ok < 0 || pm == nil || get16(pm->data) != sec->clientVers){ fprint(2, "serverMasterSecret failed ok=%d pm=%p pmvers=%x cvers=%x nepm=%d\n", sec->ok, pm, pm ? get16(pm->data) : -1, sec->clientVers, nepm); sec->ok = -1; if(pm != nil) freebytes(pm); pm = newbytes(MasterSecretSize); genrandom(pm->data, MasterSecretSize); } setMasterSecret(sec, pm); memset(pm->data, 0, pm->len); freebytes(pm); } static int clientMasterSecret(TlsSec *sec, RSApub *pub, uchar **epm, int *nepm) { Bytes *pm, *key; pm = newbytes(MasterSecretSize); put16(pm->data, sec->clientVers); genrandom(pm->data+2, MasterSecretSize - 2); setMasterSecret(sec, pm); key = pkcs1_encrypt(pm, pub, 2); memset(pm->data, 0, pm->len); freebytes(pm); if(key == nil){ werrstr("tls pkcs1_encrypt failed"); return -1; } *nepm = key->len; *epm = malloc(*nepm); if(*epm == nil){ freebytes(key); werrstr("out of memory"); return -1; } memmove(*epm, key->data, *nepm); freebytes(key); return 1; } static void sslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient) { DigestState *s; uchar h0[MD5dlen], h1[SHA1dlen], pad[48]; char *label; if(isClient) label = "CLNT"; else label = "SRVR"; md5((uchar*)label, 4, nil, &hsmd5); md5(sec->sec, MasterSecretSize, nil, &hsmd5); memset(pad, 0x36, 48); md5(pad, 48, nil, &hsmd5); md5(nil, 0, h0, &hsmd5); memset(pad, 0x5C, 48); s = md5(sec->sec, MasterSecretSize, nil, nil); s = md5(pad, 48, nil, s); md5(h0, MD5dlen, finished, s); sha1((uchar*)label, 4, nil, &hssha1); sha1(sec->sec, MasterSecretSize, nil, &hssha1); memset(pad, 0x36, 40); sha1(pad, 40, nil, &hssha1); sha1(nil, 0, h1, &hssha1); memset(pad, 0x5C, 40); s = sha1(sec->sec, MasterSecretSize, nil, nil); s = sha1(pad, 40, nil, s); sha1(h1, SHA1dlen, finished + MD5dlen, s); } // fill "finished" arg with md5(args)^sha1(args) static void tlsSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient) { uchar h0[MD5dlen], h1[SHA1dlen]; char *label; // get current hash value, but allow further messages to be hashed in md5(nil, 0, h0, &hsmd5); sha1(nil, 0, h1, &hssha1); if(isClient) label = "client finished"; else label = "server finished"; tlsPRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen); } static void sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) { DigestState *s; uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26]; int i, n, len; USED(label); len = 1; while(nbuf > 0){ if(len > 26) return; for(i = 0; i < len; i++) tmp[i] = 'A' - 1 + len; s = sha1(tmp, len, nil, nil); s = sha1(key, nkey, nil, s); s = sha1(seed0, nseed0, nil, s); sha1(seed1, nseed1, sha1dig, s); s = md5(key, nkey, nil, nil); md5(sha1dig, SHA1dlen, md5dig, s); n = MD5dlen; if(n > nbuf) n = nbuf; memmove(buf, md5dig, n); buf += n; nbuf -= n; len++; } } static mpint* bytestomp(Bytes* bytes) { mpint* ans; ans = betomp(bytes->data, bytes->len, nil); return ans; } /* * Convert mpint* to Bytes, putting high order byte first. */ static Bytes* mptobytes(mpint* big) { int n, m; uchar *a; Bytes* ans; n = (mpsignif(big)+7)/8; m = mptobe(big, nil, n, &a); ans = makebytes(a, m); return ans; } // Do RSA computation on block according to key, and pad // result on left with zeros to make it modlen long. static Bytes* rsacomp(Bytes* block, RSApub* key, int modlen) { mpint *x, *y; Bytes *a, *ybytes; int ylen; x = bytestomp(block); y = rsaencrypt(key, x, nil); mpfree(x); ybytes = mptobytes(y); ylen = ybytes->len; if(ylen < modlen) { a = newbytes(modlen); memset(a->data, 0, modlen-ylen); memmove(a->data+modlen-ylen, ybytes->data, ylen); freebytes(ybytes); ybytes = a; } else if(ylen > modlen) { // assume it has leading zeros (mod should make it so) a = newbytes(modlen); memmove(a->data, ybytes->data, modlen); freebytes(ybytes); ybytes = a; } mpfree(y); return ybytes; } // encrypt data according to PKCS#1, /lib/rfc/rfc2437 9.1.2.1 static Bytes* pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype) { Bytes *pad, *eb, *ans; int i, dlen, padlen, modlen; modlen = (mpsignif(key->n)+7)/8; dlen = data->len; if(modlen < 12 || dlen > modlen - 11) return nil; padlen = modlen - 3 - dlen; pad = newbytes(padlen); genrandom(pad->data, padlen); for(i = 0; i < padlen; i++) { if(blocktype == 0) pad->data[i] = 0; else if(blocktype == 1) pad->data[i] = 255; else if(pad->data[i] == 0) pad->data[i] = 1; } eb = newbytes(modlen); eb->data[0] = 0; eb->data[1] = blocktype; memmove(eb->data+2, pad->data, padlen); eb->data[padlen+2] = 0; memmove(eb->data+padlen+3, data->data, dlen); ans = rsacomp(eb, key, modlen); freebytes(eb); freebytes(pad); return ans; } // decrypt data according to PKCS#1, with given key. // expect a block type of 2. static Bytes* pkcs1_decrypt(TlsSec *sec, uchar *epm, int nepm) { Bytes *eb, *ans = nil; int i, modlen; mpint *x, *y; modlen = (mpsignif(sec->rsapub->n)+7)/8; if(nepm != modlen) return nil; x = betomp(epm, nepm, nil); y = factotum_rsa_decrypt(sec->rpc, x); if(y == nil) return nil; eb = mptobytes(y); if(eb->len < modlen){ // pad on left with zeros ans = newbytes(modlen); memset(ans->data, 0, modlen-eb->len); memmove(ans->data+modlen-eb->len, eb->data, eb->len); freebytes(eb); eb = ans; } if(eb->data[0] == 0 && eb->data[1] == 2) { for(i = 2; i < modlen; i++) if(eb->data[i] == 0) break; if(i < modlen - 1) ans = makebytes(eb->data+i+1, modlen-(i+1)); } freebytes(eb); return ans; } //================= general utility functions ======================== static void * emalloc(int n) { void *p; if(n==0) n=1; p = malloc(n); if(p == nil){ exits("out of memory"); } memset(p, 0, n); return p; } static void * erealloc(void *ReallocP, int ReallocN) { if(ReallocN == 0) ReallocN = 1; if(!ReallocP) ReallocP = emalloc(ReallocN); else if(!(ReallocP = realloc(ReallocP, ReallocN))){ exits("out of memory"); } return(ReallocP); } static void put32(uchar *p, u32int x) { p[0] = x>>24; p[1] = x>>16; p[2] = x>>8; p[3] = x; } static void put24(uchar *p, int x) { p[0] = x>>16; p[1] = x>>8; p[2] = x; } static void put16(uchar *p, int x) { p[0] = x>>8; p[1] = x; } static u32int get32(uchar *p) { return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; } static int get24(uchar *p) { return (p[0]<<16)|(p[1]<<8)|p[2]; } static int get16(uchar *p) { return (p[0]<<8)|p[1]; } /* ANSI offsetof() */ #define OFFSET(x, s) ((int)(&(((s*)0)->x))) /* * malloc and return a new Bytes structure capable of * holding len bytes. (len >= 0) * Used to use crypt_malloc, which aborts if malloc fails. */ static Bytes* newbytes(int len) { Bytes* ans; ans = (Bytes*)malloc(OFFSET(data[0], Bytes) + len); ans->len = len; return ans; } /* * newbytes(len), with data initialized from buf */ static Bytes* makebytes(uchar* buf, int len) { Bytes* ans; ans = newbytes(len); memmove(ans->data, buf, len); return ans; } static void freebytes(Bytes* b) { if(b != nil) free(b); } /* len is number of ints */ static Ints* newints(int len) { Ints* ans; ans = (Ints*)malloc(OFFSET(data[0], Ints) + len*sizeof(int)); ans->len = len; return ans; } static Ints* makeints(int* buf, int len) { Ints* ans; ans = newints(len); if(len > 0) memmove(ans->data, buf, len*sizeof(int)); return ans; } static void freeints(Ints* b) { if(b != nil) free(b); } drawterm-20110822.orig/libsec/decodepem.c0000644000175000017500000000253311245145712017430 0ustar tinchotincho#include #include #include #include #define STRLEN(s) (sizeof(s)-1) uchar* decodepem(char *s, char *type, int *len) { uchar *d; char *t, *e, *tt; int n; /* * find the correct section of the file, stripping garbage at the beginning and end. * the data is delimited by -----BEGIN -----\n and -----END -----\n */ n = strlen(type); e = strchr(s, '\0'); for(t = s; t != nil && t < e; ){ tt = t; t = strchr(tt, '\n'); if(t != nil) t++; if(strncmp(tt, "-----BEGIN ", STRLEN("-----BEGIN ")) == 0 && strncmp(&tt[STRLEN("-----BEGIN ")], type, n) == 0 && strncmp(&tt[STRLEN("-----BEGIN ")+n], "-----\n", STRLEN("-----\n")) == 0) break; } for(tt = t; tt != nil && tt < e; tt++){ if(strncmp(tt, "-----END ", STRLEN("-----END ")) == 0 && strncmp(&tt[STRLEN("-----END ")], type, n) == 0 && strncmp(&tt[STRLEN("-----END ")+n], "-----\n", STRLEN("-----\n")) == 0) break; tt = strchr(tt, '\n'); if(tt == nil) break; } if(tt == nil || tt == e){ werrstr("incorrect .pem file format: bad header or trailer"); return nil; } n = ((tt - t) * 6 + 7) / 8; d = malloc(n); if(d == nil){ werrstr("out of memory"); return nil; } n = dec64(d, n, t, tt - t); if(n < 0){ free(d); werrstr("incorrect .pem file format: bad base64 encoded data"); return nil; } *len = n; return d; } drawterm-20110822.orig/libsec/des3CBC.c0000644000175000017500000000215711245145712016653 0ustar tinchotincho#include "os.h" #include #include // Because of the way that non multiple of 8 // buffers are handled, the decryptor must // be fed buffers of the same size as the // encryptor // If the length is not a multiple of 8, I encrypt // the overflow to be compatible with lacy's cryptlib void des3CBCencrypt(uchar *p, int len, DES3state *s) { uchar *p2, *ip, *eip; for(; len >= 8; len -= 8){ p2 = p; ip = s->ivec; for(eip = ip+8; ip < eip; ) *p2++ ^= *ip++; triple_block_cipher(s->expanded, p, DES3EDE); memmove(s->ivec, p, 8); p += 8; } if(len > 0){ ip = s->ivec; triple_block_cipher(s->expanded, ip, DES3EDE); for(eip = ip+len; ip < eip; ) *p++ ^= *ip++; } } void des3CBCdecrypt(uchar *p, int len, DES3state *s) { uchar *ip, *eip, *tp; uchar tmp[8]; for(; len >= 8; len -= 8){ memmove(tmp, p, 8); triple_block_cipher(s->expanded, p, DES3DED); tp = tmp; ip = s->ivec; for(eip = ip+8; ip < eip; ){ *p++ ^= *ip; *ip++ = *tp++; } } if(len > 0){ ip = s->ivec; triple_block_cipher(s->expanded, ip, DES3EDE); for(eip = ip+len; ip < eip; ) *p++ ^= *ip++; } } drawterm-20110822.orig/libsec/dsaprivtopub.c0000644000175000017500000000042711245145712020225 0ustar tinchotincho#include "os.h" #include #include DSApub* dsaprivtopub(DSApriv *priv) { DSApub *pub; pub = dsapuballoc(); pub->p = mpcopy(priv->pub.p); pub->q = mpcopy(priv->pub.q); pub->alpha = mpcopy(priv->pub.alpha); pub->key = mpcopy(priv->pub.key); return pub; } drawterm-20110822.orig/libsec/dsagen.c0000644000175000017500000000232511245145712016743 0ustar tinchotincho#include "os.h" #include #include DSApriv* dsagen(DSApub *opub) { DSApub *pub; DSApriv *priv; mpint *exp; mpint *g; mpint *r; int bits; priv = dsaprivalloc(); pub = &priv->pub; if(opub != nil){ pub->p = mpcopy(opub->p); pub->q = mpcopy(opub->q); } else { pub->p = mpnew(0); pub->q = mpnew(0); DSAprimes(pub->q, pub->p, nil); } bits = Dbits*pub->p->top; pub->alpha = mpnew(0); pub->key = mpnew(0); priv->secret = mpnew(0); // find a generator alpha of the multiplicative // group Z*p, i.e., of order n = p-1. We use the // fact that q divides p-1 to reduce the exponent. // // This isn't very efficient. If anyone has a better // idea, mail presotto@closedmind.org exp = mpnew(0); g = mpnew(0); r = mpnew(0); mpsub(pub->p, mpone, exp); mpdiv(exp, pub->q, exp, r); if(mpcmp(r, mpzero) != 0) sysfatal("dsagen foul up"); while(1){ mprand(bits, genrandom, g); mpmod(g, pub->p, g); mpexp(g, exp, pub->p, pub->alpha); if(mpcmp(pub->alpha, mpone) != 0) break; } mpfree(g); mpfree(exp); // create the secret key mprand(bits, genrandom, priv->secret); mpmod(priv->secret, pub->p, priv->secret); mpexp(pub->alpha, priv->secret, pub->p, pub->key); return priv; } drawterm-20110822.orig/libsec/sha1.c0000644000175000017500000000434711245145712016344 0ustar tinchotincho#include "os.h" #include static void encode(uchar*, u32int*, ulong); extern void _sha1block(uchar*, ulong, u32int*); /* * we require len to be a multiple of 64 for all but * the last call. There must be room in the input buffer * to pad. */ SHA1state* sha1(uchar *p, ulong len, uchar *digest, SHA1state *s) { uchar buf[128]; u32int x[16]; int i; uchar *e; if(s == nil){ s = malloc(sizeof(*s)); if(s == nil) return nil; memset(s, 0, sizeof(*s)); s->malloced = 1; } if(s->seeded == 0){ /* seed the state, these constants would look nicer big-endian */ s->state[0] = 0x67452301; s->state[1] = 0xefcdab89; s->state[2] = 0x98badcfe; s->state[3] = 0x10325476; s->state[4] = 0xc3d2e1f0; s->seeded = 1; } /* fill out the partial 64 byte block from previous calls */ if(s->blen){ i = 64 - s->blen; if(len < i) i = len; memmove(s->buf + s->blen, p, i); len -= i; s->blen += i; p += i; if(s->blen == 64){ _sha1block(s->buf, s->blen, s->state); s->len += s->blen; s->blen = 0; } } /* do 64 byte blocks */ i = len & ~0x3f; if(i){ _sha1block(p, i, s->state); s->len += i; len -= i; p += i; } /* save the left overs if not last call */ if(digest == 0){ if(len){ memmove(s->buf, p, len); s->blen += len; } return s; } /* * this is the last time through, pad what's left with 0x80, * 0's, and the input count to create a multiple of 64 bytes */ if(s->blen){ p = s->buf; len = s->blen; } else { memmove(buf, p, len); p = buf; } s->len += len; e = p + len; if(len < 56) i = 56 - len; else i = 120 - len; memset(e, 0, i); *e = 0x80; len += i; /* append the count */ x[0] = s->len>>29; x[1] = s->len<<3; encode(p+len, x, 8); /* digest the last part */ _sha1block(p, len+8, s->state); s->len += len+8; /* return result and free state */ encode(digest, s->state, SHA1dlen); if(s->malloced == 1) free(s); return nil; } /* * encodes input (ulong) into output (uchar). Assumes len is * a multiple of 4. */ static void encode(uchar *output, u32int *input, ulong len) { u32int x; uchar *e; for(e = output + len; output < e;) { x = *input++; *output++ = x >> 24; *output++ = x >> 16; *output++ = x >> 8; *output++ = x; } } drawterm-20110822.orig/libsec/hmactest.c0000644000175000017500000000053011245145712017306 0ustar tinchotincho#include "os.h" #include #include uchar key[] = "Jefe"; uchar data[] = "what do ya want for nothing?"; void main(void) { int i; uchar hash[MD5dlen]; hmac_md5(data, strlen((char*)data), key, 4, hash, nil); for(i=0; i void setupRC4state(RC4state *key, uchar *start, int n) { int t; int index2; uchar *state; uchar *p, *e, *sp, *se; state = key->state; se = &state[256]; for(sp = state; sp < se; sp++) *sp = sp - state; key->x = 0; key->y = 0; index2 = 0; e = start + n; p = start; for(sp = state; sp < se; sp++) { t = *sp; index2 = (*p + t + index2) & 255; *sp = state[index2]; state[index2] = t; if(++p >= e) p = start; } } void rc4(RC4state *key, uchar *p, int len) { int tx, ty; int x, y; uchar *state; uchar *e; x = key->x; y = key->y; state = &key->state[0]; for(e = p + len; p < e; p++) { x = (x+1)&255; tx = state[x]; y = (y+tx)&255; ty = state[y]; state[x] = ty; state[y] = tx; *p ^= state[(tx+ty)&255]; } key->x = x; key->y = y; } void rc4skip(RC4state *key, int len) { int tx, ty; int x, y; uchar *state; int i; x = key->x; y = key->y; state = &key->state[0]; for(i=0; ix = x; key->y = y; } void rc4back(RC4state *key, int len) { int tx, ty; int x, y; uchar *state; int i; x = key->x; y = key->y; state = &key->state[0]; for(i=0; ix = x; key->y = y; } drawterm-20110822.orig/libsec/egverify.c0000644000175000017500000000100711245145712017316 0ustar tinchotincho#include "os.h" #include #include int egverify(EGpub *pub, EGsig *sig, mpint *m) { mpint *p = pub->p, *alpha = pub->alpha; mpint *r = sig->r, *s = sig->s; mpint *v1, *v2, *rs; int rv = -1; if(mpcmp(r, mpone) < 0 || mpcmp(r, p) >= 0) return rv; v1 = mpnew(0); rs = mpnew(0); v2 = mpnew(0); mpexp(pub->key, r, p, v1); mpexp(r, s, p, rs); mpmul(v1, rs, v1); mpmod(v1, p, v1); mpexp(alpha, m, p, v2); if(mpcmp(v1, v2) == 0) rv = 0; mpfree(v1); mpfree(rs); mpfree(v2); return rv; } drawterm-20110822.orig/libsec/prng.c0000644000175000017500000000027311245145712016450 0ustar tinchotincho#include "os.h" #include #include // // just use the libc prng to fill a buffer // void prng(uchar *p, int n) { uchar *e; for(e = p+n; p < e; p++) *p = rand(); } drawterm-20110822.orig/libsec/readcert.c0000644000175000017500000000136711245145712017300 0ustar tinchotincho#include #include #include #include static char* readfile(char *name) { int fd; char *s; Dir *d; fd = open(name, OREAD); if(fd < 0) return nil; if((d = dirfstat(fd)) == nil) return nil; s = malloc(d->length + 1); if(s == nil || readn(fd, s, d->length) != d->length){ free(s); free(d); close(fd); return nil; } close(fd); s[d->length] = '\0'; free(d); return s; } uchar* readcert(char *filename, int *pcertlen) { char *pem; uchar *binary; pem = readfile(filename); if(pem == nil){ werrstr("can't read %s", filename); return nil; } binary = decodepem(pem, "CERTIFICATE", pcertlen); free(pem); if(binary == nil){ werrstr("can't parse %s", filename); return nil; } return binary; } drawterm-20110822.orig/libsec/fastrand.c0000644000175000017500000000040211245145712017276 0ustar tinchotincho#include #include #include /* * use the X917 random number generator to create random * numbers (faster than truerand() but not as random). */ ulong fastrand(void) { ulong x; genrandom((uchar*)&x, sizeof x); return x; } drawterm-20110822.orig/libsec/md4test.c0000644000175000017500000000103111245145712017057 0ustar tinchotincho#include "os.h" #include #include char *tests[] = { "", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 0 }; void main(void) { char **pp; uchar *p; int i; uchar digest[MD5dlen]; for(pp = tests; *pp; pp++){ p = (uchar*)*pp; md4(p, strlen(*pp), digest, 0); for(i = 0; i < MD5dlen; i++) print("%2.2ux", digest[i]); print("\n"); } } drawterm-20110822.orig/README0000644000175000017500000000207211245146573014762 0ustar tinchotinchoINSTALLATION -------------- To build on Unix, run CONF=unix make. To build on Solaris using Sun cc, run CONF=sun make. To build on Windows, you need Mingw. See http://www.mingw.org. Edit Make.config to uncomment the Windows section and comment out the rest. Then run CONF=windows make. (You can download nmake from http://support.microsoft.com/default.aspx?scid=kb;en-us;Q132084 Rename it to make.exe and put it in your path somewhere. ) I haven't tested the Windows build on Windows itself. I cross-compile using mingw32 on Linux. BINARIES --------- See http://swtch.com/drawterm/ SOURCE ------ Use Mercurial: hg clone http://code.swtch.com/drawterm On the web at http://code.swtch.com/drawterm Tar file at http://swtch.com/drawterm/ In the Plan 9 distribution: /sys/src/cmd/unix/drawterm/ (sometimes out of date) HELP ---- Issue tracker: http://code.swtch.com/drawterm/issues TO DO: ------ - Should import latest /dev/draw to allow resize of window - Should copy 9term code and make console window a real 9term window instead. - Should implement /dev/label. drawterm-20110822.orig/libdraw/0000755000175000017500000000000011245145712015517 5ustar tinchotinchodrawterm-20110822.orig/libdraw/rectclip.c0000644000175000017500000000107311245145712017471 0ustar tinchotincho#include #include #include int rectclip(Rectangle *rp, Rectangle b) /* first by reference, second by value */ { Rectangle *bp = &b; /* * Expand rectXrect() in line for speed */ if((rp->min.xmax.x && bp->min.xmax.x && rp->min.ymax.y && bp->min.ymax.y)==0) return 0; /* They must overlap */ if(rp->min.x < bp->min.x) rp->min.x = bp->min.x; if(rp->min.y < bp->min.y) rp->min.y = bp->min.y; if(rp->max.x > bp->max.x) rp->max.x = bp->max.x; if(rp->max.y > bp->max.y) rp->max.y = bp->max.y; return 1; } drawterm-20110822.orig/libdraw/icossin2.c0000644000175000017500000001075311245145712017422 0ustar tinchotincho#include #include #include /* * Sine and Cosine of arctangents, calculated by * (sin(atan(index/100.0))*1024.+0.5) * (cos(atan(index/100.0))*1024.+0.5) * To use, get rational tangent between 0<=tan<=1, scale by 100, * and look up sin and cos, and use linear interpolation. divide by 1024. * Maximum error is 0.0020. Without linear interpolation, it's 0.010. */ static short sinus[] = { 0, /* 0.00 */ 10, /* 0.01 */ 20, /* 0.02 */ 31, /* 0.03 */ 41, /* 0.04 */ 51, /* 0.05 */ 61, /* 0.06 */ 72, /* 0.07 */ 82, /* 0.08 */ 92, /* 0.09 */ 102, /* 0.10 */ 112, /* 0.11 */ 122, /* 0.12 */ 132, /* 0.13 */ 142, /* 0.14 */ 152, /* 0.15 */ 162, /* 0.16 */ 172, /* 0.17 */ 181, /* 0.18 */ 191, /* 0.19 */ 201, /* 0.20 */ 210, /* 0.21 */ 220, /* 0.22 */ 230, /* 0.23 */ 239, /* 0.24 */ 248, /* 0.25 */ 258, /* 0.26 */ 267, /* 0.27 */ 276, /* 0.28 */ 285, /* 0.29 */ 294, /* 0.30 */ 303, /* 0.31 */ 312, /* 0.32 */ 321, /* 0.33 */ 330, /* 0.34 */ 338, /* 0.35 */ 347, /* 0.36 */ 355, /* 0.37 */ 364, /* 0.38 */ 372, /* 0.39 */ 380, /* 0.40 */ 388, /* 0.41 */ 397, /* 0.42 */ 405, /* 0.43 */ 412, /* 0.44 */ 420, /* 0.45 */ 428, /* 0.46 */ 436, /* 0.47 */ 443, /* 0.48 */ 451, /* 0.49 */ 458, /* 0.50 */ 465, /* 0.51 */ 472, /* 0.52 */ 480, /* 0.53 */ 487, /* 0.54 */ 493, /* 0.55 */ 500, /* 0.56 */ 507, /* 0.57 */ 514, /* 0.58 */ 520, /* 0.59 */ 527, /* 0.60 */ 533, /* 0.61 */ 540, /* 0.62 */ 546, /* 0.63 */ 552, /* 0.64 */ 558, /* 0.65 */ 564, /* 0.66 */ 570, /* 0.67 */ 576, /* 0.68 */ 582, /* 0.69 */ 587, /* 0.70 */ 593, /* 0.71 */ 598, /* 0.72 */ 604, /* 0.73 */ 609, /* 0.74 */ 614, /* 0.75 */ 620, /* 0.76 */ 625, /* 0.77 */ 630, /* 0.78 */ 635, /* 0.79 */ 640, /* 0.80 */ 645, /* 0.81 */ 649, /* 0.82 */ 654, /* 0.83 */ 659, /* 0.84 */ 663, /* 0.85 */ 668, /* 0.86 */ 672, /* 0.87 */ 676, /* 0.88 */ 681, /* 0.89 */ 685, /* 0.90 */ 689, /* 0.91 */ 693, /* 0.92 */ 697, /* 0.93 */ 701, /* 0.94 */ 705, /* 0.95 */ 709, /* 0.96 */ 713, /* 0.97 */ 717, /* 0.98 */ 720, /* 0.99 */ 724, /* 1.00 */ 728, /* 1.01 */ }; static short cosinus[] = { 1024, /* 0.00 */ 1024, /* 0.01 */ 1024, /* 0.02 */ 1024, /* 0.03 */ 1023, /* 0.04 */ 1023, /* 0.05 */ 1022, /* 0.06 */ 1022, /* 0.07 */ 1021, /* 0.08 */ 1020, /* 0.09 */ 1019, /* 0.10 */ 1018, /* 0.11 */ 1017, /* 0.12 */ 1015, /* 0.13 */ 1014, /* 0.14 */ 1013, /* 0.15 */ 1011, /* 0.16 */ 1010, /* 0.17 */ 1008, /* 0.18 */ 1006, /* 0.19 */ 1004, /* 0.20 */ 1002, /* 0.21 */ 1000, /* 0.22 */ 998, /* 0.23 */ 996, /* 0.24 */ 993, /* 0.25 */ 991, /* 0.26 */ 989, /* 0.27 */ 986, /* 0.28 */ 983, /* 0.29 */ 981, /* 0.30 */ 978, /* 0.31 */ 975, /* 0.32 */ 972, /* 0.33 */ 969, /* 0.34 */ 967, /* 0.35 */ 963, /* 0.36 */ 960, /* 0.37 */ 957, /* 0.38 */ 954, /* 0.39 */ 951, /* 0.40 */ 947, /* 0.41 */ 944, /* 0.42 */ 941, /* 0.43 */ 937, /* 0.44 */ 934, /* 0.45 */ 930, /* 0.46 */ 927, /* 0.47 */ 923, /* 0.48 */ 920, /* 0.49 */ 916, /* 0.50 */ 912, /* 0.51 */ 909, /* 0.52 */ 905, /* 0.53 */ 901, /* 0.54 */ 897, /* 0.55 */ 893, /* 0.56 */ 890, /* 0.57 */ 886, /* 0.58 */ 882, /* 0.59 */ 878, /* 0.60 */ 874, /* 0.61 */ 870, /* 0.62 */ 866, /* 0.63 */ 862, /* 0.64 */ 859, /* 0.65 */ 855, /* 0.66 */ 851, /* 0.67 */ 847, /* 0.68 */ 843, /* 0.69 */ 839, /* 0.70 */ 835, /* 0.71 */ 831, /* 0.72 */ 827, /* 0.73 */ 823, /* 0.74 */ 819, /* 0.75 */ 815, /* 0.76 */ 811, /* 0.77 */ 807, /* 0.78 */ 804, /* 0.79 */ 800, /* 0.80 */ 796, /* 0.81 */ 792, /* 0.82 */ 788, /* 0.83 */ 784, /* 0.84 */ 780, /* 0.85 */ 776, /* 0.86 */ 773, /* 0.87 */ 769, /* 0.88 */ 765, /* 0.89 */ 761, /* 0.90 */ 757, /* 0.91 */ 754, /* 0.92 */ 750, /* 0.93 */ 746, /* 0.94 */ 742, /* 0.95 */ 739, /* 0.96 */ 735, /* 0.97 */ 731, /* 0.98 */ 728, /* 0.99 */ 724, /* 1.00 */ 720, /* 1.01 */ }; void icossin2(int x, int y, int *cosp, int *sinp) { int sinsign, cossign, tan, tan10, rem; short *stp, *ctp; if(x == 0){ if(y >= 0) *sinp = ICOSSCALE, *cosp = 0; else *sinp = -ICOSSCALE, *cosp = 0; return; } sinsign = cossign = 1; if(x < 0){ cossign = -1; x = -x; } if(y < 0){ sinsign = -1; y = -y; } if(y > x){ tan = 1000*x/y; tan10 = tan/10; stp = &cosinus[tan10]; ctp = &sinus[tan10]; }else{ tan = 1000*y/x; tan10 = tan/10; stp = &sinus[tan10]; ctp = &cosinus[tan10]; } rem = tan-(tan10*10); *sinp = sinsign*(stp[0]+(stp[1]-stp[0])*rem/10); *cosp = cossign*(ctp[0]+(ctp[1]-ctp[0])*rem/10); } drawterm-20110822.orig/libdraw/chan.c0000644000175000017500000000217711245145712016603 0ustar tinchotincho#include #include #include static char channames[] = "rgbkamx"; char* chantostr(char *buf, ulong cc) { ulong c, rc; char *p; if(chantodepth(cc) == 0) return nil; /* reverse the channel descriptor so we can easily generate the string in the right order */ rc = 0; for(c=cc; c; c>>=8){ rc <<= 8; rc |= c&0xFF; } p = buf; for(c=rc; c; c>>=8) { *p++ = channames[TYPE(c)]; *p++ = '0'+NBITS(c); } *p = 0; return buf; } /* avoid pulling in ctype when using with drawterm etc. */ static int xisspace(char c) { return c==' ' || c== '\t' || c=='\r' || c=='\n'; } ulong strtochan(char *s) { char *p, *q; ulong c; int t, n; c = 0; p=s; while(*p && xisspace(*p)) p++; while(*p && !xisspace(*p)){ if((q = strchr(channames, p[0])) == nil) return 0; t = q-channames; if(p[1] < '0' || p[1] > '9') return 0; n = p[1]-'0'; c = (c<<8) | __DC(t, n); p += 2; } return c; } int chantodepth(ulong c) { int n; for(n=0; c; c>>=8){ if(TYPE(c) >= NChan || NBITS(c) > 8 || NBITS(c) <= 0) return 0; n += NBITS(c); } if(n==0 || (n>8 && n%8) || (n<8 && 8%n)) return 0; return n; } drawterm-20110822.orig/libdraw/defont.c0000644000175000017500000007351111245145712017151 0ustar tinchotincho#include #include #include /* * lucm/latin1.9, in uncompressed form */ uchar defontdata[] = { 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x32,0x33,0x30,0x34,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x35,0x20,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x30,0x06,0x06,0x03,0x42,0x40,0x00,0x00,0x00,0x18,0x03,0x03, 0x02,0x43,0x00,0x60,0x60,0x48,0x00,0x0d,0x0c,0x01,0x81,0x80,0xd0,0x90,0x00,0x00, 0x18,0x01,0x81,0x81,0x40,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x7f,0x9c,0x1c, 0x0e,0x07,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x70, 0x38,0x1c,0x0e,0x04,0x81,0xc1,0xc0,0x70,0x00,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x80,0xc0,0x63,0xe3, 0xf1,0xf8,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x7f,0xff,0xff,0x1f,0x8f, 0xc7,0xe3,0xf1,0xfb,0x7e,0x3e,0x3f,0x8f,0xff,0xe3,0xe3,0xff,0xff,0xff,0xff,0xff, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x0c,0x18,0x09,0x05,0x82,0x40,0xc0,0x00,0x00,0x06,0x0c,0x04, 0x82,0x40,0xc1,0x80,0x90,0x48,0x00,0x16,0x03,0x06,0x02,0x41,0x60,0x90,0x00,0x00, 0x06,0x06,0x02,0x41,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x7f,0xa0,0x10, 0x08,0x04,0x02,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x48, 0x24,0x12,0x09,0x06,0x82,0x01,0x00,0x90,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x04,0x80,0x00,0x40,0x00,0x00,0x38,0x06,0x18,0x00,0x00,0x00,0x00,0x00, 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x07,0xc6,0x01,0xf0,0x00,0x00,0x0c,0x00,0x18,0x00,0x00,0x30,0x00,0x3c, 0x00,0x60,0x06,0x01,0x8c,0x07,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xe0,0xc3,0xc0,0x01,0x54,0x9c,0xc0,0x5f,0xef, 0xf7,0xfb,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0x7f,0xff,0xff,0x6f,0xb7, 0xdb,0xed,0xf6,0xf9,0x7d,0xfe,0xff,0x6f,0xff,0xdf,0xef,0xff,0xff,0xff,0xff,0xff, 0xff,0x00,0x01,0x00,0x00,0x00,0x00,0x30,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x30,0x06,0x06,0x06,0x82,0x80,0xc0,0x00, 0x00,0x18,0x03,0x03,0x02,0x41,0x80,0x30,0x30,0x24,0x76,0x0d,0x0c,0x00,0xc0,0xc0, 0xd0,0x50,0x00,0x00,0x18,0x01,0x81,0x81,0x40,0x30,0x00,0x28,0x0f,0x7f,0xbc,0x1c, 0x0e,0x07,0x03,0xc0,0x10,0x70,0x24,0x10,0x09,0x07,0x03,0x80,0xe0,0x70,0x90,0x48, 0x24,0x12,0x09,0x05,0x81,0x81,0xc0,0x80,0x70,0x18,0x1c,0x07,0x01,0xc1,0xc0,0x90, 0x00,0x0c,0x04,0x84,0x83,0xe1,0xc0,0xe0,0x38,0x0c,0x0c,0x02,0x00,0x00,0x00,0x00, 0x00,0x06,0x1c,0x06,0x0f,0x87,0xc0,0x63,0xf8,0x78,0xfe,0x3e,0x0e,0x00,0x00,0x00, 0x00,0x00,0x00,0x7c,0x1c,0x0c,0x1f,0x03,0xc7,0xc3,0xf1,0xf8,0x3c,0x63,0x3f,0x0f, 0x8c,0x66,0x06,0x19,0x84,0x78,0x7e,0x1e,0x1f,0x07,0xcf,0xf3,0x1b,0x0d,0x86,0x63, 0x61,0x9f,0xc6,0x06,0x00,0x30,0x00,0x00,0x10,0x00,0x18,0x00,0x00,0x30,0x00,0x60, 0x00,0x60,0x06,0x01,0x8c,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xc0,0x60,0x00,0xaa,0xb6,0xc0,0x43,0xe3, 0xf1,0xf8,0xfc,0x3f,0xef,0x8f,0xdb,0xef,0xf6,0xf8,0xfb,0xff,0x1f,0x8f,0x6f,0xb7, 0xdb,0xed,0xf6,0xfa,0x7e,0x7e,0x3f,0x7f,0x8f,0xe7,0xe3,0xf8,0xfe,0x3e,0x3f,0x6f, 0x00,0x00,0x01,0x01,0xc8,0x0b,0x0c,0x30,0x7c,0x14,0x0f,0x0f,0x00,0x00,0x00,0x00, 0x78,0x00,0x1c,0x00,0x0f,0x07,0x81,0x80,0x00,0x7c,0x00,0x00,0x1c,0x0f,0x80,0x04, 0x42,0x23,0x90,0x00,0x18,0x0c,0x06,0x03,0x01,0x80,0xc0,0x3c,0x3c,0x3f,0x1f,0x8f, 0xc7,0xe7,0xe3,0xf1,0xf8,0xfc,0x7c,0x30,0x8f,0x07,0x83,0xc1,0xe0,0xf0,0x00,0x3d, 0x31,0x98,0xcc,0x66,0x36,0x19,0x80,0xcc,0x0c,0x18,0x09,0x0b,0x02,0x81,0x20,0x00, 0x00,0x06,0x0c,0x04,0x82,0x40,0x60,0xc0,0x48,0x24,0x18,0x16,0x03,0x03,0x01,0x21, 0x60,0x50,0x00,0x00,0x06,0x06,0x02,0x41,0x40,0xc1,0x80,0x28,0x87,0x7f,0x84,0x10, 0x08,0x04,0x02,0x40,0x38,0x48,0x24,0x10,0x09,0x04,0x04,0x81,0x00,0x80,0x90,0x48, 0x24,0x12,0x09,0x04,0x80,0x41,0x00,0x80,0x40,0x04,0x10,0x04,0x02,0x01,0x20,0x90, 0x00,0x0c,0x04,0x84,0x86,0x53,0x65,0xb0,0x08,0x18,0x06,0x0a,0x80,0x00,0x00,0x00, 0x00,0x0c,0x36,0x0e,0x19,0xcc,0xe0,0xe3,0xf8,0xcc,0xfe,0x63,0x1b,0x00,0x00,0x00, 0x00,0x00,0x00,0xc6,0x62,0x0c,0x19,0x86,0x66,0x63,0x01,0x80,0x66,0x63,0x0c,0x01, 0x8c,0xc6,0x06,0x19,0xc4,0xcc,0x63,0x33,0x19,0x8c,0x61,0x83,0x1b,0x0d,0x86,0x63, 0x61,0x80,0xc6,0x03,0x00,0x30,0x30,0x00,0x1c,0x00,0x18,0x00,0x00,0x30,0x00,0x60, 0x00,0x60,0x00,0x00,0x0c,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0xc0,0x60,0x01,0x54,0x86,0xc0,0x7b,0xef, 0xf7,0xfb,0xfd,0xbf,0xc7,0xb7,0xdb,0xef,0xf6,0xfb,0xfb,0x7e,0xff,0x7f,0x6f,0xb7, 0xdb,0xed,0xf6,0xfb,0x7f,0xbe,0xff,0x7f,0xbf,0xfb,0xef,0xfb,0xfd,0xfe,0xdf,0x6f, 0xff,0x00,0x07,0x83,0x24,0x13,0x0c,0x30,0xc6,0x00,0x10,0x81,0x80,0x00,0x00,0x00, 0x84,0x00,0x22,0x00,0x01,0x80,0xc0,0x00,0x00,0xf4,0x00,0x00,0x2c,0x18,0xc0,0x0c, 0x46,0x20,0x90,0x00,0x18,0x0c,0x06,0x03,0x01,0x80,0xc0,0x70,0x66,0x30,0x18,0x0c, 0x06,0x01,0x80,0xc0,0x60,0x30,0x66,0x38,0x99,0x8c,0xc6,0x63,0x31,0x98,0x00,0x66, 0x31,0x98,0xcc,0x66,0x36,0x19,0x80,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0xff,0x7f,0xb8,0x1c, 0x0e,0x07,0x02,0x40,0x7c,0x70,0x3c,0x10,0x09,0x07,0x04,0x00,0xc0,0x60,0xe0,0x70, 0x38,0x1c,0x0e,0x04,0x83,0x81,0xc0,0x70,0x70,0x38,0x1c,0x07,0x02,0xc1,0xc0,0x90, 0x00,0x0c,0x00,0x04,0x86,0x43,0x69,0xb0,0x30,0x18,0x06,0x07,0x01,0x00,0x00,0x00, 0x00,0x0c,0x63,0x16,0x00,0xc0,0x61,0x62,0x01,0x80,0x06,0x63,0x31,0x80,0x00,0x00, 0x60,0x00,0xc0,0x06,0x43,0x16,0x19,0x8c,0x06,0x33,0x01,0x80,0xc0,0x63,0x0c,0x01, 0x8c,0x86,0x07,0x39,0xc5,0x86,0x63,0x61,0x99,0x8c,0x01,0x83,0x1b,0x0d,0xb6,0x63, 0x31,0x01,0x86,0x03,0x00,0x30,0x30,0x00,0x1c,0x3e,0x1b,0x03,0xc1,0xf0,0xf0,0x60, 0x3e,0x6e,0x3e,0x0f,0x8c,0x60,0xc5,0xb1,0xb8,0x38,0x6c,0x0f,0x8c,0xc7,0xc1,0x83, 0x19,0x8d,0x82,0x63,0x31,0x9f,0xc1,0x80,0xc0,0xc0,0x00,0xaa,0x86,0xc0,0x47,0xe3, 0xf1,0xf8,0xfd,0xbf,0x83,0x8f,0xc3,0xef,0xf6,0xf8,0xfc,0xff,0x3f,0x9f,0x1f,0x8f, 0xc7,0xe3,0xf1,0xfb,0x7c,0x7e,0x3f,0x8f,0x8f,0xc7,0xe3,0xf8,0xfd,0x3e,0x3f,0x6f, 0x00,0x0c,0x0d,0x43,0x03,0xe1,0x88,0x30,0xc0,0x00,0x27,0x41,0x80,0x00,0x00,0x01, 0x72,0x00,0x22,0x04,0x01,0x80,0xc0,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xc0,0x04, 0x82,0x43,0x20,0x18,0x2c,0x16,0x0b,0x05,0x82,0xc1,0x60,0xb0,0xc0,0x30,0x18,0x0c, 0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x38,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x00,0xc7, 0x31,0x98,0xcc,0x66,0x33,0x11,0xf8,0xc8,0x7c,0x3e,0x1f,0x0f,0x87,0xc3,0xe1,0xd8, 0x3c,0x1e,0x0f,0x07,0x83,0xc7,0xc3,0xe1,0xf0,0xf8,0x06,0x37,0x07,0x03,0x81,0xc0, 0xe0,0x70,0x10,0x1d,0x31,0x98,0xcc,0x66,0x33,0x19,0xb0,0xc6,0x8f,0x7f,0x87,0x03, 0x81,0x80,0x90,0x30,0x6c,0x48,0x24,0x10,0x06,0x04,0x04,0x80,0x20,0x10,0x10,0x0e, 0x07,0x03,0x81,0xc0,0x60,0x88,0x38,0x0c,0x40,0x09,0x03,0x84,0x02,0x41,0x40,0x90, 0x00,0x0c,0x00,0x1f,0xe7,0x41,0xd1,0xa0,0x00,0x30,0x03,0x0a,0x81,0x00,0x00,0x00, 0x00,0x18,0x63,0x06,0x00,0xc0,0xc2,0x62,0x01,0xb0,0x0c,0x72,0x31,0x86,0x03,0x00, 0xc0,0x00,0x60,0x06,0x8f,0x16,0x19,0x0c,0x06,0x33,0x01,0x80,0xc0,0x63,0x0c,0x01, 0x8d,0x06,0x07,0x39,0x65,0x86,0x63,0x61,0x99,0x0e,0x01,0x83,0x19,0x89,0xb6,0x32, 0x33,0x03,0x06,0x01,0x80,0x30,0x78,0x00,0x00,0x03,0x1d,0x86,0x23,0x31,0x99,0xfc, 0x66,0x77,0x06,0x01,0x8c,0x40,0xc6,0xd9,0xdc,0x6c,0x76,0x19,0x8d,0xcc,0x27,0xf3, 0x19,0x8d,0x82,0x63,0x31,0x80,0xc0,0x80,0xc0,0x80,0x01,0x54,0x8c,0xc0,0x78,0xfc, 0x7e,0x7f,0x6f,0xcf,0x93,0xb7,0xdb,0xef,0xf9,0xfb,0xff,0xff,0xdf,0xef,0xef,0xf1, 0xf8,0xfc,0x7e,0x3f,0x9f,0x77,0xc7,0xf3,0xbf,0xf6,0xfc,0x7b,0xfd,0xbe,0xbf,0x6f, 0xff,0x0c,0x19,0x03,0x03,0x61,0x98,0x30,0x78,0x00,0x28,0x4f,0x83,0x30,0x00,0x01, 0x4a,0x00,0x1c,0x04,0x03,0x03,0x80,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xd9,0x84, 0x82,0x40,0xa0,0x18,0x2c,0x16,0x0b,0x05,0x82,0xc1,0x60,0xb0,0xc0,0x30,0x18,0x0c, 0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x2c,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x64,0xcb, 0x31,0x98,0xcc,0x66,0x33,0x31,0x8c,0xd8,0x06,0x03,0x01,0x80,0xc0,0x60,0x30,0x6c, 0x62,0x33,0x19,0x8c,0xc6,0x60,0xc0,0x60,0x30,0x18,0x1e,0x3b,0x8d,0x86,0xc3,0x61, 0xb0,0xd8,0x10,0x36,0x31,0x98,0xcc,0x66,0x33,0x19,0xd8,0xc6,0x0f,0x7f,0x82,0x01, 0x02,0x40,0xd0,0x40,0x6c,0x70,0x24,0x1c,0x06,0x04,0x03,0x01,0xc0,0xe0,0x10,0x12, 0x09,0x04,0x82,0x40,0x90,0x50,0x10,0x12,0x70,0x09,0x04,0x04,0x01,0xc1,0x20,0x60, 0x00,0x0c,0x00,0x04,0x83,0xc0,0x20,0xcc,0x00,0x30,0x03,0x02,0x01,0x00,0x00,0x00, 0x00,0x18,0x63,0x06,0x01,0x83,0x84,0x63,0xf1,0xd8,0x18,0x3c,0x31,0x86,0x03,0x01, 0x83,0xf8,0x30,0x1c,0x9b,0x33,0x1e,0x0c,0x06,0x33,0xe1,0x80,0xc0,0x7f,0x0c,0x01, 0x8f,0x06,0x07,0x79,0x65,0x86,0x66,0x61,0x9e,0x07,0x81,0x83,0x19,0x89,0xb6,0x1c, 0x1a,0x03,0x06,0x01,0x80,0x30,0x48,0x00,0x00,0x03,0x18,0xcc,0x06,0x33,0x18,0x60, 0xc6,0x63,0x06,0x01,0x8c,0x80,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8e,0x4c,0x01,0x83, 0x19,0x8d,0x92,0x32,0x31,0x81,0x87,0x00,0xc0,0x70,0xe4,0xaa,0x98,0xc0,0x7d,0xfe, 0xfd,0xbf,0x2f,0xbf,0x93,0x8f,0xdb,0xe3,0xf9,0xfb,0xff,0x1e,0x3f,0x1f,0xef,0xed, 0xf6,0xfb,0x7d,0xbf,0x6f,0xaf,0xef,0xed,0x8f,0xf6,0xfb,0xfb,0xfe,0x3e,0xdf,0x9f, 0x00,0x00,0x19,0x0f,0xc6,0x30,0xd0,0x00,0xcc,0x00,0x28,0x59,0x86,0x67,0xf0,0x01, 0x72,0x00,0x00,0x3f,0x86,0x00,0xc0,0x03,0x18,0xf4,0x00,0x00,0x0c,0x18,0xcc,0xc5, 0x32,0x83,0x4c,0x00,0x66,0x33,0x19,0x8c,0xc6,0x63,0x31,0xbc,0xc0,0x3e,0x1f,0x0f, 0x87,0xc1,0x80,0xc0,0x60,0x30,0xfb,0x2c,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x38,0xcb, 0x31,0x98,0xcc,0x66,0x31,0xa1,0x8c,0xcc,0x06,0x03,0x01,0x80,0xc0,0x60,0x30,0x6c, 0xc0,0x63,0x31,0x98,0xcc,0x60,0xc0,0x60,0x30,0x18,0x37,0x31,0x98,0xcc,0x66,0x33, 0x19,0x8c,0x00,0x67,0x31,0x98,0xcc,0x66,0x33,0x19,0x8c,0xc6,0x1f,0x7f,0x82,0x01, 0x02,0x40,0xb0,0x40,0x6c,0x07,0x03,0x83,0x80,0xe0,0xe0,0x00,0x18,0x0e,0x10,0x10, 0x08,0x04,0x02,0x00,0xf0,0x20,0x10,0x1e,0x08,0x89,0x03,0x00,0xe0,0x38,0x1c,0x0e, 0x00,0x0c,0x00,0x04,0x81,0xe0,0x41,0x6c,0x00,0x30,0x03,0x00,0x0f,0xe0,0x03,0xf8, 0x00,0x30,0x63,0x06,0x03,0x00,0xc7,0xf0,0x39,0x8c,0x30,0x3e,0x1b,0x80,0x00,0x03, 0x00,0x00,0x18,0x30,0x9b,0x23,0x19,0x0c,0x06,0x33,0x01,0xf8,0xc6,0x63,0x0c,0x01, 0x8d,0x86,0x05,0xd9,0x35,0x86,0x7c,0x61,0x9b,0x01,0xc1,0x83,0x19,0x99,0xb4,0x1c, 0x0c,0x06,0x06,0x00,0xc0,0x30,0xcc,0x00,0x00,0x3f,0x18,0xcc,0x06,0x33,0xf8,0x60, 0xc6,0x63,0x06,0x01,0x8f,0x00,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x0f,0x81,0x83, 0x18,0xd9,0xba,0x1c,0x1b,0x03,0x00,0x80,0xc0,0x81,0x75,0x54,0x98,0xc0,0x7d,0xfe, 0xfd,0xbf,0x4f,0xbf,0x93,0xf8,0xfc,0x7c,0x7f,0x1f,0x1f,0x6f,0xe7,0xf1,0xef,0xef, 0xf7,0xfb,0xfd,0xff,0x0f,0xdf,0xef,0xe1,0xf7,0x76,0xfc,0xff,0x1f,0xc7,0xe3,0xf1, 0xff,0x08,0x19,0x03,0x06,0x31,0xf8,0x00,0xc6,0x00,0x28,0x5b,0x8c,0xc0,0x11,0xf1, 0x4a,0x00,0x00,0x04,0x0c,0x00,0xc0,0x03,0x18,0x74,0x38,0x00,0x0c,0x18,0xc6,0x65, 0x52,0xb8,0x54,0x18,0x46,0x23,0x11,0x88,0xc4,0x62,0x31,0x30,0xc0,0x30,0x18,0x0c, 0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x26,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x10,0xd3, 0x31,0x98,0xcc,0x66,0x30,0xc1,0x8c,0xc6,0x7e,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xfc, 0xc0,0x7f,0x3f,0x9f,0xcf,0xe0,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33, 0x19,0x8c,0xfe,0x6b,0x31,0x98,0xcc,0x66,0x31,0xb1,0x8c,0x6c,0x0e,0x7f,0x82,0x01, 0x01,0x80,0x90,0x30,0xc6,0x08,0x01,0x02,0x00,0x40,0x80,0xe0,0x24,0x04,0x1c,0x10, 0x08,0x04,0x02,0x00,0x90,0x20,0x10,0x12,0x0d,0x86,0x00,0x81,0x00,0x40,0x20,0x10, 0x00,0x04,0x00,0x1f,0xe1,0x70,0xbb,0x28,0x00,0x30,0x03,0x00,0x01,0x00,0x00,0x00, 0x00,0x30,0x63,0x06,0x06,0x00,0x67,0xf0,0x19,0x8c,0x30,0x67,0x0d,0x80,0x00,0x01, 0x83,0xf8,0x30,0x30,0x9b,0x7f,0x19,0x8c,0x06,0x33,0x01,0x80,0xc6,0x63,0x0c,0x01, 0x8c,0xc6,0x05,0xd9,0x35,0x86,0x60,0x61,0x99,0x80,0xe1,0x83,0x18,0xd0,0xdc,0x26, 0x0c,0x0c,0x06,0x00,0xc0,0x30,0x84,0x00,0x00,0x63,0x18,0xcc,0x06,0x33,0x00,0x60, 0xc6,0x63,0x06,0x01,0x8d,0x80,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x03,0xe1,0x83, 0x18,0xd9,0xba,0x1c,0x1b,0x06,0x01,0x80,0xc0,0xc1,0x38,0xaa,0x80,0xc0,0x7d,0xfe, 0xfe,0x7f,0x6f,0xcf,0x39,0xf7,0xfe,0xfd,0xff,0xbf,0x7f,0x0f,0xdb,0xfb,0xe3,0xef, 0xf7,0xfb,0xfd,0xff,0x6f,0xdf,0xef,0xed,0xf2,0x79,0xff,0x7e,0xff,0xbf,0xdf,0xef, 0x00,0x0c,0x19,0x03,0x03,0x60,0x60,0x30,0x66,0x00,0x28,0x4d,0xc6,0x60,0x10,0x00, 0x84,0x00,0x00,0x04,0x0f,0x87,0x80,0x03,0x18,0x14,0x38,0x00,0x3f,0x0f,0x8c,0xc2, 0x90,0x84,0xa4,0x18,0xfe,0x7f,0x3f,0x9f,0xcf,0xe7,0xf1,0xf0,0xc0,0x30,0x18,0x0c, 0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x26,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x38,0xd3, 0x31,0x98,0xcc,0x66,0x30,0xc1,0x98,0xc6,0xc6,0x63,0x31,0x98,0xcc,0x66,0x33,0x60, 0xc0,0x60,0x30,0x18,0x0c,0x00,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33, 0x19,0x8c,0x00,0x6b,0x31,0x98,0xcc,0x66,0x31,0xb1,0x8c,0x6c,0x1c,0x7f,0x81,0x20, 0x90,0x38,0x18,0x0b,0x83,0x06,0x01,0x03,0x80,0x40,0xe0,0x90,0x24,0x04,0x03,0x8e, 0x86,0xc3,0x61,0x90,0x24,0x12,0x0e,0x04,0x8a,0x81,0xc7,0x70,0xc0,0x30,0x18,0x0c, 0x00,0x00,0x00,0x04,0x81,0x31,0x6f,0x30,0x00,0x18,0x06,0x00,0x01,0x00,0x00,0x00, 0x00,0x60,0x63,0x06,0x0c,0x00,0x60,0x60,0x19,0x8c,0x60,0x63,0x01,0x80,0x00,0x00, 0xc0,0x00,0x60,0x00,0x4d,0xe1,0x99,0x8c,0x06,0x33,0x01,0x80,0xc6,0x63,0x0c,0x01, 0x8c,0xc6,0x04,0x99,0x1d,0x86,0x60,0x61,0x99,0x80,0x61,0x83,0x18,0xd0,0xdc,0x63, 0x0c,0x0c,0x06,0x00,0x60,0x30,0x84,0x00,0x00,0x63,0x18,0xcc,0x06,0x33,0x00,0x60, 0x6e,0x63,0x06,0x01,0x8c,0xc0,0xc6,0xd9,0x8c,0xc6,0x63,0x31,0x8c,0x00,0x61,0x83, 0x18,0xd0,0xcc,0x26,0x0e,0x0c,0x03,0x00,0xc0,0x60,0x01,0x54,0x98,0xc0,0x7e,0xdf, 0x6f,0xc7,0xe7,0xf4,0x7c,0xf9,0xfe,0xfc,0x7f,0xbf,0x1f,0x5f,0xdb,0xfb,0xfc,0x71, 0x79,0x3c,0x9e,0x6f,0xdb,0xed,0xf1,0xfb,0x75,0x7e,0x38,0x8f,0x3f,0xcf,0xe7,0xf3, 0xff,0x0c,0x0d,0x03,0x03,0xe1,0xf8,0x30,0x3c,0x00,0x27,0x40,0x03,0x30,0x00,0x00, 0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x18,0x14,0x00,0x00,0x00,0x00,0x19,0x82, 0xf8,0x98,0xbe,0x70,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x30,0xc0,0x30,0x18,0x0c, 0x06,0x01,0x80,0xc0,0x60,0x30,0x63,0x23,0xb0,0xd8,0x6c,0x36,0x1b,0x0c,0x4c,0xe3, 0x31,0x98,0xcc,0x66,0x30,0xc1,0xf0,0xc6,0xc6,0x63,0x31,0x98,0xcc,0x66,0x33,0x60, 0xc0,0x60,0x30,0x18,0x0c,0x00,0xc0,0x60,0x30,0x18,0x63,0x31,0x98,0xcc,0x66,0x33, 0x19,0x8c,0x10,0x73,0x31,0x98,0xcc,0x66,0x30,0xe1,0x8c,0x38,0x1c,0x7f,0x80,0xa0, 0x50,0x10,0x24,0x0d,0xff,0x01,0x01,0x02,0x00,0x40,0x80,0xf0,0x24,0x04,0x02,0x01, 0x81,0x20,0x10,0x30,0x28,0x1a,0x09,0x06,0x8a,0x81,0x20,0x90,0x20,0x08,0x04,0x02, 0x00,0x0c,0x00,0x04,0x85,0x32,0x6f,0xb8,0x00,0x18,0x06,0x00,0x01,0x01,0xc0,0x00, 0x70,0x60,0x36,0x06,0x1f,0xcc,0xe0,0x63,0x30,0xd8,0x60,0x63,0x33,0x06,0x03,0x00, 0x60,0x00,0xc0,0x30,0x60,0x61,0x99,0x86,0x66,0x63,0x01,0x80,0x66,0x63,0x0c,0x03, 0x0c,0x66,0x04,0x19,0x1c,0xcc,0x60,0x33,0x18,0xcc,0x61,0x81,0xb0,0x60,0xcc,0x63, 0x0c,0x18,0x06,0x00,0x60,0x30,0x00,0x00,0x00,0x67,0x19,0x86,0x23,0x71,0x88,0x60, 0x36,0x63,0x06,0x01,0x8c,0x60,0xc6,0xd9,0x8c,0x6c,0x66,0x1b,0x8c,0x08,0x61,0x83, 0xb8,0x70,0xcc,0x63,0x0c,0x18,0x03,0x00,0xc0,0x60,0x00,0xaa,0x98,0xc0,0x7f,0x5f, 0xaf,0xef,0xdb,0xf2,0x00,0xfe,0xfe,0xfd,0xff,0xbf,0x7f,0x6f,0xdb,0xfb,0xfd,0xfe, 0x7e,0xdf,0xef,0xcf,0xd7,0xe5,0xf6,0xf9,0x75,0x7e,0xdf,0x6f,0xdf,0xf7,0xfb,0xfd, 0x00,0x0c,0x07,0xc6,0x04,0x10,0x60,0x30,0x06,0x00,0x10,0x80,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3f,0x80,0x00,0x00,0x03,0xb8,0x14,0x00,0x00,0x00,0x00,0x00,0x04, 0x11,0x21,0x04,0xc0,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x30,0x66,0x30,0x18,0x0c, 0x06,0x01,0x80,0xc0,0x60,0x30,0x66,0x23,0x99,0x8c,0xc6,0x63,0x31,0x98,0x00,0x66, 0x1b,0x0d,0x86,0xc3,0x60,0xc1,0x80,0xc6,0xce,0x67,0x33,0x99,0xcc,0xe6,0x73,0x74, 0x62,0x31,0x18,0x8c,0x46,0x20,0xc0,0x60,0x30,0x18,0x36,0x31,0x8d,0x86,0xc3,0x61, 0xb0,0xd8,0x10,0x36,0x3b,0x9d,0xce,0xe7,0x70,0xc1,0x98,0x30,0x00,0x7f,0x80,0xc0, 0x60,0x10,0x24,0x0c,0x38,0x0e,0x01,0x02,0x00,0x40,0x80,0xa0,0x18,0x0e,0x03,0x00, 0x80,0x40,0x60,0x50,0x30,0x16,0x0e,0x05,0x88,0x81,0xc0,0x81,0xc0,0x70,0x38,0x1c, 0x00,0x0c,0x00,0x04,0x83,0xe0,0x39,0xcc,0x00,0x0c,0x0c,0x00,0x00,0x01,0xc0,0x00, 0x70,0xc0,0x1c,0x06,0x1f,0xc7,0xc0,0x61,0xe0,0x70,0x60,0x3e,0x1e,0x06,0x03,0x00, 0x00,0x00,0x00,0x30,0x1e,0x61,0x9f,0x03,0xc7,0xc3,0xf1,0x80,0x3e,0x63,0x3f,0x1e, 0x0c,0x67,0xe4,0x19,0x0c,0x78,0x60,0x1e,0x18,0xc7,0xc1,0x80,0xe0,0x60,0xcc,0x63, 0x0c,0x1f,0xc6,0x00,0x30,0x30,0x00,0x00,0x00,0x3b,0x9f,0x03,0xc1,0xb0,0xf0,0x60, 0x06,0x63,0x06,0x01,0x8c,0x70,0xc6,0xd9,0x8c,0x38,0x7c,0x0d,0x8c,0x07,0xc0,0xf1, 0xd8,0x60,0xcc,0x63,0x0c,0x1f,0xc3,0x00,0xc0,0x60,0x01,0x54,0x80,0xc0,0x7f,0x3f, 0x9f,0xef,0xdb,0xf3,0xc7,0xf1,0xfe,0xfd,0xff,0xbf,0x7f,0xff,0xe7,0xf1,0xfc,0xff, 0x7f,0xbf,0x9f,0xaf,0xcf,0xe9,0xf1,0xfa,0x77,0x7e,0x3f,0x7e,0x3f,0x8f,0xc7,0xe3, 0xff,0x0c,0x01,0x0f,0xe8,0x08,0x60,0x30,0xc6,0x00,0x0f,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xd8,0x14,0x00,0x00,0x00,0x00,0x00,0x04, 0x11,0x3d,0x04,0xc0,0xc3,0x61,0xb0,0xd8,0x6c,0x36,0x1b,0x3c,0x3c,0x3f,0x1f,0x8f, 0xc7,0xe7,0xe3,0xf1,0xf8,0xfc,0x7c,0x21,0x8f,0x07,0x83,0xc1,0xe0,0xf0,0x00,0xbc, 0x0e,0x07,0x03,0x81,0xc0,0xc1,0x80,0xcc,0x77,0x3b,0x9d,0xce,0xe7,0x73,0xb9,0x98, 0x3c,0x1e,0x0f,0x07,0x83,0xc0,0xc0,0x60,0x30,0x18,0x1c,0x31,0x87,0x03,0x81,0xc0, 0xe0,0x70,0x00,0x5c,0x1d,0x8e,0xc7,0x63,0xb0,0xc1,0xf0,0x30,0x00,0x7f,0x81,0x40, 0xa0,0x10,0x28,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x02,0x00, 0x80,0x80,0x10,0xf8,0x28,0x12,0x09,0x04,0x80,0x01,0x20,0x80,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x06,0x18,0x00,0x00,0x00,0x40,0x00, 0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x07,0xc0,0x31,0xf0,0x01,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xcc,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x18,0x00,0x01,0xe0,0xc3,0xc0,0x00,0x00,0xff,0xc0,0x7e,0xbf, 0x5f,0xef,0xd7,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff, 0x7f,0x7f,0xef,0x07,0xd7,0xed,0xf6,0xfb,0x7f,0xfe,0xdf,0x7f,0xff,0xff,0xff,0xff, 0x00,0x0c,0x01,0x00,0x00,0x00,0x00,0x30,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x81,0x80,0x60,0x00,0x7f,0x81,0x20, 0x90,0x10,0x1c,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80, 0x81,0xe0,0x60,0x10,0x24,0x12,0x0e,0x04,0x80,0x01,0xc0,0x70,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x78,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xfe,0xdf, 0x6f,0xef,0xe3,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x7f, 0x7e,0x1f,0x9f,0xef,0xdb,0xed,0xf1,0xfb,0x7f,0xfe,0x3f,0x8f,0xff,0xff,0xff,0xff, 0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x81,0x80,0x60,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x32,0x35,0x36,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x31,0x35,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x33,0x20, 0x00,0x00,0x01,0x0c,0x00,0x09,0x09,0x00,0x01,0x0f,0x00,0x09,0x12,0x00,0x01,0x0f, 0x00,0x09,0x1b,0x00,0x01,0x0f,0x00,0x09,0x24,0x00,0x01,0x0f,0x00,0x09,0x2d,0x00, 0x01,0x0f,0x00,0x09,0x36,0x00,0x01,0x0f,0x00,0x09,0x3f,0x00,0x03,0x0d,0x00,0x09, 0x48,0x00,0x03,0x0d,0x00,0x09,0x51,0x00,0x03,0x0d,0x00,0x09,0x5a,0x00,0x03,0x0d, 0x00,0x09,0x63,0x00,0x03,0x0d,0x00,0x09,0x6c,0x00,0x03,0x0d,0x00,0x09,0x75,0x00, 0x03,0x0e,0x00,0x09,0x7e,0x00,0x03,0x0d,0x00,0x09,0x87,0x00,0x03,0x0d,0x00,0x09, 0x90,0x00,0x01,0x0f,0x00,0x09,0x99,0x00,0x01,0x0f,0x00,0x09,0xa2,0x00,0x01,0x0f, 0x00,0x09,0xab,0x00,0x01,0x0f,0x00,0x09,0xb4,0x00,0x01,0x0f,0x00,0x09,0xbd,0x00, 0x01,0x0f,0x00,0x09,0xc6,0x00,0x01,0x0f,0x00,0x09,0xcf,0x00,0x01,0x0f,0x00,0x09, 0xd8,0x00,0x01,0x0f,0x00,0x09,0xe1,0x00,0x03,0x0d,0x00,0x09,0xea,0x00,0x01,0x0f, 0x00,0x09,0xf3,0x00,0x01,0x0f,0x00,0x09,0xfc,0x00,0x03,0x0d,0x00,0x09,0x05,0x01, 0x03,0x0d,0x00,0x09,0x0e,0x01,0x03,0x0d,0x00,0x09,0x17,0x01,0x03,0x0d,0x00,0x09, 0x20,0x01,0x00,0x00,0x00,0x09,0x29,0x01,0x03,0x0d,0x00,0x09,0x32,0x01,0x02,0x05, 0x00,0x09,0x3b,0x01,0x03,0x0d,0x00,0x09,0x44,0x01,0x02,0x0e,0x00,0x09,0x4d,0x01, 0x03,0x0d,0x00,0x09,0x56,0x01,0x03,0x0d,0x00,0x09,0x5f,0x01,0x02,0x06,0x00,0x09, 0x68,0x01,0x02,0x0e,0x00,0x09,0x71,0x01,0x02,0x0e,0x00,0x09,0x7a,0x01,0x03,0x08, 0x00,0x09,0x83,0x01,0x05,0x0c,0x00,0x09,0x8c,0x01,0x0b,0x0f,0x00,0x09,0x95,0x01, 0x08,0x09,0x00,0x09,0x9e,0x01,0x0b,0x0d,0x00,0x09,0xa7,0x01,0x02,0x0e,0x00,0x09, 0xb0,0x01,0x03,0x0d,0x00,0x09,0xb9,0x01,0x03,0x0d,0x00,0x09,0xc2,0x01,0x03,0x0d, 0x00,0x09,0xcb,0x01,0x03,0x0d,0x00,0x09,0xd4,0x01,0x03,0x0d,0x00,0x09,0xdd,0x01, 0x03,0x0d,0x00,0x09,0xe6,0x01,0x03,0x0d,0x00,0x09,0xef,0x01,0x03,0x0d,0x00,0x09, 0xf8,0x01,0x03,0x0d,0x00,0x09,0x01,0x02,0x03,0x0d,0x00,0x09,0x0a,0x02,0x06,0x0d, 0x00,0x09,0x13,0x02,0x06,0x0f,0x00,0x09,0x1c,0x02,0x05,0x0c,0x00,0x09,0x25,0x02, 0x07,0x0a,0x00,0x09,0x2e,0x02,0x05,0x0c,0x00,0x09,0x37,0x02,0x03,0x0d,0x00,0x09, 0x40,0x02,0x03,0x0d,0x00,0x09,0x49,0x02,0x03,0x0d,0x00,0x09,0x52,0x02,0x03,0x0d, 0x00,0x09,0x5b,0x02,0x03,0x0d,0x00,0x09,0x64,0x02,0x03,0x0d,0x00,0x09,0x6d,0x02, 0x03,0x0d,0x00,0x09,0x76,0x02,0x03,0x0d,0x00,0x09,0x7f,0x02,0x03,0x0d,0x00,0x09, 0x88,0x02,0x03,0x0d,0x00,0x09,0x91,0x02,0x03,0x0d,0x00,0x09,0x9a,0x02,0x03,0x0d, 0x00,0x09,0xa3,0x02,0x03,0x0d,0x00,0x09,0xac,0x02,0x03,0x0d,0x00,0x09,0xb5,0x02, 0x03,0x0d,0x00,0x09,0xbe,0x02,0x03,0x0d,0x00,0x09,0xc7,0x02,0x03,0x0d,0x00,0x09, 0xd0,0x02,0x03,0x0d,0x00,0x09,0xd9,0x02,0x03,0x0f,0x00,0x09,0xe2,0x02,0x03,0x0d, 0x00,0x09,0xeb,0x02,0x03,0x0d,0x00,0x09,0xf4,0x02,0x03,0x0d,0x00,0x09,0xfd,0x02, 0x03,0x0d,0x00,0x09,0x06,0x03,0x03,0x0d,0x00,0x09,0x0f,0x03,0x03,0x0d,0x00,0x09, 0x18,0x03,0x03,0x0d,0x00,0x09,0x21,0x03,0x03,0x0d,0x00,0x09,0x2a,0x03,0x03,0x0d, 0x00,0x09,0x33,0x03,0x02,0x0e,0x00,0x09,0x3c,0x03,0x02,0x0e,0x00,0x09,0x45,0x03, 0x02,0x0e,0x00,0x09,0x4e,0x03,0x04,0x0b,0x00,0x09,0x57,0x03,0x0d,0x0e,0x00,0x09, 0x60,0x03,0x02,0x06,0x00,0x09,0x69,0x03,0x05,0x0d,0x00,0x09,0x72,0x03,0x02,0x0d, 0x00,0x09,0x7b,0x03,0x05,0x0d,0x00,0x09,0x84,0x03,0x02,0x0d,0x00,0x09,0x8d,0x03, 0x05,0x0d,0x00,0x09,0x96,0x03,0x02,0x0d,0x00,0x09,0x9f,0x03,0x05,0x0f,0x00,0x09, 0xa8,0x03,0x02,0x0d,0x00,0x09,0xb1,0x03,0x02,0x0d,0x00,0x09,0xba,0x03,0x02,0x0f, 0x00,0x09,0xc3,0x03,0x02,0x0d,0x00,0x09,0xcc,0x03,0x02,0x0d,0x00,0x09,0xd5,0x03, 0x05,0x0d,0x00,0x09,0xde,0x03,0x05,0x0d,0x00,0x09,0xe7,0x03,0x05,0x0d,0x00,0x09, 0xf0,0x03,0x05,0x0f,0x00,0x09,0xf9,0x03,0x05,0x0f,0x00,0x09,0x02,0x04,0x05,0x0d, 0x00,0x09,0x0b,0x04,0x05,0x0d,0x00,0x09,0x14,0x04,0x03,0x0d,0x00,0x09,0x1d,0x04, 0x05,0x0d,0x00,0x09,0x26,0x04,0x05,0x0d,0x00,0x09,0x2f,0x04,0x05,0x0d,0x00,0x09, 0x38,0x04,0x05,0x0d,0x00,0x09,0x41,0x04,0x05,0x0f,0x00,0x09,0x4a,0x04,0x05,0x0d, 0x00,0x09,0x53,0x04,0x02,0x0e,0x00,0x09,0x5c,0x04,0x02,0x0e,0x00,0x09,0x65,0x04, 0x02,0x0e,0x00,0x09,0x6e,0x04,0x07,0x0a,0x00,0x09,0x77,0x04,0x01,0x0d,0x00,0x09, 0x80,0x04,0x00,0x0e,0x00,0x09,0x89,0x04,0x00,0x0f,0x00,0x09,0x92,0x04,0x00,0x0f, 0x00,0x09,0x9b,0x04,0x00,0x0f,0x00,0x09,0xa4,0x04,0x00,0x0f,0x00,0x09,0xad,0x04, 0x00,0x0f,0x00,0x09,0xb6,0x04,0x00,0x0f,0x00,0x09,0xbf,0x04,0x00,0x0f,0x00,0x09, 0xc8,0x04,0x00,0x0f,0x00,0x09,0xd1,0x04,0x00,0x0f,0x00,0x09,0xda,0x04,0x00,0x0f, 0x00,0x09,0xe3,0x04,0x00,0x0f,0x00,0x09,0xec,0x04,0x00,0x0f,0x00,0x09,0xf5,0x04, 0x00,0x0f,0x00,0x09,0xfe,0x04,0x00,0x0f,0x00,0x09,0x07,0x05,0x00,0x0f,0x00,0x09, 0x10,0x05,0x00,0x0f,0x00,0x09,0x19,0x05,0x00,0x0f,0x00,0x09,0x22,0x05,0x00,0x0f, 0x00,0x09,0x2b,0x05,0x00,0x0f,0x00,0x09,0x34,0x05,0x00,0x0f,0x00,0x09,0x3d,0x05, 0x00,0x0f,0x00,0x09,0x46,0x05,0x00,0x0f,0x00,0x09,0x4f,0x05,0x00,0x0f,0x00,0x09, 0x58,0x05,0x00,0x0f,0x00,0x09,0x61,0x05,0x00,0x0f,0x00,0x09,0x6a,0x05,0x00,0x0f, 0x00,0x09,0x73,0x05,0x00,0x0f,0x00,0x09,0x7c,0x05,0x00,0x0f,0x00,0x09,0x85,0x05, 0x00,0x0f,0x00,0x09,0x8e,0x05,0x00,0x0f,0x00,0x09,0x97,0x05,0x00,0x0f,0x00,0x09, 0xa0,0x05,0x00,0x0d,0x00,0x09,0xa9,0x05,0x05,0x0f,0x00,0x09,0xb2,0x05,0x02,0x0e, 0x00,0x09,0xbb,0x05,0x03,0x0d,0x00,0x09,0xc4,0x05,0x03,0x0d,0x00,0x09,0xcd,0x05, 0x03,0x0d,0x00,0x09,0xd6,0x05,0x02,0x0e,0x00,0x09,0xdf,0x05,0x03,0x0e,0x00,0x09, 0xe8,0x05,0x02,0x04,0x00,0x09,0xf1,0x05,0x03,0x0d,0x00,0x09,0xfa,0x05,0x03,0x0a, 0x00,0x09,0x03,0x06,0x06,0x0b,0x00,0x09,0x0c,0x06,0x07,0x0a,0x00,0x09,0x15,0x06, 0x08,0x09,0x00,0x09,0x1e,0x06,0x03,0x0b,0x00,0x09,0x27,0x06,0x02,0x03,0x00,0x09, 0x30,0x06,0x03,0x07,0x00,0x09,0x39,0x06,0x05,0x0c,0x00,0x09,0x42,0x06,0x03,0x0a, 0x00,0x09,0x4b,0x06,0x03,0x0a,0x00,0x09,0x54,0x06,0x02,0x04,0x00,0x09,0x5d,0x06, 0x05,0x0f,0x00,0x09,0x66,0x06,0x03,0x0e,0x00,0x09,0x6f,0x06,0x08,0x0a,0x00,0x09, 0x78,0x06,0x0d,0x0f,0x00,0x09,0x81,0x06,0x03,0x0a,0x00,0x09,0x8a,0x06,0x03,0x0a, 0x00,0x09,0x93,0x06,0x06,0x0b,0x00,0x09,0x9c,0x06,0x03,0x0d,0x00,0x09,0xa5,0x06, 0x03,0x0d,0x00,0x09,0xae,0x06,0x03,0x0d,0x00,0x09,0xb7,0x06,0x05,0x0f,0x00,0x09, 0xc0,0x06,0x00,0x0d,0x00,0x09,0xc9,0x06,0x00,0x0d,0x00,0x09,0xd2,0x06,0x00,0x0d, 0x00,0x09,0xdb,0x06,0x00,0x0d,0x00,0x09,0xe4,0x06,0x00,0x0d,0x00,0x09,0xed,0x06, 0x01,0x0d,0x00,0x09,0xf6,0x06,0x03,0x0d,0x00,0x09,0xff,0x06,0x03,0x0f,0x00,0x09, 0x08,0x07,0x00,0x0d,0x00,0x09,0x11,0x07,0x00,0x0d,0x00,0x09,0x1a,0x07,0x00,0x0d, 0x00,0x09,0x23,0x07,0x00,0x0d,0x00,0x09,0x2c,0x07,0x00,0x0d,0x00,0x09,0x35,0x07, 0x00,0x0d,0x00,0x09,0x3e,0x07,0x00,0x0d,0x00,0x09,0x47,0x07,0x00,0x0d,0x00,0x09, 0x50,0x07,0x03,0x0d,0x00,0x09,0x59,0x07,0x00,0x0d,0x00,0x09,0x62,0x07,0x00,0x0d, 0x00,0x09,0x6b,0x07,0x00,0x0d,0x00,0x09,0x74,0x07,0x00,0x0d,0x00,0x09,0x7d,0x07, 0x00,0x0d,0x00,0x09,0x86,0x07,0x00,0x0d,0x00,0x09,0x8f,0x07,0x06,0x0b,0x00,0x09, 0x98,0x07,0x03,0x0d,0x00,0x09,0xa1,0x07,0x00,0x0d,0x00,0x09,0xaa,0x07,0x00,0x0d, 0x00,0x09,0xb3,0x07,0x00,0x0d,0x00,0x09,0xbc,0x07,0x00,0x0d,0x00,0x09,0xc5,0x07, 0x00,0x0d,0x00,0x09,0xce,0x07,0x03,0x0d,0x00,0x09,0xd7,0x07,0x02,0x0d,0x00,0x09, 0xe0,0x07,0x02,0x0d,0x00,0x09,0xe9,0x07,0x02,0x0d,0x00,0x09,0xf2,0x07,0x02,0x0d, 0x00,0x09,0xfb,0x07,0x02,0x0d,0x00,0x09,0x04,0x08,0x02,0x0d,0x00,0x09,0x0d,0x08, 0x02,0x0d,0x00,0x09,0x16,0x08,0x05,0x0d,0x00,0x09,0x1f,0x08,0x05,0x0f,0x00,0x09, 0x28,0x08,0x02,0x0d,0x00,0x09,0x31,0x08,0x02,0x0d,0x00,0x09,0x3a,0x08,0x02,0x0d, 0x00,0x09,0x43,0x08,0x02,0x0d,0x00,0x09,0x4c,0x08,0x02,0x0d,0x00,0x09,0x55,0x08, 0x02,0x0d,0x00,0x09,0x5e,0x08,0x02,0x0d,0x00,0x09,0x67,0x08,0x02,0x0d,0x00,0x09, 0x70,0x08,0x02,0x0d,0x00,0x09,0x79,0x08,0x02,0x0d,0x00,0x09,0x82,0x08,0x02,0x0d, 0x00,0x09,0x8b,0x08,0x02,0x0d,0x00,0x09,0x94,0x08,0x02,0x0d,0x00,0x09,0x9d,0x08, 0x02,0x0d,0x00,0x09,0xa6,0x08,0x02,0x0d,0x00,0x09,0xaf,0x08,0x05,0x0c,0x00,0x09, 0xb8,0x08,0x05,0x0d,0x00,0x09,0xc1,0x08,0x02,0x0d,0x00,0x09,0xca,0x08,0x02,0x0d, 0x00,0x09,0xd3,0x08,0x02,0x0d,0x00,0x09,0xdc,0x08,0x02,0x0d,0x00,0x09,0xe5,0x08, 0x02,0x0f,0x00,0x09,0xee,0x08,0x03,0x0f,0x00,0x09,0xf7,0x08,0x02,0x0f,0x00,0x09, 0x00,0x09,0x00,0x00,0x00,0x00, }; int sizeofdefont = sizeof defontdata; void _unpackinfo(Fontchar *fc, uchar *p, int n) { int j; for(j=0; j<=n; j++){ fc->x = p[0]|(p[1]<<8); fc->top = p[2]; fc->bottom = p[3]; fc->left = p[4]; fc->width = p[5]; fc++; p += 6; } } drawterm-20110822.orig/libdraw/rgb.c0000644000175000017500000000321711245145712016440 0ustar tinchotincho#include #include #include /* * This original version, although fast and a true inverse of * cmap2rgb, in the sense that rgb2cmap(cmap2rgb(c)) * returned the original color, does a terrible job for RGB * triples that do not appear in the color map, so it has been * replaced by the much slower version below, that loops * over the color map looking for the nearest point in RGB * space. There is no visual psychology reason for that * criterion, but it's easy to implement and the results are * far more pleasing. * int rgb2cmap(int cr, int cg, int cb) { int r, g, b, v, cv; if(cr < 0) cr = 0; else if(cr > 255) cr = 255; if(cg < 0) cg = 0; else if(cg > 255) cg = 255; if(cb < 0) cb = 0; else if(cb > 255) cb = 255; r = cr>>6; g = cg>>6; b = cb>>6; cv = cr; if(cg > cv) cv = cg; if(cb > cv) cv = cb; v = (cv>>4)&3; return ((((r<<2)+v)<<4)+(((g<<2)+b+v-r)&15)); } */ int rgb2cmap(int cr, int cg, int cb) { int i, r, g, b, sq; ulong rgb; int best, bestsq; best = 0; bestsq = 0x7FFFFFFF; for(i=0; i<256; i++){ rgb = cmap2rgb(i); r = (rgb>>16) & 0xFF; g = (rgb>>8) & 0xFF; b = (rgb>>0) & 0xFF; sq = (r-cr)*(r-cr)+(g-cg)*(g-cg)+(b-cb)*(b-cb); if(sq < bestsq){ bestsq = sq; best = i; } } return best; } int cmap2rgb(int c) { int j, num, den, r, g, b, v, rgb; r = c>>6; v = (c>>4)&3; j = (c-v+r)&15; g = j>>2; b = j&3; den=r; if(g>den) den=g; if(b>den) den=b; if(den==0) { v *= 17; rgb = (v<<16)|(v<<8)|v; } else{ num=17*(4*den+v); rgb = ((r*num/den)<<16)|((g*num/den)<<8)|(b*num/den); } return rgb; } int cmap2rgba(int c) { return (cmap2rgb(c)<<8)|0xFF; } drawterm-20110822.orig/libdraw/bytesperline.c0000644000175000017500000000115111245145712020366 0ustar tinchotincho#include #include #include static int unitsperline(Rectangle r, int d, int bitsperunit) { ulong l, t; if(d <= 0 || d > 32) /* being called wrong. d is image depth. */ abort(); if(r.min.x >= 0){ l = (r.max.x*d+bitsperunit-1)/bitsperunit; l -= (r.min.x*d)/bitsperunit; }else{ /* make positive before divide */ t = (-r.min.x*d+bitsperunit-1)/bitsperunit; l = t+(r.max.x*d+bitsperunit-1)/bitsperunit; } return l; } int wordsperline(Rectangle r, int d) { return unitsperline(r, d, 8*sizeof(ulong)); } int bytesperline(Rectangle r, int d) { return unitsperline(r, d, 8); } drawterm-20110822.orig/libdraw/icossin.c0000644000175000017500000000410511245145712017332 0ustar tinchotincho#include #include #include /* * Integer sine and cosine for integral degree argument. * Tables computed by (sin,cos)(PI*d/180). */ static short sinus[91] = { 0, /* 0 */ 18, /* 1 */ 36, /* 2 */ 54, /* 3 */ 71, /* 4 */ 89, /* 5 */ 107, /* 6 */ 125, /* 7 */ 143, /* 8 */ 160, /* 9 */ 178, /* 10 */ 195, /* 11 */ 213, /* 12 */ 230, /* 13 */ 248, /* 14 */ 265, /* 15 */ 282, /* 16 */ 299, /* 17 */ 316, /* 18 */ 333, /* 19 */ 350, /* 20 */ 367, /* 21 */ 384, /* 22 */ 400, /* 23 */ 416, /* 24 */ 433, /* 25 */ 449, /* 26 */ 465, /* 27 */ 481, /* 28 */ 496, /* 29 */ 512, /* 30 */ 527, /* 31 */ 543, /* 32 */ 558, /* 33 */ 573, /* 34 */ 587, /* 35 */ 602, /* 36 */ 616, /* 37 */ 630, /* 38 */ 644, /* 39 */ 658, /* 40 */ 672, /* 41 */ 685, /* 42 */ 698, /* 43 */ 711, /* 44 */ 724, /* 45 */ 737, /* 46 */ 749, /* 47 */ 761, /* 48 */ 773, /* 49 */ 784, /* 50 */ 796, /* 51 */ 807, /* 52 */ 818, /* 53 */ 828, /* 54 */ 839, /* 55 */ 849, /* 56 */ 859, /* 57 */ 868, /* 58 */ 878, /* 59 */ 887, /* 60 */ 896, /* 61 */ 904, /* 62 */ 912, /* 63 */ 920, /* 64 */ 928, /* 65 */ 935, /* 66 */ 943, /* 67 */ 949, /* 68 */ 956, /* 69 */ 962, /* 70 */ 968, /* 71 */ 974, /* 72 */ 979, /* 73 */ 984, /* 74 */ 989, /* 75 */ 994, /* 76 */ 998, /* 77 */ 1002, /* 78 */ 1005, /* 79 */ 1008, /* 80 */ 1011, /* 81 */ 1014, /* 82 */ 1016, /* 83 */ 1018, /* 84 */ 1020, /* 85 */ 1022, /* 86 */ 1023, /* 87 */ 1023, /* 88 */ 1024, /* 89 */ 1024, /* 90 */ }; void icossin(int deg, int *cosp, int *sinp) { int sinsign, cossign; short *stp, *ctp; deg %= 360; if(deg < 0) deg += 360; sinsign = 1; cossign = 1; stp = 0; ctp = 0; switch(deg/90){ case 2: sinsign = -1; cossign = -1; deg -= 180; /* fall through */ case 0: stp = &sinus[deg]; ctp = &sinus[90-deg]; break; case 3: sinsign = -1; cossign = -1; deg -= 180; /* fall through */ case 1: deg = 180-deg; cossign = -cossign; stp = &sinus[deg]; ctp = &sinus[90-deg]; break; } *sinp = sinsign*stp[0]; *cosp = cossign*ctp[0]; } drawterm-20110822.orig/libdraw/Makefile0000644000175000017500000000044511245145712017162 0ustar tinchotinchoROOT=.. include ../Make.config LIB=libdraw.a OFILES=\ alloc.$O\ arith.$O\ bytesperline.$O\ chan.$O\ defont.$O\ drawrepl.$O\ icossin.$O\ icossin2.$O\ rectclip.$O\ rgb.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/libdraw/arith.c0000644000175000017500000000542711245145712017002 0ustar tinchotincho#include #include #include Point Pt(int x, int y) { Point p; p.x = x; p.y = y; return p; } Rectangle Rect(int x, int y, int bx, int by) { Rectangle r; r.min.x = x; r.min.y = y; r.max.x = bx; r.max.y = by; return r; } Rectangle Rpt(Point min, Point max) { Rectangle r; r.min = min; r.max = max; return r; } Point addpt(Point a, Point b) { a.x += b.x; a.y += b.y; return a; } Point subpt(Point a, Point b) { a.x -= b.x; a.y -= b.y; return a; } Rectangle insetrect(Rectangle r, int n) { r.min.x += n; r.min.y += n; r.max.x -= n; r.max.y -= n; return r; } Point divpt(Point a, int b) { a.x /= b; a.y /= b; return a; } Point mulpt(Point a, int b) { a.x *= b; a.y *= b; return a; } Rectangle rectsubpt(Rectangle r, Point p) { r.min.x -= p.x; r.min.y -= p.y; r.max.x -= p.x; r.max.y -= p.y; return r; } Rectangle rectaddpt(Rectangle r, Point p) { r.min.x += p.x; r.min.y += p.y; r.max.x += p.x; r.max.y += p.y; return r; } int eqpt(Point p, Point q) { return p.x==q.x && p.y==q.y; } int eqrect(Rectangle r, Rectangle s) { return r.min.x==s.min.x && r.max.x==s.max.x && r.min.y==s.min.y && r.max.y==s.max.y; } int rectXrect(Rectangle r, Rectangle s) { return r.min.x=r.min.x && p.x=r.min.y && p.ymin.x > r2.min.x) r1->min.x = r2.min.x; if(r1->min.y > r2.min.y) r1->min.y = r2.min.y; if(r1->max.x < r2.max.x) r1->max.x = r2.max.x; if(r1->max.y < r2.max.y) r1->max.y = r2.max.y; } ulong drawld2chan[] = { GREY1, GREY2, GREY4, CMAP8, }; int log2[] = { -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5 }; ulong setalpha(ulong color, uchar alpha) { int red, green, blue; red = (color >> 3*8) & 0xFF; green = (color >> 2*8) & 0xFF; blue = (color >> 1*8) & 0xFF; /* ignore incoming alpha */ red = (red * alpha)/255; green = (green * alpha)/255; blue = (blue * alpha)/255; return (red<<3*8) | (green<<2*8) | (blue<<1*8) | (alpha<<0*8); } Point ZP; Rectangle ZR; int Rfmt(Fmt *f) { Rectangle r; r = va_arg(f->args, Rectangle); return fmtprint(f, "%P %P", r.min, r.max); } int Pfmt(Fmt *f) { Point p; p = va_arg(f->args, Point); return fmtprint(f, "[%d %d]", p.x, p.y); } drawterm-20110822.orig/libdraw/alloc.c0000644000175000017500000000777711245145712016777 0ustar tinchotincho#include #include #include Image* allocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val) { return _allocimage(nil, d, r, chan, repl, val, 0, 0); } Image* _allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong val, int screenid, int refresh) { uchar *a; char *err; Image *i; Rectangle clipr; int id; int depth; err = 0; i = 0; if(chan == 0){ werrstr("bad channel descriptor"); return nil; } depth = chantodepth(chan); if(depth == 0){ err = "bad channel descriptor"; Error: if(err) werrstr("allocimage: %s", err); else werrstr("allocimage: %r"); free(i); return 0; } /* flush pending data so we don't get error allocating the image */ flushimage(d, 0); a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4); if(a == 0) goto Error; d->imageid++; id = d->imageid; a[0] = 'b'; BPLONG(a+1, id); BPLONG(a+5, screenid); a[9] = refresh; BPLONG(a+10, chan); a[14] = repl; BPLONG(a+15, r.min.x); BPLONG(a+19, r.min.y); BPLONG(a+23, r.max.x); BPLONG(a+27, r.max.y); if(repl) /* huge but not infinite, so various offsets will leave it huge, not overflow */ clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF); else clipr = r; BPLONG(a+31, clipr.min.x); BPLONG(a+35, clipr.min.y); BPLONG(a+39, clipr.max.x); BPLONG(a+43, clipr.max.y); BPLONG(a+47, val); if(flushimage(d, 0) < 0) goto Error; if(ai) i = ai; else{ i = malloc(sizeof(Image)); if(i == nil){ a = bufimage(d, 1+4); if(a){ a[0] = 'f'; BPLONG(a+1, id); flushimage(d, 0); } goto Error; } } i->display = d; i->id = id; i->depth = depth; i->chan = chan; i->r = r; i->clipr = clipr; i->repl = repl; i->screen = 0; i->next = 0; return i; } Image* namedimage(Display *d, char *name) { uchar *a; char *err, buf[12*12+1]; Image *i; int id, n; ulong chan; err = 0; i = 0; n = strlen(name); if(n >= 256){ err = "name too long"; Error: if(err) werrstr("namedimage: %s", err); else werrstr("namedimage: %r"); if(i) free(i); return 0; } /* flush pending data so we don't get error allocating the image */ flushimage(d, 0); a = bufimage(d, 1+4+1+n); if(a == 0) goto Error; d->imageid++; id = d->imageid; a[0] = 'n'; BPLONG(a+1, id); a[5] = n; memmove(a+6, name, n); if(flushimage(d, 0) < 0) goto Error; if(pread(d->ctlfd, buf, sizeof buf, 0) < 12*12) goto Error; buf[12*12] = '\0'; i = malloc(sizeof(Image)); if(i == nil){ Error1: a = bufimage(d, 1+4); if(a){ a[0] = 'f'; BPLONG(a+1, id); flushimage(d, 0); } goto Error; } i->display = d; i->id = id; if((chan=strtochan(buf+2*12))==0){ werrstr("bad channel '%.12s' from devdraw", buf+2*12); goto Error1; } i->chan = chan; i->depth = chantodepth(chan); i->repl = atoi(buf+3*12); i->r.min.x = atoi(buf+4*12); i->r.min.y = atoi(buf+5*12); i->r.max.x = atoi(buf+6*12); i->r.max.y = atoi(buf+7*12); i->clipr.min.x = atoi(buf+8*12); i->clipr.min.y = atoi(buf+9*12); i->clipr.max.x = atoi(buf+10*12); i->clipr.max.y = atoi(buf+11*12); i->screen = 0; i->next = 0; return i; } int nameimage(Image *i, char *name, int in) { uchar *a; int n; n = strlen(name); a = bufimage(i->display, 1+4+1+1+n); if(a == 0) return 0; a[0] = 'N'; BPLONG(a+1, i->id); a[5] = in; a[6] = n; memmove(a+7, name, n); if(flushimage(i->display, 0) < 0) return 0; return 1; } int _freeimage1(Image *i) { uchar *a; Display *d; Image *w; if(i == 0) return 0; /* make sure no refresh events occur on this if we block in the write */ d = i->display; /* flush pending data so we don't get error deleting the image */ flushimage(d, 0); a = bufimage(d, 1+4); if(a == 0) return -1; a[0] = 'f'; BPLONG(a+1, i->id); if(i->screen){ w = d->windows; if(w == i) d->windows = i->next; else while(w){ if(w->next == i){ w->next = i->next; break; } w = w->next; } } if(flushimage(d, i->screen!=0) < 0) return -1; return 0; } int freeimage(Image *i) { int ret; ret = _freeimage1(i); free(i); return ret; } drawterm-20110822.orig/libdraw/drawrepl.c0000644000175000017500000000047211245145712017506 0ustar tinchotincho#include #include #include int drawreplxy(int min, int max, int x) { int sx; sx = (x-min)%(max-min); if(sx < 0) sx += max-min; return sx+min; } Point drawrepl(Rectangle r, Point p) { p.x = drawreplxy(r.min.x, r.max.x, p.x); p.y = drawreplxy(r.min.y, r.max.y, p.y); return p; } drawterm-20110822.orig/include/0000755000175000017500000000000011245145711015515 5ustar tinchotinchodrawterm-20110822.orig/include/libc.h0000644000175000017500000000004411245145711016575 0ustar tinchotincho#include "lib.h" #include "user.h" drawterm-20110822.orig/include/cursor.h0000644000175000017500000000010611245145711017200 0ustar tinchotinchostruct Cursor { Point offset; uchar clr[2*16]; uchar set[2*16]; }; drawterm-20110822.orig/include/keyboard.h0000644000175000017500000000163011245145711017466 0ustar tinchotincho#ifdef PLAN9 #pragma src "/sys/src/libdraw" #pragma lib "libdraw.a" #endif typedef struct Keyboardctl Keyboardctl; typedef struct Channel Channel; struct Keyboardctl { Channel *c; /* chan(Rune)[20] */ char *file; int consfd; /* to cons file */ int ctlfd; /* to ctl file */ int pid; /* of slave proc */ }; extern Keyboardctl* initkeyboard(char*); extern int ctlkeyboard(Keyboardctl*, char*); extern void closekeyboard(Keyboardctl*); enum { KF= 0xF000, /* Rune: beginning of private Unicode space */ Spec= 0xF800, /* KF|1, KF|2, ..., KF|0xC is F1, F2, ..., F12 */ Khome= KF|0x0D, Kup= KF|0x0E, Kpgup= KF|0x0F, Kprint= KF|0x10, Kleft= KF|0x11, Kright= KF|0x12, Kdown= Spec|0x00, Kview= Spec|0x00, Kpgdown= KF|0x13, Kins= KF|0x14, Kend= KF|0x18, Kalt= KF|0x15, Kshift= KF|0x16, Kctl= KF|0x17, }; drawterm-20110822.orig/include/unix.h0000644000175000017500000000140011245145711016644 0ustar tinchotincho#undef _FORTIFY_SOURCE /* stupid ubuntu warnings */ #define __BSD_VISIBLE 1 /* FreeBSD 5.x */ #define _BSD_SOURCE 1 #define _NETBSD_SOURCE 1 /* NetBSD */ #define _SVID_SOURCE 1 #if !defined(__APPLE__) && !defined(__OpenBSD__) # define _XOPEN_SOURCE 1000 # define _XOPEN_SOURCE_EXTENDED 1 #endif #define _LARGEFILE64_SOURCE 1 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PTHREAD #include #endif typedef long long p9_vlong; typedef unsigned long long p9_uvlong; typedef uintptr_t uintptr; drawterm-20110822.orig/include/authsrv.h0000644000175000017500000001072211245145711017364 0ustar tinchotincho#ifdef PLAN9 #pragma src "/sys/src/libauthsrv" #pragma lib "libauthsrv.a" #endif /* * Interface for talking to authentication server. */ typedef struct Ticket Ticket; typedef struct Ticketreq Ticketreq; typedef struct Authenticator Authenticator; typedef struct Nvrsafe Nvrsafe; typedef struct Passwordreq Passwordreq; typedef struct OChapreply OChapreply; typedef struct OMSchapreply OMSchapreply; enum { ANAMELEN= 28, /* maximum size of name in previous proto */ AERRLEN= 64, /* maximum size of errstr in previous proto */ DOMLEN= 48, /* length of an authentication domain name */ DESKEYLEN= 7, /* length of a des key for encrypt/decrypt */ CHALLEN= 8, /* length of a plan9 sk1 challenge */ NETCHLEN= 16, /* max network challenge length (used in AS protocol) */ CONFIGLEN= 14, SECRETLEN= 32, /* max length of a secret */ KEYDBOFF= 8, /* length of random data at the start of key file */ OKEYDBLEN= ANAMELEN+DESKEYLEN+4+2, /* length of an entry in old key file */ KEYDBLEN= OKEYDBLEN+SECRETLEN, /* length of an entry in key file */ OMD5LEN= 16, }; /* encryption numberings (anti-replay) */ enum { AuthTreq=1, /* ticket request */ AuthChal=2, /* challenge box request */ AuthPass=3, /* change password */ AuthOK=4, /* fixed length reply follows */ AuthErr=5, /* error follows */ AuthMod=6, /* modify user */ AuthApop=7, /* apop authentication for pop3 */ AuthOKvar=9, /* variable length reply follows */ AuthChap=10, /* chap authentication for ppp */ AuthMSchap=11, /* MS chap authentication for ppp */ AuthCram=12, /* CRAM verification for IMAP (RFC2195 & rfc2104) */ AuthHttp=13, /* http domain login */ AuthVNC=14, /* VNC server login (deprecated) */ AuthTs=64, /* ticket encrypted with server's key */ AuthTc, /* ticket encrypted with client's key */ AuthAs, /* server generated authenticator */ AuthAc, /* client generated authenticator */ AuthTp, /* ticket encrypted with client's key for password change */ AuthHr, /* http reply */ }; struct Ticketreq { char type; char authid[ANAMELEN]; /* server's encryption id */ char authdom[DOMLEN]; /* server's authentication domain */ char chal[CHALLEN]; /* challenge from server */ char hostid[ANAMELEN]; /* host's encryption id */ char uid[ANAMELEN]; /* uid of requesting user on host */ }; #define TICKREQLEN (3*ANAMELEN+CHALLEN+DOMLEN+1) struct Ticket { char num; /* replay protection */ char chal[CHALLEN]; /* server challenge */ char cuid[ANAMELEN]; /* uid on client */ char suid[ANAMELEN]; /* uid on server */ char key[DESKEYLEN]; /* nonce DES key */ }; #define TICKETLEN (CHALLEN+2*ANAMELEN+DESKEYLEN+1) struct Authenticator { char num; /* replay protection */ char chal[CHALLEN]; ulong id; /* authenticator id, ++'d with each auth */ }; #define AUTHENTLEN (CHALLEN+4+1) struct Passwordreq { char num; char old[ANAMELEN]; char new[ANAMELEN]; char changesecret; char secret[SECRETLEN]; /* new secret */ }; #define PASSREQLEN (2*ANAMELEN+1+1+SECRETLEN) struct OChapreply { uchar id; char uid[ANAMELEN]; char resp[OMD5LEN]; }; struct OMSchapreply { char uid[ANAMELEN]; char LMresp[24]; /* Lan Manager response */ char NTresp[24]; /* NT response */ }; /* * convert to/from wire format */ extern int convT2M(Ticket*, char*, char*); extern void convM2T(char*, Ticket*, char*); extern void convM2Tnoenc(char*, Ticket*); extern int convA2M(Authenticator*, char*, char*); extern void convM2A(char*, Authenticator*, char*); extern int convTR2M(Ticketreq*, char*); extern void convM2TR(char*, Ticketreq*); extern int convPR2M(Passwordreq*, char*, char*); extern void convM2PR(char*, Passwordreq*, char*); /* * convert ascii password to DES key */ extern int opasstokey(char*, char*); extern int passtokey(char*, char*); /* * Nvram interface */ enum { NVwrite = 1<<0, /* always prompt and rewrite nvram */ NVwriteonerr = 1<<1, /* prompt and rewrite nvram when corrupt */ }; struct Nvrsafe { char machkey[DESKEYLEN]; uchar machsum; char authkey[DESKEYLEN]; uchar authsum; char config[CONFIGLEN]; uchar configsum; char authid[ANAMELEN]; uchar authidsum; char authdom[DOMLEN]; uchar authdomsum; }; extern uchar nvcsum(void*, int); extern int readnvram(Nvrsafe*, int); /* * call up auth server */ extern int authdial(char *netroot, char *authdom); /* * exchange messages with auth server */ extern int _asgetticket(int, char*, char*); extern int _asrdresp(int, char*, int); extern int sslnegotiate(int, Ticket*, char**, char**); extern int srvsslnegotiate(int, Ticket*, char**, char**); drawterm-20110822.orig/include/user.h0000644000175000017500000000474611245145711016657 0ustar tinchotincho/* sys calls */ #define bind sysbind #define chdir syschdir #define close sysclose #define create syscreate #define dup sysdup #define export sysexport #define fstat sysfstat #define fwstat sysfwstat #define mount sysmount #define open sysopen #define read sysread #define remove sysremove #define seek sysseek #define stat sysstat #define write syswrite #define wstat syswstat #define unmount sysunmount #define pipe syspipe #define rendezvous sysrendezvous #define getpid sysgetpid #define time systime #define nsec sysnsec #define pread syspread #define pwrite syspwrite #undef sleep #define sleep osmsleep extern int bind(char*, char*, int); extern int chdir(char*); extern int close(int); extern int create(char*, int, ulong); extern int dup(int, int); extern int export(int); extern int fstat(int, uchar*, int); extern int fwstat(int, uchar*, int); extern int mount(int, int, char*, int, char*); extern int unmount(char*, char*); extern int open(char*, int); extern int pipe(int*); extern long read(int, void*, long); extern long readn(int, void*, long); extern int remove(char*); extern vlong seek(int, vlong, int); extern int stat(char*, uchar*, int); extern long write(int, void*, long); extern int wstat(char*, uchar*, int); extern void werrstr(char* ,...); extern Dir *dirstat(char*); extern Dir *dirfstat(int); extern int dirwstat(char*, Dir*); extern int dirfwstat(int, Dir*); extern long dirread(int, Dir*, long); extern int lfdfd(int); /* * network dialing and authentication */ #define NETPATHLEN 40 extern int accept(int, char*); extern int announce(char*, char*); extern int dial(char*, char*, char*, int*); extern int hangup(int); extern int listen(char*, char*); extern char *netmkaddr(char*, char*, char*); extern int reject(int, char*, char*); extern char* argv0; extern ulong truerand(void); extern int pushssl(int, char*, char*, char*, int*); extern int iounit(int); extern long pread(int, void*, long, vlong); extern long pwrite(int, void*, long, vlong); extern void* rendezvous(void*, void*); extern int kproc(char*, void(*)(void*), void*); extern int getpid(void); extern void panic(char*, ...); extern void sleep(int); extern void osyield(void); extern void setmalloctag(void*, uintptr); extern int errstr(char*, uint); extern int rerrstr(char*, uint); extern int encrypt(void*, void*, int); extern int decrypt(void*, void*, int); extern void qlock(QLock*); extern void qunlock(QLock*); extern vlong nsec(void); extern void lock(Lock*); extern void unlock(Lock*); extern int iprint(char*, ...); drawterm-20110822.orig/include/lib.h0000644000175000017500000001711511245145711016441 0ustar tinchotincho/* avoid name conflicts */ #define accept pm_accept #define listen pm_listen #define sleep ksleep #define wakeup kwakeup #define strtod fmtstrtod /* conflicts on some os's */ #define encrypt libencrypt #define decrypt libdecrypt #define oserror liboserror #define clone libclone #define atexit libatexit #define log2 liblog2 #define log liblog #define reboot libreboot #define strtoll libstrtoll #undef timeradd #define timeradd xtimeradd #define nil ((void*)0) typedef unsigned char p9_uchar; typedef unsigned int p9_uint; typedef unsigned int p9_ulong; typedef int p9_long; typedef signed char p9_schar; typedef unsigned short p9_ushort; typedef unsigned short Rune; typedef unsigned int p9_u32int; typedef p9_u32int mpdigit; /* make sure we don't conflict with predefined types */ #define schar p9_schar #define uchar p9_uchar #define ushort p9_ushort #define uint p9_uint #define u32int p9_u32int /* #define long int rather than p9_long so that "unsigned long" is valid */ #define long int #define ulong p9_ulong #define vlong p9_vlong #define uvlong p9_uvlong #define nelem(x) (sizeof(x)/sizeof((x)[0])) #define SET(x) ((x)=0) #define USED(x) if(x);else enum { UTFmax = 3, /* maximum bytes per rune */ Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ Runeself = 0x80, /* rune and UTF sequences are the same (<) */ Runeerror = 0x80 /* decoding error in UTF */ }; /* * new rune routines */ extern int runetochar(char*, Rune*); extern int chartorune(Rune*, char*); extern int runelen(long); extern int fullrune(char*, int); extern int wstrtoutf(char*, Rune*, int); extern int wstrutflen(Rune*); /* * rune routines from converted str routines */ extern long utflen(char*); extern char* utfrune(char*, long); extern char* utfrrune(char*, long); /* * Syscall data structures */ #define MORDER 0x0003 /* mask for bits defining order of mounting */ #define MREPL 0x0000 /* mount replaces object */ #define MBEFORE 0x0001 /* mount goes before others in union directory */ #define MAFTER 0x0002 /* mount goes after others in union directory */ #define MCREATE 0x0004 /* permit creation in mounted directory */ #define MCACHE 0x0010 /* cache some data */ #define MMASK 0x0017 /* all bits on */ #define OREAD 0 /* open for read */ #define OWRITE 1 /* write */ #define ORDWR 2 /* read and write */ #define OEXEC 3 /* execute, == read but check execute permission */ #define OTRUNC 16 /* or'ed in (except for exec), truncate file first */ #define OCEXEC 32 /* or'ed in, close on exec */ #define ORCLOSE 64 /* or'ed in, remove on close */ #define OEXCL 0x1000 /* or'ed in, exclusive create */ #define NCONT 0 /* continue after note */ #define NDFLT 1 /* terminate after note */ #define NSAVE 2 /* clear note but hold state */ #define NRSTR 3 /* restore saved state */ #define ERRMAX 128 /* max length of error string */ #define KNAMELEN 28 /* max length of name held in kernel */ /* bits in Qid.type */ #define QTDIR 0x80 /* type bit for directories */ #define QTAPPEND 0x40 /* type bit for append only files */ #define QTEXCL 0x20 /* type bit for exclusive use files */ #define QTMOUNT 0x10 /* type bit for mounted channel */ #define QTAUTH 0x08 /* type bit for authentication file */ #define QTFILE 0x00 /* plain file */ /* bits in Dir.mode */ #define DMDIR 0x80000000 /* mode bit for directories */ #define DMAPPEND 0x40000000 /* mode bit for append only files */ #define DMEXCL 0x20000000 /* mode bit for exclusive use files */ #define DMMOUNT 0x10000000 /* mode bit for mounted channel */ #define DMAUTH 0x08000000 /* mode bit for authentication files */ #define DMREAD 0x4 /* mode bit for read permission */ #define DMWRITE 0x2 /* mode bit for write permission */ #define DMEXEC 0x1 /* mode bit for execute permission */ typedef struct Lock { #ifdef PTHREAD int init; pthread_mutex_t mutex; #else long key; #endif } Lock; typedef struct QLock { Lock lk; struct Proc *hold; struct Proc *first; struct Proc *last; } QLock; typedef struct Qid { uvlong path; ulong vers; uchar type; } Qid; typedef struct Dir { /* system-modified data */ ushort type; /* server type */ uint dev; /* server subtype */ /* file data */ Qid qid; /* unique id from server */ ulong mode; /* permissions */ ulong atime; /* last read time */ ulong mtime; /* last write time */ vlong length; /* file length */ char *name; /* last element of path */ char *uid; /* owner name */ char *gid; /* group name */ char *muid; /* last modifier name */ } Dir; typedef struct Waitmsg { int pid; /* of loved one */ ulong time[3]; /* of loved one & descendants */ char *msg; } Waitmsg; /* * print routines */ typedef struct Fmt Fmt; struct Fmt{ uchar runes; /* output buffer is runes or chars? */ void *start; /* of buffer */ void *to; /* current place in the buffer */ void *stop; /* end of the buffer; overwritten if flush fails */ int (*flush)(Fmt *); /* called when to == stop */ void *farg; /* to make flush a closure */ int nfmt; /* num chars formatted so far */ va_list args; /* args passed to dofmt */ int r; /* % format Rune */ int width; int prec; ulong flags; }; enum{ FmtWidth = 1, FmtLeft = FmtWidth << 1, FmtPrec = FmtLeft << 1, FmtSharp = FmtPrec << 1, FmtSpace = FmtSharp << 1, FmtSign = FmtSpace << 1, FmtZero = FmtSign << 1, FmtUnsigned = FmtZero << 1, FmtShort = FmtUnsigned << 1, FmtLong = FmtShort << 1, FmtVLong = FmtLong << 1, FmtComma = FmtVLong << 1, FmtByte = FmtComma << 1, FmtFlag = FmtByte << 1, FmtLDouble = FmtFlag << 1 }; extern int print(char*, ...); extern char* seprint(char*, char*, char*, ...); extern char* vseprint(char*, char*, char*, va_list); extern int snprint(char*, int, char*, ...); extern int vsnprint(char*, int, char*, va_list); extern char* smprint(char*, ...); extern char* vsmprint(char*, va_list); extern int sprint(char*, char*, ...); extern int fprint(int, char*, ...); extern int vfprint(int, char*, va_list); extern int (*doquote)(int); extern int runesprint(Rune*, char*, ...); extern int runesnprint(Rune*, int, char*, ...); extern int runevsnprint(Rune*, int, char*, va_list); extern Rune* runeseprint(Rune*, Rune*, char*, ...); extern Rune* runevseprint(Rune*, Rune*, char*, va_list); extern Rune* runesmprint(char*, ...); extern Rune* runevsmprint(char*, va_list); extern Rune* runestrchr(Rune*, Rune); extern long runestrlen(Rune*); extern Rune* runestrstr(Rune*, Rune*); extern int fmtfdinit(Fmt*, int, char*, int); extern int fmtfdflush(Fmt*); extern int fmtstrinit(Fmt*); extern int fmtinstall(int, int (*)(Fmt*)); extern char* fmtstrflush(Fmt*); extern int runefmtstrinit(Fmt*); extern Rune* runefmtstrflush(Fmt*); extern int encodefmt(Fmt*); extern int fmtstrcpy(Fmt*, char*); extern int fmtprint(Fmt*, char*, ...); extern int fmtvprint(Fmt*, char*, va_list); extern void* mallocz(ulong, int); extern uintptr getcallerpc(void*); extern char* cleanname(char*); extern void sysfatal(char*, ...); extern char* strecpy(char*, char*, char*); extern int tokenize(char*, char**, int); extern int getfields(char*, char**, int, int, char*); extern char* utfecpy(char*, char*, char*); extern long tas(long*); extern void quotefmtinstall(void); extern int dec64(uchar*, int, char*, int); extern int enc64(char*, int, uchar*, int); extern int dec32(uchar*, int, char*, int); extern int enc32(char*, int, uchar*, int); extern int enc16(char*, int, uchar*, int); void hnputs(void *p, unsigned short v); extern int dofmt(Fmt*, char*); extern double __NaN(void); extern int __isNaN(double); extern double strtod(const char*, char**); extern int utfnlen(char*, long); extern double __Inf(int); extern int __isInf(double, int); extern int (*fmtdoquote)(int); drawterm-20110822.orig/include/x0000644000175000017500000000000011245145711015675 0ustar tinchotinchodrawterm-20110822.orig/include/u.h0000644000175000017500000000052011245145711016127 0ustar tinchotincho#include "dtos.h" /* avoid name conflicts */ #undef accept #undef listen /* sys calls */ #undef bind #undef chdir #undef close #undef create #undef dup #undef export #undef fstat #undef fwstat #undef mount #undef open #undef start #undef read #undef remove #undef seek #undef stat #undef write #undef wstat #undef unmount #undef pipe drawterm-20110822.orig/include/fcall.h0000644000175000017500000000516411245145711016755 0ustar tinchotincho#define VERSION9P "9P2000" #define MAXWELEM 16 typedef struct Fcall { uchar type; u32int fid; ushort tag; u32int msize; /* Tversion, Rversion */ char *version; /* Tversion, Rversion */ ushort oldtag; /* Tflush */ char *ename; /* Rerror */ Qid qid; /* Rattach, Ropen, Rcreate */ u32int iounit; /* Ropen, Rcreate */ Qid aqid; /* Rauth */ u32int afid; /* Tauth, Tattach */ char *uname; /* Tauth, Tattach */ char *aname; /* Tauth, Tattach */ u32int perm; /* Tcreate */ char *name; /* Tcreate */ uchar mode; /* Tcreate, Topen */ u32int newfid; /* Twalk */ ushort nwname; /* Twalk */ char *wname[MAXWELEM]; /* Twalk */ ushort nwqid; /* Rwalk */ Qid wqid[MAXWELEM]; /* Rwalk */ vlong offset; /* Tread, Twrite */ u32int count; /* Tread, Twrite, Rread */ char *data; /* Twrite, Rread */ ushort nstat; /* Twstat, Rstat */ uchar *stat; /* Twstat, Rstat */ } Fcall; #define GBIT8(p) ((p)[0]) #define GBIT16(p) ((p)[0]|((p)[1]<<8)) #define GBIT32(p) ((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) #define GBIT64(p) ((vlong)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\ ((vlong)((p)[4]|((p)[5]<<8)|((p)[6]<<16)|((p)[7]<<24)) << 32)) #define PBIT8(p,v) (p)[0]=(v) #define PBIT16(p,v) (p)[0]=(v);(p)[1]=(v)>>8 #define PBIT32(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24 #define PBIT64(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24;\ (p)[4]=(v)>>32;(p)[5]=(v)>>40;(p)[6]=(v)>>48;(p)[7]=(v)>>56 #define BIT8SZ 1 #define BIT16SZ 2 #define BIT32SZ 4 #define BIT64SZ 8 #define QIDSZ (BIT8SZ+BIT32SZ+BIT64SZ) /* STATFIXLEN includes leading 16-bit count */ /* The count, however, excludes itself; total size is BIT16SZ+count */ #define STATFIXLEN (BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+1*BIT64SZ) /* amount of fixed length data in a stat buffer */ #define NOTAG (ushort)~0U /* Dummy tag */ #define NOFID (u32int)~0U /* Dummy fid */ #define IOHDRSZ 24 /* ample room for Twrite/Rread header (iounit) */ enum { Tversion = 100, Rversion, Tauth = 102, Rauth, Tattach = 104, Rattach, Terror = 106, /* illegal */ Rerror, Tflush = 108, Rflush, Twalk = 110, Rwalk, Topen = 112, Ropen, Tcreate = 114, Rcreate, Tread = 116, Rread, Twrite = 118, Rwrite, Tclunk = 120, Rclunk, Tremove = 122, Rremove, Tstat = 124, Rstat, Twstat = 126, Rwstat, Tmax, }; uint convM2S(uchar*, uint, Fcall*); uint convS2M(Fcall*, uchar*, uint); uint sizeS2M(Fcall*); int statcheck(uchar *abuf, uint nbuf); uint convM2D(uchar*, uint, Dir*, char*); uint convD2M(Dir*, uchar*, uint); uint sizeD2M(Dir*); int fcallfmt(Fmt*); int dirfmt(Fmt*); int dirmodefmt(Fmt*); int read9pmsg(int, void*, uint); drawterm-20110822.orig/include/dtos.h0000644000175000017500000000064011245145711016637 0ustar tinchotincho#if defined(linux) || defined(IRIX) || defined(SOLARIS) || defined(OSF1) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined(__sun) || defined(sun) || defined(__OpenBSD__) # include "unix.h" # ifdef __APPLE__ # define panic dt_panic # endif #elif defined(WINDOWS) # include "9windows.h" # define main mymain #else # error "Define an OS" #endif #ifdef IRIX typedef int socklen_t; #endif drawterm-20110822.orig/include/libsec.h0000644000175000017500000002123511245145711017132 0ustar tinchotincho #ifndef _MPINT typedef struct mpint mpint; #endif ///////////////////////////////////////////////////////// // AES definitions ///////////////////////////////////////////////////////// enum { AESbsize= 16, AESmaxkey= 32, AESmaxrounds= 14 }; typedef struct AESstate AESstate; struct AESstate { ulong setup; int rounds; int keybytes; uchar key[AESmaxkey]; /* unexpanded key */ u32int ekey[4*(AESmaxrounds + 1)]; /* encryption key */ u32int dkey[4*(AESmaxrounds + 1)]; /* decryption key */ uchar ivec[AESbsize]; /* initialization vector */ }; void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec); void aesCBCencrypt(uchar *p, int len, AESstate *s); void aesCBCdecrypt(uchar *p, int len, AESstate *s); ///////////////////////////////////////////////////////// // Blowfish Definitions ///////////////////////////////////////////////////////// enum { BFbsize = 8, BFrounds = 16 }; // 16-round Blowfish typedef struct BFstate BFstate; struct BFstate { ulong setup; uchar key[56]; uchar ivec[8]; u32int pbox[BFrounds+2]; u32int sbox[1024]; }; void setupBFstate(BFstate *s, uchar key[], int keybytes, uchar *ivec); void bfCBCencrypt(uchar*, int, BFstate*); void bfCBCdecrypt(uchar*, int, BFstate*); void bfECBencrypt(uchar*, int, BFstate*); void bfECBdecrypt(uchar*, int, BFstate*); ///////////////////////////////////////////////////////// // DES definitions ///////////////////////////////////////////////////////// enum { DESbsize= 8 }; // single des typedef struct DESstate DESstate; struct DESstate { ulong setup; uchar key[8]; /* unexpanded key */ ulong expanded[32]; /* expanded key */ uchar ivec[8]; /* initialization vector */ }; void setupDESstate(DESstate *s, uchar key[8], uchar *ivec); void des_key_setup(uchar[8], ulong[32]); void block_cipher(ulong*, uchar*, int); void desCBCencrypt(uchar*, int, DESstate*); void desCBCdecrypt(uchar*, int, DESstate*); void desECBencrypt(uchar*, int, DESstate*); void desECBdecrypt(uchar*, int, DESstate*); // for backward compatibility with 7 byte DES key format void des56to64(uchar *k56, uchar *k64); void des64to56(uchar *k64, uchar *k56); void key_setup(uchar[7], ulong[32]); // triple des encrypt/decrypt orderings enum { DES3E= 0, DES3D= 1, DES3EEE= 0, DES3EDE= 2, DES3DED= 5, DES3DDD= 7 }; typedef struct DES3state DES3state; struct DES3state { ulong setup; uchar key[3][8]; /* unexpanded key */ ulong expanded[3][32]; /* expanded key */ uchar ivec[8]; /* initialization vector */ }; void setupDES3state(DES3state *s, uchar key[3][8], uchar *ivec); void triple_block_cipher(ulong keys[3][32], uchar*, int); void des3CBCencrypt(uchar*, int, DES3state*); void des3CBCdecrypt(uchar*, int, DES3state*); void des3ECBencrypt(uchar*, int, DES3state*); void des3ECBdecrypt(uchar*, int, DES3state*); ///////////////////////////////////////////////////////// // digests ///////////////////////////////////////////////////////// enum { SHA1dlen= 20, /* SHA digest length */ MD4dlen= 16, /* MD4 digest length */ MD5dlen= 16 /* MD5 digest length */ }; typedef struct DigestState DigestState; struct DigestState { ulong len; u32int state[5]; uchar buf[128]; int blen; char malloced; char seeded; }; typedef struct DigestState SHAstate; /* obsolete name */ typedef struct DigestState SHA1state; typedef struct DigestState MD5state; typedef struct DigestState MD4state; DigestState* md4(uchar*, ulong, uchar*, DigestState*); DigestState* md5(uchar*, ulong, uchar*, DigestState*); DigestState* sha1(uchar*, ulong, uchar*, DigestState*); DigestState* hmac_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); DigestState* hmac_sha1(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); char* sha1pickle(SHA1state*); SHA1state* sha1unpickle(char*); ///////////////////////////////////////////////////////// // random number generation ///////////////////////////////////////////////////////// void genrandom(uchar *buf, int nbytes); void prng(uchar *buf, int nbytes); ulong fastrand(void); ulong nfastrand(ulong); ///////////////////////////////////////////////////////// // primes ///////////////////////////////////////////////////////// void genprime(mpint *p, int n, int accuracy); // generate an n bit probable prime void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy); // prime and generator void genstrongprime(mpint *p, int n, int accuracy); // generate an n bit strong prime void DSAprimes(mpint *q, mpint *p, uchar seed[SHA1dlen]); int probably_prime(mpint *n, int nrep); // miller-rabin test int smallprimetest(mpint *p); // returns -1 if not prime, 0 otherwise ///////////////////////////////////////////////////////// // rc4 ///////////////////////////////////////////////////////// typedef struct RC4state RC4state; struct RC4state { uchar state[256]; uchar x; uchar y; }; void setupRC4state(RC4state*, uchar*, int); void rc4(RC4state*, uchar*, int); void rc4skip(RC4state*, int); void rc4back(RC4state*, int); ///////////////////////////////////////////////////////// // rsa ///////////////////////////////////////////////////////// typedef struct RSApub RSApub; typedef struct RSApriv RSApriv; // public/encryption key struct RSApub { mpint *n; // modulus mpint *ek; // exp (encryption key) }; // private/decryption key struct RSApriv { RSApub pub; mpint *dk; // exp (decryption key) // precomputed values to help with chinese remainder theorem calc mpint *p; mpint *q; mpint *kp; // dk mod p-1 mpint *kq; // dk mod q-1 mpint *c2; // (inv p) mod q }; RSApriv* rsagen(int nlen, int elen, int rounds); RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q); mpint* rsaencrypt(RSApub *k, mpint *in, mpint *out); mpint* rsadecrypt(RSApriv *k, mpint *in, mpint *out); RSApub* rsapuballoc(void); void rsapubfree(RSApub*); RSApriv* rsaprivalloc(void); void rsaprivfree(RSApriv*); RSApub* rsaprivtopub(RSApriv*); RSApub* X509toRSApub(uchar*, int, char*, int); RSApriv* asn1toRSApriv(uchar*, int); void asn1dump(uchar *der, int len); uchar* decodepem(char *s, char *type, int *len); uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen); uchar* X509req(RSApriv *priv, char *subj, int *certlen); char* X509verify(uchar *cert, int ncert, RSApub *pk); void X509dump(uchar *cert, int ncert); ///////////////////////////////////////////////////////// // elgamal ///////////////////////////////////////////////////////// typedef struct EGpub EGpub; typedef struct EGpriv EGpriv; typedef struct EGsig EGsig; // public/encryption key struct EGpub { mpint *p; // modulus mpint *alpha; // generator mpint *key; // (encryption key) alpha**secret mod p }; // private/decryption key struct EGpriv { EGpub pub; mpint *secret; // (decryption key) }; // signature struct EGsig { mpint *r, *s; }; EGpriv* eggen(int nlen, int rounds); mpint* egencrypt(EGpub *k, mpint *in, mpint *out); mpint* egdecrypt(EGpriv *k, mpint *in, mpint *out); EGsig* egsign(EGpriv *k, mpint *m); int egverify(EGpub *k, EGsig *sig, mpint *m); EGpub* egpuballoc(void); void egpubfree(EGpub*); EGpriv* egprivalloc(void); void egprivfree(EGpriv*); EGsig* egsigalloc(void); void egsigfree(EGsig*); EGpub* egprivtopub(EGpriv*); ///////////////////////////////////////////////////////// // dsa ///////////////////////////////////////////////////////// typedef struct DSApub DSApub; typedef struct DSApriv DSApriv; typedef struct DSAsig DSAsig; // public/encryption key struct DSApub { mpint *p; // modulus mpint *q; // group order, q divides p-1 mpint *alpha; // group generator mpint *key; // (encryption key) alpha**secret mod p }; // private/decryption key struct DSApriv { DSApub pub; mpint *secret; // (decryption key) }; // signature struct DSAsig { mpint *r, *s; }; DSApriv* dsagen(DSApub *opub); DSAsig* dsasign(DSApriv *k, mpint *m); int dsaverify(DSApub *k, DSAsig *sig, mpint *m); DSApub* dsapuballoc(void); void dsapubfree(DSApub*); DSApriv* dsaprivalloc(void); void dsaprivfree(DSApriv*); DSAsig* dsasigalloc(void); void dsasigfree(DSAsig*); DSApub* dsaprivtopub(DSApriv*); ///////////////////////////////////////////////////////// // TLS ///////////////////////////////////////////////////////// typedef struct Thumbprint{ struct Thumbprint *next; uchar sha1[SHA1dlen]; } Thumbprint; typedef struct TLSconn{ char dir[40]; // connection directory uchar *cert; // certificate (local on input, remote on output) uchar *sessionID; int certlen, sessionIDlen; int (*trace)(char*fmt, ...); } TLSconn; // tlshand.c extern int tlsClient(int fd, TLSconn *c); extern int tlsServer(int fd, TLSconn *c); // thumb.c extern Thumbprint* initThumbprints(char *ok, char *crl); extern void freeThumbprints(Thumbprint *ok); extern int okThumbprint(uchar *sha1, Thumbprint *ok); // readcert.c extern uchar *readcert(char *filename, int *pcertlen); drawterm-20110822.orig/include/draw.h0000644000175000017500000003726411245145711016637 0ustar tinchotincho#ifdef PLAN9 #pragma src "/sys/src/libdraw" #pragma lib "libdraw.a" #endif typedef struct Cachefont Cachefont; typedef struct Cacheinfo Cacheinfo; typedef struct Cachesubf Cachesubf; typedef struct Display Display; typedef struct Font Font; typedef struct Fontchar Fontchar; typedef struct Image Image; typedef struct Mouse Mouse; typedef struct Point Point; typedef struct Rectangle Rectangle; typedef struct RGB RGB; typedef struct Screen Screen; typedef struct Subfont Subfont; #ifdef VARARGCK #pragma varargck type "R" Rectangle #pragma varargck type "P" Point #endif extern int Rfmt(Fmt*); extern int Pfmt(Fmt*); enum { DOpaque = 0xFFFFFFFF, DTransparent = 0x00000000, /* only useful for allocimage, memfillcolor */ DBlack = 0x000000FF, DWhite = 0xFFFFFFFF, DRed = 0xFF0000FF, DGreen = 0x00FF00FF, DBlue = 0x0000FFFF, DCyan = 0x00FFFFFF, DMagenta = 0xFF00FFFF, DYellow = 0xFFFF00FF, DPaleyellow = 0xFFFFAAFF, DDarkyellow = 0xEEEE9EFF, DDarkgreen = 0x448844FF, DPalegreen = 0xAAFFAAFF, DMedgreen = 0x88CC88FF, DDarkblue = 0x000055FF, DPalebluegreen= 0xAAFFFFFF, DPaleblue = 0x0000BBFF, DBluegreen = 0x008888FF, DGreygreen = 0x55AAAAFF, DPalegreygreen = 0x9EEEEEFF, DYellowgreen = 0x99994CFF, DMedblue = 0x000099FF, DGreyblue = 0x005DBBFF, DPalegreyblue = 0x4993DDFF, DPurpleblue = 0x8888CCFF, DNotacolor = 0xFFFFFF00, DNofill = DNotacolor, }; enum { Displaybufsize = 8000, ICOSSCALE = 1024, Borderwidth = 4, }; enum { /* refresh methods */ Refbackup = 0, Refnone = 1, Refmesg = 2 }; #define NOREFRESH ((void*)-1) enum { /* line ends */ Endsquare = 0, Enddisc = 1, Endarrow = 2, Endmask = 0x1F }; #define ARROW(a, b, c) (Endarrow|((a)<<5)|((b)<<14)|((c)<<23)) typedef enum { /* Porter-Duff compositing operators */ Clear = 0, SinD = 8, DinS = 4, SoutD = 2, DoutS = 1, S = SinD|SoutD, SoverD = SinD|SoutD|DoutS, SatopD = SinD|DoutS, SxorD = SoutD|DoutS, D = DinS|DoutS, DoverS = DinS|DoutS|SoutD, DatopS = DinS|SoutD, DxorS = DoutS|SoutD, /* == SxorD */ Ncomp = 12, } Drawop; /* * image channel descriptors */ enum { CRed = 0, CGreen, CBlue, CGrey, CAlpha, CMap, CIgnore, NChan, }; #define __DC(type, nbits) ((((type)&15)<<4)|((nbits)&15)) #define CHAN1(a,b) __DC(a,b) #define CHAN2(a,b,c,d) (CHAN1((a),(b))<<8|__DC((c),(d))) #define CHAN3(a,b,c,d,e,f) (CHAN2((a),(b),(c),(d))<<8|__DC((e),(f))) #define CHAN4(a,b,c,d,e,f,g,h) (CHAN3((a),(b),(c),(d),(e),(f))<<8|__DC((g),(h))) #define NBITS(c) ((c)&15) #define TYPE(c) (((c)>>4)&15) enum { GREY1 = CHAN1(CGrey, 1), GREY2 = CHAN1(CGrey, 2), GREY4 = CHAN1(CGrey, 4), GREY8 = CHAN1(CGrey, 8), CMAP8 = CHAN1(CMap, 8), RGB15 = CHAN4(CIgnore, 1, CRed, 5, CGreen, 5, CBlue, 5), RGB16 = CHAN3(CRed, 5, CGreen, 6, CBlue, 5), RGB24 = CHAN3(CRed, 8, CGreen, 8, CBlue, 8), BGR24 = CHAN3(CBlue, 8, CGreen, 8, CRed, 8), RGBA32 = CHAN4(CRed, 8, CGreen, 8, CBlue, 8, CAlpha, 8), ARGB32 = CHAN4(CAlpha, 8, CRed, 8, CGreen, 8, CBlue, 8), /* stupid VGAs */ XRGB32 = CHAN4(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8), XBGR32 = CHAN4(CIgnore, 8, CBlue, 8, CGreen, 8, CRed, 8), }; extern char* chantostr(char*, ulong); extern ulong strtochan(char*); extern int chantodepth(ulong); struct Point { int x; int y; }; struct Rectangle { Point min; Point max; }; typedef void (*Reffn)(Image*, Rectangle, void*); struct Screen { Display *display; /* display holding data */ int id; /* id of system-held Screen */ Image *image; /* unused; for reference only */ Image *fill; /* color to paint behind windows */ }; struct Display { QLock qlock; int locking; /*program is using lockdisplay */ int dirno; int fd; int reffd; int ctlfd; int imageid; int local; void (*error)(Display*, char*); char *devdir; char *windir; char oldlabel[64]; ulong dataqid; Image *white; Image *black; Image *opaque; Image *transparent; Image *image; uchar *buf; int bufsize; uchar *bufp; Font *defaultfont; Subfont *defaultsubfont; Image *windows; Image *screenimage; int _isnewdisplay; }; struct Image { Display *display; /* display holding data */ int id; /* id of system-held Image */ Rectangle r; /* rectangle in data area, local coords */ Rectangle clipr; /* clipping region */ int depth; /* number of bits per pixel */ ulong chan; int repl; /* flag: data replicates to tile clipr */ Screen *screen; /* 0 if not a window */ Image *next; /* next in list of windows */ }; struct RGB { ulong red; ulong green; ulong blue; }; /* * Subfonts * * given char c, Subfont *f, Fontchar *i, and Point p, one says * i = f->info+c; * draw(b, Rect(p.x+i->left, p.y+i->top, * p.x+i->left+((i+1)->x-i->x), p.y+i->bottom), * color, f->bits, Pt(i->x, i->top)); * p.x += i->width; * to draw characters in the specified color (itself an Image) in Image b. */ struct Fontchar { int x; /* left edge of bits */ uchar top; /* first non-zero scan-line */ uchar bottom; /* last non-zero scan-line + 1 */ char left; /* offset of baseline */ uchar width; /* width of baseline */ }; struct Subfont { char *name; short n; /* number of chars in font */ uchar height; /* height of image */ char ascent; /* top of image to baseline */ Fontchar *info; /* n+1 character descriptors */ Image *bits; /* of font */ int ref; }; enum { /* starting values */ LOG2NFCACHE = 6, NFCACHE = (1<>8)) #define BPLONG(p, v) (BPSHORT(p, (v)), BPSHORT(p+2, (v)>>16)) /* * Compressed image file parameters and helper routines */ #define NMATCH 3 /* shortest match possible */ #define NRUN (NMATCH+31) /* longest match possible */ #define NMEM 1024 /* window size */ #define NDUMP 128 /* maximum length of dump */ #define NCBLOCK 6000 /* size of compressed blocks */ extern void _twiddlecompressed(uchar*, int); extern int _compblocksize(Rectangle, int); /* XXX backwards helps; should go */ extern int log2[]; extern ulong drawld2chan[]; extern void drawsetdebug(int); drawterm-20110822.orig/include/mp.h0000644000175000017500000001065411245145711016310 0ustar tinchotincho#define _MPINT 1 // the code assumes mpdigit to be at least an int // mpdigit must be an atomic type. mpdigit is defined // in the architecture specific u.h typedef struct mpint mpint; struct mpint { int sign; // +1 or -1 int size; // allocated digits int top; // significant digits mpdigit *p; char flags; }; enum { MPstatic= 0x01, Dbytes= sizeof(mpdigit), // bytes per digit Dbits= Dbytes*8 // bits per digit }; // allocation void mpsetminbits(int n); // newly created mpint's get at least n bits mpint* mpnew(int n); // create a new mpint with at least n bits void mpfree(mpint *b); void mpbits(mpint *b, int n); // ensure that b has at least n bits void mpnorm(mpint *b); // dump leading zeros mpint* mpcopy(mpint *b); void mpassign(mpint *old, mpint *new); // random bits mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b); // conversion mpint* strtomp(char*, char**, int, mpint*); // ascii int mpfmt(Fmt*); char* mptoa(mpint*, int, char*, int); mpint* letomp(uchar*, uint, mpint*); // byte array, little-endian int mptole(mpint*, uchar*, uint, uchar**); mpint* betomp(uchar*, uint, mpint*); // byte array, little-endian int mptobe(mpint*, uchar*, uint, uchar**); uint mptoui(mpint*); // unsigned int mpint* uitomp(uint, mpint*); int mptoi(mpint*); // int mpint* itomp(int, mpint*); uvlong mptouv(mpint*); // unsigned vlong mpint* uvtomp(uvlong, mpint*); vlong mptov(mpint*); // vlong mpint* vtomp(vlong, mpint*); // divide 2 digits by one void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient); // in the following, the result mpint may be // the same as one of the inputs. void mpadd(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2 void mpsub(mpint *b1, mpint *b2, mpint *diff); // diff = b1-b2 void mpleft(mpint *b, int shift, mpint *res); // res = b<>shift void mpmul(mpint *b1, mpint *b2, mpint *prod); // prod = b1*b2 void mpexp(mpint *b, mpint *e, mpint *m, mpint *res); // res = b**e mod m void mpmod(mpint *b, mpint *m, mpint *remainder); // remainder = b mod m // quotient = dividend/divisor, remainder = dividend % divisor void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder); // return neg, 0, pos as b1-b2 is neg, 0, pos int mpcmp(mpint *b1, mpint *b2); // extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d void mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y); // res = b**-1 mod m void mpinvert(mpint *b, mpint *m, mpint *res); // bit counting int mpsignif(mpint*); // number of sigificant bits in mantissa int mplowbits0(mpint*); // k, where n = 2**k * q for odd q // well known constants extern mpint *mpzero, *mpone, *mptwo; // sum[0:alen] = a[0:alen-1] + b[0:blen-1] // prereq: alen >= blen, sum has room for alen+1 digits void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum); // diff[0:alen-1] = a[0:alen-1] - b[0:blen-1] // prereq: alen >= blen, diff has room for alen digits void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff); // p[0:n] += m * b[0:n-1] // prereq: p has room for n+1 digits void mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p); // p[0:n] -= m * b[0:n-1] // prereq: p has room for n+1 digits int mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p); // p[0:alen*blen-1] = a[0:alen-1] * b[0:blen-1] // prereq: alen >= blen, p has room for m*n digits void mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p); // sign of a - b or zero if the same int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen); // divide the 2 digit dividend by the one digit divisor and stick in quotient // we assume that the result is one digit - overflow is all 1's void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient); // playing with magnitudes int mpmagcmp(mpint *b1, mpint *b2); void mpmagadd(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2 void mpmagsub(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2 // chinese remainder theorem typedef struct CRTpre CRTpre; // precomputed values for converting // twixt residues and mpint typedef struct CRTres CRTres; // residue form of an mpint struct CRTres { int n; // number of residues mpint *r[1]; // residues }; CRTpre* crtpre(int, mpint**); // precompute conversion values CRTres* crtin(CRTpre*, mpint*); // convert mpint to residues void crtout(CRTpre*, CRTres*, mpint*); // convert residues to mpint void crtprefree(CRTpre*); void crtresfree(CRTres*); drawterm-20110822.orig/include/auth.h0000644000175000017500000000672211245145711016636 0ustar tinchotincho#ifdef PLAN9 #pragma src "/sys/src/libauth" #pragma lib "libauth.a" #endif /* * Interface for typical callers. */ typedef struct AuthInfo AuthInfo; typedef struct Chalstate Chalstate; typedef struct Chapreply Chapreply; typedef struct MSchapreply MSchapreply; typedef struct UserPasswd UserPasswd; typedef struct AuthRpc AuthRpc; enum { MAXCHLEN= 256, /* max challenge length */ AMAXNAMELEN= 256, /* maximum name length */ MD5LEN= 16, ARok = 0, /* rpc return values */ ARdone, ARerror, ARneedkey, ARbadkey, ARwritenext, ARtoosmall, ARtoobig, ARrpcfailure, ARphase, AuthRpcMax = 4096, }; struct AuthRpc { int afd; char ibuf[AuthRpcMax]; char obuf[AuthRpcMax]; char *arg; uint narg; }; struct AuthInfo { char *cuid; /* caller id */ char *suid; /* server id */ char *cap; /* capability (only valid on server side) */ int nsecret; /* length of secret */ uchar *secret; /* secret */ }; struct Chalstate { char *user; char chal[MAXCHLEN]; int nchal; void *resp; int nresp; /* for implementation only */ int afd; /* to factotum */ AuthRpc *rpc; /* to factotum */ char userbuf[AMAXNAMELEN]; /* temp space if needed */ int userinchal; /* user was sent to obtain challenge */ }; struct Chapreply /* for protocol "chap" */ { uchar id; char resp[MD5LEN]; }; struct MSchapreply /* for protocol "mschap" */ { char LMresp[24]; /* Lan Manager response */ char NTresp[24]; /* NT response */ }; struct UserPasswd { char *user; char *passwd; }; extern int newns(char*, char*); extern int addns(char*, char*); extern int noworld(char*); extern int amount(int, char*, int, char*); /* these two may get generalized away -rsc */ extern int login(char*, char*, char*); extern int httpauth(char*, char*); typedef struct Attr Attr; typedef struct String String; enum { AttrNameval, /* name=val -- when matching, must have name=val */ AttrQuery, /* name? -- when matching, must be present */ AttrDefault, /* name:=val -- when matching, if present must match INTERNAL */ }; struct Attr { int type; Attr *next; char *name; char *val; }; typedef int AuthGetkey(char*); int _attrfmt(Fmt*); Attr *_copyattr(Attr*); Attr *_delattr(Attr*, char*); Attr *_findattr(Attr*, char*); void _freeattr(Attr*); Attr *_mkattr(int, char*, char*, Attr*); Attr *_parseattr(char*); char *_strfindattr(Attr*, char*); #ifdef VARARGCK #pragma varargck type "A" Attr* #endif extern AuthInfo* fauth_proxy(int, AuthRpc *rpc, AuthGetkey *getkey, char *params); extern AuthInfo* auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...); extern int auth_getkey(char*); extern int (*amount_getkey)(char*); extern void auth_freeAI(AuthInfo *ai); extern int auth_chuid(AuthInfo *ai, char *ns); extern Chalstate *auth_challenge(char*, ...); extern AuthInfo* auth_response(Chalstate*); extern int auth_respond(void*, uint, char*, uint, void*, uint, AuthGetkey *getkey, char*, ...); extern void auth_freechal(Chalstate*); extern AuthInfo* auth_userpasswd(char *user, char *passwd); extern UserPasswd* auth_getuserpasswd(AuthGetkey *getkey, char*, ...); extern AuthInfo* auth_getinfo(AuthRpc *rpc); extern AuthRpc* auth_allocrpc(int afd); extern Attr* auth_attr(AuthRpc *rpc); extern void auth_freerpc(AuthRpc *rpc); extern uint auth_rpc(AuthRpc *rpc, char *verb, void *a, int n); extern int auth_wep(char*, char*, ...); #ifdef VARARGCK #pragma varargck argpos auth_proxy 3 #pragma varargck argpos auth_challenge 1 #pragma varargck argpos auth_respond 3 #pragma varargck argpos auth_getuserpasswd 2 #endif drawterm-20110822.orig/include/x.c0000644000175000017500000000005011245145711016123 0ustar tinchotincho#include void main(void) { } drawterm-20110822.orig/include/memdraw.h0000644000175000017500000001424211245145711017325 0ustar tinchotincho#ifdef PLAN9 #pragma src "/sys/src/libmemdraw" #pragma lib "libmemdraw.a" #endif typedef struct Memimage Memimage; typedef struct Memdata Memdata; typedef struct Memsubfont Memsubfont; typedef struct Memlayer Memlayer; typedef struct Memcmap Memcmap; typedef struct Memdrawparam Memdrawparam; /* * Memdata is allocated from main pool, but .data from the image pool. * Memdata is allocated separately to permit patching its pointer after * compaction when windows share the image data. * The first word of data is a back pointer to the Memdata, to find * The word to patch. */ struct Memdata { ulong *base; /* allocated data pointer */ uchar *bdata; /* pointer to first byte of actual data; word-aligned */ int ref; /* number of Memimages using this data */ void* imref; int allocd; /* is this malloc'd? */ }; enum { Frepl = 1<<0, /* is replicated */ Fsimple = 1<<1, /* is 1x1 */ Fgrey = 1<<2, /* is grey */ Falpha = 1<<3, /* has explicit alpha */ Fcmap = 1<<4, /* has cmap channel */ Fbytes = 1<<5, /* has only 8-bit channels */ }; struct Memimage { Rectangle r; /* rectangle in data area, local coords */ Rectangle clipr; /* clipping region */ int depth; /* number of bits of storage per pixel */ int nchan; /* number of channels */ ulong chan; /* channel descriptions */ Memcmap *cmap; Memdata *data; /* pointer to data; shared by windows in this image */ int zero; /* data->bdata+zero==&byte containing (0,0) */ ulong width; /* width in words of a single scan line */ Memlayer *layer; /* nil if not a layer*/ ulong flags; int shift[NChan]; int mask[NChan]; int nbits[NChan]; void *X; }; struct Memcmap { uchar cmap2rgb[3*256]; uchar rgb2cmap[16*16*16]; }; /* * Subfonts * * given char c, Subfont *f, Fontchar *i, and Point p, one says * i = f->info+c; * draw(b, Rect(p.x+i->left, p.y+i->top, * p.x+i->left+((i+1)->x-i->x), p.y+i->bottom), * color, f->bits, Pt(i->x, i->top)); * p.x += i->width; * to draw characters in the specified color (itself a Memimage) in Memimage b. */ struct Memsubfont { char *name; short n; /* number of chars in font */ uchar height; /* height of bitmap */ char ascent; /* top of bitmap to baseline */ Fontchar *info; /* n+1 character descriptors */ Memimage *bits; /* of font */ }; /* * Encapsulated parameters and information for sub-draw routines. */ enum { Simplesrc=1<<0, Simplemask=1<<1, Replsrc=1<<2, Replmask=1<<3, Fullmask=1<<4, }; struct Memdrawparam { Memimage *dst; Rectangle r; Memimage *src; Rectangle sr; Memimage *mask; Rectangle mr; int op; ulong state; ulong mval; /* if Simplemask, the mask pixel in mask format */ ulong mrgba; /* mval in rgba */ ulong sval; /* if Simplesrc, the source pixel in src format */ ulong srgba; /* sval in rgba */ ulong sdval; /* sval in dst format */ }; /* * Memimage management */ extern Memimage* allocmemimage(Rectangle, ulong); extern Memimage* _allocmemimage(Rectangle, ulong); extern Memimage* allocmemimaged(Rectangle, ulong, Memdata*, void*); extern Memimage* readmemimage(int); extern Memimage* creadmemimage(int); extern int writememimage(int, Memimage*); extern void freememimage(Memimage*); extern void _freememimage(Memimage*); extern int _loadmemimage(Memimage*, Rectangle, uchar*, int); extern int _cloadmemimage(Memimage*, Rectangle, uchar*, int); extern int _unloadmemimage(Memimage*, Rectangle, uchar*, int); extern int loadmemimage(Memimage*, Rectangle, uchar*, int); extern int cloadmemimage(Memimage*, Rectangle, uchar*, int); extern int unloadmemimage(Memimage*, Rectangle, uchar*, int); extern ulong* wordaddr(Memimage*, Point); extern uchar* byteaddr(Memimage*, Point); extern int drawclip(Memimage*, Rectangle*, Memimage*, Point*, Memimage*, Point*, Rectangle*, Rectangle*); extern void memfillcolor(Memimage*, ulong); extern void _memfillcolor(Memimage*, ulong); extern int memsetchan(Memimage*, ulong); extern ulong _rgbatoimg(Memimage*, ulong); /* * Graphics */ extern void memdraw(Memimage*, Rectangle, Memimage*, Point, Memimage*, Point, int); extern void memline(Memimage*, Point, Point, int, int, int, Memimage*, Point, int); extern void mempoly(Memimage*, Point*, int, int, int, int, Memimage*, Point, int); extern void memfillpoly(Memimage*, Point*, int, int, Memimage*, Point, int); extern void _memfillpolysc(Memimage*, Point*, int, int, Memimage*, Point, int, int, int, int); extern Memdrawparam* _memimagedrawsetup(Memimage*, Rectangle, Memimage*, Point, Memimage*, Point, int); extern void _memimagedraw(Memdrawparam*); extern void memimagedraw(Memimage*, Rectangle, Memimage*, Point, Memimage*, Point, int); extern int hwdraw(Memdrawparam*); extern void memimageline(Memimage*, Point, Point, int, int, int, Memimage*, Point, int); extern void _memimageline(Memimage*, Point, Point, int, int, int, Memimage*, Point, Rectangle, int); extern Point memimagestring(Memimage*, Point, Memimage*, Point, Memsubfont*, char*); extern void memellipse(Memimage*, Point, int, int, int, Memimage*, Point, int); extern void memarc(Memimage*, Point, int, int, int, Memimage*, Point, int, int, int); extern Rectangle memlinebbox(Point, Point, int, int, int); extern int memlineendsize(int); extern void _memmkcmap(void); extern void _memimageinit(void); extern void memimageinit(void); /* * Subfont management */ extern Memsubfont* allocmemsubfont(char*, int, int, int, Fontchar*, Memimage*); extern Memsubfont* openmemsubfont(char*); extern void freememsubfont(Memsubfont*); extern Point memsubfontwidth(Memsubfont*, char*); extern Memsubfont* getmemdefont(void); /* * Predefined */ extern Memimage* memwhite; extern Memimage* memblack; extern Memimage* memopaque; extern Memimage* memtransparent; extern Memcmap *memdefcmap; /* * Kernel interface */ void memimagemove(void*, void*); /* * Kernel cruft */ extern void rdb(void); extern int iprint(char*, ...); extern int drawdebug; /* * doprint interface: numbconv bit strings */ #ifdef VARARGCK #pragma varargck argpos iprint 1 #pragma varargck type "llb" vlong #pragma varargck type "llb" uvlong #pragma varargck type "lb" long #pragma varargck type "lb" ulong #pragma varargck type "b" int #pragma varargck type "b" uint #endif extern ulong _pixelbits(Memimage*,Point); extern ulong pixelbits(Memimage*, Point); drawterm-20110822.orig/include/9windows.h0000644000175000017500000000067611245145711017462 0ustar tinchotincho#include #include #include #include #include #include #include #include #include #include #include #include /* disable various silly warnings */ #ifdef MSVC #pragma warning( disable : 4245 4305 4244 4102 4761 4090 4028 4024) #endif typedef __int64 p9_vlong; typedef unsigned __int64 p9_uvlong; typedef unsigned uintptr; drawterm-20110822.orig/include/memlayer.h0000644000175000017500000000351711245145711017507 0ustar tinchotincho#ifdef PLAN9 #pragma src "/sys/src/libmemlayer" #pragma lib "libmemlayer.a" #endif typedef struct Memscreen Memscreen; typedef void (*Refreshfn)(Memimage*, Rectangle, void*); struct Memscreen { Memimage *frontmost; /* frontmost layer on screen */ Memimage *rearmost; /* rearmost layer on screen */ Memimage *image; /* upon which all layers are drawn */ Memimage *fill; /* if non-zero, picture to use when repainting */ }; struct Memlayer { Rectangle screenr; /* true position of layer on screen */ Point delta; /* add delta to go from image coords to screen */ Memscreen *screen; /* screen this layer belongs to */ Memimage *front; /* window in front of this one */ Memimage *rear; /* window behind this one*/ int clear; /* layer is fully visible */ Memimage *save; /* save area for obscured parts */ Refreshfn refreshfn; /* function to call to refresh obscured parts if save==nil */ void *refreshptr; /* argument to refreshfn */ }; /* * These functions accept local coordinates */ int memload(Memimage*, Rectangle, uchar*, int, int); int memunload(Memimage*, Rectangle, uchar*, int); /* * All these functions accept screen coordinates, not local ones. */ void _memlayerop(void (*fn)(Memimage*, Rectangle, Rectangle, void*, int), Memimage*, Rectangle, Rectangle, void*); Memimage* memlalloc(Memscreen*, Rectangle, Refreshfn, void*, ulong); void memldelete(Memimage*); void memlfree(Memimage*); void memltofront(Memimage*); void memltofrontn(Memimage**, int); void _memltofrontfill(Memimage*, int); void memltorear(Memimage*); void memltorearn(Memimage**, int); int memlsetrefresh(Memimage*, Refreshfn, void*); void memlhide(Memimage*, Rectangle); void memlexpose(Memimage*, Rectangle); void _memlsetclear(Memscreen*); int memlorigin(Memimage*, Point, Point); void memlnorefresh(Memimage*, Rectangle, void*); drawterm-20110822.orig/drawterm.ico0000644000175000017500000000317611245145711016422 0ustar tinchotincho00h(0`"""333DDDUUUfffwwwܺU˗uUDfTiݹuTVVtV|˨SFX̨JʇeCGݸjۋZ݆ffhi[wˈuJXܦ[YYYiGweۆݦhܖۇzݦݸXݦWܷwݶ݆xݖݕ}܇dLۈًwHيۼȜݹDݷ۷|ݗۻݗ{ܘݘݬݘ܊(ݙzݙ݈݉܊gڊxȜNjiܘݘʉۛQ)˙ɽ"}˘A&ͩʙʵ$ۛ2ݻj͸wʽډr|jڛ˨Uݺۊxw˻ۗxɊݘܫdrawterm-20110822.orig/drawterm.res0000644000175000017500000000333411245145711016435 0ustar tinchotincho h 0 (0`"""333DDDUUUfffwwwܺU˗uUDfTiݹuTVVtV|˨SFX̨JʇeCGݸjۋZ݆ffhi[wˈuJXܦ[YYYiGweۆݦhܖۇzݦݸXݦWܷwݶ݆xݖݕ}܇dLۈًwHيۼȜݹDݷ۷|ݗۻݗ{ܘݘݬݘ܊(ݙzݙ݈݉܊gڊxȜNjiܘݘʉۛQ)˙ɽ"}˘A&ͩʙʵ$ۛ2ݻj͸wʽډr|jڛ˨Uݺۊxw˻ۗxɊݘܫ e0 00hdrawterm-20110822.orig/posix-amd64/0000755000175000017500000000000011245145712016146 5ustar tinchotinchodrawterm-20110822.orig/posix-amd64/tas.c0000644000175000017500000000042111245145712017076 0ustar tinchotincho#include "u.h" #include "libc.h" int tas(long *x) { int v; __asm__( "movl $1, %%eax\n\t" "xchgl %%eax,(%%rcx)" : "=a" (v) : "c" (x) ); switch(v) { case 0: case 1: return v; default: print("canlock: corrupted 0x%lux\n", v); return 1; } } drawterm-20110822.orig/posix-amd64/md5block.c0000644000175000017500000001165011245145712020015 0ustar tinchotincho#include #include #include /* * rfc1321 requires that I include this. The code is new. The constants * all come from the rfc (hence the copyright). We trade a table for the * macros in rfc. The total size is a lot less. -- presotto * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software forany particular purpose. It is provided "as is" * without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this * documentation and/or software. */ /* * Rotate ammounts used in the algorithm */ enum { S11= 7, S12= 12, S13= 17, S14= 22, S21= 5, S22= 9, S23= 14, S24= 20, S31= 4, S32= 11, S33= 16, S34= 23, S41= 6, S42= 10, S43= 15, S44= 21, }; static u32int md5tab[] = { /* round 1 */ /*[0]*/ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, /* round 2 */ /*[16]*/0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, /* round 3 */ /*[32]*/0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, /* round 4 */ /*[48]*/0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static void decode(u32int*, uchar*, ulong); extern void _md5block(uchar *p, ulong len, u32int *s); void _md5block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, sh; u32int *t; uchar *end; u32int x[16]; for(end = p+len; p < end; p += 64){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; decode(x, p, 64); t = md5tab; sh = 0; for(; sh != 16; t += 4){ a += ((c ^ d) & b) ^ d; a += x[sh] + t[0]; a = (a << S11) | (a >> (32 - S11)); a += b; d += ((b ^ c) & a) ^ c; d += x[sh + 1] + t[1]; d = (d << S12) | (d >> (32 - S12)); d += a; c += ((a ^ b) & d) ^ b; c += x[sh + 2] + t[2]; c = (c << S13) | (c >> (32 - S13)); c += d; b += ((d ^ a) & c) ^ a; b += x[sh + 3] + t[3]; b = (b << S14) | (b >> (32 - S14)); b += c; sh += 4; } sh = 1; for(; sh != 1+20*4; t += 4){ a += ((b ^ c) & d) ^ c; a += x[sh & 0xf] + t[0]; a = (a << S21) | (a >> (32 - S21)); a += b; d += ((a ^ b) & c) ^ b; d += x[(sh + 5) & 0xf] + t[1]; d = (d << S22) | (d >> (32 - S22)); d += a; c += ((d ^ a) & b) ^ a; c += x[(sh + 10) & 0xf] + t[2]; c = (c << S23) | (c >> (32 - S23)); c += d; b += ((c ^ d) & a) ^ d; b += x[(sh + 15) & 0xf] + t[3]; b = (b << S24) | (b >> (32 - S24)); b += c; sh += 20; } sh = 5; for(; sh != 5+12*4; t += 4){ a += b ^ c ^ d; a += x[sh & 0xf] + t[0]; a = (a << S31) | (a >> (32 - S31)); a += b; d += a ^ b ^ c; d += x[(sh + 3) & 0xf] + t[1]; d = (d << S32) | (d >> (32 - S32)); d += a; c += d ^ a ^ b; c += x[(sh + 6) & 0xf] + t[2]; c = (c << S33) | (c >> (32 - S33)); c += d; b += c ^ d ^ a; b += x[(sh + 9) & 0xf] + t[3]; b = (b << S34) | (b >> (32 - S34)); b += c; sh += 12; } sh = 0; for(; sh != 28*4; t += 4){ a += c ^ (b | ~d); a += x[sh & 0xf] + t[0]; a = (a << S41) | (a >> (32 - S41)); a += b; d += b ^ (a | ~c); d += x[(sh + 7) & 0xf] + t[1]; d = (d << S42) | (d >> (32 - S42)); d += a; c += a ^ (d | ~b); c += x[(sh + 14) & 0xf] + t[2]; c = (c << S43) | (c >> (32 - S43)); c += d; b += d ^ (c | ~a); b += x[(sh + 21) & 0xf] + t[3]; b = (b << S44) | (b >> (32 - S44)); b += c; sh += 28; } s[0] += a; s[1] += b; s[2] += c; s[3] += d; } } /* * decodes input (uchar) into output (u32int). Assumes len is * a multiple of 4. */ static void decode(u32int *output, uchar *input, ulong len) { uchar *e; for(e = input+len; input < e; input += 4) *output++ = input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24); } drawterm-20110822.orig/posix-amd64/Makefile0000644000175000017500000000034311245145712017606 0ustar tinchotinchoROOT=.. include ../Make.config LIB=../libmachdep.a OFILES=\ getcallerpc.$O\ md5block.$O\ sha1block.$O\ tas.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-20110822.orig/posix-amd64/sha1block.c0000644000175000017500000001114611245145712020164 0ustar tinchotincho#include #include #include void _sha1block(uchar *p, ulong len, u32int *s) { u32int a, b, c, d, e, x; uchar *end; u32int *wp, *wend; u32int w[80]; /* at this point, we have a multiple of 64 bytes */ for(end = p+len; p < end;){ a = s[0]; b = s[1]; c = s[2]; d = s[3]; e = s[4]; wend = w + 15; for(wp = w; wp < wend; wp += 5){ wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); wp[1] = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7]; d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); wp[2] = (p[8]<<24) | (p[9]<<16) | (p[10]<<8) | p[11]; c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); wp[3] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15]; b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); wp[4] = (p[16]<<24) | (p[17]<<16) | (p[18]<<8) | p[19]; a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); p += 20; } wp[0] = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; e += ((a<<5) | (a>>27)) + wp[0]; e += 0x5a827999 + (((c^d)&b)^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x5a827999 + (((b^c)&a)^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x5a827999 + (((a^b)&e)^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x5a827999 + (((e^a)&d)^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x5a827999 + (((d^e)&c)^e); c = (c<<30)|(c>>2); wp += 5; p += 4; wend = w + 40; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x6ed9eba1 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x6ed9eba1 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x6ed9eba1 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x6ed9eba1 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x6ed9eba1 + (c^d^e); c = (c<<30)|(c>>2); } wend = w + 60; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0x8f1bbcdc + ((b&c)|((b|c)&d)); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0x8f1bbcdc + ((a&b)|((a|b)&c)); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0x8f1bbcdc + ((e&a)|((e|a)&b)); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0x8f1bbcdc + ((d&e)|((d|e)&a)); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0x8f1bbcdc + ((c&d)|((c|d)&e)); c = (c<<30)|(c>>2); } wend = w + 80; for(; wp < wend; wp += 5){ x = wp[-3] ^ wp[-8] ^ wp[-14] ^ wp[-16]; wp[0] = (x<<1) | (x>>31); e += ((a<<5) | (a>>27)) + wp[0]; e += 0xca62c1d6 + (b^c^d); b = (b<<30)|(b>>2); x = wp[-2] ^ wp[-7] ^ wp[-13] ^ wp[-15]; wp[1] = (x<<1) | (x>>31); d += ((e<<5) | (e>>27)) + wp[1]; d += 0xca62c1d6 + (a^b^c); a = (a<<30)|(a>>2); x = wp[-1] ^ wp[-6] ^ wp[-12] ^ wp[-14]; wp[2] = (x<<1) | (x>>31); c += ((d<<5) | (d>>27)) + wp[2]; c += 0xca62c1d6 + (e^a^b); e = (e<<30)|(e>>2); x = wp[0] ^ wp[-5] ^ wp[-11] ^ wp[-13]; wp[3] = (x<<1) | (x>>31); b += ((c<<5) | (c>>27)) + wp[3]; b += 0xca62c1d6 + (d^e^a); d = (d<<30)|(d>>2); x = wp[1] ^ wp[-4] ^ wp[-10] ^ wp[-12]; wp[4] = (x<<1) | (x>>31); a += ((b<<5) | (b>>27)) + wp[4]; a += 0xca62c1d6 + (c^d^e); c = (c<<30)|(c>>2); } /* save state */ s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; } } drawterm-20110822.orig/posix-amd64/getcallerpc.c0000644000175000017500000000013611245145712020577 0ustar tinchotincho#include "u.h" #include "libc.h" uintptr getcallerpc(void *a) { return ((uintptr*)a)[-1]; }