initial work on fork() rewrite
Showing
3 changed files
with
101 additions
and
71 deletions
1 | Sean 'Shaleh' Perry <shaleh@debian.org> Mon, 4 Oct 1999 17:57:17 -0700 | ||
2 | |||
3 | * initial fork() rewrite, not even compiled it yet | ||
4 | |||
1 | Sean 'Shaleh' Perry <shaleh@debian.org> Mon, 4 Oct 1999 14:28:35 -0700 | 5 | Sean 'Shaleh' Perry <shaleh@debian.org> Mon, 4 Oct 1999 14:28:35 -0700 |
2 | 6 | ||
3 | * changed lock(int mode) to lock(mailbox_lock_t mode), this will allow | 7 | * changed lock(int mode) to lock(mailbox_lock_t mode), this will allow | ... | ... |
... | @@ -79,7 +79,7 @@ pop3_cmd (const char *cmd) | ... | @@ -79,7 +79,7 @@ pop3_cmd (const char *cmd) |
79 | return buf; | 79 | return buf; |
80 | } | 80 | } |
81 | 81 | ||
82 | /* This is called if GNU POP needs to quit without going to the UPDATE stage. | 82 | /* This is called if GNU POP3 needs to quit without going to the UPDATE stage. |
83 | This is used for conditions such as out of memory, a broken socket, or | 83 | This is used for conditions such as out of memory, a broken socket, or |
84 | being killed on a signal */ | 84 | being killed on a signal */ |
85 | 85 | ||
... | @@ -115,6 +115,7 @@ pop3_abquit (int reason) | ... | @@ -115,6 +115,7 @@ pop3_abquit (int reason) |
115 | break; | 115 | break; |
116 | } | 116 | } |
117 | fflush (ofile); | 117 | fflush (ofile); |
118 | closelog(); | ||
118 | exit (1); | 119 | exit (1); |
119 | } | 120 | } |
120 | 121 | ||
... | @@ -145,11 +146,7 @@ void | ... | @@ -145,11 +146,7 @@ void |
145 | pop3_signal (int signal) | 146 | pop3_signal (int signal) |
146 | { | 147 | { |
147 | if (signal == SIGCHLD) | 148 | if (signal == SIGCHLD) |
148 | { | 149 | --children; |
149 | int stat; | ||
150 | while (waitpid (-1, &stat, WNOHANG) > 0); | ||
151 | return; | ||
152 | } | ||
153 | else | 150 | else |
154 | pop3_abquit (ERR_SIGNAL); | 151 | pop3_abquit (ERR_SIGNAL); |
155 | } | 152 | } |
... | @@ -170,7 +167,7 @@ pop3_readline (int fd) | ... | @@ -170,7 +167,7 @@ pop3_readline (int fd) |
170 | tv.tv_usec = 0; | 167 | tv.tv_usec = 0; |
171 | memset (buf, '\0', 1024); | 168 | memset (buf, '\0', 1024); |
172 | 169 | ||
173 | while (strchr (buf, '\n') == NULL) | 170 | do |
174 | { | 171 | { |
175 | if (timeout > 0) | 172 | if (timeout > 0) |
176 | { | 173 | { |
... | @@ -193,5 +190,7 @@ pop3_readline (int fd) | ... | @@ -193,5 +190,7 @@ pop3_readline (int fd) |
193 | strcat (ret, buf); | 190 | strcat (ret, buf); |
194 | } | 191 | } |
195 | } | 192 | } |
193 | while (strchr (buf, '\n') == NULL); | ||
194 | |||
196 | return ret; | 195 | return ret; |
197 | } | 196 | } | ... | ... |
... | @@ -17,6 +17,10 @@ | ... | @@ -17,6 +17,10 @@ |
17 | 17 | ||
18 | #include "pop3d.h" | 18 | #include "pop3d.h" |
19 | 19 | ||
20 | typedef struct sockaddr_in SA; | ||
21 | unsigned int children = 0; | ||
22 | #define strorepid(foo) /* will add more code here later */ | ||
23 | |||
20 | static struct option long_options[] = | 24 | static struct option long_options[] = |
21 | { | 25 | { |
22 | {"daemon", 2, 0, 'd'}, | 26 | {"daemon", 2, 0, 'd'}, |
... | @@ -32,7 +36,7 @@ int | ... | @@ -32,7 +36,7 @@ int |
32 | main (int argc, char **argv) | 36 | main (int argc, char **argv) |
33 | { | 37 | { |
34 | struct group *gr; | 38 | struct group *gr; |
35 | static int mode; | 39 | static int mode = INTERACTIVE; |
36 | int maxchildren = 10; | 40 | int maxchildren = 10; |
37 | int option_index = 0; | 41 | int option_index = 0; |
38 | int c = 0; | 42 | int c = 0; |
... | @@ -47,6 +51,8 @@ main (int argc, char **argv) | ... | @@ -47,6 +51,8 @@ main (int argc, char **argv) |
47 | case 'd': | 51 | case 'd': |
48 | mode = DAEMON; | 52 | mode = DAEMON; |
49 | maxchildren = optarg ? atoi (optarg) : 10; | 53 | maxchildren = optarg ? atoi (optarg) : 10; |
54 | if (maxchildren <= 0) | ||
55 | maxchildren = 10; | ||
50 | break; | 56 | break; |
51 | case 'h': | 57 | case 'h': |
52 | pop3_usage (argv[0]); | 58 | pop3_usage (argv[0]); |
... | @@ -113,18 +119,11 @@ main (int argc, char **argv) | ... | @@ -113,18 +119,11 @@ main (int argc, char **argv) |
113 | umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ | 119 | umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ |
114 | 120 | ||
115 | /* Actually run the daemon */ | 121 | /* Actually run the daemon */ |
116 | switch (mode) | 122 | if (mode == DAEMON) |
117 | { | ||
118 | case DAEMON: | ||
119 | if (maxchildren < 10) | ||
120 | maxchildren = 10; | ||
121 | pop3_daemon (maxchildren); | 123 | pop3_daemon (maxchildren); |
122 | break; | 124 | /* exit() -- no way out of daemon except a signal */ |
123 | case INTERACTIVE: | 125 | else |
124 | default: | ||
125 | pop3_mainloop (fileno (stdin), fileno (stdout)); | 126 | pop3_mainloop (fileno (stdin), fileno (stdout)); |
126 | break; | ||
127 | } | ||
128 | 127 | ||
129 | /* Close the syslog connection and exit */ | 128 | /* Close the syslog connection and exit */ |
130 | closelog (); | 129 | closelog (); |
... | @@ -136,19 +135,36 @@ main (int argc, char **argv) | ... | @@ -136,19 +135,36 @@ main (int argc, char **argv) |
136 | void | 135 | void |
137 | pop3_daemon_init (void) | 136 | pop3_daemon_init (void) |
138 | { | 137 | { |
139 | if (fork ()) | 138 | pid_t pid; |
140 | exit (0); /* parent exits */ | 139 | unsigned int i; |
140 | #define MAXFD 64 | ||
141 | |||
142 | pid = fork(); | ||
143 | if (pid == -1) | ||
144 | { | ||
145 | perror(errno); | ||
146 | exit (-1); | ||
147 | } | ||
148 | else if (pid > 0) | ||
149 | exit (0); /* parent exits */ | ||
150 | |||
141 | setsid (); /* become session leader */ | 151 | setsid (); /* become session leader */ |
142 | 152 | ||
143 | if (fork ()) | 153 | signal (SIGHUP, SIG_IGN); /* ignore SIGHUP */ |
144 | exit (0); /* new parent exits */ | ||
145 | 154 | ||
155 | pid = fork(); | ||
156 | if (pid == -1) | ||
157 | { | ||
158 | perror(errno); | ||
159 | exit (-1); | ||
160 | } | ||
161 | else if (pid > 0) | ||
162 | exit (0); /* parent exits */ | ||
163 | |||
146 | /* close inherited file descriptors */ | 164 | /* close inherited file descriptors */ |
147 | close (0); | 165 | for (i = 0; i < MAXFD; ++i) |
148 | close (1); | 166 | close(i); |
149 | close (2); | ||
150 | 167 | ||
151 | signal (SIGHUP, SIG_IGN); /* ignore SIGHUP */ | ||
152 | signal (SIGCHLD, pop3_signal); /* for forking */ | 168 | signal (SIGCHLD, pop3_signal); /* for forking */ |
153 | } | 169 | } |
154 | 170 | ||
... | @@ -208,6 +224,10 @@ pop3_mainloop (int infile, int outfile) | ... | @@ -208,6 +224,10 @@ pop3_mainloop (int infile, int outfile) |
208 | status = ERR_TOO_LONG; | 224 | status = ERR_TOO_LONG; |
209 | else if (strlen (cmd) > 4) | 225 | else if (strlen (cmd) > 4) |
210 | status = ERR_BAD_CMD; | 226 | status = ERR_BAD_CMD; |
227 | else if (strncasecmp (cmd, "RETR", 4) == 0) | ||
228 | status = pop3_retr (arg); | ||
229 | else if (strncasecmp (cmd, "DELE", 4) == 0) | ||
230 | status = pop3_dele (arg); | ||
211 | else if (strncasecmp (cmd, "USER", 4) == 0) | 231 | else if (strncasecmp (cmd, "USER", 4) == 0) |
212 | status = pop3_user (arg); | 232 | status = pop3_user (arg); |
213 | else if (strncasecmp (cmd, "QUIT", 4) == 0) | 233 | else if (strncasecmp (cmd, "QUIT", 4) == 0) |
... | @@ -220,10 +240,6 @@ pop3_mainloop (int infile, int outfile) | ... | @@ -220,10 +240,6 @@ pop3_mainloop (int infile, int outfile) |
220 | status = pop3_stat (arg); | 240 | status = pop3_stat (arg); |
221 | else if (strncasecmp (cmd, "LIST", 4) == 0) | 241 | else if (strncasecmp (cmd, "LIST", 4) == 0) |
222 | status = pop3_list (arg); | 242 | status = pop3_list (arg); |
223 | else if (strncasecmp (cmd, "RETR", 4) == 0) | ||
224 | status = pop3_retr (arg); | ||
225 | else if (strncasecmp (cmd, "DELE", 4) == 0) | ||
226 | status = pop3_dele (arg); | ||
227 | else if (strncasecmp (cmd, "NOOP", 4) == 0) | 243 | else if (strncasecmp (cmd, "NOOP", 4) == 0) |
228 | status = pop3_noop (arg); | 244 | status = pop3_noop (arg); |
229 | else if (strncasecmp (cmd, "RSET", 4) == 0) | 245 | else if (strncasecmp (cmd, "RSET", 4) == 0) |
... | @@ -255,6 +271,8 @@ pop3_mainloop (int infile, int outfile) | ... | @@ -255,6 +271,8 @@ pop3_mainloop (int infile, int outfile) |
255 | fprintf (ofile, "-ERR [IN-USE] " MBOX_LOCK "\r\n"); | 271 | fprintf (ofile, "-ERR [IN-USE] " MBOX_LOCK "\r\n"); |
256 | else if (status == ERR_TOO_LONG) | 272 | else if (status == ERR_TOO_LONG) |
257 | fprintf (ofile, "-ERR " TOO_LONG "\r\n"); | 273 | fprintf (ofile, "-ERR " TOO_LONG "\r\n"); |
274 | else | ||
275 | fprintf (ofile, "-ERR unknown error\r\n"); | ||
258 | 276 | ||
259 | free (buf); | 277 | free (buf); |
260 | free (cmd); | 278 | free (cmd); |
... | @@ -265,58 +283,67 @@ pop3_mainloop (int infile, int outfile) | ... | @@ -265,58 +283,67 @@ pop3_mainloop (int infile, int outfile) |
265 | return OK; | 283 | return OK; |
266 | } | 284 | } |
267 | 285 | ||
268 | /* Runs GNU POP in standalone daemon mode. This opens and binds to a port | 286 | /* Runs GNU POP3 in standalone daemon mode. This opens and binds to a port |
269 | (default 110) then executes a pop3_mainloop() upon accepting a connection. | 287 | (default 110) then executes a pop3_mainloop() upon accepting a connection. |
270 | It starts maxchildren child processes to listen to and accept socket | 288 | It starts maxchildren child processes to listen to and accept socket |
271 | connections */ | 289 | connections */ |
272 | 290 | ||
273 | int | 291 | void |
274 | pop3_daemon (int maxchildren) | 292 | pop3_daemon (unsigned int maxchildren) |
275 | { | 293 | { |
276 | int children = 0; | 294 | SA server, client; |
277 | struct sockaddr_in client; | 295 | pid_t pid; |
278 | int sock, sock2; | 296 | int listenfd, connfd; |
279 | unsigned int socksize; | ||
280 | 297 | ||
281 | sock = socket (PF_INET, SOCK_STREAM, (getprotobyname ("tcp"))->p_proto); | 298 | if ( (listenfd = socket (AF_INET, SOCK_STREAM, 0)) == -1 ) |
282 | if (sock < 0) | ||
283 | { | 299 | { |
284 | syslog (LOG_ERR, "%s\n", strerror (errno)); | 300 | syslog (LOG_ERR, "socket: %s", strerror(errno)); |
285 | exit (1); | 301 | exit (-1); |
286 | } | 302 | } |
287 | memset (&client, 0, sizeof (struct sockaddr_in)); | 303 | memset (&server, 0, sizeof(server)); |
288 | client.sin_family = AF_INET; | 304 | server.sin_family = AF_INET; |
289 | client.sin_port = htons (port); | 305 | server.sin_addr.s_addr = htonl (INADDR_ANY); |
290 | client.sin_addr.s_addr = htonl (INADDR_ANY); | 306 | server.sin_port = htonl (port); |
291 | socksize = sizeof (client); | 307 | |
292 | if (bind (sock, (struct sockaddr *) &client, socksize)) | 308 | if (bind(listenfd, (SA *) &server, sizeof(server)) == -1 ) |
293 | { | 309 | { |
294 | perror ("Couldn't bind to socket"); | 310 | syslog(LOG_ERR, "bind: %s", strerror(errno)); |
295 | exit (1); | 311 | exit(-1); |
296 | } | 312 | } |
297 | listen (sock, 128); | 313 | |
298 | while (1) | 314 | if (listen(listenfd, 128) == -1) |
299 | { | 315 | { |
300 | if (children < maxchildren) | 316 | syslog(LOG_ERR, "listen: %s", strerror(errno)); |
301 | { | 317 | exit(-1); |
302 | if (!fork ()) | 318 | } |
303 | { | 319 | |
304 | sock2 = accept (sock, &client, &socksize); | 320 | for ( ; ; ) |
305 | pop3_mainloop (sock2, sock2); | 321 | { |
306 | close (sock2); | 322 | if (children > maxchildren) |
307 | exit (OK); | 323 | { |
308 | } | 324 | pause(); |
309 | else | 325 | continue; |
310 | { | 326 | } |
311 | /* wait (NULL); */ | 327 | if ( (connfd = accept(listenfd, (SA *) &client, sizeof(client))) == -1) |
312 | children++; | 328 | { |
313 | } | 329 | syslog(LOG_ERR, "accept: %s", strerror(errno)); |
314 | } | 330 | exit(-1); |
331 | } | ||
332 | |||
333 | pid = fork(); | ||
334 | if (pid == -1) | ||
335 | syslog(LOG_ERR, "fork: %s", strerror(errno)); | ||
336 | else if(pid == 0) /* child */ | ||
337 | { | ||
338 | close(listenfd); | ||
339 | pop3_mainloop(connfd, connfd); | ||
340 | } | ||
315 | else | 341 | else |
316 | { | 342 | { |
317 | wait (NULL); | 343 | storepid(pid); |
318 | children--; | 344 | ++children; |
319 | } | 345 | } |
346 | |||
347 | close(connfd); | ||
320 | } | 348 | } |
321 | return OK; | ||
322 | } | 349 | } | ... | ... |
-
Please register or sign in to post a comment