Commit fdc6161f fdc6161fe5e259ea7b1687e67abbed4fa0107eba by Sean 'Shaleh' Perry

initial work on fork() rewrite

1 parent 2957e3e3
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 }
......