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