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