Coding style fix.
[uftps.git] / uftps.c
blob74cfff7af4b1efe87ace168ce198d350a589229f
1 /*
2 * User FTP Server
3 * Author : C2H5OH
4 * License: GPL v2
6 * uftps.c - main
8 * Main program. Opens the command port until a client requests a connection.
9 * Then the server is forked the child will manage all that client's requests.
11 * Attending multiple clients is necessary to allow some clients (like lftp(1))
12 * perform multiple concurrent jops. Like moving current transfer to de
13 * background and then browse through directories.
15 * Also note that here the root directory is fixed. As we can't protect with
16 * chroot(), due to de lack of privilege, we must do a series of safety checks
17 * to simulate that behaviour. Because of this, some strong restrictions have
18 * arised; which could reduce de number of FTP clients compatible with this
19 * server.
22 #include "uftps.h"
25 * clid_finish
27 * Reaper function. For "zombies".
29 static void child_finish (int sig)
31 while (waitpid(-1, NULL, WNOHANG) > 0)
32 debug_msg("- Collecting children.\n");
37 * end
39 * End. What where you expecting?
41 static void end (int sig)
43 printf("(%d) Signal caught, exiting...\n", getpid());
44 exit(EXIT_SUCCESS);
48 /*** MAIN ***/
49 int main (int argc, char **argv)
51 int bind_sk, cmd_sk, err, yes = 1;
52 unsigned short port = 0;
53 struct sockaddr_in saddr;
54 struct sigaction my_sa;
56 setlinebuf(stderr);
57 setlinebuf(stdout);
59 if (argc > 1)
60 port = (unsigned short) atoi(argv[1]);
62 /* Fixate root directory */
63 Basedir = getcwd(NULL, 0);
64 if (Basedir == NULL)
65 fatal("Could not retrieve working directory");
66 Basedir_len = strlen(Basedir);
67 debug_msg("Working directory is: %s (strlen = %d)\n", Basedir,
68 Basedir_len);
70 /* Signal handling */
71 sigfillset(&my_sa.sa_mask);
72 my_sa.sa_flags = SA_RESTART;
73 my_sa.sa_handler = child_finish;
74 sigaction(SIGCHLD, &my_sa, NULL);
76 my_sa.sa_flags = SA_NOMASK;
77 my_sa.sa_handler = end;
78 sigaction(SIGINT, &my_sa, NULL);
80 /* Connection handling */
81 saddr.sin_family = AF_INET;
82 saddr.sin_port = htons(port > 1024 ? port : DEFAULT_PORT);
83 saddr.sin_addr.s_addr = INADDR_ANY;
85 bind_sk = socket(PF_INET, SOCK_STREAM, 0);
86 if (bind_sk == -1)
87 fatal("Could not create socket");
89 setsockopt(bind_sk, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
90 err = bind(bind_sk, (struct sockaddr *) &saddr, sizeof(saddr));
91 if (err == -1)
92 fatal("Could not bind socket");
94 err = listen(bind_sk, 5);
95 if (err == -1)
96 fatal("Could not listen at socket");
98 printf("UFTPS listening on port %d (TCP). Use CTRL+C to finish.\n\n",
99 (port > 1024 ? port : DEFAULT_PORT));
100 printf("If you want to use a different port use:\n"
101 "\t%s <port>\n\n"
102 "Where port must be between 1025 and 65535.\n", argv[0]);
104 #if 0
105 /* It's nearly impossible, to my knowledge, debug a program that forks.
106 * First try to find the error using the debug_msg() facility. Then, if
107 * you really need to use a debugger, then replace the 0 with a 1 to
108 * compile this code. But remember you won't be able to serve multiple
109 * connections */
111 cmd_sk = accept(bind_sk, (struct sockaddr *) &saddr,
112 (socklen_t *) &yes);
113 if (cmd_sk == -1)
114 fatal("could not open command connection");
116 init_session(cmd_sk);
117 command_loop();
118 return EXIT_SUCCESS;
119 #endif
121 /* Main loop (accepting connections) */
122 while (1) {
123 cmd_sk = accept(bind_sk, (struct sockaddr *) &saddr,
124 (socklen_t *) &yes);
125 if (cmd_sk == -1) {
126 if (errno == EINTR)
127 continue;
128 else
129 fatal("Could not open command connection");
131 if (fork() == 0) {
132 /* Child */
133 close(bind_sk);
134 init_session(cmd_sk);
135 command_loop();
136 } else {
137 /* Parent */
138 close(cmd_sk);
141 return EXIT_SUCCESS;