Commit b0f41a71 b0f41a7171dc889b5cf45b6d0ce60c5df462663e by Alain Magloire

Finally!!!! I can use the GNU imap4d with Netscape .... It kinda work 8-)

sigh ... still more to do.
1 parent 5c2bb927
1 2001-05-09 Alain Magloire
2
3 Take the missing pieces from the pop3d and make the
4 imap4d a standalone daemon.
5
6 * imap4d/fetch.c: Remove fetch_body_peek().
7 and use fetch_body() instead.
8 (fetch_operation): Malloc the entire message... not good.
9 * imap4d/bye.c: New file.
10 * imap4d/imap4d.c: Put the networking code taken from
11 pop3d.c.
12 * imap4d/lsub.c: Implemented.
13 * imap4d/subscribe.c: Implemented.
14 * imap4d/unsubscribe.c: Implemented.
15
16 * pop3d/pop3d.c: pop3d_usage() move from extra.c
17 * pop3d/signal.c: pop3d_signal () move from extra.c
18
19 * mailbox/url_imap.c: It was not checking for the port number.
20 * mailbox/filter_rfc822.c: Check for the lines if available.
21
1 2001-05-07 Alain Magloire 22 2001-05-07 Alain Magloire
2 23
3 Now we can have multiple access to the mailbox and the server 24 Now we can have multiple access to the mailbox and the server
......
...@@ -4,7 +4,7 @@ INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include ...@@ -4,7 +4,7 @@ INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include
4 sbin_PROGRAMS = imap4d 4 sbin_PROGRAMS = imap4d
5 5
6 imap4d_LDADD = ../mailbox/libmailbox.la ../lib/libmailutils.a @AUTHLIBS@ 6 imap4d_LDADD = ../mailbox/libmailbox.la ../lib/libmailutils.a @AUTHLIBS@
7 imap4d_SOURCES = imap4d.c imap4d.h capability.c noop.c logout.c authenticate.c \ 7 imap4d_SOURCES = append.c authenticate.c bye.c capability.c check.c close.c \
8 login.c select.c examine.c create.c delete.c rename.c subscribe.c \ 8 commands.c copy.c create.c delete.c examine.c expunge.c fetch.c imap4d.c \
9 unsubscribe.c list.c lsub.c status.c append.c check.c close.c \ 9 imap4d.h list.c logout.c login.c lsub.c noop.c rename.c search.c select.c \
10 expunge.c search.c fetch.c store.c sync.c copy.c uid.c util.c commands.c 10 signal.c status.c store.c subscribe.c sync.c uid.c unsubscribe.c util.c
......
...@@ -48,7 +48,6 @@ static int fetch_rfc822 __P ((struct fetch_command *, char*)); ...@@ -48,7 +48,6 @@ static int fetch_rfc822 __P ((struct fetch_command *, char*));
48 static int fetch_bodystructure __P ((struct fetch_command *, char*)); 48 static int fetch_bodystructure __P ((struct fetch_command *, char*));
49 static int fetch_bodystructure0 __P ((message_t, int)); 49 static int fetch_bodystructure0 __P ((message_t, int));
50 static int bodystructure __P ((message_t, int)); 50 static int bodystructure __P ((message_t, int));
51 static int fetch_body_peek __P ((struct fetch_command *, char*));
52 static int fetch_body __P ((struct fetch_command *, char*)); 51 static int fetch_body __P ((struct fetch_command *, char*));
53 static int fetch_uid __P ((struct fetch_command *, char*)); 52 static int fetch_uid __P ((struct fetch_command *, char*));
54 53
...@@ -92,11 +91,9 @@ struct fetch_command ...@@ -92,11 +91,9 @@ struct fetch_command
92 {"RFC822", fetch_rfc822, 0}, 91 {"RFC822", fetch_rfc822, 0},
93 #define F_BODYSTRUCTURE 10 92 #define F_BODYSTRUCTURE 10
94 {"BODYSTRUCTURE", fetch_bodystructure, 0}, 93 {"BODYSTRUCTURE", fetch_bodystructure, 0},
95 #define F_BODY_PEEK 11 94 #define F_BODY 11
96 {"BODY.PEEK", fetch_body_peek, 0},
97 #define F_BODY 12
98 {"BODY", fetch_body, 0}, 95 {"BODY", fetch_body, 0},
99 #define F_UID 13 96 #define F_UID 12
100 {"UID", fetch_uid, 0}, 97 {"UID", fetch_uid, 0},
101 { NULL, 0, 0} 98 { NULL, 0, 0}
102 }; 99 };
...@@ -160,40 +157,51 @@ imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen) ...@@ -160,40 +157,51 @@ imap4d_fetch0 (char *arg, int isuid, char *resp, size_t resplen)
160 char item[32]; 157 char item[32];
161 char *items = strdup (sp); 158 char *items = strdup (sp);
162 char *p = items; 159 char *p = items;
160 size_t msgno;
161 int space = 0;
163 int uid_sent = !isuid; /* Pretend we sent the uid if via fetch. */ 162 int uid_sent = !isuid; /* Pretend we sent the uid if via fetch. */
164 util_send ("* %d FETCH (", set[i]); 163
165 item[0] = '\0'; 164 msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
166 /* Get the fetch command names. */ 165 if (msgno)
167 while (*items && *items != ')')
168 { 166 {
169 util_token (item, sizeof (item), &items); 167 fcmd = NULL;
170 if (fcmd) 168 util_send ("* %d FETCH (", msgno);
171 util_send (" "); 169 item[0] = '\0';
172 /* Search in the table. */ 170 /* Server implementations MUST implicitly
173 fcmd = fetch_getcommand (item, fetch_command_table); 171 include the UID message data item as part of any FETCH response
174 if (fcmd) 172 caused by a UID command, regardless of whether a UID was specified
173 as a message data item to the FETCH. */
174 if (!uid_sent)
175 {
176 fcmd = &fetch_command_table[F_UID];
177 fcmd->msgno = msgno;
178 rc = fetch_uid (fcmd, p);
179 uid_sent = 1;
180 }
181 /* Get the fetch command names. */
182 while (*items && *items != ')')
175 { 183 {
176 fcmd->msgno = (isuid) ? uid_to_msgno (set[i]) : set[i]; 184 util_token (item, sizeof (item), &items);
177 if (fcmd->msgno != 0) 185 if (uid_sent && strcasecmp (item, "UID") == 0)
186 continue;
187 if (fcmd)
188 space = 1;
189 /* Search in the table. */
190 fcmd = fetch_getcommand (item, fetch_command_table);
191 if (fcmd)
178 { 192 {
193 if (space)
194 {
195 util_send (" ");
196 space = 0;
197 }
198 fcmd->msgno = msgno;
179 rc = fcmd->func (fcmd, items); 199 rc = fcmd->func (fcmd, items);
180 } 200 }
181 } 201 }
182 if (!uid_sent) 202 util_send (")\r\n");
183 uid_sent = ((strstr (item, "UID") != NULL)
184 || (strstr (item, "uid") != NULL));
185 }
186 /* Always send the UID when fetch was done via the uid command. */
187 if (!uid_sent)
188 {
189 struct fetch_command c_uid = fetch_command_table[F_UID];
190 c_uid.msgno = set[i];
191 if (fcmd)
192 util_send (" ");
193 rc = fetch_uid (&c_uid, items);
194 } 203 }
195 free (p); 204 free (p);
196 util_send (")\r\n");
197 } 205 }
198 free (set); 206 free (set);
199 snprintf (resp, resplen, "Completed"); 207 snprintf (resp, resplen, "Completed");
...@@ -733,8 +741,6 @@ bodystructure (message_t msg, int extension) ...@@ -733,8 +741,6 @@ bodystructure (message_t msg, int extension)
733 static int 741 static int
734 fetch_body (struct fetch_command *command, char *arg) 742 fetch_body (struct fetch_command *command, char *arg)
735 { 743 {
736 struct fetch_command c_body_p = fetch_command_table[F_BODY_PEEK];
737 c_body_p.msgno = command->msgno;
738 /* It's BODY set the message as seen */ 744 /* It's BODY set the message as seen */
739 if (*arg == '[') 745 if (*arg == '[')
740 { 746 {
...@@ -766,15 +772,8 @@ fetch_body (struct fetch_command *command, char *arg) ...@@ -766,15 +772,8 @@ fetch_body (struct fetch_command *command, char *arg)
766 util_send (")"); 772 util_send (")");
767 return RESP_OK; 773 return RESP_OK;
768 } 774 }
769 return fetch_body_peek (&c_body_p, arg); 775 util_send ("%s", command->name);
770 } 776 return fetch_operation (command->msgno, arg, 0);
771
772 static int
773 fetch_body_peek (struct fetch_command *command, char *arg)
774 {
775 util_send ("%s ", command->name);
776 fetch_operation (command->msgno, arg, 0);
777 return RESP_OK;
778 } 777 }
779 778
780 static int 779 static int
...@@ -903,32 +902,37 @@ static int ...@@ -903,32 +902,37 @@ static int
903 fetch_io (stream_t stream, unsigned long start, unsigned long end) 902 fetch_io (stream_t stream, unsigned long start, unsigned long end)
904 { 903 {
905 stream_t rfc = NULL; 904 stream_t rfc = NULL;
906 char buffer[1024]; 905 char *buffer, *p;
907 size_t n = 0; 906 size_t n = 0;
908 size_t total = 0; 907 size_t total = 0;
908 off_t offset;
909
910 offset = (start == ULONG_MAX) ? 0 : start;
909 911
910 filter_create (&rfc, stream, "rfc822", MU_FILTER_ENCODE, MU_STREAM_READ); 912 filter_create (&rfc, stream, "rfc822", MU_FILTER_ENCODE, MU_STREAM_READ);
911 if (start == ULONG_MAX) 913
914 p = buffer = calloc (end + 2, 1);
915 while (end > 0 && stream_read (rfc, buffer, end + 1, offset, &n) == 0 && n > 0)
912 { 916 {
913 start = 0; 917 offset += n;
914 util_send (" {%u}\r\n", end); 918 total += n;
919 end -= n;
920 buffer += n;
915 } 921 }
916 else 922 /* Make sure we null terminate. */
917 util_send ("<%lu> {%u}\r\n", start , end); 923 *buffer = '\0';
918 924
919 while (start < end && 925 if (start != ULONG_MAX)
920 stream_read (rfc, buffer, sizeof (buffer), start, &n) == 0 926 util_send ("<%lu>", start);
921 && n > 0) 927
928 if (total)
922 { 929 {
923 start += n; 930 util_send (" {%u}\r\n", total);
924 total += n; 931 util_send ("%s", p);
925 if (total > end)
926 {
927 size_t diff = n - (total - end);
928 buffer[diff] = '\0';
929 }
930 util_send ("%s", buffer);
931 } 932 }
933 else
934 util_send (" \"\"");
935 free (p);
932 return RESP_OK; 936 return RESP_OK;
933 } 937 }
934 938
...@@ -946,7 +950,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start, ...@@ -946,7 +950,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
946 950
947 status = memory_stream_create (&stream); 951 status = memory_stream_create (&stream);
948 if (status != 0) 952 if (status != 0)
949 util_quit (ERR_NO_MEM); 953 imap4d_bye (ERR_NO_MEM);
950 954
951 /* Save the fields in an array. */ 955 /* Save the fields in an array. */
952 { 956 {
...@@ -957,7 +961,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start, ...@@ -957,7 +961,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
957 { 961 {
958 array = realloc (array, (array_len + 1) * sizeof (*array)); 962 array = realloc (array, (array_len + 1) * sizeof (*array));
959 if (!array) 963 if (!array)
960 util_quit (ERR_NO_MEM); 964 imap4d_bye (ERR_NO_MEM);
961 array[array_len] = field; 965 array[array_len] = field;
962 } 966 }
963 } 967 }
...@@ -984,7 +988,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start, ...@@ -984,7 +988,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
984 if (status != 0) 988 if (status != 0)
985 { 989 {
986 free (array); 990 free (array);
987 util_quit (ERR_NO_MEM); 991 imap4d_bye (ERR_NO_MEM);
988 } 992 }
989 } 993 }
990 } 994 }
...@@ -1027,7 +1031,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start, ...@@ -1027,7 +1031,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
1027 1031
1028 status = memory_stream_create (&stream); 1032 status = memory_stream_create (&stream);
1029 if (status) 1033 if (status)
1030 util_quit (ERR_NO_MEM); 1034 imap4d_bye (ERR_NO_MEM);
1031 1035
1032 /* Save the field we want to ignore. */ 1036 /* Save the field we want to ignore. */
1033 { 1037 {
...@@ -1038,7 +1042,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start, ...@@ -1038,7 +1042,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
1038 { 1042 {
1039 array = realloc (array, (array_len + 1) * sizeof (*array)); 1043 array = realloc (array, (array_len + 1) * sizeof (*array));
1040 if (!array) 1044 if (!array)
1041 util_quit (ERR_NO_MEM); 1045 imap4d_bye (ERR_NO_MEM);
1042 array[array_len] = field; 1046 array[array_len] = field;
1043 } 1047 }
1044 } 1048 }
...@@ -1093,7 +1097,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start, ...@@ -1093,7 +1097,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
1093 if (status != 0) 1097 if (status != 0)
1094 { 1098 {
1095 free (array); 1099 free (array);
1096 util_quit (ERR_NO_MEM); 1100 imap4d_bye (ERR_NO_MEM);
1097 } 1101 }
1098 } 1102 }
1099 } 1103 }
......
...@@ -23,37 +23,177 @@ mailbox_t mbox; ...@@ -23,37 +23,177 @@ mailbox_t mbox;
23 char *homedir; 23 char *homedir;
24 int state = STATE_NONAUTH; 24 int state = STATE_NONAUTH;
25 25
26 static int imap4d_mainloop __P ((int, int)); 26 /* Number of child processes. */
27 volatile size_t children;
28
29 static struct option long_options[] =
30 {
31 {"daemon", optional_argument, 0, 'd'},
32 {"help", no_argument, 0, 'h'},
33 {"inetd", no_argument, 0, 'i'},
34 {"port", required_argument, 0, 'p'},
35 {"timeout", required_argument, 0, 't'},
36 {"version", no_argument, 0, 'v'},
37 {0, 0, 0, 0}
38 };
39
40 const char *short_options ="d::hip:t:v";
41
42 static int syslog_error_printer __P ((const char *fmt, va_list ap));
43 static int imap4d_mainloop __P ((int, int));
44 static void imap4d_daemon_init __P ((void));
45 static void imap4d_daemon __P ((unsigned int, unsigned int));
46 static int imap4d_mainloop __P ((int, int));
47 static void imap4d_usage __P ((char *));
48
49 #ifndef DEFMAXCHILDREN
50 # define DEFMAXCHILDREN 20 /* Default maximum number of children */
51 #endif
27 52
28 int 53 int
29 main (int argc, char **argv) 54 main (int argc, char **argv)
30 { 55 {
31 chdir ("/"); 56 struct group *gr;
32 openlog ("imap4d", LOG_PID, LOG_MAIL); 57 static int mode = INTERACTIVE;
58 size_t maxchildren = DEFMAXCHILDREN;
59 int c = 0;
60 int status = EXIT_SUCCESS;
61 unsigned int port;
62
63 port = 143; /* Default IMAP4 port. */
64 timeout = 1800; /* RFC2060: 30 minutes, if enable. */
65 state = STATE_NONAUTH; /* Starting state in non-auth. */
66
67 while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
68 != -1)
69 {
70 switch (c)
71 {
72 case 'd':
73 mode = DAEMON;
74 if (optarg)
75 maxchildren = strtoul (optarg, NULL, 10);
76 if (maxchildren == 0)
77 maxchildren = DEFMAXCHILDREN;
78 break;
79
80 case 'h':
81 imap4d_usage (argv[0]);
82 break;
83
84 case 'i':
85 mode = INTERACTIVE;
86 break;
87
88 case 'p':
89 mode = DAEMON;
90 port = strtoul (optarg, NULL, 10);
91 break;
92
93 case 't':
94 timeout = strtoul (optarg, NULL, 10);
95 break;
96
97 case 'v':
98 printf ("GNU imap4 daemon" "("PACKAGE " " VERSION ")\n");
99 exit (0);
100 break;
101
102 default:
103 break;
104 }
105 }
106
107 /* First we want our group to be mail so we can access the spool. */
108 gr = getgrnam ("mail");
109 if (gr == NULL)
110 {
111 perror ("Error getting mail group");
112 exit (1);
113 }
114
115 if (setgid (gr->gr_gid) == -1)
116 {
117 perror ("Error setting mail group");
118 exit (1);
119 }
33 120
34 /* Register the desire formats. We only need Mbox mail format. */ 121 /* Register the desire formats. We only need Mbox mail format. */
35 { 122 {
36 list_t bookie; 123 list_t bookie;
37 registrar_get_list (&bookie); 124 registrar_get_list (&bookie);
125 /* list_append (bookie, mbox_record); */
38 list_append (bookie, path_record); 126 list_append (bookie, path_record);
39 } 127 }
40 /* FIXME: Incomplete, make it work for standalone, see pop3d. */ 128
41 imap4d_mainloop (fileno (stdin), fileno (stdout)); 129 /* Set the signal handlers. */
42 return 0; 130 signal (SIGINT, imap4d_signal);
131 signal (SIGQUIT, imap4d_signal);
132 signal (SIGILL, imap4d_signal);
133 signal (SIGBUS, imap4d_signal);
134 signal (SIGFPE, imap4d_signal);
135 signal (SIGSEGV, imap4d_signal);
136 signal (SIGTERM, imap4d_signal);
137 signal (SIGSTOP, imap4d_signal);
138 signal (SIGPIPE, imap4d_signal);
139 /*signal (SIGPIPE, SIG_IGN); */
140 signal (SIGABRT, imap4d_signal);
141
142 if (mode == DAEMON)
143 imap4d_daemon_init ();
144
145 /* Make sure we are in the root. */
146 chdir ("/");
147
148 /* Set up for syslog. */
149 openlog ("gnu-imap4d", LOG_PID, LOG_FACILITY);
150
151 /* Redirect any stdout error from the library to syslog, they
152 should not go to the client. */
153 mu_error_set_print (syslog_error_printer);
154
155 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */
156
157 /* Actually run the daemon. */
158 if (mode == DAEMON)
159 imap4d_daemon (maxchildren, port);
160 /* exit (0) -- no way out of daemon except a signal. */
161 else
162 status = imap4d_mainloop (fileno (stdin), fileno (stdout));
163
164 /* Close the syslog connection and exit. */
165 closelog ();
166
167 return status;
43 } 168 }
44 169
45 static int 170 static int
46 imap4d_mainloop (int infile, int outfile) 171 imap4d_mainloop (int infile, int outfile)
47 { 172 {
48 const char *remote_host = "";
49 FILE *ifile; 173 FILE *ifile;
174
175 /* Reset hup to exit. */
176 signal (SIGHUP, imap4d_signal);
177 /* Timeout alarm. */
178 signal (SIGALRM, imap4d_signal);
179
50 ifile = fdopen (infile, "r"); 180 ifile = fdopen (infile, "r");
51 ofile = fdopen (outfile, "w"); 181 ofile = fdopen (outfile, "w");
52 if (!ofile || !ifile) 182 if (!ofile || !ifile)
53 util_quit (ERR_NO_OFILE); 183 imap4d_bye (ERR_NO_OFILE);
54 184
55 /* FIXME: Retreive hostname with getpeername() and log. */ 185 syslog (LOG_INFO, "Incoming connection opened");
56 syslog (LOG_INFO, "Incoming connection from %s", remote_host); 186
187 /* log information on the connecting client */
188 {
189 struct sockaddr_in cs;
190 int len = sizeof cs;
191 if (getpeername (infile, (struct sockaddr*)&cs, &len) < 0)
192 syslog (LOG_ERR, "can't obtain IP address of client: %s",
193 strerror (errno));
194 else
195 syslog (LOG_INFO, "connect from %s", inet_ntoa(cs.sin_addr));
196 }
57 197
58 /* Greetings. */ 198 /* Greetings. */
59 util_out (RESP_OK, "IMAP4rev1 GNU " PACKAGE " " VERSION); 199 util_out (RESP_OK, "IMAP4rev1 GNU " PACKAGE " " VERSION);
...@@ -71,5 +211,164 @@ imap4d_mainloop (int infile, int outfile) ...@@ -71,5 +211,164 @@ imap4d_mainloop (int infile, int outfile)
71 } 211 }
72 212
73 closelog (); 213 closelog ();
214 return EXIT_SUCCESS;
215 }
216
217 /* Sets things up for daemon mode. */
218 static void
219 imap4d_daemon_init (void)
220 {
221 pid_t pid;
222
223 pid = fork ();
224 if (pid == -1)
225 {
226 perror ("fork failed:");
227 exit (1);
228 }
229 else if (pid > 0)
230 exit (0); /* Parent exits. */
231
232 setsid (); /* Become session leader. */
233
234 signal (SIGHUP, SIG_IGN); /* Ignore SIGHUP. */
235
236 /* The second fork is to guarantee that the daemon cannot acquire a
237 controlling terminal. */
238 pid = fork ();
239 if (pid == -1)
240 {
241 perror("fork failed:");
242 exit (1);
243 }
244 else if (pid > 0)
245 exit (0); /* Parent exits. */
246
247 /* Close inherited file descriptors. */
248 {
249 size_t i;
250 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
251 size_t fdlimit = sysconf(_SC_OPEN_MAX);
252 #else
253 size_t fdlimit = 64;
254 #endif
255 for (i = 0; i < fdlimit; ++i)
256 close (i);
257 }
258
259 /* SIGCHLD is not ignore but rather use to do some simple load balancing. */
260 #ifdef HAVE_SIGACTION
261 {
262 struct sigaction act;
263 act.sa_handler = imap4d_sigchld;
264 sigemptyset (&act.sa_mask);
265 act.sa_flags = 0;
266 sigaction (SIGCHLD, &act, NULL);
267 }
268 #else
269 signal (SIGCHLD, imap4d_sigchld);
270 #endif
271 }
272
273 /* Runs GNU imap4d in standalone daemon mode. This opens and binds to a port
274 (default 143) then executes a imap4d_mainloop() upon accepting a connection.
275 It starts maxchildren child processes to listen to and accept socket
276 connections. */
277 static void
278 imap4d_daemon (unsigned int maxchildren, unsigned int port)
279 {
280 struct sockaddr_in server, client;
281 pid_t pid;
282 int listenfd, connfd;
283 size_t size;
284
285 listenfd = socket (AF_INET, SOCK_STREAM, 0);
286 if (listenfd == -1)
287 {
288 syslog (LOG_ERR, "socket: %s", strerror(errno));
289 exit (1);
290 }
291 size = 1; /* Use size here to avoid making a new variable. */
292 setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size));
293 size = sizeof (server);
294 memset (&server, 0, size);
295 server.sin_family = AF_INET;
296 server.sin_addr.s_addr = htonl (INADDR_ANY);
297 server.sin_port = htons (port);
298
299 if (bind (listenfd, (struct sockaddr *)&server, size) == -1)
300 {
301 syslog (LOG_ERR, "bind: %s", strerror (errno));
302 exit (1);
303 }
304
305 if (listen (listenfd, 128) == -1)
306 {
307 syslog (LOG_ERR, "listen: %s", strerror (errno));
308 exit (1);
309 }
310
311 for (;;)
312 {
313 if (children > maxchildren)
314 {
315 syslog (LOG_ERR, "too many children (%d)", children);
316 pause ();
317 continue;
318 }
319 connfd = accept (listenfd, (struct sockaddr *)&client, &size);
320 if (connfd == -1)
321 {
322 if (errno == EINTR)
323 continue;
324 syslog (LOG_ERR, "accept: %s", strerror (errno));
325 exit (1);
326 }
327
328 pid = fork ();
329 if (pid == -1)
330 syslog(LOG_ERR, "fork: %s", strerror (errno));
331 else if (pid == 0) /* Child. */
332 {
333 int status;
334 close (listenfd);
335 status = imap4d_mainloop (connfd, connfd);
336 closelog ();
337 exit (status);
338 }
339 else
340 {
341 ++children;
342 }
343 close (connfd);
344 }
345 }
346
347 /* Prints out usage information and exits the program */
348
349 static void
350 imap4d_usage (char *argv0)
351 {
352 printf ("Usage: %s [OPTIONS]\n", argv0);
353 printf ("Runs the GNU IMAP4 daemon.\n\n");
354 printf (" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum\n");
355 printf (" of MAXCHILDREN child processes\n");
356 printf (" -h, --help display this help and exit\n");
357 printf (" -i, --inetd runs in inetd mode (default)\n");
358 printf (" -p, --port=PORT specifies port to listen on, implies -d\n"
359 );
360 printf (" defaults to 143, which need not be specifi
361 ed\n");
362 printf (" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds\n");
363 printf (" TIMEOUT default is 1800 (30 minutes)\n");
364 printf (" -v, --version display version information and exit\n");
365 printf ("\nReport bugs to bug-mailutils@gnu.org\n");
366 exit (0);
367 }
368
369 static int
370 syslog_error_printer (const char *fmt, va_list ap)
371 {
372 vsyslog (LOG_CRIT, fmt, ap);
74 return 0; 373 return 0;
75 } 374 }
......
...@@ -49,6 +49,12 @@ ...@@ -49,6 +49,12 @@
49 #include <sys/stat.h> 49 #include <sys/stat.h>
50 #include <dirent.h> 50 #include <dirent.h>
51 #include <fcntl.h> 51 #include <fcntl.h>
52 #include <signal.h>
53 #include <sys/socket.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
56 #include <netdb.h>
57 #include "getopt.h"
52 58
53 #ifdef HAVE_ALLOCA_H 59 #ifdef HAVE_ALLOCA_H
54 # include <alloca.h> 60 # include <alloca.h>
...@@ -66,6 +72,7 @@ ...@@ -66,6 +72,7 @@
66 #include <mailutils/registrar.h> 72 #include <mailutils/registrar.h>
67 #include <mailutils/filter.h> 73 #include <mailutils/filter.h>
68 #include <mailutils/stream.h> 74 #include <mailutils/stream.h>
75 #include <mailutils/error.h>
69 76
70 #ifdef __cplusplus 77 #ifdef __cplusplus
71 extern "C" { 78 extern "C" {
...@@ -89,6 +96,10 @@ struct imap4d_command ...@@ -89,6 +96,10 @@ struct imap4d_command
89 char *tag; 96 char *tag;
90 }; 97 };
91 98
99 /* Daemon modes. */
100 #define INTERACTIVE 0
101 #define DAEMON 1
102
92 /* Global variables and constants*/ 103 /* Global variables and constants*/
93 #define STATE_NONE (0) 104 #define STATE_NONE (0)
94 #define STATE_NONAUTH (1 << 0) 105 #define STATE_NONAUTH (1 << 0)
...@@ -107,8 +118,11 @@ struct imap4d_command ...@@ -107,8 +118,11 @@ struct imap4d_command
107 #define RESP_NONE 4 118 #define RESP_NONE 4
108 119
109 /* Error values. */ 120 /* Error values. */
121 #define OK 0
110 #define ERR_NO_MEM 1 122 #define ERR_NO_MEM 1
111 #define ERR_NO_OFILE 2 123 #define ERR_NO_OFILE 2
124 #define ERR_TIMEOUT 3
125 #define ERR_SIGNAL 4
112 126
113 extern struct imap4d_command imap4d_command_table[]; 127 extern struct imap4d_command imap4d_command_table[];
114 extern FILE *ofile; 128 extern FILE *ofile;
...@@ -116,42 +130,48 @@ extern unsigned int timeout; ...@@ -116,42 +130,48 @@ extern unsigned int timeout;
116 extern mailbox_t mbox; 130 extern mailbox_t mbox;
117 extern char *homedir; 131 extern char *homedir;
118 extern int state; 132 extern int state;
133 extern volatile size_t children;
119 134
120 /* Imap4 commands */ 135 /* Imap4 commands */
121 extern int imap4d_capability __P ((struct imap4d_command *, char *));
122 extern int imap4d_noop __P ((struct imap4d_command *, char *));
123 extern int imap4d_logout __P ((struct imap4d_command *, char *));
124 extern int imap4d_authenticate __P ((struct imap4d_command *, char *));
125 extern int imap4d_login __P ((struct imap4d_command *, char *));
126 extern int imap4d_select __P ((struct imap4d_command *, char *));
127 extern int imap4d_select0 __P ((struct imap4d_command *, char *, int));
128 extern int imap4d_examine __P ((struct imap4d_command *, char *));
129 extern int imap4d_create __P ((struct imap4d_command *, char *));
130 extern int imap4d_delete __P ((struct imap4d_command *, char *));
131 extern int imap4d_rename __P ((struct imap4d_command *, char *));
132 extern int imap4d_subscribe __P ((struct imap4d_command *, char *));
133 extern int imap4d_unsubscribe __P ((struct imap4d_command *, char *));
134 extern int imap4d_list __P ((struct imap4d_command *, char *));
135 extern int imap4d_lsub __P ((struct imap4d_command *, char *));
136 extern int imap4d_status __P ((struct imap4d_command *, char *));
137 extern int imap4d_append __P ((struct imap4d_command *, char *)); 136 extern int imap4d_append __P ((struct imap4d_command *, char *));
137 extern int imap4d_authenticate __P ((struct imap4d_command *, char *));
138 extern int imap4d_capability __P ((struct imap4d_command *, char *));
138 extern int imap4d_check __P ((struct imap4d_command *, char *)); 139 extern int imap4d_check __P ((struct imap4d_command *, char *));
139 extern int imap4d_close __P ((struct imap4d_command *, char *)); 140 extern int imap4d_close __P ((struct imap4d_command *, char *));
141 extern int imap4d_copy __P ((struct imap4d_command *, char *));
142 extern int imap4d_copy0 __P ((char *, int, char *, size_t));
143 extern int imap4d_create __P ((struct imap4d_command *, char *));
144 extern int imap4d_delete __P ((struct imap4d_command *, char *));
145 extern int imap4d_examine __P ((struct imap4d_command *, char *));
140 extern int imap4d_expunge __P ((struct imap4d_command *, char *)); 146 extern int imap4d_expunge __P ((struct imap4d_command *, char *));
141 extern int imap4d_search __P ((struct imap4d_command *, char *));
142 extern int imap4d_fetch __P ((struct imap4d_command *, char *)); 147 extern int imap4d_fetch __P ((struct imap4d_command *, char *));
143 extern int imap4d_fetch0 __P ((char *, int, char *, size_t)); 148 extern int imap4d_fetch0 __P ((char *, int, char *, size_t));
149 extern int imap4d_list __P ((struct imap4d_command *, char *));
150 extern int imap4d_lsub __P ((struct imap4d_command *, char *));
151 extern int imap4d_login __P ((struct imap4d_command *, char *));
152 extern int imap4d_logout __P ((struct imap4d_command *, char *));
153 extern int imap4d_noop __P ((struct imap4d_command *, char *));
154 extern int imap4d_rename __P ((struct imap4d_command *, char *));
155 extern int imap4d_search __P ((struct imap4d_command *, char *));
156 extern int imap4d_select __P ((struct imap4d_command *, char *));
157 extern int imap4d_select0 __P ((struct imap4d_command *, char *, int));
158 extern int imap4d_status __P ((struct imap4d_command *, char *));
144 extern int imap4d_store __P ((struct imap4d_command *, char *)); 159 extern int imap4d_store __P ((struct imap4d_command *, char *));
145 extern int imap4d_store0 __P ((char *, int, char *, size_t)); 160 extern int imap4d_store0 __P ((char *, int, char *, size_t));
146 extern int imap4d_copy __P ((struct imap4d_command *, char *)); 161 extern int imap4d_subscribe __P ((struct imap4d_command *, char *));
147 extern int imap4d_copy0 __P ((char *, int, char *, size_t));
148 extern int imap4d_uid __P ((struct imap4d_command *, char *)); 162 extern int imap4d_uid __P ((struct imap4d_command *, char *));
163 extern int imap4d_unsubscribe __P ((struct imap4d_command *, char *));
149 164
150 /* Synchronisation on simultenous access. */ 165 /* Synchronisation on simultenous access. */
151 extern int imap4d_sync __P ((void)); 166 extern int imap4d_sync __P ((void));
152 extern int imap4d_sync_flags __P ((size_t)); 167 extern int imap4d_sync_flags __P ((size_t));
153 extern size_t uid_to_msgno __P ((size_t)); 168 extern size_t uid_to_msgno __P ((size_t));
154 169
170 /* Signal handling. */
171 extern RETSIGTYPE imap4d_sigchld __P ((int));
172 extern RETSIGTYPE imap4d_signal __P ((int));
173 extern int imap4d_bye __P ((int));
174
155 /* Helper functions. */ 175 /* Helper functions. */
156 extern int util_out __P ((int, const char *, ...)); 176 extern int util_out __P ((int, const char *, ...));
157 extern int util_send __P ((const char *, ...)); 177 extern int util_send __P ((const char *, ...));
...@@ -160,7 +180,6 @@ extern int util_finish __P ((struct imap4d_command *, int, const char *, ...)); ...@@ -160,7 +180,6 @@ extern int util_finish __P ((struct imap4d_command *, int, const char *, ...));
160 extern int util_getstate __P ((void)); 180 extern int util_getstate __P ((void));
161 extern int util_do_command __P ((char *)); 181 extern int util_do_command __P ((char *));
162 extern char *imap4d_readline __P ((FILE*)); 182 extern char *imap4d_readline __P ((FILE*));
163 extern void util_quit __P ((int));
164 extern char *util_getword __P ((char *, char **)); 183 extern char *util_getword __P ((char *, char **));
165 extern int util_token __P ((char *, size_t, char **)); 184 extern int util_token __P ((char *, size_t, char **));
166 extern void util_unquote __P ((char **)); 185 extern void util_unquote __P ((char **));
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
47 47
48 static int match __P ((const char *, const char *, const char *)); 48 static int match __P ((const char *, const char *, const char *));
49 static int imap_match __P ((const char *, const char *, const char *)); 49 static int imap_match __P ((const char *, const char *, const char *));
50 static void list_file __P ((const char *, const char *, char *, const char *)); 50 static void list_file __P ((const char *, const char *, const char *, const char *));
51 static void print_file __P ((const char *, const char *, const char *)); 51 static void print_file __P ((const char *, const char *, const char *));
52 static void print_dir __P ((const char *, const char *, const char *)); 52 static void print_dir __P ((const char *, const char *, const char *));
53 53
...@@ -150,7 +150,7 @@ imap4d_list (struct imap4d_command *command, char *arg) ...@@ -150,7 +150,7 @@ imap4d_list (struct imap4d_command *command, char *arg)
150 150
151 if (chdir (cwd) == 0) 151 if (chdir (cwd) == 0)
152 { 152 {
153 list_file (cwd, ref, dir, delim); 153 list_file (cwd, ref, (dir) ? dir : "", delim);
154 chdir (homedir); 154 chdir (homedir);
155 } 155 }
156 free (cwd); 156 free (cwd);
...@@ -161,17 +161,22 @@ imap4d_list (struct imap4d_command *command, char *arg) ...@@ -161,17 +161,22 @@ imap4d_list (struct imap4d_command *command, char *arg)
161 161
162 /* Recusively calling the files. */ 162 /* Recusively calling the files. */
163 static void 163 static void
164 list_file (const char *cwd, const char *ref, char *pattern, const char *delim) 164 list_file (const char *cwd, const char *ref, const char *pattern,
165 const char *delim)
165 { 166 {
166 DIR *dirp; 167 DIR *dirp;
167 struct dirent *dp; 168 struct dirent *dp;
168 char *next; 169 char *next;
169 170
170 /* Shortcut no wildcards. */ 171 /* Shortcut no wildcards. */
171 if (!strpbrk (pattern, "%*")) 172 if (*pattern == '\0' || !strpbrk (pattern, "%*"))
172 { 173 {
173 /* Equivalent to stat(). */ 174 /* Equivalent to stat(). */
174 int status = match (pattern, pattern, delim); 175 int status;
176 if (*pattern == '\0')
177 status = match (cwd, cwd, delim);
178 else
179 status = match (pattern, pattern, delim);
175 if (status & NOSELECT) 180 if (status & NOSELECT)
176 print_dir (ref, pattern, delim); 181 print_dir (ref, pattern, delim);
177 else if (status & NOINFERIORS) 182 else if (status & NOINFERIORS)
......
...@@ -32,7 +32,7 @@ static int _perr = 0; ...@@ -32,7 +32,7 @@ static int _perr = 0;
32 return util_finish (command, RESP_NO, "User name or passwd rejected"); } 32 return util_finish (command, RESP_NO, "User name or passwd rejected"); }
33 33
34 static int 34 static int
35 PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg, 35 PAM_gnuimap4d_conv (int num_msg, const struct pam_message **msg,
36 struct pam_response **resp, void *appdata_ptr) 36 struct pam_response **resp, void *appdata_ptr)
37 { 37 {
38 int replies = 0; 38 int replies = 0;
...@@ -73,7 +73,7 @@ PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg, ...@@ -73,7 +73,7 @@ PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg,
73 return PAM_SUCCESS; 73 return PAM_SUCCESS;
74 } 74 }
75 75
76 static struct pam_conv PAM_conversation = { &PAM_gnupop3d_conv, NULL }; 76 static struct pam_conv PAM_conversation = { &PAM_gnuimap4d_conv, NULL };
77 #endif /* USE_LIBPAM */ 77 #endif /* USE_LIBPAM */
78 78
79 int 79 int
...@@ -91,12 +91,16 @@ imap4d_login (struct imap4d_command *command, char *arg) ...@@ -91,12 +91,16 @@ imap4d_login (struct imap4d_command *command, char *arg)
91 username = util_getword (arg, &sp); 91 username = util_getword (arg, &sp);
92 pass = util_getword (NULL, &sp); 92 pass = util_getword (NULL, &sp);
93 93
94 if (username == NULL || pass == NULL) 94 /* Remove the double quotes. */
95 util_unquote (&username);
96 util_unquote (&pass);
97
98 if (username == NULL || *username == '\0' || pass == NULL)
95 return util_finish (command, RESP_NO, "Too few args"); 99 return util_finish (command, RESP_NO, "Too few args");
96 else if (util_getword (NULL, &sp)) 100 else if (util_getword (NULL, &sp))
97 return util_finish (command, RESP_NO, "Too many args"); 101 return util_finish (command, RESP_NO, "Too many args");
98 102
99 pw = getpwnam (arg); 103 pw = getpwnam (username);
100 104
101 #ifndef USE_LIBPAM 105 #ifndef USE_LIBPAM
102 if (pw == NULL || pw->pw_uid < 1) 106 if (pw == NULL || pw->pw_uid < 1)
...@@ -105,17 +109,17 @@ imap4d_login (struct imap4d_command *command, char *arg) ...@@ -105,17 +109,17 @@ imap4d_login (struct imap4d_command *command, char *arg)
105 { 109 {
106 #ifdef HAVE_SHADOW_H 110 #ifdef HAVE_SHADOW_H
107 struct spwd *spw; 111 struct spwd *spw;
108 spw = getspnam (arg); 112 spw = getspnam (username);
109 if (spw == NULL || strcmp (spw->sp_pwdp, (char *)crypt (pass, spw->sp_pwdp))) 113 if (spw == NULL || strcmp (spw->sp_pwdp, (char *)crypt (pass, spw->sp_pwdp)))
110 #endif /* HAVE_SHADOW_H */ 114 #endif /* HAVE_SHADOW_H */
111 return util_finish (command, RESP_NO, "User name or passwd rejected"); 115 return util_finish (command, RESP_NO, "User name or passwd rejected");
112 } 116 }
113 #else /* !USE_LIBPAM */ 117 #else /* !USE_LIBPAM */
114 _user = (char *) arg; 118 _user = (char *) username;
115 _pwd = pass; 119 _pwd = pass;
116 /* libpam doesn't log to LOG_MAIL */ 120 /* libpam doesn't log to LOG_MAIL */
117 closelog (); 121 closelog ();
118 pamerror = pam_start ("gnu-imap4d", arg, &PAM_conversation, &pamh); 122 pamerror = pam_start ("gnu-imap4d", username, &PAM_conversation, &pamh);
119 PAM_ERROR; 123 PAM_ERROR;
120 pamerror = pam_authenticate (pamh, 0); 124 pamerror = pam_authenticate (pamh, 0);
121 PAM_ERROR; 125 PAM_ERROR;
......
...@@ -29,7 +29,6 @@ imap4d_logout (struct imap4d_command *command, char *arg) ...@@ -29,7 +29,6 @@ imap4d_logout (struct imap4d_command *command, char *arg)
29 return util_finish (command, RESP_BAD, "Wrong state"); 29 return util_finish (command, RESP_BAD, "Wrong state");
30 if (util_getword (arg, &sp)) 30 if (util_getword (arg, &sp))
31 return util_finish (command, RESP_BAD, "Too many args"); 31 return util_finish (command, RESP_BAD, "Too many args");
32 util_out (RESP_BYE, "Logging out");
33 util_finish (command, RESP_OK, "Completed"); 32 util_finish (command, RESP_OK, "Completed");
34 /* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT 33 /* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT
35 command MAY be issued without previously issuing a CLOSE command. 34 command MAY be issued without previously issuing a CLOSE command.
...@@ -40,6 +39,6 @@ imap4d_logout (struct imap4d_command *command, char *arg) ...@@ -40,6 +39,6 @@ imap4d_logout (struct imap4d_command *command, char *arg)
40 mailbox_close (mbox); 39 mailbox_close (mbox);
41 mailbox_destroy (&mbox); 40 mailbox_destroy (&mbox);
42 } 41 }
43 util_quit (0); 42 imap4d_bye (OK);
44 return 0; 43 return 0;
45 } 44 }
......
...@@ -24,7 +24,41 @@ ...@@ -24,7 +24,41 @@
24 int 24 int
25 imap4d_lsub (struct imap4d_command *command, char *arg) 25 imap4d_lsub (struct imap4d_command *command, char *arg)
26 { 26 {
27 char *sp;
28 char *ref;
29 char *wcard;
30 char *file;
31 const char *delim = "/";
32 FILE *fp;
33
27 if (! (command->states & state)) 34 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state"); 35 return util_finish (command, RESP_BAD, "Wrong state");
29 return util_finish (command, RESP_NO, "Not supported"); 36
37 ref = util_getword (arg, &sp);
38 wcard = util_getword (NULL, &sp);
39 if (!ref || !wcard)
40 return util_finish (command, RESP_BAD, "Too few arguments");
41
42 /* Remove the double quotes. */
43 util_unquote (&ref);
44 util_unquote (&wcard);
45
46 /* FIXME: Get the matching in list. */
47 asprintf (&file, "%s/.mailboxlist", homedir);
48 fp = fopen (file, "r");
49 free (file);
50 if (fp)
51 {
52 char buffer[124];
53 while (fgets (buffer, sizeof (buffer), fp))
54 {
55 size_t n = strlen (buffer);
56 if (n && buffer[n - 1] == '\n')
57 buffer[n - 1] = '\0';
58 util_out (RESP_NONE, "LIST () \"%s\" %s", delim, buffer);
59 }
60 fclose (fp);
61 return util_finish (command, RESP_OK, "Completed");
62 }
63 return util_finish (command, RESP_NO, "Can not list subscriber");
30 } 64 }
......
...@@ -37,10 +37,9 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) ...@@ -37,10 +37,9 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
37 /* FIXME: Check state. */ 37 /* FIXME: Check state. */
38 38
39 mailbox_name = util_getword (arg, &sp); 39 mailbox_name = util_getword (arg, &sp);
40 if (mailbox_name == NULL) 40 util_unquote (&mailbox_name);
41 if (mailbox_name == NULL || *mailbox_name == '\0')
41 return util_finish (command, RESP_BAD, "Too few arguments"); 42 return util_finish (command, RESP_BAD, "Too few arguments");
42 if (util_getword (NULL, &sp))
43 return util_finish (command, RESP_BAD, "Too many arguments");
44 43
45 /* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT 44 /* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT
46 command MAY be issued without previously issuing a CLOSE command. 45 command MAY be issued without previously issuing a CLOSE command.
...@@ -56,7 +55,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) ...@@ -56,7 +55,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
56 55
57 if (strcasecmp (mailbox_name, "INBOX") == 0) 56 if (strcasecmp (mailbox_name, "INBOX") == 0)
58 { 57 {
59 pw = getpwuid (getuid()); 58 pw = getpwuid (getuid ());
60 if (pw) 59 if (pw)
61 mailbox_name = pw->pw_name; 60 mailbox_name = pw->pw_name;
62 } 61 }
......
...@@ -109,41 +109,45 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen) ...@@ -109,41 +109,45 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen)
109 char *flags = strdup (""); 109 char *flags = strdup ("");
110 int first = 1; 110 int first = 1;
111 size_t msgno; 111 size_t msgno;
112 char *p = items;
112 113
113 msgno = (isuid) ? uid_to_msgno (set[i]) : set[i]; 114 msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
114 mailbox_get_message (mbox, msgno, &msg); 115 if (msgno)
115 message_get_attribute (msg, &attr);
116
117 /* Get the fetch command names. */
118 while (*items && *items != ')')
119 { 116 {
120 int type = 0; 117 mailbox_get_message (mbox, msgno, &msg);
121 char item[64] = ""; 118 message_get_attribute (msg, &attr);
122 util_token (item, sizeof (item), &items); 119
123 if (get_attribute_type (item, &type)) 120 /* Get the fetch command names. */
121 while (*items && *items != ')')
124 { 122 {
125 if (how == STORE_ADD ) 123 int type = 0;
126 attribute_set_flags (attr, type); 124 char item[64] = "";
127 else if (how == STORE_UNSET ) 125 util_token (item, sizeof (item), &items);
128 attribute_unset_flags (attr, type); 126 if (get_attribute_type (item, &type))
129 else if (how == STORE_SET )
130 { 127 {
131 if (first) 128 if (how == STORE_ADD )
129 attribute_set_flags (attr, type);
130 else if (how == STORE_UNSET )
131 attribute_unset_flags (attr, type);
132 else if (how == STORE_SET )
132 { 133 {
133 attribute_set_flags (attr, 0); 134 if (first)
134 first = 0; 135 {
136 attribute_set_flags (attr, 0);
137 first = 0;
138 }
139 attribute_set_flags (attr, type);
135 } 140 }
136 attribute_set_flags (attr, type); 141 flags = realloc (flags, strlen (flags) + strlen (item) + 2);
142 if (*flags)
143 strcat (flags, " ");
144 strcat (flags, item);
137 } 145 }
138 flags = realloc (flags, strlen (flags) + strlen (item) + 2);
139 if (*flags)
140 strcat (flags, " ");
141 strcat (flags, item);
142 } 146 }
143 } 147 }
144 if (ack && *flags) 148 if (ack && *flags)
145 util_out (RESP_NONE, "%d FETCH FLAGS (%s)", set[i], flags); 149 util_out (RESP_NONE, "%d FETCH FLAGS (%s)", msgno, flags);
146 free (items); 150 free (p);
147 free (flags); 151 free (flags);
148 /* Update the flags of uid table. */ 152 /* Update the flags of uid table. */
149 imap4d_sync_flags (set[i]); 153 imap4d_sync_flags (set[i]);
......
...@@ -18,13 +18,34 @@ ...@@ -18,13 +18,34 @@
18 #include "imap4d.h" 18 #include "imap4d.h"
19 19
20 /* 20 /*
21 * 21 FIXME: We need to lock the file to prevent simultaneous access.
22 */ 22 */
23 23
24 int 24 int
25 imap4d_subscribe (struct imap4d_command *command, char *arg) 25 imap4d_subscribe (struct imap4d_command *command, char *arg)
26 { 26 {
27 char *sp = NULL;
28 char *name;
29 char *file;
30 FILE *fp;
31
27 if (! (command->states & state)) 32 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state"); 33 return util_finish (command, RESP_BAD, "Wrong state");
29 return util_finish (command, RESP_NO, "Not supported"); 34
35 name = util_getword (arg, &sp);
36 util_unquote (&name);
37 if (!name || *name == '\0')
38 return util_finish (command, RESP_BAD, "Too few arguments");
39
40 asprintf (&file, "%s/.mailboxlist", homedir);
41 fp = fopen (file, "a");
42 free (file);
43 if (fp)
44 {
45 fputs (name, fp);
46 fputs ("\n", fp);
47 fclose (fp);
48 return util_finish (command, RESP_OK, "Completed");
49 }
50 return util_finish (command, RESP_NO, "Can not subscribe");
30 } 51 }
......
...@@ -37,7 +37,7 @@ add_flag (char **pbuf, const char *f) ...@@ -37,7 +37,7 @@ add_flag (char **pbuf, const char *f)
37 char *abuf = *pbuf; 37 char *abuf = *pbuf;
38 abuf = realloc (abuf, strlen (abuf) + strlen (f) + 2); 38 abuf = realloc (abuf, strlen (abuf) + strlen (f) + 2);
39 if (abuf == NULL) 39 if (abuf == NULL)
40 util_quit (ERR_NO_MEM); 40 imap4d_bye (ERR_NO_MEM);
41 if (*abuf) 41 if (*abuf)
42 strcat (abuf, " "); 42 strcat (abuf, " ");
43 strcat (abuf, "\\Seen"); 43 strcat (abuf, "\\Seen");
...@@ -58,7 +58,7 @@ notify_flag (size_t msgno, attribute_t oattr) ...@@ -58,7 +58,7 @@ notify_flag (size_t msgno, attribute_t oattr)
58 { 58 {
59 char *abuf = malloc (1);; 59 char *abuf = malloc (1);;
60 if (!abuf) 60 if (!abuf)
61 util_quit (ERR_NO_MEM); 61 imap4d_bye (ERR_NO_MEM);
62 *abuf = '\0'; 62 *abuf = '\0';
63 if (attribute_is_seen (nattr) && attribute_is_read (nattr)) 63 if (attribute_is_seen (nattr) && attribute_is_read (nattr))
64 if (!attribute_is_seen (oattr) && !attribute_is_read (oattr)) 64 if (!attribute_is_seen (oattr) && !attribute_is_read (oattr))
...@@ -197,7 +197,7 @@ reset_uids (void) ...@@ -197,7 +197,7 @@ reset_uids (void)
197 uid_table = realloc (uid_table, sizeof (*uid_table) * 197 uid_table = realloc (uid_table, sizeof (*uid_table) *
198 (uid_table_count + 1)); 198 (uid_table_count + 1));
199 if (!uid_table) 199 if (!uid_table)
200 util_quit (ERR_NO_MEM); 200 imap4d_bye (ERR_NO_MEM);
201 mailbox_get_message (mbox, i, &msg); 201 mailbox_get_message (mbox, i, &msg);
202 message_get_attribute (msg, &attr); 202 message_get_attribute (msg, &attr);
203 message_get_uid (msg, &uid); 203 message_get_uid (msg, &uid);
......
...@@ -24,7 +24,68 @@ ...@@ -24,7 +24,68 @@
24 int 24 int
25 imap4d_unsubscribe (struct imap4d_command *command, char *arg) 25 imap4d_unsubscribe (struct imap4d_command *command, char *arg)
26 { 26 {
27 char *sp = NULL;
28 char *name;
29 char *file;
30 FILE *fp;
31
27 if (! (command->states & state)) 32 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state"); 33 return util_finish (command, RESP_BAD, "Wrong state");
29 return util_finish (command, RESP_NO, "Not supported"); 34
35 name = util_getword (arg, &sp);
36 util_unquote (&name);
37 if (!name || *name == '\0')
38 return util_finish (command, RESP_BAD, "Too few arguments");
39
40 asprintf (&file, "%s/.mailboxlist", homedir);
41 fp = fopen (file, "r");
42 free (file);
43 if (fp)
44 {
45 char buffer[124];
46 int found = 0;
47 while (fgets (buffer, sizeof (buffer), fp))
48 {
49 size_t n = strlen (buffer);
50 if (n && buffer[n - 1] == '\n')
51 buffer[n - 1] = '\0';
52 if (strcmp (buffer, name) == 0)
53 {
54 found = 1;
55 break;
56 }
57 }
58 if (found)
59 {
60 FILE *fp2;
61 asprintf (&file, "%s/.mailboxlist.%d", homedir, getpid ());
62 fp2 = fopen (file, "a");
63 if (fp2)
64 {
65 rewind (fp);
66 while (fgets (buffer, sizeof (buffer), fp))
67 {
68 size_t n = strlen (buffer);
69 if (n && buffer[n - 1] == '\n')
70 buffer[n - 1] = '\0';
71 if (strcmp (buffer, name) == 0)
72 continue;
73 fputs (buffer, fp2);
74 fputs ("\n", fp2);
75 }
76 fclose (fp2);
77 remove (file);
78 }
79 free (file);
80 }
81 else
82 {
83 fclose (fp);
84 return util_finish (command, RESP_NO, "Can not unsubscribe");
85 }
86 fclose (fp);
87 }
88 else
89 return util_finish (command, RESP_NO, "Can not unsubscribe");
90 return util_finish (command, RESP_OK, "Completed");
30 } 91 }
......
...@@ -184,6 +184,9 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -184,6 +184,9 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
184 status = mailbox_messages_count (mbox, &max); 184 status = mailbox_messages_count (mbox, &max);
185 if (status != 0) 185 if (status != 0)
186 return status; 186 return status;
187 /* The number after the "*" in an untagged FETCH response is always a
188 message sequence number, not a unique identifier, even for a UID
189 command response. But do what they meant not what they say. */
187 /* If it is a uid sequence, override max with the UID. */ 190 /* If it is a uid sequence, override max with the UID. */
188 if (isuid) 191 if (isuid)
189 { 192 {
...@@ -357,24 +360,26 @@ imap4d_readline (FILE *fp) ...@@ -357,24 +360,26 @@ imap4d_readline (FILE *fp)
357 char *line = malloc (1); 360 char *line = malloc (1);
358 361
359 if (!line) 362 if (!line)
360 util_quit (ERR_NO_MEM); 363 imap4d_bye (ERR_NO_MEM);
361 364
362 line[0] = '\0'; /* start with a empty string. */ 365 line[0] = '\0'; /* start with a empty string. */
363 do 366 do
364 { 367 {
365 alarm (timeout); 368 alarm (timeout);
366 if (fgets (buffer, sizeof (buffer), fp) == NULL) 369 if (fgets (buffer, sizeof (buffer), fp) == NULL)
367 util_quit (0); /* Logout. */ 370 {
371 imap4d_bye (ERR_NO_OFILE); /* Logout. */
372 }
368 alarm (0); 373 alarm (0);
369 374
370 len = strlen (buffer); 375 len = strlen (buffer);
371 /* If we were in a litteral substract. We have to do it since the CR 376 /* If we were in a litteral substract. We have to do here since the CR
372 is part of the count in a literal. */ 377 is part of the count in a literal. */
373 if (number) 378 if (number)
374 number -= len; 379 number -= len;
375 380
376 /* Remove CR. */ 381 /* Remove CR. */
377 if (len > 2 && buffer[len - 1] == '\n') 382 if (len > 1 && buffer[len - 1] == '\n')
378 { 383 {
379 if (buffer[len - 2] == '\r') 384 if (buffer[len - 2] == '\r')
380 { 385 {
...@@ -382,10 +387,9 @@ imap4d_readline (FILE *fp) ...@@ -382,10 +387,9 @@ imap4d_readline (FILE *fp)
382 buffer[len - 1] = '\0'; 387 buffer[len - 1] = '\0';
383 } 388 }
384 } 389 }
385
386 line = realloc (line, total + len + 1); 390 line = realloc (line, total + len + 1);
387 if (!line) 391 if (!line)
388 util_quit (ERR_NO_MEM); 392 imap4d_bye (ERR_NO_MEM);
389 strcat (line, buffer); 393 strcat (line, buffer);
390 394
391 total = strlen (line); 395 total = strlen (line);
...@@ -413,6 +417,7 @@ imap4d_readline (FILE *fp) ...@@ -413,6 +417,7 @@ imap4d_readline (FILE *fp)
413 } 417 }
414 } 418 }
415 while (number > 0); 419 while (number > 0);
420 /* syslog (LOG_INFO, "readline: %s", line); */
416 return line; 421 return line;
417 } 422 }
418 423
...@@ -474,24 +479,6 @@ util_start (char *tag) ...@@ -474,24 +479,6 @@ util_start (char *tag)
474 return 0; 479 return 0;
475 } 480 }
476 481
477 /* FIXME: Incomplete send errmsg to syslog, see pop3d:pop3_abquit(). */
478 void
479 util_quit (int err)
480 {
481 switch (err)
482 {
483 case ERR_NO_OFILE:
484 /*util_out (RESP_BYE, "Server terminating dead socket."); */
485 break;
486 case ERR_NO_MEM:
487 util_out (RESP_BYE, "Server terminating no more ressources.");
488 break;
489 default:
490 util_out (RESP_BYE, "Server terminating");
491 }
492 exit (err);
493 }
494
495 /* FIXME: What is this for? */ 482 /* FIXME: What is this for? */
496 int 483 int
497 util_getstate (void) 484 util_getstate (void)
......
...@@ -126,11 +126,18 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen, ...@@ -126,11 +126,18 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
126 /* Catch up i.e bring us to the current offset. */ 126 /* Catch up i.e bring us to the current offset. */
127 if (rfc822->r_offset != off) 127 if (rfc822->r_offset != off)
128 { 128 {
129 rfc822->r_offset = off - rfc822->lines;
130 rfc822->residue = 0; 129 rfc822->residue = 0;
131 130
132 if (rfc822->r_offset < 0) 131 /* Try to find a starting point. */
132 if (rfc822->lines)
133 {
134 rfc822->r_offset = off - rfc822->lines;
135 if (rfc822->r_offset < 0)
136 rfc822->r_offset = 0;
137 }
138 else
133 rfc822->r_offset = 0; 139 rfc822->r_offset = 0;
140
134 rfc822->s_offset = rfc822->r_offset; 141 rfc822->s_offset = rfc822->r_offset;
135 142
136 while (rfc822->r_offset < off) 143 while (rfc822->r_offset < off)
...@@ -141,7 +148,11 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen, ...@@ -141,7 +148,11 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
141 if (status != 0) 148 if (status != 0)
142 return status; 149 return status;
143 if (n == 0) 150 if (n == 0)
144 break; 151 {
152 if (pnread)
153 *pnread = 0;
154 return 0;
155 }
145 if (c == '\n') 156 if (c == '\n')
146 { 157 {
147 rfc822->r_offset++; 158 rfc822->r_offset++;
...@@ -191,7 +202,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen, ...@@ -191,7 +202,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
191 buffer += nread; 202 buffer += nread;
192 } while (buflen > 0 && !isreadline); 203 } while (buflen > 0 && !isreadline);
193 204
194 if (isreadline) 205 if (isreadline && buffer)
195 *buffer = '\0'; 206 *buffer = '\0';
196 207
197 if (pnread) 208 if (pnread)
......
...@@ -812,6 +812,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr) ...@@ -812,6 +812,7 @@ imap_literal_string (f_imap_t f_imap, char **ptr)
812 for (len0 = len = total = 0; total < f_imap->callback.nleft; total += (len + 1)) 812 for (len0 = len = total = 0; total < f_imap->callback.nleft; total += (len + 1))
813 { 813 {
814 status = imap_readline (f_imap); 814 status = imap_readline (f_imap);
815 /*fprintf (stderr, "%d: %s", strlen (f_imap->buffer), f_imap->buffer);*/
815 if (status != 0) 816 if (status != 0)
816 { 817 {
817 /* Return what we got so far. */ 818 /* Return what we got so far. */
......
...@@ -45,7 +45,8 @@ url_imap_destroy (url_t url) ...@@ -45,7 +45,8 @@ url_imap_destroy (url_t url)
45 int 45 int
46 _url_imap_init (url_t url) 46 _url_imap_init (url_t url)
47 { 47 {
48 const char *host, *indexe; 48 const char *host_port;
49 const char *indexe;
49 char *name = url->name; 50 char *name = url->name;
50 51
51 /* reject the obvious */ 52 /* reject the obvious */
...@@ -67,12 +68,12 @@ _url_imap_init (url_t url) ...@@ -67,12 +68,12 @@ _url_imap_init (url_t url)
67 68
68 name += MU_IMAP_SCHEME_LEN; /* pass the scheme */ 69 name += MU_IMAP_SCHEME_LEN; /* pass the scheme */
69 70
70 host = strchr (name, '@'); 71 host_port = strchr (name, '@');
71 if (host == NULL) 72 if (host_port == NULL)
72 host= name; 73 host_port = name;
73 74
74 /* looking for ";auth=auth-enc" */ 75 /* looking for ";auth=auth-enc" */
75 for (indexe = name; indexe != host; indexe++) 76 for (indexe = name; indexe != host_port; indexe++)
76 { 77 {
77 /* Auth ? */ 78 /* Auth ? */
78 if (*indexe == ';') 79 if (*indexe == ';')
...@@ -93,7 +94,7 @@ _url_imap_init (url_t url) ...@@ -93,7 +94,7 @@ _url_imap_init (url_t url)
93 ((char *)memcpy(url->user, name, indexe - name))[indexe - name] = '\0'; 94 ((char *)memcpy(url->user, name, indexe - name))[indexe - name] = '\0';
94 95
95 /* AUTH */ 96 /* AUTH */
96 if (indexe == host) 97 if (indexe == host_port)
97 { 98 {
98 /* Use default AUTH '*' */ 99 /* Use default AUTH '*' */
99 url->auth = malloc (1 + 1); 100 url->auth = malloc (1 + 1);
...@@ -107,11 +108,11 @@ _url_imap_init (url_t url) ...@@ -107,11 +108,11 @@ _url_imap_init (url_t url)
107 { 108 {
108 /* move pass AUTH= */ 109 /* move pass AUTH= */
109 indexe += 6; 110 indexe += 6;
110 url->auth = malloc (host - indexe + 1); 111 url->auth = malloc (host_port - indexe + 1);
111 if (url->auth) 112 if (url->auth)
112 { 113 {
113 ((char *)memcpy (url->auth, indexe, host - indexe)) 114 ((char *)memcpy (url->auth, indexe, host_port - indexe))
114 [host - indexe] = '\0'; 115 [host_port - indexe] = '\0';
115 } 116 }
116 } 117 }
117 118
...@@ -121,19 +122,45 @@ _url_imap_init (url_t url) ...@@ -121,19 +122,45 @@ _url_imap_init (url_t url)
121 return -1; 122 return -1;
122 } 123 }
123 124
124 /* HOST*/ 125 /* HOST:PORT*/
125 if (*host == '@') 126 if (*host_port == '@')
126 host++; 127 host_port++;
128
129 indexe = strchr (host_port, ':');
130 if (indexe)
131 {
132 char *s = NULL;
133 long int p = strtol (indexe + 1, &s, 10);
134 url->host = malloc (indexe - host_port + 1);
135 if (url->host)
136 {
137 ((char *)memcpy (url->host, host_port, indexe - host_port))
138 [indexe - host_port] = '\0';
139 }
140 url->port = (p == 0) ? MU_IMAP_PORT : p;
141 host_port = s;
142 }
143 else
144 url->port = MU_IMAP_PORT;
145
146
147 indexe = strchr (host_port, '/');
127 148
128 indexe = strchr (host, '/');
129 if (indexe == NULL) 149 if (indexe == NULL)
130 url->host = strdup (host); 150 {
151 if (url->host == NULL)
152 url->host = strdup (host_port);
153 }
131 else 154 else
132 { 155 {
133 char *question; 156 char *question;
134 url->host = malloc (indexe - host + 1); 157 if (url->host == NULL)
135 if (url->host) 158 {
136 ((char *)memcpy (url->host, host, indexe - host))[indexe - host] = '\0'; 159 url->host = malloc (indexe - host_port + 1);
160 if (url->host)
161 ((char *)memcpy (url->host, host_port, indexe - host_port))
162 [indexe - host_port] = '\0';
163 }
137 indexe++; 164 indexe++;
138 /* The query starts after a '?'. */ 165 /* The query starts after a '?'. */
139 question = strchr (indexe, '?'); 166 question = strchr (indexe, '?');
...@@ -155,6 +182,5 @@ _url_imap_init (url_t url) ...@@ -155,6 +182,5 @@ _url_imap_init (url_t url)
155 return ENOMEM; 182 return ENOMEM;
156 } 183 }
157 184
158 url->port = MU_IMAP_PORT;
159 return 0; 185 return 0;
160 } 186 }
......
...@@ -126,45 +126,7 @@ pop3d_abquit (int reason) ...@@ -126,45 +126,7 @@ pop3d_abquit (int reason)
126 } 126 }
127 127
128 closelog(); 128 closelog();
129 exit (1); 129 exit (EXIT_FAILURE);
130 }
131
132 /* Prints out usage information and exits the program */
133
134 void
135 pop3d_usage (char *argv0)
136 {
137 printf ("Usage: %s [OPTIONS]\n", argv0);
138 printf ("Runs the GNU POP3 daemon.\n\n");
139 printf (" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum\n");
140 printf (" of MAXCHILDREN child processes\n");
141 printf (" -h, --help display this help and exit\n");
142 printf (" -i, --inetd runs in inetd mode (default)\n");
143 printf (" -p, --port=PORT specifies port to listen on, implies -d\n");
144 printf (" defaults to 110, which need not be specified\n");
145 printf (" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds\n");
146 printf (" TIMEOUT default is 600 (10 minutes)\n");
147 printf (" -v, --version display version information and exit\n");
148 printf ("\nReport bugs to bug-mailutils@gnu.org\n");
149 exit (0);
150 }
151
152 /* Default signal handler to call the pop3d_abquit() function */
153
154 RETSIGTYPE
155 pop3d_signal (int signo)
156 {
157 syslog (LOG_CRIT, "got signal %d", signo);
158 /* Master process. */
159 if (!ofile)
160 {
161 syslog(LOG_CRIT, "MASTER: exiting on signal");
162 exit (1); /* abort(); */
163 }
164
165 if (signo == SIGALRM)
166 pop3d_abquit (ERR_TIMEOUT);
167 pop3d_abquit (ERR_SIGNAL);
168 } 130 }
169 131
170 /* Gets a line of input from the client, caller should free() */ 132 /* Gets a line of input from the client, caller should free() */
......
...@@ -41,6 +41,10 @@ static struct option long_options[] = ...@@ -41,6 +41,10 @@ static struct option long_options[] =
41 const char *short_options ="d::hip:t:v"; 41 const char *short_options ="d::hip:t:v";
42 42
43 static int syslog_error_printer __P ((const char *fmt, va_list ap)); 43 static int syslog_error_printer __P ((const char *fmt, va_list ap));
44 static int pop3d_mainloop __P ((int, int));
45 static void pop3d_daemon_init __P ((void));
46 static void pop3d_daemon __P ((unsigned int, unsigned int));
47 static void pop3d_usage __P ((char *));
44 48
45 #ifndef DEFMAXCHILDREN 49 #ifndef DEFMAXCHILDREN
46 # define DEFMAXCHILDREN 10 /* Default maximum number of children */ 50 # define DEFMAXCHILDREN 10 /* Default maximum number of children */
...@@ -91,7 +95,7 @@ main (int argc, char **argv) ...@@ -91,7 +95,7 @@ main (int argc, char **argv)
91 95
92 case 'v': 96 case 'v':
93 printf (IMPL " ("PACKAGE " " VERSION ")\n"); 97 printf (IMPL " ("PACKAGE " " VERSION ")\n");
94 exit (0); 98 exit (EXIT_SUCCESS);
95 break; 99 break;
96 100
97 default: 101 default:
...@@ -104,13 +108,13 @@ main (int argc, char **argv) ...@@ -104,13 +108,13 @@ main (int argc, char **argv)
104 if (gr == NULL) 108 if (gr == NULL)
105 { 109 {
106 perror ("Error getting mail group"); 110 perror ("Error getting mail group");
107 exit (1); 111 exit (EXIT_FAILURE);
108 } 112 }
109 113
110 if (setgid (gr->gr_gid) == -1) 114 if (setgid (gr->gr_gid) == -1)
111 { 115 {
112 perror ("Error setting mail group"); 116 perror ("Error setting mail group");
113 exit (1); 117 exit (EXIT_FAILURE);
114 } 118 }
115 119
116 /* Register the desire formats. We only need Mbox mail format. */ 120 /* Register the desire formats. We only need Mbox mail format. */
...@@ -136,7 +140,7 @@ main (int argc, char **argv) ...@@ -136,7 +140,7 @@ main (int argc, char **argv)
136 if (mode == DAEMON) 140 if (mode == DAEMON)
137 pop3d_daemon_init (); 141 pop3d_daemon_init ();
138 142
139 /* Make sure that to be in the root directory. */ 143 /* Make sure we are in the root directory. */
140 chdir ("/"); 144 chdir ("/");
141 145
142 /* Set up for syslog. */ 146 /* Set up for syslog. */
...@@ -150,7 +154,7 @@ main (int argc, char **argv) ...@@ -150,7 +154,7 @@ main (int argc, char **argv)
150 /* Actually run the daemon. */ 154 /* Actually run the daemon. */
151 if (mode == DAEMON) 155 if (mode == DAEMON)
152 pop3d_daemon (maxchildren, port); 156 pop3d_daemon (maxchildren, port);
153 /* exit (0) -- no way out of daemon except a signal. */ 157 /* exit (EXIT_SUCCESS) -- no way out of daemon except a signal. */
154 else 158 else
155 status = pop3d_mainloop (fileno (stdin), fileno (stdout)); 159 status = pop3d_mainloop (fileno (stdin), fileno (stdout));
156 160
...@@ -160,7 +164,7 @@ main (int argc, char **argv) ...@@ -160,7 +164,7 @@ main (int argc, char **argv)
160 } 164 }
161 165
162 /* Sets things up for daemon mode. */ 166 /* Sets things up for daemon mode. */
163 void 167 static void
164 pop3d_daemon_init (void) 168 pop3d_daemon_init (void)
165 { 169 {
166 pid_t pid; 170 pid_t pid;
...@@ -169,10 +173,10 @@ pop3d_daemon_init (void) ...@@ -169,10 +173,10 @@ pop3d_daemon_init (void)
169 if (pid == -1) 173 if (pid == -1)
170 { 174 {
171 perror ("fork failed:"); 175 perror ("fork failed:");
172 exit (1); 176 exit (EXIT_FAILURE);
173 } 177 }
174 else if (pid > 0) 178 else if (pid > 0)
175 exit (0); /* Parent exits. */ 179 exit (EXIT_SUCCESS); /* Parent exits. */
176 180
177 setsid (); /* Become session leader. */ 181 setsid (); /* Become session leader. */
178 182
...@@ -184,10 +188,10 @@ pop3d_daemon_init (void) ...@@ -184,10 +188,10 @@ pop3d_daemon_init (void)
184 if (pid == -1) 188 if (pid == -1)
185 { 189 {
186 perror("fork failed:"); 190 perror("fork failed:");
187 exit (1); 191 exit (EXIT_FAILURE);
188 } 192 }
189 else if (pid > 0) 193 else if (pid > 0)
190 exit (0); /* Parent exits. */ 194 exit (EXIT_SUCCESS); /* Parent exits. */
191 195
192 /* Close inherited file descriptors. */ 196 /* Close inherited file descriptors. */
193 { 197 {
...@@ -217,7 +221,7 @@ pop3d_daemon_init (void) ...@@ -217,7 +221,7 @@ pop3d_daemon_init (void)
217 221
218 /* The main part of the daemon. This function reads input from the client and 222 /* The main part of the daemon. This function reads input from the client and
219 executes the proper functions. Also handles the bulk of error reporting. */ 223 executes the proper functions. Also handles the bulk of error reporting. */
220 int 224 static int
221 pop3d_mainloop (int infile, int outfile) 225 pop3d_mainloop (int infile, int outfile)
222 { 226 {
223 int status = OK; 227 int status = OK;
...@@ -377,7 +381,7 @@ pop3d_mainloop (int infile, int outfile) ...@@ -377,7 +381,7 @@ pop3d_mainloop (int infile, int outfile)
377 (default 110) then executes a pop3d_mainloop() upon accepting a connection. 381 (default 110) then executes a pop3d_mainloop() upon accepting a connection.
378 It starts maxchildren child processes to listen to and accept socket 382 It starts maxchildren child processes to listen to and accept socket
379 connections. */ 383 connections. */
380 void 384 static void
381 pop3d_daemon (unsigned int maxchildren, unsigned int port) 385 pop3d_daemon (unsigned int maxchildren, unsigned int port)
382 { 386 {
383 struct sockaddr_in server, client; 387 struct sockaddr_in server, client;
...@@ -389,7 +393,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port) ...@@ -389,7 +393,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
389 if (listenfd == -1) 393 if (listenfd == -1)
390 { 394 {
391 syslog (LOG_ERR, "socket: %s", strerror(errno)); 395 syslog (LOG_ERR, "socket: %s", strerror(errno));
392 exit (1); 396 exit (EXIT_FAILURE);
393 } 397 }
394 size = 1; /* Use size here to avoid making a new variable. */ 398 size = 1; /* Use size here to avoid making a new variable. */
395 setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size)); 399 setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size));
...@@ -402,13 +406,13 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port) ...@@ -402,13 +406,13 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
402 if (bind (listenfd, (struct sockaddr *)&server, size) == -1) 406 if (bind (listenfd, (struct sockaddr *)&server, size) == -1)
403 { 407 {
404 syslog (LOG_ERR, "bind: %s", strerror (errno)); 408 syslog (LOG_ERR, "bind: %s", strerror (errno));
405 exit (1); 409 exit (EXIT_FAILURE);
406 } 410 }
407 411
408 if (listen (listenfd, 128) == -1) 412 if (listen (listenfd, 128) == -1)
409 { 413 {
410 syslog (LOG_ERR, "listen: %s", strerror (errno)); 414 syslog (LOG_ERR, "listen: %s", strerror (errno));
411 exit (1); 415 exit (EXIT_FAILURE);
412 } 416 }
413 417
414 for (;;) 418 for (;;)
...@@ -425,7 +429,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port) ...@@ -425,7 +429,7 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
425 if (errno == EINTR) 429 if (errno == EINTR)
426 continue; 430 continue;
427 syslog (LOG_ERR, "accept: %s", strerror (errno)); 431 syslog (LOG_ERR, "accept: %s", strerror (errno));
428 exit (1); 432 exit (EXIT_FAILURE);
429 } 433 }
430 434
431 pid = fork (); 435 pid = fork ();
...@@ -447,6 +451,28 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port) ...@@ -447,6 +451,28 @@ pop3d_daemon (unsigned int maxchildren, unsigned int port)
447 } 451 }
448 } 452 }
449 453
454 /* Prints out usage information and exits the program */
455
456 static void
457 pop3d_usage (char *argv0)
458 {
459 printf ("Usage: %s [OPTIONS]\n", argv0);
460 printf ("Runs the GNU POP3 daemon.\n\n");
461 printf (" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum\n");
462 printf (" of MAXCHILDREN child processes\n");
463 printf (" -h, --help display this help and exit\n");
464 printf (" -i, --inetd runs in inetd mode (default)\n");
465 printf (" -p, --port=PORT specifies port to listen on, implies -d\n"
466 );
467 printf (" defaults to 110, which need not be specifi
468 ed\n");
469 printf (" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds\n");
470 printf (" TIMEOUT default is 600 (10 minutes)\n");
471 printf (" -v, --version display version information and exit\n");
472 printf ("\nReport bugs to bug-mailutils@gnu.org\n");
473 exit (EXIT_SUCCESS);
474 }
475
450 static int 476 static int
451 syslog_error_printer (const char *fmt, va_list ap) 477 syslog_error_printer (const char *fmt, va_list ap)
452 { 478 {
......
...@@ -175,31 +175,27 @@ extern FILE *ofile; ...@@ -175,31 +175,27 @@ extern FILE *ofile;
175 extern char *md5shared; 175 extern char *md5shared;
176 extern volatile size_t children; 176 extern volatile size_t children;
177 177
178 extern int pop3d_abquit __P ((int));
179 extern int pop3d_apop __P ((const char *));
180 extern char *pop3d_apopuser __P ((const char *));
181 extern char *pop3d_args __P ((const char *));
182 extern int pop3d_auth __P ((const char *));
183 extern int pop3d_capa __P ((const char *));
184 extern char *pop3d_cmd __P ((const char *));
178 extern int pop3d_dele __P ((const char *)); 185 extern int pop3d_dele __P ((const char *));
179 extern int pop3d_list __P ((const char *)); 186 extern int pop3d_list __P ((const char *));
187 extern int pop3d_lock __P ((void));
180 extern int pop3d_noop __P ((const char *)); 188 extern int pop3d_noop __P ((const char *));
181 extern int pop3d_quit __P ((const char *)); 189 extern int pop3d_quit __P ((const char *));
190 extern char *pop3d_readline __P ((FILE *));
182 extern int pop3d_retr __P ((const char *)); 191 extern int pop3d_retr __P ((const char *));
183 extern int pop3d_rset __P ((const char *)); 192 extern int pop3d_rset __P ((const char *));
193 extern RETSIGTYPE pop3d_sigchld __P ((int));
194 extern RETSIGTYPE pop3d_signal __P ((int));
184 extern int pop3d_stat __P ((const char *)); 195 extern int pop3d_stat __P ((const char *));
185 extern int pop3d_top __P ((const char *)); 196 extern int pop3d_top __P ((const char *));
197 extern int pop3d_touchlock __P ((void));
186 extern int pop3d_uidl __P ((const char *)); 198 extern int pop3d_uidl __P ((const char *));
187 extern int pop3d_user __P ((const char *)); 199 extern int pop3d_user __P ((const char *));
188 extern int pop3d_apop __P ((const char *));
189 extern int pop3d_auth __P ((const char *));
190 extern int pop3d_capa __P ((const char *));
191 extern char *pop3d_args __P ((const char *));
192 extern char *pop3d_cmd __P ((const char *));
193 extern int pop3d_abquit __P ((int));
194 extern int pop3d_lock __P ((void));
195 extern int pop3d_touchlock __P ((void));
196 extern int pop3d_unlock __P ((void)); 200 extern int pop3d_unlock __P ((void));
197 extern int pop3d_mainloop __P ((int, int));
198 extern void pop3d_daemon __P ((size_t, unsigned int));
199 extern void pop3d_usage __P ((char *));
200 extern RETSIGTYPE pop3d_signal __P ((int));
201 extern RETSIGTYPE pop3d_sigchld __P ((int));
202 extern void pop3d_daemon_init __P ((void));
203 extern char *pop3d_apopuser __P ((const char *));
204 extern char *pop3d_readline __P ((FILE *));
205 #endif /* _POP3D_H */ 201 #endif /* _POP3D_H */
......
...@@ -32,3 +32,21 @@ pop3d_sigchld (int signo) ...@@ -32,3 +32,21 @@ pop3d_sigchld (int signo)
32 signal (signo, pop3d_sigchld); 32 signal (signo, pop3d_sigchld);
33 #endif 33 #endif
34 } 34 }
35
36 /* Default signal handler to call the pop3d_abquit() function */
37
38 RETSIGTYPE
39 pop3d_signal (int signo)
40 {
41 syslog (LOG_CRIT, "got signal %d", signo);
42 /* Master process. */
43 if (!ofile)
44 {
45 syslog (LOG_CRIT, "MASTER: exiting on signal");
46 exit (EXIT_FAILURE); /* abort(); */
47 }
48
49 if (signo == SIGALRM)
50 pop3d_abquit (ERR_TIMEOUT);
51 pop3d_abquit (ERR_SIGNAL);
52 }
......