コード例 #1
0
ファイル: cmd_resequence.c プロジェクト: Rick33/freevms
void cmd_resequence (char *cp)

{
  Line *line;

  count = 0;

  /* If no range given, resequence the whole current buffer */

  if (*cp == 0) {
    for (line = buffer_first_line (cur_position.buffer); line != NULL; line = line_next (line)) {
      line_reseq (line);
      count ++;
    }
  }

  /* Otherwise, process the requested lines */

  else if (range_multiple (cp, &cp, resequence_range, NULL) >= 0) eoltest (cp);

  /* Either way, print out summary */

  if (count == 0) outerr (0, "no lines resequenced\n");
  else outerr (12, "%u line%s resequenced\n", count, (count == 1) ? "" : "s");
}
コード例 #2
0
ファイル: ga.c プロジェクト: 89erik/cellularautomata-C
bool singleFitness(int individual) {
    int sOnes, rOnes, sZeroes, rZeroes;
	int i;    
	init_line(population + individual);
    line_count(&sOnes, &sZeroes);
    if (sZeroes > sOnes) {
        sZeroes = sZeroes + sOnes;
        sOnes = 0;
    } else {
        sOnes = sZeroes + sOnes;
        sZeroes = 0;
    }

    for (i=0; i<STEPS_PER_FITNESS; i++) {
        if (!line_is_stable()) {
            line_next();
#ifdef FITNESS_DEBUG
			line_print();
#endif			
        } else {
            break;
        }
    }
    line_count(&rOnes, &rZeroes);
	bool success = sZeroes == rZeroes && sOnes == rOnes;
#ifdef FITNESS_DEBUG
	printf("Success: %s\n\n", success? "true" : "false");
#endif
    return success; 
}
コード例 #3
0
ファイル: cmd_delete.c プロジェクト: Rick33/freevms
static int delete_range (void *dummy, Buffer *buffer, Line *line)

{
  /* Don't even try to delete the [EOB] line */

  if (line == NULL) return (0);

  /* Set current position to beginning of next line after first line deleted */

  if (first) {
    first = 0;
    if (buffer != cur_position.buffer) {
      *buffer_savpos (cur_position.buffer) = cur_position;
      cur_position.buffer = buffer;
    }
    cur_position.line   = line;
    cur_position.offset = 0;
    buffer_dirty (buffer, 1);
  }

  if (cur_position.line == line) cur_position.line = line_next (line);

  /* Delete the line (and your little string, too!) */

  string_delete (line_remove (line));
  count ++;

  /* Keep going */

  return (0);
}
コード例 #4
0
ファイル: relposition.c プロジェクト: Rick33/freevms
int relposition (Position *p1, Position *p2)

{
  int firstimethru, p1relp2;
  Line *linebwd, *linefwd;

  p1relp2 = 0;
  if ((p1 -> buffer == p2 -> buffer) && ((p1 -> line != p2 -> line) || (p1 -> offset != p2 -> offset))) {
    if (p1 -> line != p2 -> line) {
      firstimethru = 1;
      for (linebwd = linefwd = p2 -> line; (linebwd != p1 -> line) && (linefwd != p1 -> line);) {
        if (linebwd != NULL) linebwd = line_prev (linebwd);
        else if (firstimethru) linebwd = buffer_last_line (p2 -> buffer);
        if (linefwd != NULL) linefwd = line_next (linefwd);
        if ((linefwd == NULL) && (linebwd == NULL)) break;
        firstimethru = 0;
      }
      if (p1 -> line == linebwd) p1relp2 = -1;
      if (p1 -> line == linefwd) p1relp2 =  1;
    } else {
      p1relp2 = (p1 -> offset > p2 -> offset) * 2 - 1;
    }
  }

  return (p1relp2);
}
コード例 #5
0
ファイル: logcut.c プロジェクト: yasuoka/logcut
static off_t
search_by_time(int fd, const char *fmt, time_t t, off_t off_m, off_t off_n)
{
	int	 rval;
	time_t	 val_p;
	off_t	 off_p;
#ifdef	LOGCUT_DEBUG
	char	 buf0[256], buf1[256];
#endif

	while (off_m < off_n) {
		off_p = line_head(fd, (off_m + off_n) / 2);
		do {
			rval = read_time(fd, fmt, &val_p);
			if (off_p > 1 && rval == 0) {
				off_p = line_head(fd, off_p - 1);
				continue;
			}
			break;
		} while (1);
		if (t <= val_p) {
			LOGCUT_DBG((stderr, "n %10lld => %10lld %s <= %s\n",
			    off_n, off_p, my_ctime(&t, buf0, sizeof(buf0)),
			    my_ctime(&val_p, buf1, sizeof(buf1))));
			off_n = off_p;
		} else {
			off_p = line_next(fd, (off_m + off_n) / 2);
			do {
				rval = read_time(fd, fmt, &val_p);
				if (rval == 0) {
					off_p = line_next(fd, off_p);
					continue;
				}
				break;
			} while (off_p < off_n);
			LOGCUT_DBG((stderr,
			    "m %10lld => %10lld %s >  %s\n",
			    off_n, off_p, my_ctime(&t, buf0, sizeof(buf0)),
			    my_ctime(&val_p, buf1, sizeof(buf1))));
			off_m = off_p;
		}

	}

	return (off_m);
}
コード例 #6
0
ファイル: mail.c プロジェクト: avkrotov/fdm
/*
 * Find offset of body. The body is the offset of the first octet after the
 * separator (\n\n), or zero.
 */
size_t
find_body(struct mail *m)
{
	size_t	 len;
	char	*ptr;

	line_init(m, &ptr, &len);
	while (ptr != NULL) {
		if (len == 1 && *ptr == '\n') {
			line_next(m, &ptr, &len);
			/* If no next line, body is end of mail. */
			if (ptr == NULL)
				return (m->size);
			/* Otherwise, body is start of line after separator. */
			return (ptr - m->data);
		}
		line_next(m, &ptr, &len);
	}
	return (0);
}
コード例 #7
0
ファイル: mail.c プロジェクト: avkrotov/fdm
/* Match a header. Same as find_header but uses fnmatch. */
char *
match_header(struct mail *m, const char *patt, size_t *len, int value)
{
	char	*ptr, *last, *hdr;
	size_t	 hdrlen;

	line_init(m, &ptr, len);
	while (ptr != NULL) {
		if (ptr >= m->data + m->body)
			return (NULL);

		if ((last = memchr(ptr, ':', *len)) != NULL) {
			hdrlen = last - ptr;
			hdr = xmalloc(hdrlen + 1);
			strlcpy(hdr, ptr, hdrlen + 1);

			if (fnmatch(patt, hdr, FNM_CASEFOLD) == 0)
				break;

			xfree(hdr);
		}

		line_next(m, &ptr, len);
	}
	if (ptr == NULL)
		return (NULL);
	xfree(hdr);

	/* If the entire header is wanted, return it. */
	if (!value)
		return (ptr);

	/* Include the : in the length. */
	hdrlen++;

	/* Otherwise skip the header and following spaces. */
	ptr += hdrlen;
	*len -= hdrlen;
	while (*len > 0 && isspace((u_char) *ptr)) {
		ptr++;
		(*len)--;
	}

	/* And trim newlines. */
	while (*len > 0 && ptr[*len - 1] == '\n')
		(*len)--;

	if (len == 0)
		return (NULL);
	return (ptr);
}
コード例 #8
0
ファイル: ga.c プロジェクト: 89erik/cellularautomata-C
int printRuleTest(int rule, int n) {
    if (n<0) exit(-1);
	int i,j;
    for (i=0; i<n; i++) {
        init_line(population+rule);
        for (j=0; j<STEPS_PER_FITNESS; j++) {
            line_print();
            printf("\n");
            if (!line_is_stable()) {
                line_next();
            } else {
                break;
            }
        }
        line_print();
        printf("\nSucess: %s\n\n", (singleFitness(rule)? "true" : "false"));
    }
}
コード例 #9
0
ファイル: mail.c プロジェクト: avkrotov/fdm
/*
 * Find a header. If value is set, only the header value is returned, with EOL
 * stripped
 */
char *
find_header(struct mail *m, const char *hdr, size_t *len, int value)
{
	char	*ptr;
	size_t	 hdrlen;

	hdrlen = strlen(hdr) + 1; /* include : */
	if (m->body < hdrlen || m->size < hdrlen)
		return (NULL);

	line_init(m, &ptr, len);
	while (ptr != NULL) {
		if (ptr >= m->data + m->body)
			return (NULL);
		if (*len >= hdrlen && ptr[hdrlen - 1] == ':') {
			if (strncasecmp(ptr, hdr, hdrlen - 1) == 0)
				break;
		}
		line_next(m, &ptr, len);
	}
	if (ptr == NULL)
		return (NULL);

	/* If the entire header is wanted, return it. */
	if (!value)
		return (ptr);

	/* Otherwise skip the header and following spaces. */
	ptr += hdrlen;
	*len -= hdrlen;
	while (*len > 0 && isspace((u_char) *ptr)) {
		ptr++;
		(*len)--;
	}

	/* And trim newlines. */
	while (*len > 0 && ptr[*len - 1] == '\n')
		(*len)--;

	if (len == 0)
		return (NULL);
	return (ptr);
}
コード例 #10
0
ファイル: mail.c プロジェクト: avkrotov/fdm
/* Count mail lines. */
void
count_lines(struct mail *m, u_int *total, u_int *body)
{
	size_t	 len;
	char	*ptr;
	int	 flag;

	flag = 0;
	*total = *body = 0;

	line_init(m, &ptr, &len);
	while (ptr != NULL) {
		if (flag)
			(*body)++;
		if (len == 1 && *ptr == '\n')
			flag = 1;
		(*total)++;
		line_next(m, &ptr, &len);
	}
}
コード例 #11
0
ファイル: cmd_write.c プロジェクト: Rick33/freevms
void cmd_write (char *cp)

{
  int rc;
  Line *line;
  Position beg_write, end_write;

  out_file  = NULL;
  linecount = 0;

  /* Get filename */

  out_name = cp;
  cp = uptospace (cp);
  if (*cp != 0) {
    *(cp ++) = 0;
    cp = skipspaces (cp);
  }

  /* Get optional range.  If not specified, use the whole current buffer. */

  if (*cp != 0) {
    rc = range_multiple (cp, &cp, write_range, out_name);
    if (rc == 0) eoltest (cp);
  } else {
    for (line = buffer_first_line (cur_position.buffer); line != NULL; line = line_next (line)) {
      rc = write_range (out_name, cur_position.buffer, line);
      if (rc != 0) break;
    }
  }

  /* Close output file */

  if (out_file == NULL) outerr (0, "no file created\n");
  else {
    if (linecount == 0) outerr (strlen (out_name), "no lines written to %s\n", out_name);
    else outerr (12 + strlen (out_name), "%u line%s written to %s\n", linecount, (linecount == 1) ? "" : "s", out_name);
    if (fclose (out_file) < 0) outerr (strlen (out_name) + strlen (strerror (errno)), "error closing file %s: %s\n", out_name, strerror (errno));
    out_file = NULL;
  }
}
コード例 #12
0
ファイル: deliver-mbox.c プロジェクト: mbeck-/fdm
int
deliver_mbox_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
    struct account			*a = dctx->account;
    struct mail			*m = dctx->mail;
    struct deliver_mbox_data	*data = ti->data;
    char				*path, *ptr, *lptr, *from = NULL;
    const char			*msg;
    size_t				 len, llen;
    int				 fd, saved_errno;
    FILE				*f;
    gzFile				 gzf;
    long long			 used;
    sigset_t			 set, oset;
    struct stat			 sb;

    f = gzf = NULL;
    fd = -1;

    path = replacepath(&data->path, m->tags, m, &m->rml, dctx->udata->home);
    if (path == NULL || *path == '\0') {
        log_warnx("%s: empty path", a->name);
        goto error;
    }
    if (data->compress) {
        len = strlen(path);
        if (len < 3 || strcmp(path + len - 3, ".gz") != 0) {
            path = xrealloc(path, 1, len + 4);
            strlcat(path, ".gz", len + 4);
        }
    }
    log_debug2("%s: saving to mbox %s", a->name, path);

    /* Save the mbox path. */
    add_tag(&m->tags, "mbox_file", "%s", path);

    /* Check permissions and ownership. */
    if (stat(path, &sb) != 0) {
        if (conf.no_create || errno != ENOENT)
            goto error_log;

        log_debug2("%s: creating %s", a->name, xdirname(path));
        if (xmkpath(xdirname(path), -1, conf.file_group, DIRMODE) != 0)
            goto error_log;
    } else {
        if ((msg = checkmode(&sb, UMASK(FILEMODE))) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
        if ((msg = checkowner(&sb, -1)) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
        if ((msg = checkgroup(&sb, conf.file_group)) != NULL)
            log_warnx("%s: %s: %s", a->name, path, msg);
    }

    /* Create or open the mbox. */
    used = 0;
    do {
        if (conf.no_create)
            fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types);
        else {
            fd = createlock(path, O_WRONLY|O_APPEND,
                            -1, conf.file_group, FILEMODE, conf.lock_types);
        }
        if (fd == -1 && errno == EEXIST)
            fd = openlock(path, O_WRONLY|O_APPEND, conf.lock_types);
        if (fd == -1) {
            if (errno == EAGAIN) {
                if (locksleep(a->name, path, &used) != 0)
                    goto error;
                continue;
            }
            goto error_log;
        }
    } while (fd < 0);

    /* Open gzFile or FILE * for writing. */
    if (data->compress) {
        if ((gzf = gzdopen(fd, "a")) == NULL) {
            errno = ENOMEM;
            goto error_log;
        }
    } else {
        if ((f = fdopen(fd, "a")) == NULL)
            goto error_log;
    }

    /*
     * mboxes are a pain: if we are interrupted after this we risk
     * having written a partial mail. So, block SIGTERM until we're
     * done.
     */
    sigemptyset(&set);
    sigaddset(&set, SIGTERM);
    if (sigprocmask(SIG_BLOCK, &set, &oset) < 0)
        fatal("sigprocmask failed");

    /* Write the from line. */
    from = make_from(m, dctx->udata->name);
    if (deliver_mbox_write(f, gzf, from, strlen(from)) < 0) {
        xfree(from);
        goto error_unblock;
    }
    if (deliver_mbox_write(f, gzf, "\n", 1) < 0) {
        xfree(from);
        goto error_unblock;
    }
    log_debug3("%s: using from line: %s", a->name, from);
    xfree(from);

    /* Write the mail, escaping from lines. */
    line_init(m, &ptr, &len);
    while (ptr != NULL) {
        if (ptr != m->data) {
            /* Skip leading >s. */
            lptr = ptr;
            llen = len;
            while (*lptr == '>' && llen > 0) {
                lptr++;
                llen--;
            }

            if (llen >= 5 && strncmp(lptr, "From ", 5) == 0) {
                log_debug2("%s: quoting from line: %.*s",
                           a->name, (int) len - 1, ptr);
                if (deliver_mbox_write(f, gzf, ">", 1) < 0)
                    goto error_unblock;
            }
        }

        if (deliver_mbox_write(f, gzf, ptr, len) < 0)
            goto error_unblock;

        line_next(m, &ptr, &len);
    }

    /* Append newlines. */
    if (m->data[m->size - 1] == '\n') {
        if (deliver_mbox_write(f, gzf, "\n", 1) < 0)
            goto error_unblock;
    } else {
        if (deliver_mbox_write(f, gzf, "\n\n", 2) < 0)
            goto error_unblock;
    }

    /* Flush buffers and sync. */
    if (gzf == NULL) {
        if (fflush(f) != 0)
            goto error_unblock;
    } else {
        if (gzflush(gzf, Z_FINISH) != Z_OK) {
            errno = EIO;
            goto error_unblock;
        }
    }
    if (fsync(fd) != 0)
        goto error_unblock;

    if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
        fatal("sigprocmask failed");

    if (gzf != NULL)
        gzclose(gzf);
    if (f != NULL)
        fclose(f);
    closelock(fd, path, conf.lock_types);

    xfree(path);
    return (DELIVER_SUCCESS);

error_unblock:
    saved_errno = errno;
    if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
        fatal("sigprocmask failed");
    errno = saved_errno;

error_log:
    log_warn("%s: %s", a->name, path);

error:
    if (gzf != NULL)
        gzclose(gzf);
    if (f != NULL)
        fclose(f);
    if (fd != -1)
        closelock(fd, path, conf.lock_types);

    if (path != NULL)
        xfree(path);
    return (DELIVER_FAILURE);
}
コード例 #13
0
ファイル: deliver-smtp.c プロジェクト: avkrotov/fdm
int
deliver_smtp_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
	struct account			*a = dctx->account;
	struct mail			*m = dctx->mail;
	struct deliver_smtp_data	*data = ti->data;
	int				 done, code;
	struct io			*io;
	char				*cause, *to, *from, *line, *ptr, *lbuf;
	enum deliver_smtp_state		 state;
	size_t				 len, llen;

	io = connectproxy(&data->server,
	    conf.verify_certs, conf.proxy, IO_CRLF, conf.timeout, &cause);
	if (io == NULL) {
		log_warnx("%s: %s", a->name, cause);
		xfree(cause);
		return (DELIVER_FAILURE);
	}
	if (conf.debug > 3 && !conf.syslog)
		io->dup_fd = STDOUT_FILENO;

	llen = IO_LINESIZE;
	lbuf = xmalloc(llen);

	if (conf.host_fqdn != NULL)
		xasprintf(&ptr, "%s@%s", dctx->udata->name, conf.host_fqdn);
	else
		xasprintf(&ptr, "%s@%s", dctx->udata->name, conf.host_name);
	if (data->to.str == NULL)
		to = xstrdup(ptr);
	else {
		to = replacestr(&data->to, m->tags, m, &m->rml);
		if (to == NULL || *to == '\0') {
			xasprintf(&cause, "%s: empty to", a->name);
			from = NULL;
			goto error;
		}
	}
	if (data->from.str == NULL)
		from = xstrdup(ptr);
	else {
		from = replacestr(&data->from, m->tags, m, &m->rml);
		if (from == NULL || *from == '\0') {
			xasprintf(&cause, "%s: empty from", a->name);
			goto error;
		}
	}
	xfree(ptr);

	state = SMTP_CONNECTING;
	line = NULL;
	done = 0;
	do {
		switch (io_pollline2(io,
		    &line, &lbuf, &llen, conf.timeout, &cause)) {
		case 0:
			cause = xstrdup("connection unexpectedly closed");
			goto error;
		case -1:
			goto error;
		}
		code = deliver_smtp_code(line);

		cause = NULL;
		switch (state) {
		case SMTP_CONNECTING:
			if (code != 220)
				goto error;
			state = SMTP_HELO;
			if (conf.host_fqdn != NULL)
				io_writeline(io, "HELO %s", conf.host_fqdn);
			else
				io_writeline(io, "HELO %s", conf.host_name);
			break;
		case SMTP_HELO:
			if (code != 250)
				goto error;
			state = SMTP_FROM;
			io_writeline(io, "MAIL FROM:<%s>", from);
			break;
		case SMTP_FROM:
			if (code != 250)
				goto error;
			state = SMTP_TO;
			io_writeline(io, "RCPT TO:<%s>", to);
			break;
		case SMTP_TO:
			if (code != 250)
				goto error;
			state = SMTP_DATA;
			io_writeline(io, "DATA");
			break;
		case SMTP_DATA:
			if (code != 354)
				goto error;
			line_init(m, &ptr, &len);
			while (ptr != NULL) {
				if (len > 1) {
					if (*ptr == '.')
						io_write(io, ".", 1);
					io_write(io, ptr, len - 1);
				}
				io_writeline(io, NULL);

				/* Update if necessary. */
				if (io_update(io, conf.timeout, &cause) != 1)
					goto error;

				line_next(m, &ptr, &len);
			}
			state = SMTP_DONE;
			io_writeline(io, ".");
			io_flush(io, conf.timeout, NULL);
			break;
		case SMTP_DONE:
			if (code != 250)
				goto error;
			state = SMTP_QUIT;
			io_writeline(io, "QUIT");
			break;
		case SMTP_QUIT:
			/*
			 * Exchange sometimes refuses to accept QUIT as a valid
			 * command, but since we got a 250 the mail has been
			 * accepted. So, allow 500 here too.
			 */
			if (code != 500 && code != 221)
				goto error;
			done = 1;
			break;
		}
	} while (!done);

	xfree(lbuf);
	xfree(from);
	xfree(to);

	io_close(io);
	io_free(io);

	return (DELIVER_SUCCESS);

error:
	if (cause != NULL) {
		log_warnx("%s: %s", a->name, cause);
		xfree(cause);
	} else
		log_warnx("%s: unexpected response: %s", a->name, line);

	io_writeline(io, "QUIT");
	io_flush(io, conf.timeout, NULL);

	xfree(lbuf);
	if (from != NULL)
		xfree(from);
	if (to != NULL)
		xfree(to);

	io_close(io);
	io_free(io);

	return (DELIVER_FAILURE);
}
コード例 #14
0
struct attach *
attach_get(struct mail *m, char **ptr, size_t *len, const char *b, int *last)
{
	struct attach	*atr, *at;
	char		*name = NULL, *b2 = NULL;
	size_t		 bl, bl2;
	int		 last2;
	u_int		 n;

	bl = strlen(b);

	atr = xmalloc(sizeof *atr);
	memset(atr, 0, sizeof *atr);
	TAILQ_INIT(&atr->children);

	atr->data = *ptr - m->data;

	while (*ptr != NULL) {
		if (*len >= 13 && strncasecmp(*ptr, "content-type:", 13) == 0)
			break;
		line_next(m, ptr, len);
	}
	if (*ptr == NULL)
		goto error;

	atr->type = attach_type(m, *ptr, "name", &name);
	if (atr->type == NULL) {
		if (name != NULL)
			xfree(name);
		goto error;
	}
	atr->name = name;

	if (strncasecmp(atr->type, "multipart/", 10) != 0) {
		/* Skip the remaining headers. */
		while (*ptr != NULL && *len > 1)
			line_next(m, ptr, len);
		if (*ptr == NULL)
			goto error;

		atr->body = *ptr - m->data;
		for (;;) {
			line_next(m, ptr, len);
			if (*ptr == NULL)
				break;
			if (*len < 3 || (*ptr)[0] != '-' || (*ptr)[1] != '-')
				continue;

			if (*len - 5 == bl && strncmp(*ptr + 2, b, bl) == 0 &&
			    strncmp(*ptr + bl + 2, "--", 2) == 0) {
				*last = 1;
				break;
			}
			if (*len - 3 == bl && strncmp(*ptr + 2, b, bl) == 0)
				break;
		}
		if (*ptr == NULL)
			goto error;

		atr->size = *ptr - m->data - atr->data;
	} else {
		/* XXX avoid doing this twice. */
		xfree(atr->type);
		atr->type = attach_type(m, *ptr, "boundary", &b2);
		if (b2 == NULL)
			goto error;
		bl2 = strlen(b2);

		/* Find the first boundary. */
		while (*ptr != NULL) {
			if ((*ptr)[0] == '-' && (*ptr)[1] == '-') {
				if (*len - 3 == bl2 &&
				    strncmp(*ptr + 2, b2, bl2) == 0)
					break;
			}
			line_next(m, ptr, len);
		}
		if (ptr == NULL)
			goto error;

		/* Now iterate over the rest. */
		last2 = 0;
		n = 0;
		while (*ptr != NULL && !last2) {
			at = attach_get(m, ptr, len, b2, &last2);
			if (at == NULL)
				goto error;
			at->idx = n++;
			at->parent = atr;
			TAILQ_INSERT_TAIL(&atr->children, at, entry);
		}

		/* And skip on to the end of the multipart. */
		while (*ptr != NULL) {
			if ((*ptr)[0] == '-' && (*ptr)[1] == '-') {
				if (*len - 5 == bl2 &&
				    strncmp(*ptr + 2, b2, bl2) == 0)
					break;
			}
			line_next(m, ptr, len);
		}
		if (*ptr == NULL)
			goto error;
		line_next(m, ptr, len);

		xfree(b2);
	}

	return (atr);

error:
	if (b2 != NULL)
		xfree(b2);

	attach_free(atr);
	return (NULL);
}
コード例 #15
0
struct attach *
attach_build(struct mail *m)
{
	struct attach	*atr = NULL, *at;
	char		*hdr, *ptr, *b = NULL, *type;
	size_t		 len, bl;
	int		 last;
	u_int		 n;

	hdr = find_header(m, "content-type", &len, 0);
	if (hdr == NULL)
		return (NULL);

	type = attach_type(m, hdr, "boundary", &b);
	if (type == NULL || b == NULL) {
		if (type != NULL)
			xfree(type);
		goto error;
	}
	if (strncasecmp(type, "multipart/", 10) != 0) {
		xfree(type);
		goto error;
	}
	bl = strlen(b);

	atr = xmalloc(sizeof *atr);
	memset(atr, 0, sizeof *atr);
	TAILQ_INIT(&atr->children);
	atr->type = type;

	/* Find the first boundary. */
	line_init(m, &ptr, &len);
	while (ptr != NULL) {
		if (ptr[0] == '-' && ptr[1] == '-') {
			if (len - 3 == bl && strncmp(ptr + 2, b, bl) == 0)
				break;
		}
		line_next(m, &ptr, &len);
	}
	if (ptr == NULL)
		goto error;

	/* Now iterate over the rest. */
	last = 0;
	n = 0;
	while (ptr != NULL && !last) {
		if (ptr[0] == '-' && ptr[1] == '-') {
			if (len - 5 == bl && strncmp(ptr + 2, b, bl) == 0)
				break;
		}

		at = attach_get(m, &ptr, &len, b, &last);
		if (at == NULL)
			goto error;
		at->idx = n++;
		at->parent = atr;
		TAILQ_INSERT_TAIL(&atr->children, at, entry);
	}
	if (ptr == NULL)
		goto error;

	xfree(b);
	return (atr);

error:
	if (atr != NULL)
		attach_free(atr);

	if (b != NULL)
		xfree(b);
	return (NULL);
}
コード例 #16
0
ファイル: deliver-imap.c プロジェクト: avkrotov/fdm
int
deliver_imap_deliver(struct deliver_ctx *dctx, struct actitem *ti)
{
	struct account			*a = dctx->account;
	struct mail			*m = dctx->mail;
	struct deliver_imap_data	*data = ti->data;
	struct io			*io;
	struct fetch_ctx		 fctx;
	struct fetch_imap_data		 fdata;
	char				*cause, *folder, *ptr, *line;
	size_t				 len, maillen;
	u_int				 total, body;

	/* Connect to the IMAP server. */
	io = connectproxy(&data->server,
	    conf.verify_certs, conf.proxy, IO_CRLF, conf.timeout, &cause);
	if (io == NULL) {
		log_warnx("%s: %s", a->name, cause);
		xfree(cause);
		return (DELIVER_FAILURE);
	}
	if (conf.debug > 3 && !conf.syslog)
		io->dup_fd = STDOUT_FILENO;

	/* Work out the folder name. */
	folder = replacestr(&data->folder, m->tags, m, &m->rml);
	if (folder == NULL || *folder == '\0') {
		log_warnx("%s: empty folder", a->name);
		goto error;
	}

	/* Fake up the fetch context for the fetch code. */
	memset(&fdata, 0, sizeof fdata);
	fdata.user = data->user;
	fdata.pass = data->pass;
	fdata.nocrammd5 = data->nocrammd5;
	fdata.nologin = data->nologin;
	memcpy(&fdata.server, &data->server, sizeof fdata.server);
	fdata.io = io;
	fdata.only = FETCH_ONLY_ALL;
	a->data = &fdata;
	fetch_imap_state_init(a, &fctx);
	fctx.state = imap_state_connected;
	fctx.llen = IO_LINESIZE;
	fctx.lbuf = xmalloc(fctx.llen);

	/* Use the fetch code until the select1 state is reached. */
	if (deliver_imap_pollto(imap_state_select1, a, io, &fctx) != 0)
		goto error;

retry:
	/* Send an append command. */
	if (imap_putln(a, "%u APPEND {%zu}", ++fdata.tag, strlen(folder)) != 0)
		goto error;
	switch (deliver_imap_waitappend(a, &fctx, io, &line)) {
	case IMAP_TAG_ERROR:
		if (line != NULL)
			imap_invalid(a, line);
		goto error;
	case IMAP_TAG_CONTINUE:
		break;
	default:
		if (imap_no(line) && strstr(line, "[TRYCREATE]") != NULL)
			goto try_create;
		imap_invalid(a, line);
		goto error;
	}

	/*
	 * Send the mail size, not forgetting lines are CRLF terminated. The
	 * Google IMAP server is written strangely, so send the size as if
	 * every CRLF was a CR if the server has XYZZY.
	 */
	count_lines(m, &total, &body);
	maillen = m->size + total - 1;
	if (fdata.capa & IMAP_CAPA_XYZZY) {
		log_debug2("%s: adjusting size: actual %zu", a->name, maillen);
		maillen = m->size;
	}
	if (fdata.capa & IMAP_CAPA_NOSPACE) {
		if (imap_putln(a, "%s{%zu}", folder, maillen) != 0)
			goto error;
	} else {
		if (imap_putln(a, "%s {%zu}", folder, maillen) != 0)
			goto error;
	}
	switch (deliver_imap_waitappend(a, &fctx, io, &line)) {
	case IMAP_TAG_ERROR:
		if (line != NULL)
			imap_invalid(a, line);
		goto error;
	case IMAP_TAG_CONTINUE:
		break;
	default:
		if (imap_no(line) && strstr(line, "[TRYCREATE]") != NULL)
			goto try_create;
		imap_invalid(a, line);
		goto error;
	}

	/* Send the mail data. */
	line_init(m, &ptr, &len);
	while (ptr != NULL) {
		if (len > 1)
			io_write(io, ptr, len - 1);
		io_writeline(io, NULL);

		/* Update if necessary. */
		if (io_update(io, conf.timeout, &cause) != 1) {
			log_warnx("%s: %s", a->name, cause);
			xfree(cause);
			goto error;
		}

		line_next(m, &ptr, &len);
	}

	/* Wait for an okay from the server. */
	switch (deliver_imap_waitappend(a, &fctx, io, &line)) {
	case IMAP_TAG_ERROR:
	case IMAP_TAG_CONTINUE:
		if (line != NULL)
			imap_invalid(a, line);
		goto error;
	default:
		if (imap_okay(line))
			break;
		if (strstr(line, "[TRYCREATE]") != NULL)
			goto try_create;
		imap_invalid(a, line);
		goto error;
	}

	xfree(fctx.lbuf);
	xfree(folder);

	if (imap_putln(a, "%u LOGOUT", ++fdata.tag) != 0)
		goto error;
	if (deliver_imap_waitokay(a, &fctx, io, &line) != 0)
		goto error;

	fdata.disconnect(a);
	return (DELIVER_SUCCESS);

try_create:	/* XXX function? */
	/* Try to create the folder. */
	if (imap_putln(a, "%u CREATE {%zu}", ++fdata.tag, strlen(folder)) != 0)
		goto error;
	if (deliver_imap_waitcontinue(a, &fctx, io, &line) != 0)
		goto error;
	if (imap_putln(a, "%s", folder) != 0)
		goto error;
	if (deliver_imap_waitokay(a, &fctx, io, &line) != 0)
		goto error;
	goto retry;

error:
	io_writeline(io, "QUIT");
	io_flush(io, conf.timeout, NULL);

	xfree(fctx.lbuf);
	if (folder != NULL)
		xfree(folder);

	fdata.disconnect(a);
	return (DELIVER_FAILURE);
}