URI:
       tctl.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tctl.c (3781B)
       ---
            1 #include "std.h"
            2 #include "dat.h"
            3 
            4 /*
            5  *        key attr=val... - add a key
            6  *                the attr=val pairs are protocol-specific.
            7  *                for example, both of these are valid:
            8  *                        key p9sk1 gre cs.bell-labs.com mysecret
            9  *                        key p9sk1 gre cs.bell-labs.com 11223344556677 fmt=des7hex
           10  *        delkey ... - delete a key
           11  *                if given, the attr=val pairs are used to narrow the search
           12  *                [maybe should require a password?]
           13  *
           14  *        debug - toggle debugging
           15  */
           16 
           17 static char *msg[] = {
           18         "key",
           19         "delkey",
           20         "debug"
           21 };
           22 
           23 static int
           24 classify(char *s)
           25 {
           26         int i;
           27 
           28         for(i=0; i<nelem(msg); i++)
           29                 if(strcmp(msg[i], s) == 0)
           30                         return i;
           31         return -1;
           32 }
           33 
           34 int
           35 ctlwrite(char *a)
           36 {
           37         char *p;
           38         int i, nmatch, ret;
           39         Attr *attr, *kpa, **l, **lpriv, **lprotos, *pa, *priv, *protos;
           40         Key *k;
           41         Proto *proto;
           42 
           43         while(*a == ' ' || *a == '\t' || *a == '\n')
           44                 a++;
           45 
           46         if(a[0] == '#' || a[0] == '\0')
           47                 return 0;
           48 
           49         /*
           50          * it would be nice to emit a warning of some sort here.
           51          * we ignore all but the first line of the write.  this helps
           52          * both with things like "echo delkey >/mnt/factotum/ctl"
           53          * and writes that (incorrectly) contain multiple key lines.
           54          */
           55         if(p = strchr(a, '\n')){
           56                 if(p[1] != '\0'){
           57                         werrstr("multiline write not allowed");
           58                         return -1;
           59                 }
           60                 *p = '\0';
           61         }
           62 
           63         if((p = strchr(a, ' ')) == nil)
           64                 p = "";
           65         else
           66                 *p++ = '\0';
           67         switch(classify(a)){
           68         default:
           69                 werrstr("unknown verb %s", a);
           70                 return -1;
           71         case 0:        /* key */
           72                 attr = parseattr(p);
           73                 /* separate out proto= attributes */
           74                 lprotos = &protos;
           75                 for(l=&attr; (*l); ){
           76                         if(strcmp((*l)->name, "proto") == 0){
           77                                 *lprotos = *l;
           78                                 lprotos = &(*l)->next;
           79                                 *l = (*l)->next;
           80                         }else
           81                                 l = &(*l)->next;
           82                 }
           83                 *lprotos = nil;
           84                 if(protos == nil){
           85                         werrstr("key without protos");
           86                         freeattr(attr);
           87                         return -1;
           88                 }
           89 
           90                 /* separate out private attributes */
           91                 lpriv = &priv;
           92                 for(l=&attr; (*l); ){
           93                         if((*l)->name[0] == '!'){
           94                                 *lpriv = *l;
           95                                 lpriv = &(*l)->next;
           96                                 *l = (*l)->next;
           97                         }else
           98                                 l = &(*l)->next;
           99                 }
          100                 *lpriv = nil;
          101                 flog("addkey %A %A %N", protos, attr, priv);
          102 
          103                 /* add keys */
          104                 ret = 0;
          105                 for(pa=protos; pa; pa=pa->next){
          106                         if((proto = protolookup(pa->val)) == nil){
          107                                 werrstr("unknown proto %s", pa->val);
          108                                 flog("addkey: %r");
          109                                 ret = -1;
          110                                 continue;
          111                         }
          112                         if(proto->keyprompt){
          113                                 kpa = parseattr(proto->keyprompt);
          114                                 if(!matchattr(kpa, attr, priv)){
          115                                         freeattr(kpa);
          116                                         werrstr("missing attributes -- want %s", proto->keyprompt);
          117                                         flog("addkey %s: %r", proto->name);
          118                                         ret = -1;
          119                                         continue;
          120                                 }
          121                                 freeattr(kpa);
          122                         }
          123                         k = emalloc(sizeof(Key));
          124                         k->attr = mkattr(AttrNameval, "proto", proto->name, copyattr(attr));
          125                         k->privattr = copyattr(priv);
          126                         k->ref = 1;
          127                         k->proto = proto;
          128                         if(proto->checkkey && (*proto->checkkey)(k) < 0){
          129                                 flog("addkey %s: %r", proto->name);
          130                                 ret = -1;
          131                                 keyclose(k);
          132                                 continue;
          133                         }
          134                         flog("adding key: %A %N", k->attr, k->privattr);
          135                         keyadd(k);
          136                         keyclose(k);
          137                 }
          138                 freeattr(attr);
          139                 freeattr(priv);
          140                 freeattr(protos);
          141                 return ret;
          142         case 1:        /* delkey */
          143                 nmatch = 0;
          144                 attr = parseattr(p);
          145                 flog("delkey %A", attr);
          146                 for(pa=attr; pa; pa=pa->next){
          147                         if(pa->type != AttrQuery && pa->name[0]=='!'){
          148                                 werrstr("only !private? patterns are allowed for private fields");
          149                                 freeattr(attr);
          150                                 return -1;
          151                         }
          152                 }
          153                 for(i=0; i<ring.nkey; ){
          154                         if(matchattr(attr, ring.key[i]->attr, ring.key[i]->privattr)){
          155                                 nmatch++;
          156                                 flog("deleting %A %N", ring.key[i]->attr, ring.key[i]->privattr);
          157                                 keyclose(ring.key[i]);
          158                                 ring.nkey--;
          159                                 memmove(&ring.key[i], &ring.key[i+1], (ring.nkey-i)*sizeof(ring.key[0]));
          160                         }else
          161                                 i++;
          162                 }
          163                 freeattr(attr);
          164                 if(nmatch == 0){
          165                         werrstr("found no keys to delete");
          166                         return -1;
          167                 }
          168                 return 0;
          169         case 2:        /* debug */
          170                 debug ^= 1;
          171                 flog("debug = %d", debug);
          172                 return 0;
          173         }
          174 }