123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "dat.h"
- #include <draw.h>
- #include <mouse.h>
- #include <keyboard.h>
- #include <control.h>
- int ctldeletequits = 1;
- typedef struct RequestType RequestType;
- typedef struct Request Request;
- typedef struct Memory Memory;
- struct RequestType
- {
- char *file; /* file to read requests from */
- void (*f)(Request*); /* request handler */
- void (*r)(Controlset*); /* resize handler */
- int fd; /* fd = open(file, ORDWR) */
- Channel *rc; /* channel requests are multiplexed to */
- Controlset *cs;
- };
- struct Request
- {
- RequestType *rt;
- Attr *a;
- Attr *tag;
- };
- struct Memory
- {
- Memory *next;
- Attr *a;
- Attr *val;
- };
- Memory *mem;
- static void readreq(void*);
- static void hide(void);
- static void unhide(void);
- static void openkmr(void);
- static void closekmr(void);
- static Memory* searchmem(Attr*);
- static void addmem(Attr*, Attr*);
- static void confirm(Request*);
- static void resizeconfirm(Controlset*);
- static void needkey(Request*);
- static void resizeneedkey(Controlset*);
- Control *b_remember;
- Control *b_accept;
- Control *b_refuse;
- RequestType rt[] =
- {
- { "/mnt/factotum/confirm", confirm, resizeconfirm, },
- { "/mnt/factotum/needkey", needkey, resizeneedkey, },
- { 0 },
- };
- enum
- {
- ButtonDim= 15,
- };
- void
- threadmain(int argc, char *argv[])
- {
- Request r;
- Channel *rc;
- RequestType *p;
- Font *invis;
- ARGBEGIN{
- }ARGEND;
- if(newwindow("-hide") < 0)
- sysfatal("newwindow: %r");
- fmtinstall('A', _attrfmt);
- /* create the proc's that read */
- rc = chancreate(sizeof(Request), 0);
- for(p = rt; p->file != 0; p++){
- p->fd = -1;
- p->rc = rc;
- proccreate(readreq, p, 16*1024);
- }
- /* gui initialization */
- if(initdraw(0, 0, "auth/fgui") < 0)
- sysfatal("initdraw failed: %r");
- initcontrols();
- hide();
- /* get an invisible font for passwords */
- invis = openfont(display, "/lib/font/bit/lucm/passwd.9.font");
- if (invis == nil)
- sysfatal("fgui: %s: %r", "/lib/font/bit/lucm/passwd.9.font");
- namectlfont(invis, "invisible");
- /* serialize all requests */
- for(;;){
- if(recv(rc, &r) < 0)
- break;
- (*r.rt->f)(&r);
- _freeattr(r.a);
- _freeattr(r.tag);
- }
- threadexitsall(nil);
- }
- /*
- * read requests and pass them to the main loop
- */
- enum
- {
- Requestlen=4096,
- };
- static void
- readreq(void *a)
- {
- RequestType *rt = a;
- char *buf, *p;
- int n;
- Request r;
- Attr **l;
- rt->fd = open(rt->file, ORDWR);
- if(rt->fd < 0)
- sysfatal("opening %s: %r", rt->file);
- rt->cs = nil;
- buf = malloc(Requestlen);
- if(buf == nil)
- sysfatal("allocating read buffer: %r");
- r.rt = rt;
- for(;;){
- n = read(rt->fd, buf, Requestlen-1);
- if(n < 0)
- break;
- buf[n] = 0;
- /* skip verb, parse attributes, and remove tag */
- p = strchr(buf, ' ');
- if(p != nil)
- p++;
- else
- p = buf;
- r.a = _parseattr(p);
- /* separate out the tag */
- r.tag = nil;
- for(l = &r.a; *l != nil; l = &(*l)->next)
- if(strcmp((*l)->name, "tag") == 0){
- r.tag = *l;
- *l = r.tag->next;
- r.tag->next = nil;
- break;
- }
- /* if no tag, forget it */
- if(r.tag == nil){
- _freeattr(r.a);
- continue;
- }
- send(rt->rc, &r);
- }
- }
- #ifdef asdf
- static void
- readreq(void *a)
- {
- RequestType *rt = a;
- char *buf, *p;
- int n;
- Request r;
- rt->fd = -1;
- rt->cs = nil;
- buf = malloc(Requestlen);
- if(buf == nil)
- sysfatal("allocating read buffer: %r");
- r.rt = rt;
- for(;;){
- strcpy(buf, "adfasdf=afdasdf asdfasdf=asdfasdf");
- r.a = _parseattr(buf);
- send(rt->rc, &r);
- sleep(5000);
- }
- }
- #endif //asdf
- /*
- * open/close the keyboard, mouse and resize channels
- */
- static Channel *kbdc;
- static Channel *mousec;
- static Channel *resizec;
- static Keyboardctl *kctl;
- static Mousectl *mctl;
- static void
- openkmr(void)
- {
- /* get channels for subsequent newcontrolset calls */
- kctl = initkeyboard(nil);
- if(kctl == nil)
- sysfatal("can't initialize keyboard: %r");
- kbdc = kctl->c;
- mctl = initmouse(nil, screen);
- if(mctl == nil)
- sysfatal("can't initialize mouse: %r");
- mousec = mctl->c;
- resizec = mctl->resizec;
- }
- static void
- closekmr(void)
- {
- Mouse m;
- while(nbrecv(kbdc, &m) > 0)
- ;
- closekeyboard(kctl);
- while(nbrecv(mousec, &m) > 0)
- ;
- closemouse(mctl);
- }
- /*
- * called when the window is resized
- */
- void
- resizecontrolset(Controlset *cs)
- {
- RequestType *p;
- for(p = rt; p->file != 0; p++){
- if(p->cs == cs){
- (*p->r)(cs);
- break;
- }
- }
- }
- /*
- * hide window when not in use
- */
- static void
- unhide(void)
- {
- int wctl;
- wctl = open("/dev/wctl", OWRITE);
- if(wctl < 0)
- return;
- fprint(wctl, "unhide");
- close(wctl);
- }
- static void
- hide(void)
- {
- int wctl;
- int tries;
- wctl = open("/dev/wctl", OWRITE);
- if(wctl < 0)
- return;
- for(tries = 0; tries < 10; tries++){
- if(fprint(wctl, "hide") >= 0)
- break;
- sleep(100);
- }
- close(wctl);
- }
- /*
- * set up the controls for the confirmation window
- */
- static Channel*
- setupconfirm(Request *r)
- {
- Controlset *cs;
- Channel *c;
- Attr *a;
- /* create a new control set for the confirmation */
- openkmr();
- cs = newcontrolset(screen, kbdc, mousec, resizec);
- createtext(cs, "msg");
- chanprint(cs->ctl, "msg image paleyellow");
- chanprint(cs->ctl, "msg border 1");
- chanprint(cs->ctl, "msg add 'The following key is being used:'");
- for(a = r->a; a != nil; a = a->next)
- chanprint(cs->ctl, "msg add ' %s = %s'", a->name,
- a->val);
- namectlimage(display->white, "i_white");
- namectlimage(display->black, "i_black");
- b_remember = createbutton(cs, "b_remember");
- chanprint(cs->ctl, "b_remember border 1");
- chanprint(cs->ctl, "b_remember mask i_white");
- chanprint(cs->ctl, "b_remember image i_white");
- chanprint(cs->ctl, "b_remember light i_black");
- createtext(cs, "t_remember");
- chanprint(cs->ctl, "t_remember image white");
- chanprint(cs->ctl, "t_remember bordercolor white");
- chanprint(cs->ctl, "t_remember add 'Remember this answer for future confirmations'");
- b_accept = createtextbutton(cs, "b_accept");
- chanprint(cs->ctl, "b_accept border 1");
- chanprint(cs->ctl, "b_accept align center");
- chanprint(cs->ctl, "b_accept text Accept");
- chanprint(cs->ctl, "b_accept image i_white");
- chanprint(cs->ctl, "b_accept light i_black");
- b_refuse = createtextbutton(cs, "b_refuse");
- chanprint(cs->ctl, "b_refuse border 1");
- chanprint(cs->ctl, "b_refuse align center");
- chanprint(cs->ctl, "b_refuse text Refuse");
- chanprint(cs->ctl, "b_refuse image i_white");
- chanprint(cs->ctl, "b_refuse light i_black");
- c = chancreate(sizeof(char*), 0);
- controlwire(b_remember, "event", c);
- controlwire(b_accept, "event", c);
- controlwire(b_refuse, "event", c);
- /* make the controls interactive */
- activate(b_remember);
- activate(b_accept);
- activate(b_refuse);
- r->rt->cs = cs;
- unhide();
- resizecontrolset(cs);
- return c;
- }
- /*
- * resize the controls for the confirmation window
- */
- static void
- resizeconfirm(Controlset *cs)
- {
- Rectangle r, mr, nr, ntr, ar, rr;
- int fontwidth;
- fontwidth = font->height;
- /* get usable window rectangle */
- if(getwindow(display, Refnone) < 0)
- ctlerror("resize failed: %r");
- r = insetrect(screen->r, 10);
- /* message box fills everything not needed for buttons */
- mr = r;
- mr.max.y = mr.min.y + font->height*((Dy(mr)-3*ButtonDim-font->height-4)/font->height);
- /* remember button */
- nr.min = Pt(mr.min.x, mr.max.y+ButtonDim);
- nr.max = Pt(mr.max.x, r.max.y);
- if(Dx(nr) > ButtonDim)
- nr.max.x = nr.min.x+ButtonDim;
- if(Dy(nr) > ButtonDim)
- nr.max.y = nr.min.y+ButtonDim;
- ntr.min = Pt(nr.max.x+ButtonDim, nr.min.y);
- ntr.max = Pt(r.max.x, nr.min.y+font->height);
- /* accept/refuse buttons */
- ar.min = Pt(r.min.x+Dx(r)/2-ButtonDim-6*fontwidth, nr.max.y+ButtonDim);
- ar.max = Pt(ar.min.x+6*fontwidth, ar.min.y+font->height+4);
- rr.min = Pt(r.min.x+Dx(r)/2+ButtonDim, nr.max.y+ButtonDim);
- rr.max = Pt(rr.min.x+6*fontwidth, rr.min.y+font->height+4);
- /* make the controls visible */
- chanprint(cs->ctl, "msg rect %R\nmsg show", mr);
- chanprint(cs->ctl, "b_remember rect %R\nb_remember show", nr);
- chanprint(cs->ctl, "t_remember rect %R\nt_remember show", ntr);
- chanprint(cs->ctl, "b_accept rect %R\nb_accept show", ar);
- chanprint(cs->ctl, "b_refuse rect %R\nb_refuse show", rr);
- }
- /*
- * free the controls for the confirmation window
- */
- static void
- teardownconfirm(Request *r)
- {
- Controlset *cs;
- cs = r->rt->cs;
- r->rt->cs = nil;
- hide();
- closecontrolset(cs);
- closekmr();
- }
- /*
- * get user confirmation of a key
- */
- static void
- confirm(Request *r)
- {
- Channel *c;
- char *s;
- int n;
- char *args[3];
- int remember;
- Attr *val;
- Memory *m;
- /* if it's something that the user wanted us not to ask again about */
- m = searchmem(r->a);
- if(m != nil){
- fprint(r->rt->fd, "%A %A", r->tag, m->val);
- return;
- }
- /* set up the controls */
- c = setupconfirm(r);
- /* wait for user to reply */
- remember = 0;
- for(;;){
- s = recvp(c);
- n = tokenize(s, args, nelem(args));
- if(n==3 && strcmp(args[1], "value")==0){
- if(strcmp(args[0], "b_remember:") == 0){
- remember = atoi(args[2]);
- }
- if(strcmp(args[0], "b_accept:") == 0){
- val = _mkattr(AttrNameval, "answer", "yes", nil);
- free(s);
- break;
- }
- if(strcmp(args[0], "b_refuse:") == 0){
- val = _mkattr(AttrNameval, "answer", "no", nil);
- free(s);
- break;
- }
- }
- free(s);
- }
- teardownconfirm(r);
- fprint(r->rt->fd, "%A %A", r->tag, val);
- if(remember)
- addmem(_copyattr(r->a), val);
- else
- _freeattr(val);
- }
- /*
- * confirmations that are remembered
- */
- static int
- match(Attr *a, Attr *b)
- {
- Attr *x;
- for(; a != nil; a = a->next){
- x = _findattr(b, a->name);
- if(x == nil || strcmp(a->val, x->val) != 0)
- return 0;
- }
- return 1;
- }
- static Memory*
- searchmem(Attr *a)
- {
- Memory *m;
- for(m = mem; m != nil; m = m->next){
- if(match(a, m->a))
- break;
- }
- return m;
- }
- static void
- addmem(Attr *a, Attr *val)
- {
- Memory *m;
- m = malloc(sizeof *m);
- if(m == nil)
- return;
- m->a = a;
- m->val = val;
- m->next = mem;
- mem = m;
- }
- /* controls for needkey */
- Control *msg;
- Control *b_done;
- enum {
- Pprivate= 1<<0,
- Pneed= 1<<1,
- };
- typedef struct Entry Entry;
- struct Entry {
- Control *name;
- Control *val;
- Control *eq;
- Attr *a;
- };
- static Entry *entry;
- static int entries;
- /*
- * set up the controls for the confirmation window
- */
- static Channel*
- setupneedkey(Request *r)
- {
- Controlset *cs;
- Channel *c;
- Attr *a;
- Attr **l;
- char cn[10];
- int i;
- /* create a new control set for the confirmation */
- openkmr();
- cs = newcontrolset(screen, kbdc, mousec, resizec);
- /* count attributes and allocate entry controls */
- entries = 0;
- for(l = &r->a; *l; l = &(*l)->next)
- entries++;
- if(entries == 0){
- closecontrolset(cs);
- closekmr();
- return nil;
- }
- *l = a = mallocz(sizeof *a, 1);
- a->type = AttrQuery;
- entries++;
- l = &(*l)->next;
- *l = a = mallocz(sizeof *a, 1);
- a->type = AttrQuery;
- entries++;
- entry = malloc(entries*sizeof(Entry));
- if(entry == nil){
- closecontrolset(cs);
- closekmr();
- return nil;
- }
- namectlimage(display->white, "i_white");
- namectlimage(display->black, "i_black");
- /* create controls */
- msg = createtext(cs, "msg");
- chanprint(cs->ctl, "msg image white");
- chanprint(cs->ctl, "msg bordercolor white");
- chanprint(cs->ctl, "msg add 'You need the following key. Fill in the blanks'");
- chanprint(cs->ctl, "msg add 'and click on the DONE button.'");
- for(i = 0, a = r->a; a != nil; i++, a = a->next){
- entry[i].a = a;
- snprint(cn, sizeof cn, "name_%d", i);
- if(entry[i].a->name == nil){
- entry[i].name = createentry(cs, cn);
- chanprint(cs->ctl, "%s image yellow", cn);
- chanprint(cs->ctl, "%s border 1", cn);
- } else {
- entry[i].name = createtext(cs, cn);
- chanprint(cs->ctl, "%s image white", cn);
- chanprint(cs->ctl, "%s bordercolor white", cn);
- chanprint(cs->ctl, "%s add '%s'", cn, a->name);
- }
- snprint(cn, sizeof cn, "val_%d", i);
- if(a->type == AttrQuery){
- entry[i].val = createentry(cs, cn);
- chanprint(cs->ctl, "%s image yellow", cn);
- chanprint(cs->ctl, "%s border 1", cn);
- if(a->name != nil){
- if(strcmp(a->name, "user") == 0)
- chanprint(cs->ctl, "%s value %q", cn, getuser());
- if(*a->name == '!')
- chanprint(cs->ctl, "%s font invisible", cn);
- }
- } else {
- entry[i].val = createtext(cs, cn);
- chanprint(cs->ctl, "%s image white", cn);
- chanprint(cs->ctl, "%s add %q", cn, a->val);
- }
- snprint(cn, sizeof cn, "eq_%d", i);
- entry[i].eq = createtext(cs, cn);
- chanprint(cs->ctl, "%s image white", cn);
- chanprint(cs->ctl, "%s add ' = '", cn);
- }
- b_done = createtextbutton(cs, "b_done");
- chanprint(cs->ctl, "b_done border 1");
- chanprint(cs->ctl, "b_done align center");
- chanprint(cs->ctl, "b_done text DONE");
- chanprint(cs->ctl, "b_done image green");
- chanprint(cs->ctl, "b_done light green");
- /* wire controls for input */
- c = chancreate(sizeof(char*), 0);
- controlwire(b_done, "event", c);
- for(i = 0; i < entries; i++)
- if(entry[i].a->type == AttrQuery)
- controlwire(entry[i].val, "event", c);
- /* make the controls interactive */
- activate(msg);
- activate(b_done);
- for(i = 0; i < entries; i++){
- if(entry[i].a->type != AttrQuery)
- continue;
- if(entry[i].a->name == nil)
- activate(entry[i].name);
- activate(entry[i].val);
- }
- /* change the display */
- r->rt->cs = cs;
- unhide();
- resizecontrolset(cs);
- return c;
- }
- /*
- * resize the controls for the confirmation window
- */
- static void
- resizeneedkey(Controlset *cs)
- {
- Rectangle r, mr;
- int mid, i, n, lasty;
- /* get usable window rectangle */
- if(getwindow(display, Refnone) < 0)
- ctlerror("resize failed: %r");
- r = insetrect(screen->r, 10);
- /* find largest name */
- mid = 0;
- for(i = 0; i < entries; i++){
- if(entry[i].a->name == nil)
- continue;
- n = strlen(entry[i].a->name);
- if(n > mid)
- mid = n;
- }
- mid = (mid+2) * font->height;
- /* top line is the message */
- mr = r;
- mr.max.y = mr.min.y + 2*font->height + 2;
- chanprint(cs->ctl, "msg rect %R\nmsg show", mr);
- /* one line per attribute */
- mr.min.x += 2*font->height;
- lasty = mr.max.y;
- for(i = 0; i < entries; i++){
- r.min.x = mr.min.x;
- r.min.y = lasty+2;
- r.max.x = r.min.x + mid - 3*stringwidth(font, "=");
- r.max.y = r.min.y + font->height;
- chanprint(cs->ctl, "name_%d rect %R\nname_%d show", i, r, i);
- r.min.x = r.max.x;
- r.max.x = r.min.x + 3*stringwidth(font, "=");
- chanprint(cs->ctl, "eq_%d rect %R\neq_%d show", i, r, i);
- r.min.x = r.max.x;
- r.max.x = mr.max.x;
- if(Dx(r) > 32*font->height)
- r.max.x = r.min.x + 32*font->height;
- chanprint(cs->ctl, "val_%d rect %R\nval_%d show", i, r, i);
- lasty = r.max.y;
- }
- /* done button */
- mr.min.x -= 2*font->height;
- r.min.x = mr.min.x + mid - 3*font->height;
- r.min.y = lasty+10;
- r.max.x = r.min.x + 6*font->height;
- r.max.y = r.min.y + font->height + 2;
- chanprint(cs->ctl, "b_done rect %R\nb_done show", r);
- }
- /*
- * free the controls for the confirmation window
- */
- static void
- teardownneedkey(Request *r)
- {
- Controlset *cs;
- cs = r->rt->cs;
- r->rt->cs = nil;
- hide();
- closecontrolset(cs);
- closekmr();
- if(entry != nil)
- free(entry);
- entry = nil;
- }
- static void
- needkey(Request *r)
- {
- Channel *c;
- char *nam, *val;
- int i, n;
- int fd;
- char *args[3];
- /* set up the controls */
- c = setupneedkey(r);
- if(c == nil)
- goto out;
- /* wait for user to reply */
- for(;;){
- val = recvp(c);
- n = tokenize(val, args, nelem(args));
- if(n==3 && strcmp(args[1], "value")==0){ /* user hit 'enter' */
- free(val);
- break;
- }
- free(val);
- }
- /* get entry values */
- for(i = 0; i < entries; i++){
- if(entry[i].a->type != AttrQuery)
- continue;
- chanprint(r->rt->cs->ctl, "val_%d data", i);
- val = recvp(entry[i].val->data);
- if(entry[i].a->name == nil){
- chanprint(r->rt->cs->ctl, "name_%d data", i);
- nam = recvp(entry[i].name->data);
- if(nam == nil || *nam == 0){
- free(val);
- continue;
- }
- entry[i].a->val = estrdup(val);
- free(val);
- entry[i].a->name = estrdup(nam);
- free(nam);
- } else {
- if(val != nil){
- entry[i].a->val = estrdup(val);
- free(val);
- }
- }
- entry[i].a->type = AttrNameval;
- }
- /* enter the new key !!!!need to do something in case of error!!!! */
- fd = open("/mnt/factotum/ctl", OWRITE);
- fprint(fd, "key %A", r->a);
- close(fd);
- teardownneedkey(r);
- out:
- fprint(r->rt->fd, "%A", r->tag);
- }
|