Finally!!!! I can use the GNU imap4d with Netscape .... It kinda work 8-)
sigh ... still more to do.
Showing
22 changed files
with
761 additions
and
264 deletions
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 | } | ... | ... |
-
Please register or sign in to post a comment