1 /* $Id$ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 
21 #include <string.h>
22 #include <unistd.h>
23 
24 #include "fdm.h"
25 #include "fetch.h"
26 
27 void	fetch_pop3pipe_fill(struct account *, struct iolist *);
28 void	fetch_pop3pipe_desc(struct account *, char *, size_t);
29 
30 int	fetch_pop3pipe_connect(struct account *);
31 void	fetch_pop3pipe_disconnect(struct account *);
32 int	fetch_pop3pipe_putln(struct account *, const char *, va_list);
33 int	fetch_pop3pipe_getln(struct account *, struct fetch_ctx *, char **);
34 
35 int	fetch_pop3pipe_state_init(struct account *, struct fetch_ctx *);
36 
37 struct fetch fetch_pop3pipe = {
38 	"pop3",
39 	fetch_pop3pipe_state_init,
40 
41 	fetch_pop3pipe_fill,
42 	pop3_commit,	/* from pop3-common.c */
43 	pop3_abort,	/* from pop3-common.c */
44 	pop3_total,	/* from pop3-common.c */
45 	fetch_pop3pipe_desc
46 };
47 
48 /* Write line to server. */
49 int
fetch_pop3pipe_putln(struct account * a,const char * fmt,va_list ap)50 fetch_pop3pipe_putln(struct account *a, const char *fmt, va_list ap)
51 {
52 	struct fetch_pop3_data	*data = a->data;
53 
54 	if (data->cmd->io_in == NULL) {
55 		log_warnx("%s: %s", a->name, strerror(EPIPE));
56 		return (-1);
57 	}
58 
59 	io_vwriteline(data->cmd->io_in, fmt, ap);
60 	return (0);
61 }
62 
63 /* Get line from server. */
64 int
fetch_pop3pipe_getln(struct account * a,struct fetch_ctx * fctx,char ** line)65 fetch_pop3pipe_getln(struct account *a, struct fetch_ctx *fctx, char **line)
66 {
67 	struct fetch_pop3_data	*data = a->data;
68 	char			*out, *err, *cause;
69 
70 	switch (cmd_poll(
71 	    data->cmd, &out, &err, &fctx->lbuf, &fctx->llen, 0, &cause)) {
72 	case 0:
73 		break;
74 	case -1:
75 		log_warnx("%s: %s", a->name, cause);
76 		xfree(cause);
77 		return (-1);
78 	default:
79 		log_warnx("%s: connection unexpectedly closed", a->name);
80 		return (-1);
81 	}
82 
83 	if (err != NULL)
84 		log_warnx("%s: %s: %s", a->name, data->pipecmd, err);
85 	*line = out;
86 	return (0);
87 }
88 
89 /* Fill io list. */
90 void
fetch_pop3pipe_fill(struct account * a,struct iolist * iol)91 fetch_pop3pipe_fill(struct account *a, struct iolist *iol)
92 {
93 	struct fetch_pop3_data	*data = a->data;
94 
95 	if (data->cmd->io_in != NULL)
96 		ARRAY_ADD(iol, data->cmd->io_in);
97 	if (data->cmd->io_out != NULL)
98 		ARRAY_ADD(iol, data->cmd->io_out);
99 	if (data->cmd->io_err != NULL)
100 		ARRAY_ADD(iol, data->cmd->io_err);
101 }
102 
103 /* Connect to server. */
104 int
fetch_pop3pipe_connect(struct account * a)105 fetch_pop3pipe_connect(struct account *a)
106 {
107 	struct fetch_pop3_data	*data = a->data;
108 	char			*cause;
109 
110 	data->cmd = cmd_start(data->pipecmd, CMD_IN|CMD_OUT, NULL, 0, &cause);
111 	if (data->cmd == NULL) {
112 		log_warnx("%s: %s", a->name, cause);
113 		xfree(cause);
114 		return (-1);
115 	}
116 	if (conf.debug > 3 && !conf.syslog) {
117 		data->cmd->io_in->dup_fd = STDOUT_FILENO;
118 		data->cmd->io_out->dup_fd = STDOUT_FILENO;
119 	}
120 
121 	return (0);
122 }
123 
124 /* Close connection. */
125 void
fetch_pop3pipe_disconnect(struct account * a)126 fetch_pop3pipe_disconnect(struct account *a)
127 {
128 	struct fetch_pop3_data	*data = a->data;
129 
130 	if (data->cmd != NULL)
131 		cmd_free(data->cmd);
132 }
133 
134 /* POP3 over pipe initial state. */
135 int
fetch_pop3pipe_state_init(struct account * a,struct fetch_ctx * fctx)136 fetch_pop3pipe_state_init(struct account *a, struct fetch_ctx *fctx)
137 {
138 	struct fetch_pop3_data	*data = a->data;
139 
140 	data->connect = fetch_pop3pipe_connect;
141 	data->getln = fetch_pop3pipe_getln;
142 	data->putln = fetch_pop3pipe_putln;
143 	data->disconnect = fetch_pop3pipe_disconnect;
144 
145 	data->src = NULL;
146 
147 	return (pop3_state_init(a, fctx));
148 }
149 
150 void
fetch_pop3pipe_desc(struct account * a,char * buf,size_t len)151 fetch_pop3pipe_desc(struct account *a, char *buf, size_t len)
152 {
153 	struct fetch_pop3_data	*data = a->data;
154 
155 	if (data->user == NULL)
156 		xsnprintf(buf, len, "pop3 pipe \"%s\"", data->pipecmd);
157 	else {
158 		xsnprintf(buf, len,
159 		    "pop3 pipe \"%s\" user \"%s\"", data->pipecmd, data->user);
160 	}
161 }
162