1 /* $Id$ */
2 
3 /*
4  * Copyright (c) 2006 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_imappipe_fill(struct account *, struct iolist *);
28 void	fetch_imappipe_desc(struct account *, char *, size_t);
29 
30 int	fetch_imappipe_connect(struct account *);
31 void	fetch_imappipe_disconnect(struct account *);
32 int	fetch_imappipe_putln(struct account *, const char *, va_list);
33 int	fetch_imappipe_getln(struct account *, struct fetch_ctx *, char **);
34 
35 int	fetch_imappipe_state_init(struct account *, struct fetch_ctx *);
36 
37 struct fetch fetch_imappipe = {
38 	"imap",
39 	fetch_imappipe_state_init,
40 
41 	fetch_imappipe_fill,
42 	imap_commit,	/* from imap-common.c */
43 	imap_abort,	/* from imap-common.c */
44 	imap_total,	/* from imap-common.c */
45 	fetch_imappipe_desc
46 };
47 
48 /* Write line to server. */
49 int
fetch_imappipe_putln(struct account * a,const char * fmt,va_list ap)50 fetch_imappipe_putln(struct account *a, const char *fmt, va_list ap)
51 {
52 	struct fetch_imap_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_imappipe_getln(struct account * a,struct fetch_ctx * fctx,char ** line)65 fetch_imappipe_getln(struct account *a, struct fetch_ctx *fctx, char **line)
66 {
67 	struct fetch_imap_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_imappipe_fill(struct account * a,struct iolist * iol)91 fetch_imappipe_fill(struct account *a, struct iolist *iol)
92 {
93 	struct fetch_imap_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_imappipe_connect(struct account * a)105 fetch_imappipe_connect(struct account *a)
106 {
107 	struct fetch_imap_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_imappipe_disconnect(struct account * a)126 fetch_imappipe_disconnect(struct account *a)
127 {
128 	struct fetch_imap_data	*data = a->data;
129 
130 	if (data->cmd != NULL)
131 		cmd_free(data->cmd);
132 }
133 
134 /* IMAP over pipe initial state. */
135 int
fetch_imappipe_state_init(struct account * a,struct fetch_ctx * fctx)136 fetch_imappipe_state_init(struct account *a, struct fetch_ctx *fctx)
137 {
138 	struct fetch_imap_data	*data = a->data;
139 
140 	data->connect = fetch_imappipe_connect;
141 	data->getln = fetch_imappipe_getln;
142 	data->putln = fetch_imappipe_putln;
143 	data->disconnect = fetch_imappipe_disconnect;
144 
145 	data->src = NULL;
146 
147 	return (imap_state_init(a, fctx));
148 }
149 
150 void
fetch_imappipe_desc(struct account * a,char * buf,size_t len)151 fetch_imappipe_desc(struct account *a, char *buf, size_t len)
152 {
153 	struct fetch_imap_data	*data = a->data;
154 	char			*folders;
155 
156 	folders = fmt_strings("folders ", data->folders);
157 	if (data->user == NULL) {
158 		xsnprintf(buf, len, "imap pipe \"%s\" %s",
159 		    data->pipecmd, folders);
160 	} else {
161 		xsnprintf(buf, len, "imap pipe \"%s\" user \"%s\" %s",
162 		    data->pipecmd, data->user, folders);
163 	}
164 	xfree(folders);
165 }
166