Esempio n. 1
0
static int
pls_reader(playlist* pl) {
  int ret;
    static playlist_entry entry;
  buffer* inbuf = pl->ptr;
  stralloc line;
  stralloc_init(&line);
  if(( ret = buffer_getline_sa(inbuf, &line))) {
    size_t index2, index;
    index2 = index = 0;
    while(line.len > 1 &&
          (line.s[line.len - 1] == '\r' || line.s[line.len - 1] == '\n'))
      line.len--;
    stralloc_0(&line);
    if(!str_diffn(&line.s[index], "Number", 6)) {
    } else if(line.s[index] == '[') {
    } else if((index2 = str_chr(&line.s[index], '=')) > 0) {
      unsigned long trackno = 0;
      index = index2;
      index2++;
      do { index--; } while(isdigit(line.s[index]) && index > 0);
      scan_ulong(&line.s[index], &trackno);
      if(!str_diffn(&line.s[index], "File", 4)) {
        stralloc_copys(&entry.path, &line.s[index2]);
        stralloc_0(&entry.path);
      } else if(!str_diffn(&line.s[index], "Title", 5)) {
        stralloc_copys(&entry.title, &line.s[index2]);
        stralloc_0(&entry.title);
      } else if(!str_diffn(&line.s[index], "Length", 6)) {
        unsigned long len;
        scan_ulong(&line.s[index2], &len);
        entry.length = len;
      }
      /*
      uint32 index = 8;
      index += scan_ulong(&line.s[index], &len);
      entry.length = len;
      index++;
      stralloc_copys(&entry.title, &line.s[index]);
      stralloc_0(&entry.title);
      */
    } else {
      /*
      stralloc_copy(&entry.path, &line);
      stralloc_0(&entry.path);
      if(pl->callback) {
      pl->callback(pl, &entry.title, &entry.path, entry.length);
      }*/
    }
  }
  return ret;
}
Esempio n. 2
0
File: sln.c Progetto: rsenn/dirlist
int
reduce(stralloc* sa) {
  ssize_t i, j;
  j = stralloc_finds(sa, ".so");

  for(i = sa->len - 1; i >= 0; --i) {
    if(!(isdigit(sa->s[i]) || sa->s[i] == '.'))
      break;
    if(i == j + 3 || sa->s[i] == '.') {
      sa->len = i;
      return 1;
    }
  }

  for(i = 0; i < sa->len; ++i) {
    if(sa->s[i] == '-' && isdigit(sa->s[i + 1])) {

      size_t k = i + 1;

      while(isdigit(sa->s[k])) ++k;

      if(!str_diffn(&sa->s[k], ".so", 3))
        break;

      byte_copy(&sa->s[i], sa->len - j, &sa->s[j]);
      sa->len -= j - i;
      return 1;
    }
  }

  return 0;
}
Esempio n. 3
0
static int
it_loops_dms (direntry *d, void *data)
{
    stralloc **sas = data;
    int i;
    size_t l;

    if (d->d_type != DT_BLK)
        return 0;

    if (!str_diffn (d->d_name, "loop", 4) && d->d_name[4] >= '0' && d->d_name[4] <= '9')
        i = 0;
    else if (!str_diffn (d->d_name, "dm-", 3))
        i = 1;
    else
        return 0;

    l = sas[i]->len;
    if (!stralloc_cats (sas[i], "/dev/") || !stralloc_cats (sas[i], d->d_name)
            || !stralloc_0 (sas[i]))
        aa_strerr_diefu1sys (2, "stralloc_catb");

    /* /dev/loop* always exists, let's find the actual ones */
    if (i == 0)
    {
        int fd;

        fd = open_read (sas[i]->s + l);
        if (fd < 0)
            sas[i]->len = l;
        else
        {
            struct loop_info64 info;
            int r;

            /* make sure it is one/in use; we get ENXIO when not */
            r = ioctl (fd, LOOP_GET_STATUS64, &info);
            if (r < 0)
                /* treat all errors the same though */
                sas[i]->len = l;

            fd_close (fd);
        }
    }

    return 0;
}
Esempio n. 4
0
File: env.c Progetto: abh/ezmlm-idx
static void env_unsetlen(const char *s,int len)
{
 int i;
 for (i = en - 1;i >= 0;--i)
   if (!str_diffn(s,environ[i],len))
     if (environ[i][len] == '=')
       env_goodbye(i);
}
Esempio n. 5
0
static void try_dispatch(const char *def,const char *prefix,unsigned int len,
			 const char *fn)
     /* Test if def has a certain prefix, and if so execute the
      * associated file. */
{
  if (str_diffn(def,prefix,len) == 0
      && is_file(fn))
    execute(fn,def+len);
}
Esempio n. 6
0
int
call_put(struct call *cc, const char *s, unsigned int len)
{
	if (cc->flagerr || cc->flagabort) return -1;
	if (cc->flagstar && str_diffn(s, "*", len) == 0) {
		cc->flagabort = 1;
		return -1;
	}
	if (substdio_put(&cc->ssto, s, len) == -1) {
		cc->flagerr = 1;
		return -1;
	}
	return 0;
}
Esempio n. 7
0
int
list_dir_internal(stralloc* dir, char type) {
  size_t l;
  struct dir_s d;
  stralloc pre;
  int dtype;
  int is_dir, is_symlink;
  size_t len;
#if !WINDOWS_NATIVE
  struct stat st;
  static dev_t root_dev;
#endif
  char *name, *s;
  (void)type;
  while(dir->len > 1 && IS_DIRSEP(dir->s[dir->len - 1])) dir->len--;
  stralloc_nul(dir);
#if !WINDOWS_NATIVE
  if(root_dev == 0) {
    if(stat(dir->s, &st) != -1) {
      root_dev = st.st_dev;
    }
  }
#endif
  if(dir_open(&d, dir->s) != 0) {
    buffer_puts(buffer_2, "ERROR: Opening directory ");
    buffer_putsa(buffer_2, dir);
    buffer_puts(buffer_2, " failed!\n");
    buffer_flush(buffer_2);
    goto end;
  }
  if(dir->s[dir->len - 1] != DIRSEP_C)
    stralloc_cats(dir, DIRSEP_S);
  l = dir->len;
  while((name = dir_read(&d))) {
    unsigned int mode = 0, nlink = 0, uid = 0, gid = 0;
    uint64 size = 0, mtime = 0;
    dtype = dir_type(&d);
    dir->len = l;
    if(str_equal(name, "") || str_equal(name, ".") || str_equal(name, "..")) {
      continue;
    }
    stralloc_readyplus(dir, str_len(name) + 1);
    str_copy(dir->s + dir->len, name);
    dir->len += str_len(name);
    is_symlink = !!(dtype & D_SYMLINK);
#if !WINDOWS_NATIVE
    if(!opt_deref && lstat(dir->s, &st) != -1) {
      if(root_dev && st.st_dev) {
        if(st.st_dev != root_dev) {
          continue;
        }
      }
    }
#endif
#if !WINDOWS_NATIVE
    if(S_ISLNK(st.st_mode)) {
      stat(dir->s, &st);
    }
    mode = st.st_mode;
#endif
    if(dtype) {
      is_dir = !!(dtype & D_DIRECTORY);
    } else {
#if WINDOWS_NATIVE
      is_dir = 0;
#else
      is_dir = !!S_ISDIR(mode);
#endif
    }
    if(dtype & D_SYMLINK)
      is_symlink = 1;
#if !WINDOWS_NATIVE
    nlink = st.st_nlink;
    uid = st.st_uid;
    gid = st.st_gid;
    size = st.st_size;
    mtime = st.st_mtime;
#else
    mode = (is_dir ? 0040000 : 0100000) | (is_symlink ? 0120000 : 0);
#if USE_READDIR
    if(!is_dir) {
      size = dir_size(&d); /* dir_INTERNAL(&d)->dir_entry->d_name); */
      mtime = dir_time(&d);
    } else {
      mtime = 0;
      size = 0;
    }
#else
    size = dir_size(&d);
    mtime = dir_time(&d, D_TIME_MODIFICATION);
#endif
#endif
    if(opt_list && size >= opt_minsize) {
      stralloc_init(&pre);
      /* Mode string */
      mode_str(&pre, mode);
      stralloc_catb(&pre, " ", 1);
      /* num links */
      make_num(&pre, nlink, 3);
      stralloc_catb(&pre, " ", 1);
      /* uid */
      make_num(&pre, uid, 0);
      stralloc_catb(&pre, " ", 1);
      /* gid */
      make_num(&pre, gid, 0);
      stralloc_catb(&pre, " ", 1);
      /* size */
      make_num(&pre, size, 6);
      stralloc_catb(&pre, " ", 1);
      /* time */
      make_num(&pre, mtime, 0);
      /*     make_time(&pre, mtime, 10); */
      stralloc_catb(&pre, " ", 1);
    }
    /* fprintf(stderr, "%d %08x\n", is_dir, dir_ATTRS(&d)); */
    if(is_dir)
      stralloc_catc(dir, opt_separator);
    if(dir->len > MAX_PATH) {
      buffer_puts(buffer_2, "ERROR: Directory ");
      buffer_putsa(buffer_2, dir);
      buffer_puts(buffer_2, " longer than MAX_PATH (" STRINGIFY(MAX_PATH) ")!\n");
      /*buffer_putulong(buffer_2, MAX_PATH);
      buffer_puts(buffer_2, ")!\n");*/
      buffer_flush(buffer_2);
      goto end;
    }
    s = dir->s;
    len = dir->len;
    if(len >= 2 && s[0] == '.' && IS_DIRSEP(s[1])) {
      len -= 2;
      s += 2;
    }
    if(opt_list && size >= opt_minsize)
      buffer_putsa(buffer_1, &pre);

    if(opt_relative_to) {
      size_t sz = str_len(opt_relative_to);
      if(str_diffn(s, opt_relative_to, sz) == 0) {
        s += sz;
        len -= sz;
        while(*s == '\\' || *s == '/') {
          s++;
          len--;
        }
      }
    }

    if(size >= opt_minsize) {
      buffer_put(buffer_1, s, len);
      buffer_put(buffer_1, "\n", 1);
      buffer_flush(buffer_1);
    }

    if(is_dir && (opt_deref || !is_symlink)) {
      dir->len--;
      list_dir_internal(dir, 0);
    }
  }
end:
  dir_close(&d);
  return 0;
}
static void do_ed(char *action)
{
  datetime_sec u;
  int flaggoodfield;
  int fd;
  char *x, *y;
  char *cp,*cplast,*cpnext,*cpafter;
  int flagdone;
  unsigned int len;
  const char *fname;
  unsigned int i;

  x = action + LENGTH_ED;
  x += scan_ulong(x,&u);
  if ((u > when) || (u < when - 100000)) die_cookie();
  if (*x == '.') ++x;
  fname = x;
  x += str_chr(x,'.');
  if (!*x) die_cookie();
  *x = (char) 0;
  ++x;
  stralloc_copys(&fnedit,"text/");
  stralloc_cats(&fnedit,fname);
  stralloc_0(&fnedit);
  y = fnedit.s + 5;		/* after "text/" */
  while (*++y) {		/* Name should be guaranteed by the cookie, */
				/* but better safe than sorry ... */
    if (((*y > 'z') || (*y < 'a')) && (*y != '_'))
      strerr_die2x(100,FATAL,MSG(ERR_BAD_NAME));
    if (*y == '_') *y = '-';
  }

  lock();			/* file must not change while here */

  switch (slurp(fnedit.s,&text,1024)) {
  case -1:
    strerr_die2sys(111,FATAL,MSG1(ERR_READ,fnedit.s));
  case 0:
    strerr_die5x(100,FATAL,dir,"/",fnedit.s,MSG(ERR_NOEXIST));
  }
  stralloc_copy(&line,&text);

  subst_nuls(&line);

  stralloc_cat(&line,&fnedit);	/* including '\0' */
  strnum[fmt_ulong(strnum,(unsigned long) u)] = 0;
  cookie(hash,key.s,key.len,strnum,line.s,"-e");
  if (str_len(x) != COOKIE) die_cookie();
  if (byte_diff(hash,COOKIE,x)) die_cookie();
	/* cookie is ok, file exists, lock's on, new file ends in '_' */
  stralloc_copys(&fneditn,fnedit.s);
  stralloc_append(&fneditn,'_');
  stralloc_0(&fneditn);
  fd = open_trunc(fneditn.s);
  if (fd == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fneditn.s));
  substdio_fdbuf(&sstext,write,fd,textbuf,sizeof(textbuf));
  stralloc_copys(&quoted,"");	/* clear */
  stralloc_copys(&text,"");

  for (;;) {			/* get message body */
    if (getln(&ssin,&line,&match,'\n') == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    if (!match) break;
    stralloc_cat(&text,&line);
  }
  if (encin) {			/* decode if necessary */
    if (encin == 'B')
      decodeB(text.s,text.len,&line);
    else
      decodeQ(text.s,text.len,&line);
    stralloc_copy(&text,&line);
  }
  cp = text.s;
  cpafter = text.s+text.len;
  flaggoodfield = 0;
  flagdone = 0;
  len = 0;
  while ((cpnext = cp + byte_chr(cp,cpafter-cp,'\n')) != cpafter) {
    i = byte_chr(cp,cpnext-cp,'%');
    if (i != (unsigned int) (cpnext - cp)) {
      if (!flaggoodfield) {	/* MSG(TXT_EDIT_START)/END */
	if (case_startb(cp+i,cpnext-cp-i,MSG(TXT_EDIT_START))) {
		/* start tag. Store users 'quote characters', e.g. '> ' */
	  stralloc_copyb(&quoted,cp,i);
	  flaggoodfield = 1;
	  cp = cpnext + 1;
	  continue;
	}
      } else
	if (case_startb(cp+i,cpnext-cp-i,MSG(TXT_EDIT_END))) {
	  flagdone = 1;
	  break;
	}
    }
    if (flaggoodfield) {
      if ((len += cpnext - cp - quoted.len + 1) > MAXEDIT)
	strerr_die1x(100,MSG(ERR_EDSIZE));

      if (quoted.len && cpnext-cp >= (int) quoted.len &&
	  !str_diffn(cp,quoted.s,quoted.len))
	cp += quoted.len;	/* skip quoting characters */
      cplast = cpnext - 1;
      if (*cplast == '\r')	/* CRLF -> '\n' for base64 encoding */
	*cplast = '\n';
      else
	++cplast;
      if (substdio_put(&sstext,cp,cplast-cp+1) == -1)
	strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fneditn.s));
    }
    cp = cpnext + 1;
  }
  if (!flagdone)
    strerr_die2x(100,FATAL,MSG(ERR_NO_MARK));
  if (substdio_flush(&sstext) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fneditn.s));
  if (fsync(fd) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_SYNC,fneditn.s));
  if (fchmod(fd, 0600) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_CHMOD,fneditn.s));
  if (close(fd) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_CLOSE,fneditn.s));
  wrap_rename(fneditn.s,fnedit.s);

  unlock();
  hdr_subject(MSG1(SUB_EDIT_SUCCESS,fname));
  hdr_ctboundary();
  copy(&qq,"text/top",flagcd);
  copy_act("text/edit-done");
  copybottom(0);
  qmail_to(&qq,sender);		/* not necessarily from mod */
}
Esempio n. 9
0
int main(int argc,char **argv)
{
  int child;
  const char *sendargs[4];
  stralloc addr = {0};
  unsigned int pos = 0,pos2,poslocal,len;
  const char *cp;

  unsigned long hh = 4L;		/* default time 04:12 */
  unsigned long mm = 12L;
  const char *dow = "*";		/* day of week */
  const char *qmail_inject = "/bin/qmail-inject ";
  char strnum[FMT_ULONG];
  unsigned long uid,euid = 0;

  stralloc rp = {0};
  stralloc user = {0};
  stralloc euser = {0};
  stralloc dir = {0};
  stralloc listaddr = {0};
  stralloc line = {0};

  struct passwd *ppasswd;

  int match;
  int hostmatch;
  int localmatch;
  unsigned long dh,t;
  int founduser = 0;
  int listmatch = 0;
  int flagdigit = 0;
  int flagours;
  int foundlocal = 0;
  int foundmatch = 0;
  unsigned int nolists = 0;
  unsigned long maxlists;
  unsigned int lenhost,lenlocal;
  int fdin,fdout = -1;

  char *local = (char *) 0;	/* list = local@host */
  const char *host = (char *) 0;
  char *code = (char *) 0;	/* digest code */

  char inbuf[512];
  substdio ssin;

  char outbuf[512];
  substdio ssout;

  (void) umask(077);
  sig_pipeignore();

  optind = getconfopt(argc,argv,options,0,0);
  if (flagt != 0) {
    pos = scan_ulong(flagt,&hh);
    if (flagt[pos++] != ':') die_usage();
    (void) scan_ulong(flagt + pos,&mm);
  }
  if (flagw != 0) {
    dow = flagw;
    cp = flagw - 1;
    while (*(++cp)) {
      if (*cp >= '0' && *cp <= '7') {
	if (flagdigit) die_dow();
	flagdigit = 1;
      } else if (*cp == ',') {
	if (!flagdigit) die_dow();
	flagdigit = 0;
      } else
	die_dow();
    }
  }

  if (flaglist + flagdelete + flagconfig > 1)
    strerr_die2x(100,FATAL,MSG(ERR_EXCLUSIVE));
  uid = getuid();
  if (uid && !(euid = geteuid()))
    strerr_die2x(100,FATAL,MSG(ERR_SUID));
  if (!(ppasswd = getpwuid(uid)))
    strerr_die2x(100,FATAL,MSG(ERR_UID));
  if (!stralloc_copys(&user,ppasswd->pw_name)) die_nomem();
  if (!stralloc_0(&user)) die_nomem();
  if (!(ppasswd = getpwuid(euid)))
    strerr_die2x(100,FATAL,MSG(ERR_EUID));
  if (!stralloc_copys(&dir,ppasswd->pw_dir)) die_nomem();
  if (!stralloc_0(&dir)) die_nomem();
  if (!stralloc_copys(&euser,ppasswd->pw_name)) die_nomem();
  if (!stralloc_0(&euser)) die_nomem();

  wrap_chdir(dir.s);

  local = argv[optind++];	/* list address, optional for -c & -l */
  if (!local) {
    if (!flagconfig && !flaglist)
      die_usage();
    lenlocal = 0;
    lenhost = 0;
  } else {
    if (!stralloc_copys(&listaddr,local)) die_nomem();
    if (!isclean(local,1))
      die_argument();
    pos = str_chr(local,'@');
    lenlocal = pos;
    local[pos] = '\0';
    host = local + pos + 1;
    lenhost = str_len(host);
    code = argv[optind];
    if (!code) {		/* ignored for -l, -c, and -d */
      if (flagdelete || flaglist || flagconfig)
				/* get away with not putting code for delete */
        code = (char*)"a";	/* a hack - so what! */
      else
        die_usage();
    } else
      if (!isclean(code,0))
        die_argument();
  }
  if ((fdin = open_read(TXT_EZCRONRC)) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,TXT_EZCRONRC));
	/* first line is special */
  substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof(inbuf));
  if (getln(&ssin,&line,&match,'\n') == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_READ,TXT_EZCRONRC));

  if (!match)
    strerr_die2sys(111,FATAL,MSG1(ERR_READ,TXT_EZCRONRC));
	/* (since we have match line.len has to be >= 1) */
  line.s[line.len - 1] = '\0';
  if (!isclean(line.s,0))	 /* host for bounces */
    strerr_die2x(100,FATAL,MSG1(ERR_CFHOST,TXT_EZCRONRC));
  if (!stralloc_copys(&rp,line.s)) die_nomem();

  match = 1;
  for(;;) {
    if (!match) break;		/* to allow last line without '\n' */
    if (getln(&ssin,&line,&match,'\n') == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_READ,TXT_EZCRONRC));
    if (!line.len)
      break;
    line.s[line.len-1] = '\0';
    if (!case_startb(line.s,line.len,user.s))
      continue;
    pos = user.len - 1;
    if (pos >= line.len || line.s[pos] != ':')
      continue;
    founduser = 1;		 /* got user line */
    break;
  }
  close(fdin);
  if (!founduser)
    strerr_die2x(100,FATAL,MSG(ERR_BADUSER));
  
  if (flagconfig) {
    line.s[line.len-1] = '\n';	/* not very elegant ;-) */
    substdio_fdbuf(&ssout,write,1,outbuf,sizeof(outbuf));
    if (substdio_put(&ssout,line.s,line.len) == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
    if (substdio_flush(&ssout) == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
    _exit(0);
  }
  ++pos;				/* points to first ':' */
  len = str_chr(line.s+pos,':');	/* second ':' */
    if (!line.s[pos + len])
      die_syntax(&line);
  if (!local) {				/* only -d and std left */
    localmatch = 1;
    hostmatch = 1;
  } else {
    hostmatch = 0;
    if (len <= str_len(local))
      if (!str_diffn(line.s+pos,local,len))
        localmatch = 1;
  }
  pos += len + 1;
  len = str_chr(line.s + pos,':');	/* third */
  if (!line.s[pos + len])
    die_syntax(&line);
  if (local) {				/* check host */
    if (len == 0)			/* empty host => any host */
      hostmatch = 1;
    else
      if (len == str_len(host))
        if (!case_diffb(line.s+pos,len,host))
          hostmatch = 1;
  }
  pos += len + 1;
  pos += scan_ulong(line.s+pos,&maxlists);
  if (line.s[pos]) {			/* check additional lists */
    if (line.s[pos] != ':')
      die_syntax(&line);
    if (line.s[pos+1+str_chr(line.s+pos+1,':')])
      die_syntax(&line);	/* reminder lists are not separated by ':'  */
				/* otherwise a ':' or arg miscount will die */
				/* silently */
    if (local) {
      while (++pos < line.len) {
        len = str_chr(line.s + pos,'@');
        if (len == lenlocal && !str_diffn(line.s + pos,local,len)) {
          pos += len;
          if (!line.s[pos]) break;
          pos++;
          len = str_chr(line.s+pos,',');
            if (len == lenhost && !case_diffb(line.s+pos,len,host)) {
              listmatch = 1;
              break;
            }
        }
        pos += len;
      }
    }
  }
  if (!listmatch) {
    if (!hostmatch)
      strerr_die2x(100,FATAL,MSG(ERR_BADHOST));
    if (!localmatch)
      strerr_die2x(100,FATAL,MSG(ERR_BADLOCAL));
  }
	/* assemble correct line */
  if (!flaglist) {
    if (!stralloc_copyb(&addr,strnum,fmt_ulong(strnum,mm))) die_nomem();
    if (!stralloc_cats(&addr," ")) die_nomem();
    dh = 0L;
    if (deltah <= 3L) dh = deltah;
    else if (deltah <= 6L) dh = 6L;
    else if (deltah <= 12L) dh = 12L;
    else if (deltah <= 24L) dh = 24L;
    else if (deltah <= 48L) {
      if (dow[0] == '*') dow = "1,3,5";
    } else if (deltah <= 72L) {
      if (dow[0] == '*') dow = "1,4";
    } else
    if (dow[0] == '*') dow = "1";

    if (!dh) {
      if (!stralloc_cats(&addr,"*")) die_nomem();
    } else {
      if (!stralloc_catb(&addr,strnum,fmt_ulong(strnum,hh))) die_nomem();
      for (t = hh + dh; t < hh + 24L; t+=dh) {
        if (!stralloc_cats(&addr,",")) die_nomem();
        if (!stralloc_catb(&addr,strnum,fmt_ulong(strnum,t % 24L))) die_nomem();
      }
    }
    if (!stralloc_cats(&addr," * * ")) die_nomem();
    if (!stralloc_cats(&addr,dow)) die_nomem();
    if (!stralloc_cats(&addr," ")) die_nomem();
    if (!stralloc_cats(&addr,auto_qmail)) die_nomem();
    if (!stralloc_cats(&addr,qmail_inject)) die_nomem();
    if (!stralloc_cats(&addr,local)) die_nomem();
    if (!stralloc_cats(&addr,"-dig-")) die_nomem();
    if (!stralloc_cats(&addr,code)) die_nomem();
    if (!stralloc_cats(&addr,"@")) die_nomem();
    if (!stralloc_cats(&addr,host)) die_nomem();
		/* feed 'Return-Path: <user@host>' to qmail-inject */
    if (!stralloc_cats(&addr,"%Return-path: <")) die_nomem();
    if (!stralloc_cats(&addr,user.s)) die_nomem();
    if (!stralloc_cats(&addr,"@")) die_nomem();
    if (!stralloc_cat(&addr,&rp)) die_nomem();
    if (!stralloc_cats(&addr,">\n")) die_nomem();
  }
  if (!stralloc_0(&addr)) die_nomem();

  if (!flaglist) {
	/* now to rewrite crontab we need to lock */
    lockfile("crontabl");
  } /* if !flaglist */
  if ((fdin = open_read("crontab")) == -1) {
    if (errno != error_noent)
      strerr_die2sys(111,FATAL,MSG1(ERR_READ,"crontab"));
  } else
    substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof(inbuf));
  if (flaglist)
    substdio_fdbuf(&ssout,write,1,outbuf,sizeof(outbuf));
  else {
    if ((fdout = open_trunc("crontabn")) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"crontabn"));
    substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof(outbuf));
  }
  line.len = 0;

  if (fdin != -1) {
    for (;;) {
      if (!flaglist && line.len) {
        line.s[line.len-1] = '\n';
        if (substdio_put(&ssout,line.s,line.len) == -1)
          strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"crontabn"));
      }
      if (getln(&ssin,&line,&match,'\n') == -1)
        strerr_die2sys(111,FATAL,MSG1(ERR_READ,"crontab"));
      if (!match)
        break;
      flagours = 0;			/* assume entry is not ours */
      foundlocal = 0;
      line.s[line.len - 1] = '\0';	/* match so at least 1 char */
      pos = 0;
      while (line.s[pos] == ' ' || line.s[pos] == '\t') ++pos;
      if (line.s[pos] == '#')
        continue;			/* cron comment */
      pos = str_chr(line.s,'/');
      if (!str_start(line.s+pos,auto_qmail)) continue;
      pos += str_len(auto_qmail);
      if (!str_start(line.s+pos,qmail_inject)) continue;
      pos += str_len(qmail_inject);
      poslocal = pos;
      pos = byte_rchr(line.s,line.len,'<');	/* should be Return-Path: < */
      if (pos == line.len)
        continue;			/* not ezmlm-cron line */
      pos++;
     len = str_chr(line.s+pos,'@');
      if (len == user.len - 1 && !str_diffn(line.s+pos,user.s,len)) {
        flagours = 1;
        ++nolists;		/* belongs to this user */
      }
      if (!local) {
        foundlocal = 1;
      } else {
        pos = poslocal + str_chr(line.s+poslocal,'@');
        if (pos + lenhost +1 >= line.len) continue;
        if (case_diffb(line.s+pos+1,lenhost,host)) continue;
        if (line.s[pos+lenhost+1] != '%') continue;
				/* check local */
        if (poslocal + lenlocal + 5 >= line.len) continue;
        if (!str_start(line.s+poslocal,local)) continue;
        pos2 = poslocal+lenlocal;
        if (!str_start(line.s+pos2,"-dig-")) continue;
        foundlocal = 1;
      }
      if (foundlocal) {
        foundmatch = 1;
        if (flaglist && (local || flagours)) {
          if (substdio_put(&ssout,line.s,line.len) == -1)
            strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
          if (substdio_put(&ssout,"\n",1) == -1)
            strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT));
        }
        line.len = 0;		/* same - kill line */
        if (flagours)
          --nolists;
      }
    }
    close(fdin);
  }
  if (flaglist) {
    if (substdio_flush(&ssout) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_FLUSH,"stdout"));
    if (foundmatch)		/* means we had a match */
      _exit(0);
    else
      strerr_die2x(100,FATAL,MSG(ERR_NO_MATCH));
  }
	/* only -d and regular use left */

  if (nolists >= maxlists && !flagdelete)
    strerr_die2x(100,FATAL,MSG(ERR_LISTNO));
  if (!flagdelete)
    if (substdio_put(&ssout,addr.s,addr.len-1) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"crontabn"));
  if (flagdelete && !foundlocal)
    strerr_die2x(111,FATAL,MSG(ERR_NO_MATCH));
  if (substdio_flush(&ssout) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_FLUSH,"crontabn"));
  if (fsync(fdout) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_SYNC,"crontabn++"));
  if (close(fdout) == -1)
    strerr_die2sys(111,FATAL,MSG1(ERR_CLOSE,"crontabn"));
  wrap_rename("crontabn","crontab");
  sendargs[0] = "sh";
  sendargs[1] = "-c";

  if (!stralloc_copys(&line,auto_cron)) die_nomem();
  if (!stralloc_cats(&line,"/crontab '")) die_nomem();
  if (!stralloc_cats(&line,dir.s)) die_nomem();
  if (!stralloc_cats(&line,"/crontab'")) die_nomem();
  if (!stralloc_0(&line)) die_nomem();
  sendargs[2] = line.s;
  sendargs[3] = 0;
  if ((child = wrap_fork()) == 0) {
    if (setreuid(euid,euid) == -1)
      strerr_die2sys(100,FATAL,MSG(ERR_SETUID));
    wrap_execvp(sendargs);
  }
  /* parent */
  switch (wrap_waitpid(child)) {
      case 0:
        _exit(0);
      default:
        strerr_die2x(111,FATAL,MSG(ERR_CRONTAB));
  }
}
Esempio n. 10
0
void main(int argc,char **argv)
{
  char *sender;
  char *def;
  char *local;
  char *action;
  int flaginheader;
  int flagcomment;
  int flaggoodfield;
  int flagdone;
  int fd, fdlock;
  int match;
  const char *err;
  char encin = '\0';
  unsigned int start,confnum;
  unsigned int pos,i;
  int child;
  int opt;
  char *cp,*cpnext,*cpfirst,*cplast,*cpafter;

  (void) umask(022);
  sig_pipeignore();
  when = now();

  if (!stralloc_copys(&sendopt,"-")) die_nomem();
  opt = getconfopt(argc,argv,options,1,&dir);

  sender = get_sender();
  if (!sender) strerr_die2x(100,FATAL,MSG(ERR_NOSENDER));
  local = env_get("LOCAL");
  if (!local) strerr_die2x(100,FATAL,MSG(ERR_NOLOCAL));
  def = env_get("DEFAULT");
  if (!def) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT));

  if (!*sender)
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));
  if (!sender[str_chr(sender,'@')])
    strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS));
  if (str_equal(sender,"#@[]"))
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));

  /* local should be >= def, but who knows ... */
  cp = local + str_len(local) - str_len(def) - 2;
  if (cp < local) die_badformat();
  action = local + byte_rchr(local,cp - local,'-');
  if (action == cp) die_badformat();
  action++;

  if (!action[0]) die_badformat();
  if (!str_start(action,ACTION_ACCEPT) && !str_start(action,ACTION_REJECT))
    die_badformat();
  start = str_chr(action,'-');
  if (!action[start]) die_badformat();
  confnum = 1 + start + str_chr(action + start + 1,'.');
  if (!action[confnum]) die_badformat();
  confnum += 1 + str_chr(action + confnum + 1,'.');
  if (!action[confnum]) die_badformat();
  if (!stralloc_copyb(&fnbase,action+start+1,confnum-start-1)) die_nomem();
  if (!stralloc_0(&fnbase)) die_nomem();
  cookie(hash,key.s,key.len,fnbase.s,"","a");
  if (byte_diff(hash,COOKIE,action+confnum+1))
    die_badformat();

  fdlock = lockfile("mod/lock");

  switch(checkfile(fnbase.s)) {
    case 0:
      strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT));
    case -1:			/* only error if new request != action taken */
      if (str_start(action,ACTION_ACCEPT))
        strerr_die2x(0,INFO,MSG(ERR_MOD_ACCEPTED));
      else
        strerr_die2x(100,FATAL,MSG(ERR_MOD_ACCEPTED));
    case -2:
      if (str_start(action,ACTION_REJECT))
        strerr_die2x(0,INFO,MSG(ERR_MOD_REJECTED));
      else
        strerr_die2x(100,FATAL,MSG(ERR_MOD_REJECTED));
    default:
      break;
  }
/* Here, we have an existing filename in fnbase with the complete path */
/* from the current dir in fnmsg. */

  if (str_start(action,ACTION_REJECT)) {

    if (qmail_open(&qq, (stralloc *) 0) == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE));


				/* Build recipient from msg return-path */
    fd = open_read(fnmsg.s);
    if (fd == -1) {
      if (errno != error_noent)
        strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s));
      else
        strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT));
    }
    substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));

    if (getln(&sstext,&line,&match,'\n') == -1 || !match)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    maketo();			/* extract SENDER from return-path */
						/* Build message */
    hdr_add2s("Mailing-List: ",MSG(TXT_MAILING_LIST));
    if (listid.len > 0)
      hdr_add2("List-ID: ",listid.s,listid.len);
    hdr_datemsgid(when);
    hdr_from("-owner");
    if (replyto)
      hdr_add2s("Reply-To: ",replyto);
    hdr_add2s("To: ",to.s);
    hdr_subject(MSG(SUB_RETURNED_POST));

    if (flagmime) {
      hdr_mime(CTYPE_MULTIPART);
      hdr_boundary(0);
      hdr_ctype(CTYPE_TEXT);
      hdr_transferenc();
    }
    copy(&qq,"text/top",flagcd);
    copy(&qq,"text/mod-reject",flagcd);

    flagcomment = 0;
    flaginheader = 1;
    if (!stralloc_copys(&text,"")) die_nomem();
    if (!stralloc_ready(&text,1024)) die_nomem(); 
    for (;;) {		/* copy moderator's rejection comment */
      if (getln(subfdin,&line,&match,'\n') == -1)
        strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
      if (!match) break;
      if (flaginheader) {
        if (case_startb(line.s,line.len,"Content-Transfer-Encoding:")) {
          pos = 26;
          while (line.s[pos] == ' ' || line.s[pos] == '\t') ++pos;
          if (case_startb(line.s+pos,line.len-pos,"base64"))
            encin = 'B';
          else if (case_startb(line.s+pos,line.len-pos,"quoted-printable"))
            encin = 'Q';
        }
        if (line.len == 1)
          flaginheader = 0;
      } else
        if (!stralloc_cat(&text,&line)) die_nomem();
    }	/* got body */
    if (encin) {
      if (encin == 'B')
        decodeB(text.s,text.len,&line);
      else
        decodeQ(text.s,text.len,&line);
      if (!stralloc_copy(&text,&line)) die_nomem();
    }
    cp = text.s;
    cpafter = text.s + text.len;
    if (!stralloc_copys(&line,"\n>>>>> -------------------- >>>>>\n"))
			die_nomem();
    flaggoodfield = 0;
    flagdone = 0;
    while ((cpnext = cp + byte_chr(cp,cpafter-cp,'\n')) != cpafter) {
      i = byte_chr(cp,cpnext-cp,'%');
      if (i <= 5 && cpnext-cp-i >= 3) {
				/* max 5 "quote characters" and space for %%% */
        if (cp[i+1] == '%' && cp[i+2] == '%') {
          if (!flaggoodfield) {					/* Start tag */
            if (!stralloc_copyb(&quoted,cp,i)) die_nomem();	/* quote chars*/
            flaggoodfield = 1;
            cp = cpnext + 1;
            cpfirst = cp;
            continue;
          } else {						/* end tag */
            if (flagdone)	/* 0 no comment lines, 1 comment line */
              flagdone = 2;	/* 2 at least 1 comment line & end tag */
            break;
          }
        }
      }
      if (flaggoodfield) {
        cplast = cpnext - 1;
        if (*cplast == '\r')	/* CRLF -> '\n' for base64 encoding */
          *cplast = '\n';
        else
          ++cplast;
			/* NUL is now ok, so the test for it was removed */
        flagdone = 1;
        i = cplast - cp + 1;
        if (quoted.len && quoted.len <= i &&
		!str_diffn(cp,quoted.s,quoted.len)) {	/* quote chars */
          if (!stralloc_catb(&line,cp+quoted.len,i-quoted.len)) die_nomem();
        } else
          if (!stralloc_catb(&line,cp,i)) die_nomem();	/* no quote chars */
      }
      cp = cpnext + 1;
    }
    if (flagdone == 2) {
    if (!stralloc_cats(&line,"<<<<< -------------------- <<<<<\n")) die_nomem();
      code_qput(line.s,line.len);
    }
    if (flagcd == 'B') {
      encodeB("",0,&line,2);
      qmail_put(&qq,line.s,line.len);
    }
    if (flagmime) {
      hdr_boundary(0);
      hdr_ctype(CTYPE_MESSAGE);
    }
    qmail_puts(&qq,"\n");
    if (seek_begin(fd) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s));

    substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
    if (qmail_copy(&qq,&sstext,-1) != 0)
      strerr_die2sys(111,FATAL,MSG1(ERR_READ,fnmsg.s));
    close(fd);

    if (flagmime)
      hdr_boundary(1);

    if (!stralloc_copy(&line,&outlocal)) die_nomem();
    if (!stralloc_cats(&line,"-return-@")) die_nomem();
    if (!stralloc_cat(&line,&outhost)) die_nomem();
    if (!stralloc_0(&line)) die_nomem();
    qmail_from(&qq,line.s);
    if (to.len)
      qmail_to(&qq,to.s);

    if (!stralloc_copys(&fnnew,"mod/rejected/")) die_nomem();
    if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem();
    if (!stralloc_0(&fnnew)) die_nomem();

/* this is strictly to track what happended to a message to give informative */
/* messages to the 2nd-nth moderator that acts on the same message. Since    */
/* this isn't vital we ignore errors. Also, it is no big ideal if unlinking  */
/* the old file fails. In the worst case it gets acted on again. If we issue */
/*  a temp error the reject will be redone, which is slightly worse.         */

    if (*(err = qmail_close(&qq)) == '\0') {
        fd = open_trunc(fnnew.s);
        if (fd != -1)
          close(fd);
        unlink(fnmsg.s);
        strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
        strerr_die2x(0,"ezmlm-moderate: info: qp ",strnum);
    } else
        strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1);

  } else if (str_start(action,ACTION_ACCEPT)) {
        fd = open_read(fnmsg.s);
        if (fd == -1) {
          if (errno !=error_noent)
            strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s));
          else	/* shouldn't happen since we've got lock */
            strerr_die3x(100,FATAL,fnmsg.s,MSG(ERR_MOD_TIMEOUT));
	}

    substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf));
				/* read "Return-Path:" line */
    if (getln(&sstext,&line,&match,'\n') == -1 || !match)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    maketo();			/* extract SENDER to "to" */
    env_put2("SENDER",to.s);	/* set SENDER */
    if (seek_begin(fd) == -1)	/* rewind, since we read an entire buffer */
      strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s));

    if ((child = wrap_fork()) == 0) {
      close(0);
      dup(fd);	/* make fnmsg.s stdin */
      if (argc > opt + 1)
	wrap_execvp((const char **)argv + opt);
      else if (argc > opt)
        wrap_execsh(argv[opt]);
      else
        wrap_execbin("/ezmlm-send", &sendopt, dir);
    }
      /* parent */
      close(fd);
      wrap_exitcode(child);
      if (!stralloc_copys(&fnnew,"mod/accepted/")) die_nomem();

      if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem();
      if (!stralloc_0(&fnnew)) die_nomem();
/* ignore errors */
      fd = open_trunc(fnnew.s);
      if (fd != -1)
        close(fd);
      unlink(fnmsg.s);
      _exit(0);
   }
}
Esempio n. 11
0
int main(int argc,char **argv)
{
  unsigned long maxmsgsize = 0L;
  unsigned long minmsgsize = 0L;
  unsigned long msgsize = 0L;
  char linetype = ' ';
  char *cp, *cpstart, *cpafter;
  const char *dir;
  const char *err;
  const char *sender;
  unsigned int len;
  int match;

  getconfopt(argc,argv,options,-1,&dir);
  if (dir) {
    startup(dir);
    flagparsemime = 1;		/* only if dir do we have mimeremove/reject */
    if (getconf_line(&line,"msgsize",0)) {
      if (!stralloc_0(&line)) die_nomem();
      len = scan_ulong(line.s,&maxmsgsize);
      if (line.s[len] == ':')
        scan_ulong(line.s+len+1,&minmsgsize);
    }
    if (flagforward) {
      if (!stralloc_copys(&mydtline,"Delivered-To: command forwarder for "))
	die_nomem();
      if (!stralloc_catb(&mydtline,outlocal.s,outlocal.len)) die_nomem();
      if (!stralloc_cats(&mydtline,"@")) die_nomem();
      if (!stralloc_catb(&mydtline,outhost.s,outhost.len)) die_nomem();
      if (!stralloc_cats(&mydtline,"\n")) die_nomem();
    }
  } else {
    flagtook = 1;		/* if no "dir" we can't get outlocal/outhost */
    flagforward = 0;		/* nor forward requests */
  }

  sender = get_sender();
  if (!sender)
    die_sender();
  if (!*sender)
    strerr_die2x(100,FATAL,MSG(ERR_BOUNCE));

  if (flagparsemime) {		/* set up MIME parsing */
    if (getconf(&mimeremove,"mimekeep",0))
      mimeremoveflag = 1;
    else
      getconf(&mimeremove,"mimeremove",0);
    constmap_init(&mimeremovemap,mimeremove.s,mimeremove.len,0);
    getconf(&mimereject,"mimereject",0);
    constmap_init(&mimerejectmap,mimereject.s,mimereject.len,0);
  }
  if (flagheaderreject && dir) {
    getconf(&headerreject,"headerreject",0);
    constmap_init(&headerrejectmap,headerreject.s,headerreject.len,0);
  }
  for (;;) {
    if (getln(&ssin,&line,&match,'\n') == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    if (!match) break;
    if (flagheaderreject && dir)
      if (constmap(&headerrejectmap,line.s,byte_chr(line.s,line.len,':')))
        strerr_die2x(100,FATAL,MSG(ERR_MAILING_LIST));

    if (line.len == 1) break;
    cp = line.s; len = line.len;
    if ((*cp == ' ' || *cp == '\t')) {
      switch(linetype) {
	case 'T': if (!stralloc_catb(&to,cp,len-1)) die_nomem(); break;
	case 'S': if (!stralloc_catb(&subject,cp,len-1)) die_nomem(); break;
	case 'C': if (!stralloc_catb(&content,cp,len-1)) die_nomem(); break;
	case 'P': if (!stralloc_catb(&precd,cp,len-1)) die_nomem(); break;
	default: break;
      }
    } else {
      if (!flagtook &&
		(case_startb(cp,len,"to:") || case_startb(cp,len,"cc:"))) {
	linetype = 'T';		/* cat so that To/Cc don't overwrite */
        if (!stralloc_catb(&to,line.s + 3,line.len - 4)) die_nomem();
      } else if ((flagneedsubject || flagrejectcommands) &&
			 case_startb(cp,len,"subject:")) {
	if (!stralloc_copyb(&subject,cp+8,len-9)) die_nomem();
	linetype = 'S';
      } else if (case_startb(cp,len,"content-type:")) {
	if (!stralloc_copyb(&content,cp+13,len-14)) die_nomem();
	linetype = 'C';
      } else if (case_startb(cp,len,"precedence:")) {
	if (!stralloc_copyb(&precd,cp+11,len-12)) die_nomem();
	linetype = 'P';
      } else {
	if (flagforward && line.len == mydtline.len) {
	  if (!byte_diff(line.s,line.len,mydtline.s))
            strerr_die2x(100,FATAL,MSG(ERR_LOOPING));
        }
        linetype = ' ';
      }
    }
  }
  if (precd.len >= 4 &&
		(!case_diffb(precd.s + precd.len - 4,4,"junk") ||
		!case_diffb(precd.s + precd.len - 4,4,"bulk")))
	  strerr_die1x(99,MSG(ERR_JUNK));	/* ignore precedence junk/bulk */
  cp = subject.s;
  len = subject.len;
  while (len && (cp[len-1] == ' ' || cp[len-1] == '\t')) --len;
  while (len && ((*cp == ' ') || (*cp == '\t'))) { ++cp; --len; }
  flaghavesubject = 1;

  if (flagbody)
    if ((len > 9 && case_starts(cp,"subscribe"))
	|| (len > 11 && case_starts(cp,"unsubscribe")))
      flaghavecommand = 1;

  switch(len) {
    case 0: flaghavesubject = 0; break;
    case 4: if (!case_diffb("help",4,cp)) flaghavecommand = 1; break;
    case 6:	/* Why can't they just leave an empty subject empty? */
	    if (!case_diffb("(null)",6,cp))
              flaghavesubject = 0;
            else
	    if (!case_diffb("(none)",6,cp))
              flaghavesubject = 0;
            else
              if (!case_diffb("remove",6,cp))
	        flaghavecommand = 1;
            break;
    case 9: if (!case_diffb("subscribe",9,cp)) flaghavecommand = 1; break;
    case 11: if (!case_diffb("unsubscribe",11,cp)) flaghavecommand = 1; break;
    case 12: if (!case_diffb("(no subject)",12,cp)) flaghavesubject = 0; break;
    default: break;
  }

  if (!flagtook && !getto(&to))
    strerr_die2x(exitquiet,FATAL,MSG(ERR_NO_ADDRESS));

  if (flagneedsubject && !flaghavesubject)
    strerr_die2x(100,FATAL,MSG(ERR_NO_SUBJECT));

  if (flagrejectcommands && flaghavecommand) {
    if (flagforward) {			/* flagforward => forward */
      if (qmail_open(&qq) == -1)	/* open queue */
	strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE));
      qmail_put(&qq,mydtline.s,mydtline.len);
      if (seek_begin(0) == -1)
	strerr_die2sys(111,FATAL,MSG(ERR_SEEK_INPUT));
      if (qmail_copy(&qq,&ssin2,copylines) != 0)
	strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
      if (!stralloc_copy(&to,&outlocal)) die_nomem();
      if (!stralloc_cats(&to,"-request@")) die_nomem();
      if (!stralloc_cat(&to,&outhost)) die_nomem();
      if (!stralloc_0(&to)) die_nomem();
      qmail_from(&qq,sender);
      qmail_to(&qq,to.s);
      if (*(err = qmail_close(&qq)) == '\0') {
        strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0;
        strerr_die2x(99,"ezmlm-request: info: forward qp ",strnum);
      } else
        strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1);
    } else
      strerr_die2x(100,FATAL,MSG(ERR_SUBCOMMAND));
  }

  if (content.len) {			/* MIME header */
    cp = content.s;
    len = content.len;
    while (len && (*cp == ' ' || *cp == '\t')) { ++cp; --len; }
    cpstart = cp;
    if (*cp == '"') {			/* might be commented */
      ++cp; cpstart = cp;
      while (len && *cp != '"') { ++cp; --len; }
    } else {
      while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
        ++cp; --len;
      }
    }

    if (flagparsemime)
      if ((!!constmap(&mimeremovemap,cpstart,cp-cpstart) ^ mimeremoveflag) ||
	  constmap(&mimerejectmap,cpstart,cp-cpstart)) {
	*(cp) = (char) 0;
	strerr_die2x(100,FATAL,MSG1(ERR_BAD_TYPE,cpstart));
      }

    cpafter = content.s+content.len;
    while((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) {
      ++cp;
      while (cp < cpafter && (*cp == ' ' || *cp == '\t')) ++cp;
      if (case_startb(cp,cpafter - cp,"boundary=")) {
        cp += 9;			/* after boundary= */
        if (cp < cpafter && *cp == '"') {
          ++cp;
          cpstart = cp;
          while (cp < cpafter && *cp != '"') ++cp;
	  if (cp == cpafter)
		strerr_die1x(100,MSG(ERR_MIME_QUOTE));
        } else {
          cpstart = cp;
          while (cp < cpafter &&
             *cp != ';' && *cp != ' ' && *cp != '\t') ++cp;
        }
        if (!stralloc_copys(&boundary,"--")) die_nomem();
        if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
		die_nomem();
	break;
      }
    }		/* got boundary, now parse for parts */
  }

  for (;;) {
    if (getln(&ssin,&line,&match,'\n') == -1)
      strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT));
    if (!match) break;
    if (line.len == 1) {
      flagcheck = 0;
      continue;
		/* Doesn't do continuation lines. _very_ unusual, and worst */
		/* case one slips through that shouldn't have */
    } else if (flagcheck && case_startb(line.s,line.len,"content-type:")) {
        cp = line.s + 13;
	len = line.len - 14;			/* zap '\n' */
        while (*cp == ' ' || *cp == '\t') { ++cp; --len; }
        cpstart = cp;
	if (*cp == '"') {			/* quoted */
	  ++cp; cpstart = cp;
	  while (len && *cp != '"') { ++cp; --len; }
        } else {				/* not quoted */
          while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
	    ++cp; --len;
	  }
        }
	if (flagparsemime && constmap(&mimerejectmap,cpstart,cp-cpstart)) {
          *cp = '\0';
          strerr_die2x(100,FATAL,MSG1(ERR_BAD_PART,cpstart));
        }
    } else if (boundary.len && *line.s == '-' && line.len > boundary.len &&
	!str_diffn(line.s,boundary.s,boundary.len)) {
        flagcheck = 1;
    } else {
      if (!msgsize && flagbody)
	if (case_startb(line.s,line.len,"subscribe") ||
		case_startb(line.s,line.len,"unsubscribe"))
	  strerr_die2x(100,FATAL,MSG(ERR_BODYCOMMAND));
      if (!flagcheck) {
	  msgsize += line.len;
	  if (maxmsgsize && msgsize > maxmsgsize) {
	    strnum[fmt_ulong(strnum,maxmsgsize)] = 0;
	    strerr_die2x(100,FATAL,MSG1(ERR_MAX_SIZE,strnum));
	  }
      }
    }
  }
  if (msgsize < minmsgsize) {
    strnum[fmt_ulong(strnum,minmsgsize)] = 0;
        strerr_die2x(100,FATAL,MSG1(ERR_MIN_SIZE,strnum));
  }
  _exit(0);
}
Esempio n. 12
0
void write_threads(const msgentry *msgtable,
		   subentry *subtable,
		   const authentry *authtable,
		   const dateentry *datetable,
		   unsigned long from,unsigned long to)
/* Add the current threading data to the thread database without dups */
/* Writes the subject index first, then processes the individual files */
{
  const msgentry *pmsgt;
  subentry *psubt,*psubtm;
  subentry *presubt = (subentry *)0;
  const authentry *pautht;
  const dateentry *pdatet;
  const char *cp;
  unsigned int cp1;
  unsigned long msg;
  unsigned long ulmsginthread;
  unsigned long subnum;
  unsigned long authnum;
  unsigned long msgnum;
  unsigned int pos;
  unsigned int startdate,nextdate;
  unsigned int startmsg,nextmsg;
  int fd = -1;
  int fdn = -1;
  int match;
  int ffound;
  int lineno;
  int res;

  psubtm = subtable;		/* now for new threads */
  pdatet = datetable;
  startmsg = nextmsg = 0L;
  nextdate = pdatet->date;
  while (psubtm->sub) {		/* these are in msgnum order */
    if (!presubt)		/* for rewind */
      if (psubtm->lastmsg >= nextmsg)
	presubt = psubtm;	/* this thread extends beyond current month */
    if (psubtm->firstmsg >= nextmsg) {	/* done with this month */
      if (fdn != -1) close_proper(&ssout,fn.s,fnn.s);
      if (presubt)			/* need to rewind? */
	psubtm = presubt;		/* do it */
      psubt = psubtm;			/* tmp pointer to reset done flag */
      presubt = (subentry *)0;		/* reset rewind pointer */
      pdatet++;				/* next month */
      startdate = nextdate;		/* startdate */
      nextdate = pdatet->date;		/* end date */
      startmsg = nextmsg;		/* first message in month */
      nextmsg = pdatet->msg;		/* first message in next month */
      stralloc_copys(&fn,"archive/threads/");
      stralloc_catb(&fn,strnum,fmt_uint(strnum,startdate));
      stralloc_copy(&fnn,&fn);
      stralloc_0(&fn);
      stralloc_cats(&fnn,"n");
      stralloc_0(&fnn);
      if ((fdn = open_trunc(fnn.s)) == -1)
	strerr_die2sys(111,FATAL,MSG1(ERR_CREATE,fnn.s));
      substdio_fdbuf(&ssout,write,fdn,outbuf,sizeof(outbuf));
      if ((fd = open_read(fn.s)) == -1) {
      if (errno != error_noent)
             strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fn.s));
      } else {
	substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
      for (;;) {
      if (getln(&ssin,&line,&match,'\n') == -1)
             strerr_die2sys(111,FATAL,MSG1(ERR_READ,fn.s));
      if (!match) break;
      pos = scan_ulong(line.s,&msgnum);
      pos++;			/* skip ':' */
      if (msgnum >= from)
	continue;		/* ignore entries from threading range */
      if (line.len < pos + HASHLEN) {
	flagerror = -1;		/* and bad ones */
	continue;
      }
      psubt = subtable;
      cp = line.s + pos;
      ffound = 0;		/* search among already known subjects */
      for (;;) {
	res = str_diffn(psubt->sub,cp,HASHLEN);
	if (res < 0) {
	  if (psubt->higher)
	    psubt = psubt->higher;
	 else
	   break;
	} else if (res > 0) {
	  if (psubt->lower)
	    psubt = psubt->lower;
	  else
	    break;
	} else {
	  ffound = 1;
	  break;
	}
      }
      if (!ffound) {
	if (substdio_put(&ssout,line.s,line.len) == -1)
	  strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
      } else {			/* new # of msg in thread */
	cp += HASHLEN;		/* HASHLEN [#] Subject always \n at end */
	if (*(cp++) == ' ' && *(cp++) == '[') {
	  cp += scan_ulong(cp,&ulmsginthread);
	  if (*cp == ']') {
	    psubt->msginthread += (unsigned char) (ulmsginthread & 0xff);
	  }
	} else
	  flagerror = -5;
      }
    }
    close(fd);
  }
  continue;
  }

    if (psubtm->firstmsg < nextmsg && psubtm->lastmsg >= startmsg) {
      stralloc_copyb(&line,strnum,fmt_ulong(strnum,psubtm->lastmsg));
    stralloc_cats(&line,":");
    stralloc_catb(&line,psubtm->sub,HASHLEN);
    stralloc_cats(&line," [");
    stralloc_catb(&line,strnum,fmt_ulong(strnum,(unsigned long) psubtm->msginthread));
    stralloc_cats(&line,"]");
    stralloc_catb(&line,psubtm->sub + HASHLEN,psubtm->sublen - HASHLEN); /* has \n */
    if (substdio_put(&ssout,line.s,line.len) == -1)
	strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
    }
  psubtm++;
  }
  if (fdn != -1)
    close_proper(&ssout,fn.s,fnn.s);

  psubt = subtable;
  while (psubt->sub) {		/* now the threads */
    stralloc_copys(&fn,"archive/subjects/");
    stralloc_catb(&fn,psubt->sub,2);
    stralloc_0(&fn);
    if (mkdir(fn.s,0755) == -1)
    if (errno != error_exist)
      strerr_die2sys(111,FATAL,MSG1(ERR_CREATE,fn.s));
    fn.s[fn.len - 1] = '/';
    stralloc_catb(&fn,psubt->sub+2,HASHLEN-2);
    stralloc_copy(&fnn,&fn);
    stralloc_cats(&fnn,"n");
    stralloc_0(&fn);
    stralloc_0(&fnn);
    if ((fdn = open_trunc(fnn.s)) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_CREATE,fnn.s));
    substdio_fdbuf(&ssout,write,fdn,outbuf,sizeof(outbuf));
    if ((fd = open_read(fn.s)) == -1) {
      if (errno != error_noent)
	  strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fn.s));
      if (substdio_put(&ssout,psubt->sub,psubt->sublen) == -1)	/* write subject */
	     strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
    } else {					/* copy data */
	substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
	lineno = 0;
	for (;;) {
	  if (getln(&ssin,&line,&match,'\n') == -1)
             strerr_die2sys(111,FATAL,MSG1(ERR_READ,fn.s));
          if (!match) break;
	  if (!lineno) {			/* write subject */
	    if (line.len < HASHLEN + 1 || line.s[HASHLEN] != ' ')
		flagerror = -3;
	    if (substdio_put(&ssout,line.s,line.len) == -1)
	       strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
	    lineno = 1;
	    continue;
	  }
	  (void) scan_ulong(line.s,&msgnum);
	  if (msgnum >= from) break;
	  if (substdio_put(&ssout,line.s,line.len) == -1)
	     strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
	}
	(void) close(fd);	/* close old index */
      }

    subnum = (unsigned long) (psubt - subtable + 1);	/* idx of this subj */
    pmsgt = msgtable + psubt->firstmsg - from;	/* first message entry */
    for (msg = psubt->firstmsg; msg <= psubt->lastmsg; msg++) {
      if (pmsgt->subnum == subnum) {
        stralloc_copyb(&line,strnum,fmt_ulong(strnum,msg));
        stralloc_cats(&line,":");
	stralloc_catb(&line,strnum,fmt_uint(strnum,pmsgt->date));
	stralloc_cats(&line,":");
        if (pmsgt->authnum) {
	  pautht = authtable + pmsgt->authnum - 1;
	  cp1 = byte_chr(pautht->auth,pautht->authlen,' ');
	  if (cp1 != HASHLEN)
	    strerr_die1x(100,MSG(ERR_BAD_INDEX));
	  stralloc_catb(&line,pautht->auth,pautht->authlen); /* hash */
	} else
          stralloc_cats(&line,"\n");
	if (substdio_put(&ssout,line.s,line.len) == -1)
	  strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
      }
      pmsgt++;
    }
    close_proper(&ssout,fn.s,fnn.s);
    psubt++;
  }

					/* (no master author index) */
  pautht = authtable;
  while (pautht->auth) {		/* now the authors */
    stralloc_copys(&fn,"archive/authors/");
    stralloc_catb(&fn,pautht->auth,2);
    stralloc_0(&fn);
    if (mkdir(fn.s,0755) == -1)
    if (errno != error_exist)
      strerr_die2sys(111,FATAL,MSG1(ERR_CREATE,fn.s));
    fn.s[fn.len - 1] = '/';
    stralloc_catb(&fn,pautht->auth+2,HASHLEN-2);
    stralloc_copy(&fnn,&fn);
    stralloc_cats(&fnn,"n");
    stralloc_0(&fn);
    stralloc_0(&fnn);
    if ((fdn = open_trunc(fnn.s)) == -1)
      strerr_die2sys(111,FATAL,MSG1(ERR_CREATE,fnn.s));
    substdio_fdbuf(&ssout,write,fdn,outbuf,sizeof(outbuf));
      if ((fd = open_read(fn.s)) == -1) {
	if (errno != error_noent)
	  strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fn.s));
        else {			/* didn't exist before: write author */
          if (substdio_put(&ssout,pautht->auth,pautht->authlen) == -1)
	     strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
	}
      } else {					/* copy data */
	substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
	lineno = 0;
	for (;;) {
	  if (getln(&ssin,&line,&match,'\n') == -1)
             strerr_die2sys(111,FATAL,MSG1(ERR_READ,fn.s));
          if (!match) break;
	  if (!lineno) {			/* write author */
	    if (line.len < HASHLEN + 1 || line.s[HASHLEN] != ' ')
		flagerror = - 4;
	    if (substdio_put(&ssout,line.s,line.len) == -1)
	       strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
	    lineno = 1;
	    continue;
	  }
	  (void) scan_ulong(line.s,&msgnum);
	  if (msgnum >= from) break;
	  if (substdio_put(&ssout,line.s,line.len) == -1)
	     strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
	}
	(void) close(fd);			/* close old index */
      }

    authnum = (unsigned long) (pautht - authtable + 1);	/* idx of this auth */
    pmsgt = msgtable + pautht->firstmsg - from;	/* first message entry */
    for (msg = pautht->firstmsg; msg <= to; msg++) {
      if (pmsgt->authnum == authnum) {
        stralloc_copyb(&line,strnum,fmt_ulong(strnum,msg));
        stralloc_cats(&line,":");
	stralloc_catb(&line,strnum,fmt_uint(strnum,pmsgt->date));
	stralloc_cats(&line,":");
        if (pmsgt->subnum) {
	  psubt = subtable + pmsgt->subnum - 1;
          stralloc_catb(&line,psubt->sub,psubt->sublen);
	}
	if (substdio_put(&ssout,line.s,line.len) == -1)
	  strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,fnn.s));
      }
      pmsgt++;
    }
    close_proper(&ssout,fn.s,fnn.s);
    pautht++;
  }
}