nightmaremail

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

qmail-pw2u.c (9720B)


      1 #include <sys/types.h>
      2 #include <sys/stat.h>
      3 #include "byte.h"
      4 #include "substdio.h"
      5 #include "readwrite.h"
      6 #include "subfd.h"
      7 #include "sgetopt.h"
      8 #include "control.h"
      9 #include "constmap.h"
     10 #include "stralloc.h"
     11 #include "fmt.h"
     12 #include "str.h"
     13 #include "scan.h"
     14 #include "open.h"
     15 #include "error.h"
     16 #include "getln.h"
     17 #include "exit.h"
     18 #include "auto_break.h"
     19 #include "auto_qmail.h"
     20 #include "auto_users.h"
     21 
     22 void die_chdir()
     23 {
     24   substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to chdir\n");
     25   _exit(111);
     26 }
     27 void die_nomem()
     28 {
     29   substdio_putsflush(subfderr,"qmail-pw2u: fatal: out of memory\n");
     30   _exit(111);
     31 }
     32 void die_read()
     33 {
     34   substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to read input\n");
     35   _exit(111);
     36 }
     37 void die_write()
     38 {
     39   substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to write output\n");
     40   _exit(111);
     41 }
     42 void die_control()
     43 {
     44   substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to read controls\n");
     45   _exit(111);
     46 }
     47 void die_alias()
     48 {
     49   substdio_puts(subfderr,"qmail-pw2u: fatal: unable to find ");
     50   substdio_puts(subfderr,auto_usera);
     51   substdio_puts(subfderr," user\n");
     52   substdio_flush(subfderr);
     53   _exit(111);
     54 }
     55 void die_home(fn) char *fn;
     56 {
     57   substdio_puts(subfderr,"qmail-pw2u: fatal: unable to stat ");
     58   substdio_puts(subfderr,fn);
     59   substdio_puts(subfderr,"\n");
     60   substdio_flush(subfderr);
     61   _exit(111);
     62 }
     63 void die_user(s,len) char *s; unsigned int len;
     64 {
     65   substdio_puts(subfderr,"qmail-pw2u: fatal: unable to find ");
     66   substdio_put(subfderr,s,len);
     67   substdio_puts(subfderr," user for subuser\n");
     68   substdio_flush(subfderr);
     69   _exit(111);
     70 }
     71 
     72 char *dashcolon = "-:";
     73 int flagalias = 0;
     74 int flagnoupper = 1;
     75 int homestrategy = 2;
     76 /* 2: skip if home does not exist; skip if home is not owned by user */
     77 /* 1: stop if home does not exist; skip if home is not owned by user */
     78 /* 0: don't worry about home */
     79 
     80 int dotend = 1, onlybreak = 0; // 1 if to output with a terminal dot, 1 if only to output breaked users
     81 
     82 int okincl; stralloc incl = {0}; struct constmap mapincl;
     83 int okexcl; stralloc excl = {0}; struct constmap mapexcl;
     84 int okmana; stralloc mana = {0}; struct constmap mapmana;
     85 
     86 stralloc allusers = {0}; struct constmap mapuser;
     87 
     88 stralloc uugh = {0};
     89 stralloc user = {0};
     90 stralloc uidstr = {0};
     91 stralloc gidstr = {0};
     92 stralloc home = {0};
     93 unsigned long uid;
     94 
     95 stralloc line = {0};
     96 
     97 void doaccount()
     98 {
     99   struct stat st;
    100   int i;
    101   char *mailnames;
    102   char *x;
    103   unsigned int xlen;
    104 
    105   if (byte_chr(line.s,line.len,'\0') < line.len) return;
    106 
    107   x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    108   if (!stralloc_copyb(&user,x,i)) die_nomem();
    109   if (!stralloc_0(&user)) die_nomem();
    110   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    111   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    112   if (!stralloc_copyb(&uidstr,x,i)) die_nomem();
    113   if (!stralloc_0(&uidstr)) die_nomem();
    114   scan_ulong(uidstr.s,&uid);
    115   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    116   if (!stralloc_copyb(&gidstr,x,i)) die_nomem();
    117   if (!stralloc_0(&gidstr)) die_nomem();
    118   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    119   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    120   if (!stralloc_copyb(&home,x,i)) die_nomem();
    121   if (!stralloc_0(&home)) die_nomem();
    122 
    123   if (!uid) return;
    124   if (flagnoupper)
    125     for (i = 0;i < user.len;++i)
    126       if ((user.s[i] >= 'A') && (user.s[i] <= 'Z'))
    127 	return;
    128   if (okincl)
    129     if (!constmap(&mapincl,user.s,user.len - 1))
    130       return;
    131   if (okexcl)
    132     if (constmap(&mapexcl,user.s,user.len - 1))
    133       return;
    134   if (homestrategy) {
    135     if (stat(home.s,&st) == -1) {
    136       if (errno != error_noent) die_home(home.s);
    137       if (homestrategy == 1) die_home(home.s);
    138       return;
    139     }
    140     if (st.st_uid != uid) return;
    141   }
    142 
    143   if (!stralloc_copys(&uugh,":")) die_nomem();
    144   if (!stralloc_cats(&uugh,user.s)) die_nomem();
    145   if (!stralloc_cats(&uugh,":")) die_nomem();
    146   if (!stralloc_cats(&uugh,uidstr.s)) die_nomem();
    147   if (!stralloc_cats(&uugh,":")) die_nomem();
    148   if (!stralloc_cats(&uugh,gidstr.s)) die_nomem();
    149   if (!stralloc_cats(&uugh,":")) die_nomem();
    150   if (!stralloc_cats(&uugh,home.s)) die_nomem();
    151   if (!stralloc_cats(&uugh,":")) die_nomem();
    152 
    153   /* XXX: avoid recording in allusers unless sub actually needs it */
    154   if (!stralloc_cats(&allusers,user.s)) die_nomem();
    155   if (!stralloc_cats(&allusers,":")) die_nomem();
    156   if (!stralloc_catb(&allusers,uugh.s,uugh.len)) die_nomem();
    157   if (!stralloc_0(&allusers)) die_nomem();
    158 
    159   if (str_equal(user.s,auto_usera)) {
    160     if (substdio_puts(subfdout,"+") == -1) die_write();
    161     if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write();
    162     if (substdio_puts(subfdout,dashcolon) == -1) die_write();
    163     if (substdio_puts(subfdout,":\n") == -1) die_write();
    164     flagalias = 1;
    165   }
    166 
    167   mailnames = 0;
    168   if (okmana)
    169     mailnames = constmap(&mapmana,user.s,user.len - 1);
    170   if (!mailnames)
    171     mailnames = user.s;
    172 
    173   for (;;) {
    174     while (*mailnames == ':') ++mailnames;
    175     if (!*mailnames) break;
    176 
    177     i = str_chr(mailnames,':');
    178 
    179     if (!onlybreak) {
    180       if (substdio_puts(subfdout,"=") == -1) die_write();
    181       if (substdio_put(subfdout,mailnames,i) == -1) die_write();
    182       if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write();
    183       if (substdio_puts(subfdout,"::\n") == -1) die_write();
    184     }
    185 
    186     if (*auto_break) {
    187       if (substdio_puts(subfdout,"+") == -1) die_write();
    188       if (substdio_put(subfdout,mailnames,i) == -1) die_write();
    189       if (substdio_put(subfdout,auto_break,1) == -1) die_write();
    190       if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write();
    191       if (substdio_puts(subfdout,dashcolon) == -1) die_write();
    192       if (substdio_puts(subfdout,":\n") == -1) die_write();
    193     }
    194 
    195     mailnames += i;
    196   }
    197 }
    198 
    199 stralloc sub = {0};
    200 
    201 void dosubuser()
    202 {
    203   int i;
    204   char *x;
    205   unsigned int xlen;
    206   char *u;
    207 
    208   x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    209   if (!stralloc_copyb(&sub,x,i)) die_nomem();
    210   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    211   u = constmap(&mapuser,x,i);
    212   if (!u) die_user(x,i);
    213   ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return;
    214 
    215   if (!onlybreak) {
    216     if (substdio_puts(subfdout,"=") == -1) die_write();
    217     if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
    218     if (substdio_puts(subfdout,u) == -1) die_write();
    219     if (substdio_puts(subfdout,dashcolon) == -1) die_write();
    220     if (substdio_put(subfdout,x,i) == -1) die_write();
    221     if (substdio_puts(subfdout,":\n") == -1) die_write();
    222   }
    223 
    224   if (*auto_break) {
    225     if (substdio_puts(subfdout,"+") == -1) die_write();
    226     if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write();
    227     if (substdio_put(subfdout,auto_break,1) == -1) die_write();
    228     if (substdio_puts(subfdout,u) == -1) die_write();
    229     if (substdio_puts(subfdout,dashcolon) == -1) die_write();
    230     if (substdio_put(subfdout,x,i) == -1) die_write();
    231     if (substdio_puts(subfdout,"-:\n") == -1) die_write();
    232   }
    233 }
    234 
    235 int fd;
    236 substdio ss;
    237 char ssbuf[SUBSTDIO_INSIZE];
    238 stralloc scolon;
    239 
    240 int main(int argc, char **argv)
    241 {
    242   int opt;
    243   int match;
    244 
    245   while ((opt = getopt(argc,argv,"/ohHuUs:dDkKc:C")) != opteof)
    246     switch(opt) {
    247       case '/': dashcolon = "-/:"; break;
    248       case 's':
    249         if (!stralloc_copys(&scolon, optarg)) die_nomem();
    250         if (!stralloc_cats(&scolon, ":")) die_nomem();
    251         if (!stralloc_0(&scolon)) die_nomem();
    252         dashcolon = scolon.s;
    253       break;
    254       case 'o': homestrategy = 2; break;
    255       case 'h': homestrategy = 1; break;
    256       case 'H': homestrategy = 0; break;
    257       case 'u': flagnoupper = 0; break;
    258       case 'U': flagnoupper = 1; break;
    259       case 'd': dotend = 1; break;
    260       case 'D': dotend = 0; break;
    261       case 'k': onlybreak = 1; break;
    262       case 'K': onlybreak = 0; break;
    263       case 'c': *auto_break = *optarg; break;
    264       case 'C': *auto_break = 0; break;
    265       case '?':
    266       default:
    267 	return 100;
    268     }
    269 
    270   if (chdir(auto_qmail) == -1) die_chdir();
    271 
    272   /* no need for control_init() */
    273 
    274   okincl = control_readfile(&incl,"users/include",0);
    275   if (okincl == -1) die_control();
    276   if (okincl) if (!constmap_init(&mapincl,incl.s,incl.len,0)) die_nomem();
    277 
    278   okexcl = control_readfile(&excl,"users/exclude",0);
    279   if (okexcl == -1) die_control();
    280   if (okexcl) if (!constmap_init(&mapexcl,excl.s,excl.len,0)) die_nomem();
    281 
    282   okmana = control_readfile(&mana,"users/mailnames",0);
    283   if (okmana == -1) die_control();
    284   if (okmana) if (!constmap_init(&mapmana,mana.s,mana.len,1)) die_nomem();
    285 
    286   if (!stralloc_copys(&allusers,"")) die_nomem();
    287 
    288   for (;;) {
    289     if (getln(subfdin,&line,&match,'\n') == -1) die_read();
    290     doaccount();
    291     if (!match) break;
    292   }
    293   if (!flagalias) die_alias();
    294 
    295   fd = open_read("users/subusers");
    296   if (fd == -1) {
    297     if (errno != error_noent) die_control();
    298   }
    299   else {
    300     substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));
    301 
    302     if (!constmap_init(&mapuser,allusers.s,allusers.len,1)) die_nomem();
    303 
    304     for (;;) {
    305       if (getln(&ss,&line,&match,'\n') == -1) die_read();
    306       dosubuser();
    307       if (!match) break;
    308     }
    309 
    310     close(fd);
    311   }
    312 
    313   fd = open_read("users/append");
    314   if (fd == -1) {
    315     if (errno != error_noent) die_control();
    316   }
    317   else {
    318     substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));
    319     for (;;) {
    320       if (getln(&ss,&line,&match,'\n') == -1) die_read();
    321       if (substdio_put(subfdout,line.s,line.len) == -1) die_write();
    322       if (!match) break;
    323     }
    324   }
    325 
    326   if (dotend) if (substdio_puts(subfdout,".\n") == -1) die_write();
    327   else if (substdio_puts(subfdout,"\n") == -1) die_write();
    328   if (substdio_flush(subfdout) == -1) die_write();
    329   return 0;
    330 }