Ejemplo n.º 1
0
static int str_catfromby(str* s, const char* helo_domain,
			 const char* host, const char* ip)
{
  int c;

  if (helo_domain == 0)
    helo_domain = (host != 0 && *host != 0) ? host : (ip != 0) ? ip : UNKNOWN;
  while((c = *helo_domain++) != 0) {
    if(!str_catc(s, (isalnum(c) || (c == '.') || (c == '-'))? c:'_')) return 0;
  }
  /* if (!str_cats(s, helo_domain)) return 0; */
  if (host != 0 || ip != 0) {
    if (!str_cats(s, " (")) return 0;
    if (host != 0) {
      if (!str_cats(s, host)) return 0;
      if (ip != 0)
	if (!str_catc(s, ' ')) return 0;
    }
    if (ip != 0) {
      if (!str_catc(s, '[')) return 0;
      if(strchr(ip, ':') && !str_cats(s, "IPV6:")) return 0;
      if( !str_cats(s, ip) ||
	  !str_catc(s, ']'))
	return 0;
    }
    if (!str_catc(s, ')')) return 0;
  }
  return 1;
}
Ejemplo n.º 2
0
static const response* check_fqdn(str* s)
{
  int at;
  int dot;
  const char* name;

  if ((at = str_findlast(s, '@')) <= 0) {
    if ((name = session_getenv("DEFAULTHOST")) != 0) {
      at = s->len;
      if (!str_catc(s, '@')
	  || !str_cats(s, name))
	return &resp_oom;
    }
    else
      return &resp_nodomain;
  }
  if ((dot = str_findlast(s, '.')) < at) {
    if ((name = session_getenv("DEFAULTDOMAIN")) != 0) {
      if (!str_catc(s, '.')
	  || !str_cats(s, name))
	return &resp_oom;
    }
    else
      return &resp_nofqdn;
  }
  return 0;
}
Ejemplo n.º 3
0
const char* temppath(const char* prefix, str* path)
{
  struct timeval tv;
  gettimeofday(&tv, 0);
  if (!str_copy2s(path, prefix, ".tmp.barch.") ||
      !str_catu(path, pid) ||
      !str_catc(path, '.') ||
      !str_catu(path, tv.tv_sec) ||
      !str_catc(path, '.') ||
      !str_catuw(path, tv.tv_usec, 6, '0'))
    die_oom(1);
  return path->s;
}
Ejemplo n.º 4
0
/* ------------------------------------------------------------------------- */
const char* format_connection(const struct connections_entry* c)
{
  static str s;
  if (!str_copys(&s, ipv4_format(&c->key.ip))) return 0;
  if (!str_catc(&s, '/')) return 0;
  if (!str_catu(&s, c->key.port)) return 0;
  if (!str_catc(&s, '/')) return 0;
  if (!str_cat(&s, &c->data.service->key.sender)) return 0;
  if (!str_catc(&s, '/')) return 0;
  if (!str_cat(&s, &c->data.service->key.service)) return 0;
  if (!str_cats(&s, ": ")) return 0;
  return s.s;
}
Ejemplo n.º 5
0
Archivo: sort.c Proyecto: bruceg/bglibs
/** Sort a string.

\param s The string to sort.
\param sep The character which delimits the substrings.
\param count The number of substrings within \c s (set to \c -1 if not known).
\param fn The comparison function.  Defaults to a function that works like \c memcmp.

\note This function allocates a temporary array of substring pointers,
and so may return \c 0 if memory allocation fails.  The string itself is
not reallocated.
*/
int str_sort(str* s, char sep, long count,
	     int (*fn)(const str_sortentry* a, const str_sortentry* b))
{
  str_sortentry* ptrs;
  const char* ptr;
  const char* end;
  long i;
  str tmp = {0,0,0};
  if (count == -1) {
    for (count = 0, ptr = s->s, end = s->s+s->len; ptr != 0 && ptr < end;
	 ++count) {
      ptr = memchr(ptr, sep, end-ptr);
      if (ptr) ++ptr;
    }
  }
  if ((ptrs = alloca(count * sizeof *ptrs)) == 0) return 0;
  if (!str_copy(&tmp, s)) { str_free(&tmp); return 0; }
  if (fn == 0) fn = default_cmp;
  for (i = 0, ptr = tmp.s, end = tmp.s+tmp.len; i < count; ++i) {
    const char* ptrend = memchr(ptr, sep, end-ptr);
    if (ptrend == 0) ptrend = end;
    ptrs[i].str = ptr;
    ptrs[i].len = ptrend - ptr;
    ptr = ptrend + 1;
  }
  qsort(ptrs, count, sizeof(*ptrs), (int (*)(const void*,const void*))fn);
  str_truncate(s, 0);
  for (i = 0; i < count; i++) {
    str_catb(s, ptrs[i].str, ptrs[i].len);
    str_catc(s, sep);
  }
  str_free(&tmp);
  return 1;
}
Ejemplo n.º 6
0
int session_putenv(const char* s)
{
  if (session.env.len > 0)
    if (!str_catc(&session.env, 0))
      return 0;
  return str_catb(&session.env, s, strlen(s) + 1);
}
Ejemplo n.º 7
0
static void parse_env(const char* ptr, str* out)
{
  while (ptr && *ptr != 0)
    if ((ptr = parse_str(ptr, ',', out)) != 0) {
      str_catc(out, 0);
      if (*ptr == ',') ++ptr;
    }
}
Ejemplo n.º 8
0
static const response* sq_recipient(str* recipient, str* params)
{
  str_cat(&qrecips, recipient);
  str_catc(&qrecips, 0);

  return 0;
  (void)params;
}
Ejemplo n.º 9
0
void make_username(const char* start, ssize_t len, const char* msgprefix)
{
  str_copyb(&username, start, len);
  if (local_name && str_findfirst(&username, AT) < 0) {
    str_catc(&username, AT);
    str_cats(&username, local_name);
  }
  str_copy2s(&msgstr, msgprefix, username.s);
  log_line(msgstr.s, msgstr.len);
}
Ejemplo n.º 10
0
/** Create a temporary file.

This function creates a temporary file by adding an difficult-to-predict
suffix (using the PID and microsecond timestamp) to the given prefix.
If this filename does not exist, it is opened in read/write mode.
*/
int path_mktemp(const char* prefix, str* filename)
{
  struct stat s;
  static long pid = 0;
  struct timeval tv;
  if (pid == 0)
    pid = getpid();
  do {
    if (!str_copys(filename, prefix)) return -1;
    if (!str_catc(filename, '.')) return -1;
    if (!str_catu(filename, pid)) return -1;
    gettimeofday(&tv, 0);
    if (!str_catc(filename, '.')) return -1;
    if (!str_catu(filename, tv.tv_sec)) return -1;
    if (!str_catc(filename, '.')) return -1;
    if (!str_catuw(filename, tv.tv_usec, 6, '0')) return -1;
  } while (lstat(filename->s, &s) != -1);
  return open(filename->s, O_RDWR | O_EXCL | O_CREAT, 0600);
}
Ejemplo n.º 11
0
static void cmd_stat(void)
{
  if (!str_copys(&tmp, "+OK ") ||
      !str_catu(&tmp, msg_count - del_count) ||
      !str_catc(&tmp, SPACE) ||
      !str_catu(&tmp, msg_bytes - del_bytes))
    respond(err_internal);
  else
    respond(tmp.s);
}
Ejemplo n.º 12
0
int open_file(const char* prefix, const char* filename)
{
  static str fullname;
  if (!str_truncate(&fullname, 0)) oom();
  if (prefix != 0) {
    if (!str_copys(&fullname, prefix)) oom();
    if (!str_catc(&fullname, '/')) oom();
  }
  if (!str_cats(&fullname, filename)) oom();
  return open(fullname.s, O_RDONLY);
}
Ejemplo n.º 13
0
static const char* parse_str(const char* ptr, char sep, str* out)
{
  char ch = 0;
  /* str_truncate(out, 0); */
  for (;;) {
    if (*ptr == sep || *ptr == NUL) return ptr;
    ptr = parse_char(ptr, &ch);
    str_catc(out, ch);
  }
  return ptr;
}
Ejemplo n.º 14
0
static void cmd_list_one(const str* arg)
{
  long i;
  if ((i = msgnum(arg)) == 0) return;
  if (!str_copys(&tmp, "+OK ") ||
      !str_catu(&tmp, i) ||
      !str_catc(&tmp, SPACE) ||
      !str_catu(&tmp, msgs[i-1].size))
    respond(err_internal);
  else
    respond(tmp.s);
}
Ejemplo n.º 15
0
/** Put an assignment, in \c NAME=value format, into the environment
 * string.
 * \note Unlike putenv, a copy of the assignment is made instead of
 * keeping a copy of the given pointer. */
int envstr_put(struct str* env, const char* asgn, int overwrite)
{
  long varlen;
  const char* found;
  found = strchr(asgn, '=');
  varlen = (found == 0) ? (long)strlen(asgn) : found - asgn;
  if ((found = envstr_find(env, asgn, varlen)) != 0) {
    if (!overwrite)
      return 1;
    str_spliceb(env, found - env->s, strlen(found) + 1, 0, 0);
  }
  return str_cats(env, asgn)
    && str_catc(env, 0);
}
Ejemplo n.º 16
0
int sendpacket(int fd, const str* s)
{
  const char* ptr;
  long wr;
  long len;
  packet.len = 0;
  if (!str_catu(&packet, s->len)
      || !str_catc(&packet, ':')
      || !str_cat(&packet, s)
      || !str_catc(&packet, ',')) {
    errno = ENOMEM;
    return -1;
  }
  len = packet.len;
  ptr = packet.s;
  while (len > 0) {
    if ((wr = write(fd, ptr, len)) <= 0)
      return wr;
    len -= wr;
    ptr += wr;
  }
  return packet.len;
}
Ejemplo n.º 17
0
static void cmd_uidl_one(const str* arg)
{
  long i;
  if ((i = msgnum(arg)) != 0) {
    msg* m = &msgs[i-1];
    const char* fn = m->filename + 4;
    if (!str_copys(&tmp, "+OK ") ||
	!str_catu(&tmp, i) ||
	!str_catc(&tmp, SPACE) ||
	!str_catb(&tmp, fn, m->uid_len))
      respond(err_internal);
    else
      respond(tmp.s);
  }
}
Ejemplo n.º 18
0
static long scan_dir(const char* subdir, str* list, long* countptr, long max)
{
  DIR* dir;
  direntry* entry;
  long count;
  
  if ((dir = opendir(subdir)) == 0) return 0;
  count = 0;
  while (!(max_count > 0 && msg_count >= max_count) &&
	 !(max > 0 && count >= max) &&
	 (entry = readdir(dir)) != 0) {
    if (entry->d_name[0] == '.') continue;
    if (!str_copys(&tmp, subdir)) return 0;
    if (!str_catc(&tmp, '/')) return 0;
    if (!str_cats(&tmp, entry->d_name)) return 0;
    if (!str_cat(list, &tmp)) return 0;
    if (!str_catc(list, 0)) return 0;
    ++count;
    ++msg_count;
  }
  closedir(dir);
  *countptr = count;
  return 1;
}
Ejemplo n.º 19
0
static void make_prq(void)
{
  brandom_fill(nonce, sizeof nonce);
  pkt_start(&packet, PRQ1);
  pkt_add_b(&packet, nonce, sizeof nonce);
  pkt_add_s1c(&packet, AUTHENTICATOR_NAME);
  wrap_str(str_copys(&keyex_name, nistp224_cb.name));
  if (keylist_get(&shared_secrets, &curve25519_cb) != 0) {
    wrap_str(str_catc(&keyex_name, 0));
    wrap_str(str_cats(&keyex_name, curve25519_cb.name));
  }
  pkt_add_s1(&packet, &keyex_name);
  pkt_add_s1c(&packet, KEYHASH_NAME);
  pkt_add_s1c(&packet, ENCRYPTOR_NAME);
  pkt_add_s1c(&packet, "null");
}
Ejemplo n.º 20
0
/* Mark a maildir filename with the named flag */
static int add_flag(str* fn, char flag)
{
  int c;
  /* If the filename has no flags, append them */
  if ((c = str_findfirst(fn, ':')) == -1) {
    if (!str_cats(fn, ":2,")) return 0;
  }
  else {
    /* If it has a colon (start of flags), see if they are a type we
     * recognize, and bail out if they aren't */
    if (fn->s[c+1] != '2' || fn->s[c+2] != ',') return 1;
    /* Scan through the flag characters and return success
     * if the message is already marked with the flag */
    if (strchr(fn->s+c+3, flag) != 0) return 1;
  }
  return str_catc(fn, flag);
}
Ejemplo n.º 21
0
static const response* parse_addr_arg(void)
{
  unsigned i;
  char term;
  int quoted;
  
  if (!str_truncate(&addr, 0)) return &resp_oom;
  if (!str_truncate(&params, 0)) return &resp_oom;

  addr.len = 0;
  if ((i = str_findfirst(&arg, LBRACE) + 1) != 0)
    term = RBRACE;
  else {
    term = SPACE;
    if ((i = str_findfirst(&arg, COLON) + 1) == 0)
      if ((i = str_findfirst(&arg, SPACE) + 1) == 0)
	return &resp_badaddr;
    while (i < arg.len && arg.s[i] == SPACE)
      ++i;
  }

  for (quoted = 0; i < arg.len && (quoted || arg.s[i] != term); ++i) {
    switch (arg.s[i]) {
    case QUOTE:
      quoted = !quoted;
      break;
    case ESCAPE:
      ++i;
      /* fall through */
    default:
      if (!str_catc(&addr, arg.s[i])) return &resp_oom;
    }
  }
  ++i;
  if (i > arg.len) return &resp_badaddr;
  while (i < arg.len && arg.s[i] == SPACE) ++i;
  if (!str_copyb(&params, arg.s+i, arg.len-i)) return &resp_oom;
  str_subst(&params, ' ', 0);

  /* strip source routing */
  if (addr.s[0] == AT
      && (i = str_findfirst(&addr, COLON) + 1) != 0)
    str_lcut(&addr, i);
    
  return 0;
}
Ejemplo n.º 22
0
static int dblchk(str *domain, str *dbltxt)
{
	str dblstr;
	char *dbl = getenv("DBLLOOKUP");
	int l, i;
	unsigned char ansbuf[512];
	
	if(!dbl || domain->len == 0) return 0;
	if(session_getnum("sump",0)) return 0; /* no point */


	str_init(&dblstr);
	str_copy(&dblstr, domain);
	str_catc(&dblstr, '.');
	str_cats(&dblstr, dbl);
			
	l = res_query(dblstr.s, C_IN, T_TXT, ansbuf, sizeof(ansbuf));
	if(l > 0 && ((HEADER *)ansbuf)->ancount != 0) {  /* something in the answer */
		unsigned char *recbuf = ansbuf+NS_HFIXEDSZ;
		
		/* skip over questions, why am I still writing stuff
		 * like this? */
		for(i = ns_get16(ansbuf+4); i != 0; --i)
			recbuf += dn_skipname(recbuf, ansbuf+l)+4;

		for(i = ns_get16(ansbuf+6); i != 0; --i) {
			recbuf += dn_skipname(recbuf, ansbuf+l);

			if(ns_get16(recbuf) != T_TXT) { /* CNAME or something */
				recbuf += 10 + ns_get16(recbuf+8);
				continue;
			}
			/* it's a TXT record, wow */
			str_init(dbltxt);
			str_copyb(dbltxt, (char*)recbuf+11, recbuf[10]);
			str_free(&dblstr);
			return 1;
		}
	} /* didn't find anything */
	str_free(&dblstr);
	return 0;
	}
Ejemplo n.º 23
0
static void handle_packet(struct connection* c)
{
  str* packet;
  const char* id;
  const char* runas;
  const char* command;
  const char* envstart;
  long slot;
  unsigned int i;
  struct passwd* pw;

  packet = &c->packet;
  id = packet->s;
  if (*id == NUL)
    FAIL(id, "DInvalid ID");

  if ((slot = pick_slot()) < 0)
    FAIL(id, "DCould not allocate a slot");
  wrap_str(str_copys(&slots[slot].id, id));

  if ((i = str_findfirst(packet, NUL) + 1) >= packet->len)
    FAIL(id, "DInvalid packet");
  runas = packet->s + i;
  if (*runas == NUL
      || (pw = getpwnam(runas)) == 0)
    FAIL(id, "DInvalid username");

  if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len)
    FAIL(id, "DInvalid packet");
  command = packet->s + i;

  if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len)
    envstart = 0;
  else {
    envstart = packet->s + i;
    wrap_str(str_catc(packet, 0));
  }

  if (!init_slot(slot, pw))
    FAIL(id, "ZOut of memory");
  start_slot(slot, command, envstart);
}
Ejemplo n.º 24
0
static void end_slot(int slot, int status)
{
  struct stat st;
  slots[slot].pid = 0;
  --slots_used;
  if (slots[slot].sending_email) {
    slots[slot].sending_email = 0;
    if (status)
      report_slot(slot, "ZJob complete, sending email failed");
    else
      report_slot(slot, "KJob complete, email sent");
  }
  else {
    /* No header, no possible way to send email. */
    if (slots[slot].headerlen == 0)
      report_slot(slot, "KJob complete, no MAILTO");
    else {
      /* If the job crashed, make sure it is noted. */
      if (WIFSIGNALED(status)) {
	debugf(DEBUG_EXEC, "{slot }d{ Job was killed by signal #}d",
	       slot, WTERMSIG(status));
	wrap_str(str_copys(&tmp, "\n\nJob was killed by signal #"));
	wrap_str(str_cati(&tmp, WTERMSIG(status)));
	wrap_str(str_catc(&tmp, '\n'));
	write(slots[slot].tmpfd, tmp.s, tmp.len);
      }
      if (fstat(slots[slot].tmpfd, &st) == -1)
	failsys_slot(slot, "ZCould not fstat");
      else if (st.st_size > slots[slot].headerlen)
	send_email(slot);
      else
	report_slot(slot, "KJob complete, no mail sent");
    }
    /* To simplify the procedure, close the temporary file early.
     * The email sender still has it open, and will effect the final
     * deletion of the file when it completes. */
    if (slots[slot].tmpfd != devnull)
      close(slots[slot].tmpfd);
    slots[slot].tmpfd = -1;
  }
}
Ejemplo n.º 25
0
static void cmd_listsys(void)
{
  DIR* dir;
  direntry* entry;
  str data = {0,0,0};
  if ((dir = opendir(CRONTAB_DIR)) == 0)
    respond("ZCould not open crontabs directory");
  while ((entry = readdir(dir)) != 0) {
    if (entry->d_name[0] != ':')
      continue;
    make_filename(entry->d_name);
    if (!str_cat3s(&data, "==> ", entry->d_name, " <==\n"))
      respond("ZOut of memory");
    if (ibuf_openreadclose(filename.s, &data) == -1)
      respond("ZCould not read crontab");
    if (!str_catc(&data, '\n'))
      respond("ZOut of memory");
  }
  closedir(dir);
  respond_okstr(&data);
}
Ejemplo n.º 26
0
/** Read a line from the \c ibuf into a dynamic string. */
int ibuf_getstr(ibuf* in, struct str* s, char boundary)
{
  iobuf* io;
  int ch;
  
  io = &in->io;
  in->count = 0;
  str_truncate(s, 0);
  if (ibuf_eof(in) || ibuf_error(in) || ibuf_timedout(in)) return 0;
  for (;;) {
    if (io->bufstart >= io->buflen && !ibuf_refill(in)) {
      if (ibuf_eof(in)) break;
      return 0;
    }
    in->count++;
    ch = io->buffer[io->bufstart++];
    if (!str_catc(s, ch)) return 0;
    if (ch == boundary) break;
  }
  return in->count > 0;
}
Ejemplo n.º 27
0
/* This parser is rather liberal in what it accepts:
   The IMAP standard mandates seperate character sets for tags, commands,
   unquoted strings.  Since they all must be seperated by spaces, this
   parser allows all non-whitespace characters for each of the above. */
static int parse_line(void)
{
#define RESPOND(T,S) do{ respond(T,S); return 0; }while(0)
  unsigned i;
  unsigned len;
  const char* ptr;
  str* arg;
  
  /* Parse out the command tag */
  str_truncate(&tag, 0);
  for (i = 0, ptr = line.s; i < line.len && isspace(*ptr); ++i, ++ptr) ;
  for (; i < line.len && !isspace(*ptr); ++i, ++ptr)
    str_catc(&tag, line.s[i]);
  if (!tag.len) RESPOND(NOTAG, "BAD Syntax error");
  if (i >= line.len) RESPOND(0, "BAD Syntax error");

  /* Parse out the command itself */
  str_truncate(&cmd, 0);
  for (; i < line.len && isspace(*ptr); ++i, ++ptr) ;
  for (; i < line.len && !isspace(*ptr); ++i, ++ptr)
    str_catc(&cmd, line.s[i]);
  if (!cmd.len) RESPOND(0, "BAD Syntax error");

  /* Parse out the command-line args */
  for (line_argc = 0; line_argc < MAX_ARGC; ++line_argc) {
    arg = &line_args[line_argc];
    str_truncate(arg, 0);
    for (; i < line.len && isspace(*ptr); ++i, ++ptr) ;
    if (i >= line.len) break;

    switch (*ptr) {
    case LBRACE:
      /* Handle a string literal */
      ++i, ++ptr;
      if (!isdigit(*ptr)) RESPOND(0, "BAD Syntax error: missing integer");
      for (len = 0; i < line.len && *ptr != RBRACE; ++i, ++ptr) {
	if (!isdigit(*ptr))
	  RESPOND(0, "BAD Syntax error: invalid integer");
	len = len * 10 + *ptr - '0';
      }
      ++i, ++ptr;
      if (*ptr != 0) RESPOND(0, "BAD Syntax error: missing LF after integer");
      str_ready(arg, len);
      respond(CONT, "OK");
      if (len > 0)
	ibuf_read(&inbuf, arg->s, len);
      arg->s[arg->len = len] = 0;
      ibuf_getstr_crlf(&inbuf, &line);
      i = 0;
      ptr = line.s;
      break;

    case QUOTE:
      /* Handle a quoted string */
      for (++i, ++ptr; i < line.len && *ptr != QUOTE; ++i, ++ptr) {
	if (*ptr == ESCAPE) {
	  if (++i >= line.len) break;
	  ++ptr;
	}
	str_catc(arg, *ptr);
      }
      if (i >= line.len || *ptr != QUOTE)
	RESPOND(0, "BAD Syntax error: unterminated quoted string");
      ++i, ++ptr;
      break;

    default:
      /* Normal case is very simple */
      for (; i < line.len && !isspace(*ptr); ++i, ++ptr)
	str_catc(arg, *ptr);
    }
  }
  for (; i < line.len && isspace(*ptr); ++i, ++ptr) ;
  if (i < line.len) RESPOND(0, "BAD Too many command arguments");
  return 1;
}