]> git.sesse.net Git - betaftpd/blob - ftpd.c
Fixed a few problems reported by Valgrind (still not sure if BetaFTPD is totally...
[betaftpd] / ftpd.c
1 /*  ftpd.c: BetaFTPD main
2     Copyright (C) 1999-2000 Steinar H. Gunderson
3
4     This program is is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License, version 2 of the
6     License as published by the Free Software Foundation.
7
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12
13     You should have received a copy of the GNU General Public License
14     along with this program; if not, write to the Free Software
15     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 */
17
18 /*
19  * Special note: this file has been overwritten by another (0-byte) file, been
20  * through the dead, and restored (with the help of dd, grep, gpm, vi and less)
21  * with a sucess rate of 99.9%. Show it a little respect -- don't add junk
22  * to it. :-)
23  */
24
25 #define _GNU_SOURCE
26
27 #if HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #if HAVE_ERRNO_H
32 #include <errno.h>
33 #endif
34
35 #if HAVE_STROPTS_H
36 #include <stropts.h>
37 #endif
38
39 #if HAVE_SYS_TYPES_H
40 #include <sys/types.h>
41 #endif
42
43 #if HAVE_SYS_CONF_H
44 #include <sys/conf.h>
45 #endif
46
47 #if HAVE_FCNTL_H
48 #include <fcntl.h>
49 #endif
50
51 #if HAVE_STDIO_H
52 #include <stdio.h>
53 #endif
54
55 #if HAVE_ASSERT_H
56 #include <assert.h>
57 #endif
58
59 #if HAVE_STRING_H
60 #include <string.h>
61 #endif
62
63 #if HAVE_STRINGS_H
64 #include <strings.h>
65 #endif
66
67 #if HAVE_STDARG_H
68 #include <stdarg.h>
69 #endif
70
71 #if HAVE_STDLIB_H
72 #include <stdlib.h>
73 #endif
74
75 #if HAVE_UNISTD_H
76 #include <unistd.h>
77 #endif
78
79 #if HAVE_NETINET_IN_SYSTM_H
80 #include <netinet/in_systm.h>
81 #endif
82
83 #if HAVE_NETINET_IN_H
84 #include <netinet/in.h>
85 #endif
86
87 #if HAVE_NETINET_IP_H
88 #include <netinet/ip.h>
89 #endif
90
91 #if HAVE_NETINET_TCP_H
92 #include <netinet/tcp.h>
93 #endif
94
95 #if HAVE_ARPA_INET_H
96 #include <arpa/inet.h>
97 #endif
98
99 #if HAVE_SYS_STAT_H
100 #include <sys/stat.h>
101 #endif
102
103 #if HAVE_SYS_IOCTL_H
104 #include <sys/ioctl.h>
105 #endif
106
107 #if HAVE_LINUX_SOCKET_H
108 #include <linux/socket.h>
109 #endif
110
111 #if HAVE_LINUX_TCP_H
112 #include <linux/tcp.h>
113 #endif
114
115 #if HAVE_MMAP
116 #include <sys/mman.h>
117 #endif
118
119 #if HAVE_TIME_H
120 #include <time.h>
121 #endif
122
123 #if HAVE_SYS_TIME_H
124 #include <sys/time.h>
125 #endif
126
127 #if HAVE_SYS_TIME_H
128 #include <sys/time.h>
129 #endif
130
131 #if HAVE_SYS_FILIO_H
132 #include <sys/filio.h>
133 #endif
134
135 #if HAVE_NETDB_H
136 #include <netdb.h>
137 #endif
138
139 #if HAVE_SIGNAL_H
140 #include <signal.h>
141 #endif
142
143 #if HAVE_GLOB_H
144 #include <glob.h>
145 #endif
146
147 #if HAVE_SYS_SIGNAL_H
148 #include <sys/signal.h>
149 #endif
150
151 #if HAVE_SYS_POLL_H
152 #include <sys/poll.h>
153 #endif
154
155 #if HAVE_SYS_SENDFILE_H
156 #include <sys/sendfile.h>
157 #endif
158
159 /*
160  * <linux/socket.h> does not export this to glibc2 systems, and it isn't
161  * always defined anywhere else.
162  */
163 #if !defined(TCP_CORK) && defined(__linux__)
164 #define TCP_CORK 3
165 #endif
166
167 #include <ftpd.h>
168 #include <cmds.h>
169
170 #if WANT_ASCII
171 #include <ascii.h>
172 #endif
173
174 #if WANT_DCACHE
175 #include <dcache.h>
176 #endif
177
178 #ifndef MAP_FAILED
179 #define MAP_FAILED -1
180 #endif
181
182 struct conn *first_conn = NULL;
183 struct ftran *first_ftran = NULL;
184 #if WANT_DCACHE
185 struct dcache *first_dcache = NULL;
186 #endif
187 char message_buf[512];
188
189 #if HAVE_POLL
190 unsigned int highest_fds = 0;
191
192 #define FD_MAX 1024
193 #define fds_send fds
194 struct pollfd fds[FD_MAX];
195
196 #define MAXCLIENTS FD_MAX
197 #else
198 fd_set master_fds, master_send_fds;
199 #define MAXCLIENTS FD_SETSIZE
200 #endif
201
202 #if WANT_XFERLOG
203 FILE *xferlog = NULL;
204 #endif
205
206 #if HAVE_LINUX_SENDFILE || HAVE_BSD_SENDFILE
207 int sendfile_supported = 1;
208 #endif
209
210 /*
211  * This variable specifies if it's soon time to check for timed out
212  * clients, and timed out directory listing cache entries. It is
213  * set to 1 by a signal handler every minute, and set to 0 when the
214  * checking has been performed.
215  */
216 int time_to_check = 1;
217
218 #ifndef HAVE_SPRINTF
219 /*
220  * snprintf():  snprintf() replacement for systems that miss it. Note
221  *              that this implementation does _not_ necessarily protect
222  *              against all buffer overflows. Get a real snprintf() in
223  *              your C library. That being said, the 8k limit is
224  *              substantially larger than any other string in BetaFTPD,
225  *              which should make such an attack harder.
226  */
227 int snprintf(char *str, size_t n, const char *format, ...)
228 {
229         char buf[8192];
230         va_list args;
231         int err;
232
233         va_start(args, format);
234         err = vsprintf(buf, format, args);
235         va_end(args);
236
237         buf[(int)n] = 0;
238         strcpy(str, buf);
239
240         return err;
241 }
242 #endif
243
244 #ifndef HAVE_VSNPRINTF
245 /*
246  * vsnprintf:   vsnprintf() replacement for systems that miss it. Please
247  *              see snprintf (above) for more information.
248  */
249 int vsnprintf(char *str, size_t n, const char *format, va_list ap)
250 {
251         char buf[8192];
252         int err;
253
254         err = vsprintf(buf, format, ap);
255         buf[(int)n] = 0;
256         strcpy(str, buf);
257         return err;
258 }
259 #endif
260
261 /*
262  * add_fd():    Add an fd to the set we monitor. Return 0 on success.
263  *              This code is shared between poll() and select() versions.
264  */
265 int add_fd(const int fd, const int events)
266 {
267 #if HAVE_POLL
268         if (fd >= FD_MAX) {
269                 printf("add_fd(%d, %x): failed\n", fd, events);
270                 return E2BIG;
271         }
272
273         fds[fd].fd = fd;
274         fds[fd].events = events;
275         if (highest_fds < fd) 
276                 highest_fds = fd;
277 #else 
278         if (fd >= FD_SETSIZE)
279                 return E2BIG;
280         if (events & POLLIN)
281                 FD_SET(fd, &master_fds);
282         if (events & POLLOUT)
283                 FD_SET(fd, &master_send_fds);
284 #endif
285         return 0;
286 }
287
288 /*
289  * del_fd():    Close and remove an fd from the set(s) we monitor. (See also add_fd().)
290  */
291 void del_fd(const int fd)
292 {
293 #if HAVE_POLL
294         if (fd >= FD_MAX)
295                 return;
296
297         fds[fd].fd = -1;
298         fds[fd].events = 0;
299
300         /* Reduce poll()'s workload by not making it watch past end of array */
301         while ((highest_fds > 0) && (fds[highest_fds].fd == -1))
302                 highest_fds--;
303 #else 
304         if (fd >= FD_SETSIZE)
305                 return;
306         FD_CLR(fd, &master_fds);
307         FD_CLR(fd, &master_send_fds);
308 #endif
309
310         close(fd);
311 }
312
313 #if 0
314 void list_clients()
315 {
316         struct conn *c = first_conn;
317         printf("list_clients:\n");
318         while (c && c->next_conn) {
319                 c = c->next_conn;
320                 printf("list_clients: fd %d\n", c->sock);
321         }
322 }
323 #endif
324
325 /*
326  * add_to_linked_list():
327  *              Inserts an element (conn, ftran or dcache) into its linked list.
328  *              The list is placed at the beginning, right after the (bogus)
329  *              first element of the list.
330  */
331 void add_to_linked_list(struct list_element * const first,
332                         struct list_element * const elem)
333 {
334         elem->prev = first;
335
336         if (first) {
337                 elem->next = first->next;
338                 if (elem->next) elem->next->prev = elem;
339                 first->next = elem;
340         } else {
341                 /* this is the bogus head of the list */
342                 elem->next = NULL;
343         }
344 }
345
346 /*
347  * remove_from_linked_list():
348  *              Removes an element (conn, ftran or dcache) from its linked list,
349  *              then frees it.
350  */
351 void remove_from_linked_list(struct list_element * const elem)
352 {
353         if (elem->prev != NULL) elem->prev->next = elem->next;
354         if (elem->next != NULL) elem->next->prev = elem->prev;
355         free(elem);
356 }
357
358 /*
359  * alloc_new_conn():
360  *              Allocates a new control connection (type `struct conn'),
361  *              initializes it, and adds it to the linked list. The connection
362  *              operates on the socket SOCK.
363  */
364 struct conn *alloc_new_conn(const int sock)
365 {
366         const unsigned int one = 1;
367         struct conn *c = (struct conn *)(malloc(sizeof(struct conn)));
368
369         if (c == NULL) return NULL;
370
371         if (sock != -1) {
372                 ioctl(sock, FIONBIO, &one);
373                 if (add_fd(sock, POLLIN) != 0) {
374                         /* temp unavail */
375                         send(sock, "230 Server too busy, please try again later.\r\n", 46, 0);
376                         close(sock);
377                         return NULL;
378                 }
379
380                 add_to_linked_list((struct list_element *)first_conn,
381                                    (struct list_element *)c);
382         } else {
383                 /* this is the bogus head of the list */
384                 c->next_conn = NULL;
385                 c->prev_conn = NULL;
386         }
387
388         c->transfer = NULL;
389         c->sock = sock;
390         c->buf_len = c->auth = c->rest_pos = 0;
391 #if WANT_ASCII
392         c->ascii_mode = 0;
393 #endif
394         c->free_me = 0;
395
396         /*
397          * equals:
398          * strcpy(c->curr_dir, "/");
399          * strcpy(c->last_cmd, "");
400          * strcpy(c->rename_from, "")
401          */
402         c->curr_dir[0] = '/';
403 #if WANT_FULLSCREEN
404         c->curr_dir[1] = c->last_cmd[0] = c->rename_from[0] = '\0';
405 #else
406         c->curr_dir[1] = c->rename_from[0] = '\0';
407 #endif
408
409         time(&(c->last_transfer));
410
411         /* list_clients(); */
412
413         return c;
414 }
415
416 /*
417  * alloc_new_ftran():
418  *              Allocates a new data connection (type `struct ftran'), and
419  *              adds it to the linked list. The connection operates on the
420  *              socket SOCK, and has the control connection C as its parent.
421  */
422 struct ftran *alloc_new_ftran(const int sock, const struct conn * const c)
423 {
424         struct ftran *f = (struct ftran *)(malloc(sizeof(struct ftran)));
425
426         if (f == NULL) return f;
427         if (c == NULL) {
428                 /* this is the bogus head of the list */
429                 f->next_ftran = NULL;
430                 f->prev_ftran = NULL;
431         } else {
432                 add_to_linked_list((struct list_element *)first_ftran,
433                                    (struct list_element *)f);
434         }
435
436 #if HAVE_MMAP
437         f->file_data = NULL;
438 #endif
439         f->owner = (struct conn * const)c;
440         f->sock = sock;
441         f->state = 0;
442         f->local_file = -1;
443
444 #if WANT_DCACHE
445         f->dir_cache = NULL;
446 #endif
447
448         f->dir_listing = 0;
449         f->upload = 0;
450         return f;
451 }
452
453 /*
454  * destroy_conn():
455  *              Destroy a control connection, remove it from the linked
456  *              list, and clean up after it.
457  */
458 void destroy_conn(struct conn * const c)
459 {
460         if (c == NULL) return;
461         del_fd(c->sock);
462
463         destroy_ftran(c->transfer);
464         remove_from_linked_list((struct list_element *)c);
465 }
466
467 /*
468  * destroy_ftran():
469  *              Destroy a data connection, remove it from the linked list,
470  *              and clean up after it.
471  *
472  *              For some reason, TCP_CORK (Linux 2.2.x-only) doesn't flush
473  *              even _after_ the socket is closed, so we zero it just before
474  *              closing. We also zero just before sending the last packet,
475  *              as it seems to be needed on some systems.
476  *
477  *              If you wonder why I check for `defined(SOL_TCP)' and don't
478  *              provide an alternative, see the comments on init_file_transfer().
479  */
480 void destroy_ftran(struct ftran * const f)
481 {
482         const unsigned int zero = 0;
483
484         if (f == NULL) return;
485 #if defined(TCP_CORK) && defined(SOL_TCP)
486         setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));
487 #endif
488         del_fd(f->sock);
489
490 #if WANT_DCACHE
491         if (f->dir_cache) {
492                 time(&(f->dir_cache->last_used));
493                 f->dir_cache->use_count--;
494                 f->dir_cache = NULL;
495         } else
496 #endif
497 #if HAVE_MMAP
498                 if (f->file_data) {
499                         if (f->dir_listing) {
500                                 free(f->file_data);
501                                 f->file_data = NULL;
502                         } else {
503                                 munmap(f->file_data, f->size);
504                         }
505                 }
506
507         if (!f->dir_listing)
508 #endif
509                 if (f->local_file != -1) close(f->local_file);
510
511 #if !HAVE_MMAP
512         if (f->dir_listing) unlink(f->filename);
513 #endif
514
515         f->owner->transfer = NULL;
516
517 #if WANT_DCACHE
518         if (f->dir_cache != NULL) f->dir_cache->use_count--;
519 #endif
520
521         remove_from_linked_list((struct list_element *)f);
522 }
523
524 /*
525  * process_all_clients():
526  *              Processes all the _control_ connections in active_clients
527  *              (normally returned from a select(), there are at max
528  *              NUM_AC active connections in the set), sending them
529  *              through to the command parser if a command has been
530  *              entered.
531  */
532 #if HAVE_POLL
533 int process_all_clients(const int num_ac)
534 #else
535 int process_all_clients(const fd_set * const active_clients, const int num_ac)
536 #endif
537 {
538         struct conn *c = NULL, *next = first_conn->next_conn;
539         int checked_through = 0;
540
541         /* run through the linked list */
542         while (next != NULL && checked_through < num_ac) {
543                 int bytes_avail;
544
545                 c = next;
546                 next = c->next_conn;
547 #if HAVE_POLL
548                 if ((fds[c->sock].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) == 0) {
549                         continue;
550                 }
551 #else
552                 if (!FD_ISSET(c->sock, active_clients)) {
553                         continue;
554                 }
555 #endif
556
557                 checked_through++;
558
559                 bytes_avail = recv(c->sock, c->recv_buf + c->buf_len,
560                                    255 - c->buf_len, 0);
561                 if (bytes_avail <= 0) {
562                         /*
563                          * select() has already told us there's something about
564                          * this socket, so if we get a return value of zero, the
565                          * client has closed the socket. If we get a return value
566                          * of -1 (error), we close the socket ourselves.
567                          *
568                          * We do the same for poll(), even though we actually have
569                          * bits that tell us what is happening (in case of new 
570                          * input AND error/hangup at the same time, we do an
571                          * explicit check at the bottom of the loop as well).
572                          */
573                         destroy_conn(c);
574                         continue;
575                 }
576
577                 /* overrun = disconnect */
578                 if (c->buf_len + bytes_avail > 254) {
579                         numeric(c, 503, "Buffer overrun; disconnecting.");
580                         destroy_conn(c);
581                         continue;
582                 }
583
584                 c->buf_len += bytes_avail;
585                 parse_command(c);
586
587                 if (c->free_me || (fds[c->sock].revents & (POLLERR|POLLHUP|POLLNVAL))) {
588                         destroy_conn(c);
589                 }
590         }
591         return checked_through;
592 }
593
594 /*
595  * finish_transfer():
596  *              Send a message that the transfer is completed, write xferlog
597  *              entry (optional), and update the last_transfer record in the
598  *              file transfer object. Goes for both uploads and downloads.
599  */
600 void finish_transfer(struct ftran * const f)
601 {
602         char finished[] = "226 Transfer complete.\r\n";
603         if (send(f->owner->sock, finished, strlen(finished), 0) == -1 && errno == EPIPE) {
604                 destroy_conn(f->owner);
605                 return;
606         }
607         
608         time(&(f->owner->last_transfer));
609
610 #if WANT_XFERLOG
611         if (!f->dir_listing) {
612                 write_xferlog(f);
613         }
614 #endif
615
616         destroy_ftran(f);
617 #if WANT_FULLSCREEN
618         update_display(first_conn);
619 #endif
620 }
621
622 /*
623  * process_all_sendfiles():
624  *              Sends data to all clients that are ready to receive it.
625  *              Also checks for data connections that are newly-connected,
626  *              and handler xferlog entries for the files that are finished.
627  */
628 #if HAVE_POLL
629 int process_all_sendfiles(const int num_ac)
630 #else
631 int process_all_sendfiles(fd_set * const active_clients, const int num_ac)
632 #endif
633 {
634         struct ftran *f = NULL, *next = first_ftran->next_ftran;
635         int checked_through = 0;
636         int tempaddr_len = sizeof(struct sockaddr_in);
637  
638         while (next != NULL && checked_through < num_ac) {
639                 f = next;
640                 next = f->next_ftran;
641
642 #if WANT_UPLOAD
643                 if ((f->upload == 1) && (fds[f->sock].revents & POLLHUP)) {
644                         finish_transfer(f);
645                         continue;
646                 }
647 #endif
648
649 #if HAVE_POLL
650                 if (fds[f->sock].revents & (POLLERR|POLLNVAL|POLLHUP)) {
651                         destroy_ftran(f);
652                         continue;
653                 }
654 #endif
655
656                 /* state = 2: incoming PASV, state >3: send file */
657 #if HAVE_POLL
658                 if ((f->state < 2) || (f->state == 3) || (fds[f->sock].revents & (POLLIN|POLLOUT)) == 0) {
659 #else
660                 if ((f->state < 2) || (f->state == 3) || !FD_ISSET(f->sock, active_clients)) {
661 #endif
662                         continue;
663                 }
664
665                 checked_through++;
666
667 #if HAVE_POLL
668                 /* Nothing is needed for the poll() version? */
669 #else
670                 FD_CLR(f->sock, active_clients);
671 #endif
672
673                 if (f->state == 2) {            /* incoming PASV */
674                         const unsigned int one = 1;
675                         const int tempsock = accept(f->sock, &(f->sin), &tempaddr_len);
676
677                         del_fd(f->sock);
678
679                         if (tempsock == -1) {
680                                 destroy_ftran(f);
681                                 continue;
682                         }
683
684                         f->sock = tempsock;
685                         ioctl(f->sock, FIONBIO, &one);
686                         init_file_transfer(f);
687                         
688                         flush_numeric(f->owner);
689                         if (f->owner->free_me) {
690                                 destroy_conn(f->owner);
691                                 continue;
692                         }
693         
694 #if WANT_UPLOAD
695                         if (f->upload) continue;
696 #endif
697                 }
698                 if (f->state < 5) {
699                         init_file_transfer(f);
700                         
701                         flush_numeric(f->owner);
702                         if (f->owner->free_me) {
703                                 destroy_conn(f->owner);
704                                 continue;
705                         }
706 #if WANT_UPLOAD
707                         if (f->upload) continue;
708 #endif
709                 }
710
711                 /* for download, we send the first packets right away */
712 #if WANT_UPLOAD
713                 if (f->upload) {
714                         if (do_upload(f)) continue;
715                 } else
716 #endif
717                         if (do_download(f)) continue;
718
719                 /* do_{upload,download} returned 0, the transfer is complete */
720                 finish_transfer(f);
721 #if WANT_FULLSCREEN
722                 update_display(first_conn);
723 #endif
724         }
725
726         return checked_through;
727 }
728
729 #if WANT_UPLOAD
730 int do_upload(struct ftran *f)
731 {
732         char upload_buf[16384];
733         int size;
734 #if WANT_ASCII
735         /* keep buffer size small in ascii transfers 
736            to prevent process stalling while filtering
737            data on slower computers */
738
739         /* 
740          * This isn't a big problem, since we won't get
741          * packets this big anyway, the biggest I've seen
742          * was 12kB on 100mbit (but that was from a Windows
743          * machine), so I've reduced the buffer from 64 kB
744          * to 16 kB :-) --Steinar
745          */
746         const int maxlen = (f->ascii_mode == 1) ? 4096 : 16384;
747 #else
748         const int maxlen = 16384;
749 #endif
750
751         errno = 0;
752         size = recv(f->sock, upload_buf, maxlen, 0);
753         if (size >= 0) {
754                 f->pos += size;
755         }
756 #if WANT_ASCII
757         if (size > 0 && f->ascii_mode == 1) {
758                 size = ascii_uploadfilter(upload_buf, size);
759         }
760 #endif
761         if (size > 0 && (write(f->local_file, upload_buf, size) == size)) {
762                 return 1;
763         } else if (size == -1 && errno != EAGAIN) {
764                 /* don't write xferlog... or? */
765                 numeric(f->owner, 426, strerror(errno));
766                 destroy_ftran(f);
767                 return 1;
768         }
769         return 0;
770
771 #endif
772
773 int do_download(struct ftran *f)
774 {
775 #if defined(TCP_CORK) && defined(SOL_TCP)
776         unsigned int zero = 0;
777 #endif
778         char *sendfrom_buf;
779         int bytes_to_send;
780         int more_to_send = 0;
781
782 #if !HAVE_MMAP
783         char buf[MAX_BLOCK_SIZE];
784 #endif
785 #if WANT_ASCII
786         char buf2[MAX_BLOCK_SIZE * 2];
787 #endif
788         int size;
789
790 #if HAVE_LINUX_SENDFILE || HAVE_BSD_SENDFILE
791         /*
792          * We handle the optimal case first, which is sendfile().
793          * Here we use a rather simplified sending `algorithm',
794          * leaving most of the quirks to the system calls.
795          */
796         if (sendfile_supported == 1 && f->dir_listing == 0) {
797                 int err;
798                 size = f->size - f->pos;
799
800                 if (size > f->block_size) size = f->block_size;
801                 if (size < 0) size = 0;
802
803 #ifdef TCP_CORK
804                 if (size != f->block_size) {
805                         setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));
806                 }       
807 #endif
808
809                 err = mysendfile(f->sock, f->local_file, &f->pos, size);
810                 return (f->pos < f->size) && (err > -1);
811         }
812 #endif
813
814 #if HAVE_MMAP
815         size = f->size - f->pos;
816
817         if (size > f->block_size) size = f->block_size;
818         if (size < 0) size = 0;
819
820         bytes_to_send = size;
821         sendfrom_buf = f->file_data + f->pos;
822 #else
823         bytes_to_send = read(f->local_file, buf, f->block_size);
824         sendfrom_buf = buf;
825 #endif
826
827         if (bytes_to_send == f->block_size) more_to_send = 1;
828
829 #if WANT_ASCII
830         if (f->ascii_mode == 1) {
831                 bytes_to_send = ascii_downloadfilter(sendfrom_buf,
832                                                      buf2, bytes_to_send);
833                 sendfrom_buf = buf2;
834         }
835 #endif /* WANT_ASCII */
836
837 #if defined(TCP_CORK) && defined(SOL_TCP)
838         /* if we believe this is the last packet, unset TCP_CORK */
839         if (more_to_send == 0) {
840                 setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&zero, sizeof(zero));
841         }
842 #endif
843
844         size = send(f->sock, sendfrom_buf, bytes_to_send, 0);
845         if (size < bytes_to_send) more_to_send = 1;
846
847 #if WANT_ASCII
848         if (f->ascii_mode == 1 && size < bytes_to_send && size > 0) {
849                 size = ascii_findlength(sendfrom_buf, size);
850         }
851 #endif
852
853 #if HAVE_MMAP
854         if (size > 0) f->pos += size;
855 #endif
856
857         return more_to_send;
858 }
859
860 #if WANT_XFERLOG
861 void write_xferlog(struct ftran *f)
862 {
863         char temp[256];
864         time_t now = time(NULL);
865         struct tm *t = localtime(&now);
866
867         if (xferlog == NULL) return;
868
869         strftime(temp, 256, "%a  %b %d %H:%M:%S %Y", t);
870 #if WANT_UPLOAD
871         fprintf(xferlog, "%s %u %s %lu %s b _ %c %c %s ftp 0 *\n",
872 #else
873         fprintf(xferlog, "%s %u %s %lu %s b _ o %c %s ftp 0 *\n",
874 #endif
875                 temp, (int)(difftime(now, f->tran_start)),
876                 inet_ntoa(f->sin.sin_addr), f->size,
877                 f->filename,
878 #if WANT_UPLOAD
879                 (f->upload) ? 'i' : 'o',
880 #endif
881                 (f->owner->auth == 4) ? 'r' : 'a', f->owner->username);
882         fflush(xferlog);
883
884 #if 0
885         /* vim needs this to work properly :-( */
886         )
887 #endif
888 }
889 #endif
890
891 #if 0
892 /* Reallocate the buggers constantly */
893 void screw_clients()
894 {
895         struct conn *c = first_conn;
896         int maxloops = MAXCLIENTS;
897
898         while (c && c->next_conn) {
899                 struct conn *temp = malloc(sizeof(*temp));
900                 if (!temp) break;
901                 *temp = *(c->next_conn);
902                 if (temp->transfer) temp->transfer->owner = temp;
903                 memset(c->next_conn, 0, sizeof(struct conn));
904                 free(c->next_conn);
905                 temp->prev_conn = c;
906                 c->next_conn = temp;
907                 c = c->next_conn;
908                 maxloops--;
909                 assert(maxloops > 0);
910         }
911 }
912 #endif
913
914 /*
915  * main():      Main function. Does the initialization, and contains
916  *              the main server loop. Takes no command-line arguments
917  *              (see README for justification).
918  */
919 int main(void)
920 {
921         int server_sock;
922
923 #if HAVE_POLL
924         /* the sets are declared globally if we use poll() */
925 #else
926         fd_set fds, fds_send;
927 #endif
928
929         /*setlinebuf(stdout);*/
930         setvbuf(stdout, (char *)NULL, _IOLBF, 0); 
931
932         signal(SIGPIPE, SIG_IGN);
933
934         printf("BetaFTPD version %s, Copyright (C) 1999-2000 Steinar H. Gunderson\n", VERSION);
935         puts("BetaFTPD comes with ABSOLUTELY NO WARRANTY; for details see the file");
936         puts("COPYING. This is free software, and you are welcome to redistribute it");
937         puts("under certain conditions; again see the file COPYING for details.");
938         puts("");
939
940         /* we don't need stdin */
941         close(0);
942
943 #if HAVE_POLL
944         {
945                 int i;
946                 for (i = 0; i < FD_MAX; i++) {
947                         fds[i].fd = -1;
948                         fds[i].events = 0;
949                 }
950         }
951 #else
952         FD_ZERO(&master_fds);
953         FD_ZERO(&master_send_fds);
954 #endif
955
956         server_sock = create_server_socket();
957
958 #if WANT_FULLSCREEN
959         printf("%cc", (char)27);        /* reset and clear the screen */
960 #endif
961
962         /* init dummy first connection */
963         first_conn = alloc_new_conn(-1);
964         first_ftran = alloc_new_ftran(0, NULL);
965 #if WANT_DCACHE
966         first_dcache = alloc_new_dcache();
967 #endif
968
969 #if WANT_XFERLOG
970 #if WANT_NONROOT
971 #warning No xferlog support for nonroot yet
972 #else
973         /* open xferlog */
974         xferlog = fopen("/var/log/xferlog", "a");
975         if (xferlog == NULL) xferlog = fopen("/usr/adm/xferlog", "a");
976
977         if (xferlog != NULL) {
978                  fseek(xferlog, 0L, SEEK_END);
979         }
980 #endif
981 #endif
982
983 #if WANT_FORK
984         switch (fork()) {
985         case -1:
986                 perror("fork()");
987                 puts("fork() failed, exiting");
988                 exit(0);
989         case 0:
990                 break;
991         default:
992                 puts("BetaFTPD forked into the background");
993                 exit(0);
994         }
995 #else
996         puts("BetaFTPD active");
997 #endif
998
999         /* set timeout alarm here (after the fork) */
1000         alarm(60);
1001         signal(SIGALRM, handle_alarm);
1002
1003 #if HAVE_LINUX_SENDFILE || HAVE_BSD_SENDFILE
1004         /* check that sendfile() is really implemented (same check as configure does) */
1005         {
1006                 int out_fd = 1, in_fd = 0;
1007                 off_t offset = 0;
1008                 size_t size = 1024;
1009
1010                 errno = 0;
1011                 mysendfile(out_fd, in_fd, &offset, size);
1012                 if (errno == ENOSYS) sendfile_supported = 0;
1013         }
1014 #endif
1015
1016         for ( ;; ) {
1017                 int i;
1018 #ifndef HAVE_POLL
1019                 struct timeval timeout;
1020 #endif
1021
1022                 /*screw_clients();       //look for memory errors */
1023
1024 #if WANT_FULLSCREEN
1025                 update_display(first_conn);
1026 #endif
1027
1028 #if HAVE_POLL
1029                 i = poll(fds, highest_fds + 1, 60000);
1030 #if 0
1031                 {
1032                         int j;
1033                         for (j=0; j<=highest_fds; j++) {
1034                                 if (fds[j].revents) printf("fds[%d].fd %d, .revents %x\n", j, fds[j].fd, fds[j].revents);
1035                         }
1036                 }
1037 #endif
1038 #else
1039                 /* reset fds (gets changed by select()) */
1040                 fds = master_fds;
1041                 fds_send = master_send_fds;
1042
1043                 /*
1044                  * wait up to 60 secs for any activity 
1045                  */
1046                 timeout.tv_sec = 60;
1047                 timeout.tv_usec = 0;
1048
1049                 i = select(FD_SETSIZE, &fds, &fds_send, NULL, &timeout);
1050 #endif
1051
1052                 if (i == -1) {
1053                         if (errno == EBADF) {
1054 #if !HAVE_POLL
1055                                 /* don't like this, but we have to */
1056                                 clear_bad_fds(&server_sock);
1057 #endif
1058                         } else if (errno != EINTR) {
1059 #if HAVE_POLL
1060                                 perror("poll()");
1061 #else
1062                                 perror("select()");
1063 #endif
1064                                 continue;
1065                         }
1066                 }
1067
1068 #if HAVE_POLL
1069                 /* fix an invalid server socket */
1070                 if (fds[server_sock].revents & POLLERR) {
1071                         del_fd(server_sock);
1072                         server_sock = create_server_socket();
1073                 }
1074 #endif
1075
1076                 /* remove any timed out sockets */
1077                 if (time_to_check) {
1078                         time_out_sockets();
1079 #if WANT_DCACHE
1080                         time_out_dcache();
1081 #endif
1082                         time_to_check = 0;
1083                 }
1084
1085                 if (i <= 0) continue;
1086
1087 #if HAVE_POLL
1088                 i -= process_all_sendfiles(i);
1089                 process_all_clients(i);
1090 #else
1091                 /* sends are given highest `priority' */
1092                 i -= process_all_sendfiles(&fds_send, i);
1093
1094                 /* incoming PASV connections and uploads */
1095                 i -= process_all_sendfiles(&fds, i);
1096
1097                 /*
1098                  * check the incoming PASV connections first, so
1099                  * process_all_clients() won't be confused.
1100                  */ 
1101                 process_all_clients(&fds, i);
1102 #endif
1103
1104 #if HAVE_POLL
1105                 if (fds[server_sock].revents & POLLIN) {
1106 #else
1107                 if (FD_ISSET(server_sock, &fds)) {
1108 #endif
1109                         accept_new_client(&server_sock);
1110                         i--;
1111                 }
1112         }
1113 }
1114
1115 /*
1116  * accept_new_client():
1117  *              Open a socket for the new client, say hello and put it in
1118  *              among the others.
1119  */
1120 void accept_new_client(int * const server_sock)
1121 {
1122         struct sockaddr_in tempaddr;
1123         int tempaddr_len = sizeof(tempaddr);
1124         const int tempsock = accept(*server_sock, (struct sockaddr *)&tempaddr, &tempaddr_len);
1125
1126         static int num_err = 0;
1127
1128         if (tempsock < 0) {
1129 #ifndef WANT_FORK
1130                 perror("accept()");
1131 #endif
1132                 close(tempsock);
1133                 if ((errno == EBADF || errno == EPIPE) && ++num_err >= 3) {
1134                         del_fd(*server_sock);
1135                         *server_sock = create_server_socket();
1136                 }
1137         } else {
1138                 struct conn * const c = alloc_new_conn(tempsock);
1139                 num_err = 0;
1140                 if (c != NULL) {
1141                         char hello[] = "220 BetaFTPD " VERSION " ready.\r\n";
1142                         
1143 #if WANT_STAT
1144                         memcpy(&(c->addr), &tempaddr, sizeof(struct sockaddr));
1145 #endif
1146
1147                         if (send(tempsock, hello, strlen(hello), 0) == -1 && errno == EPIPE)
1148                                 destroy_conn(c);
1149                 }
1150         }
1151 }
1152
1153 /*
1154  * time_out_sockets():
1155  *              Times out any socket that has not had any transfer
1156  *              in the last 15 minutes (delay not customizable by FTP
1157  *              user -- you must change it in ftpd.h).
1158  *
1159  *              Note that RFC959 explicitly states that there are no
1160  *              `spontaneous' error replies, yet we have to do it to
1161  *              get the message through at all.
1162  *
1163  *              If we check this list for every accept() call, it's
1164  *              actually eating a lot of CPU time, so we only check
1165  *              it every minute. We used to do a time() call here,
1166  *              but we've changed to do use an alarm() call and set
1167  *              the time_to_check_flag in the SIGALRM handler.
1168  */
1169 RETSIGTYPE handle_alarm(int signum)
1170 {
1171         time_to_check = 1;
1172         alarm(60);
1173
1174         /* for libc5 */
1175         signal(SIGALRM, handle_alarm);
1176 }
1177
1178 void time_out_sockets()
1179 {
1180         struct conn *c = NULL, *next = first_conn->next_conn;
1181         time_t now = time(NULL);  
1182
1183         /* run through the linked list */
1184         while (next != NULL) {
1185                 c = next;
1186                 next = c->next_conn;
1187
1188                 if ((c->transfer == NULL || c->transfer->state != 5) &&
1189                     (now - c->last_transfer > TIMEOUT_SECS)) {
1190                         /* RFC violation? */
1191                         numeric(c, 421, "Timeout (%u minutes): Closing control connection.", TIMEOUT_SECS/60);
1192                         destroy_conn(c);
1193                 }
1194         }
1195 }
1196
1197 /*
1198  * remove_bytes():
1199  *              Remove some bytes from the incoming buffer. This gives
1200  *              room for new data on the control connection, and should
1201  *              be called when the code has finished using the data.
1202  *              (This is done automatically for all commands, so you
1203  *              normally need not worry about it.)
1204  */
1205 void remove_bytes(struct conn * const c, const int num)
1206 {
1207         if (c->buf_len <= num) {
1208                 c->buf_len = 0;
1209         } else {
1210                 c->buf_len -= num;
1211                 memmove(c->recv_buf, c->recv_buf + num, c->buf_len);
1212         }
1213 }
1214
1215 /*
1216  * numeric():   Sends a numeric FTP reply to the client. Note that
1217  *              you can use this command much the same way as you
1218  *              would use a printf() (with all the normal %s, %d,
1219  *              etc.), since it actually uses printf() internally.
1220  *
1221  *              This command doesn't actually SEND the data -- it
1222  *              just puts it in a buffer which is sent after the
1223  *              command handler has completed. The reasons for this
1224  *              are simple -- it makes error checking and cleanup
1225  *              MUCH cleaner, so we won't have to check for errors
1226  *              in every single little branch of the code.
1227  */
1228 void numeric(struct conn * const c, const int numeric, const char * const format, ...)
1229 {
1230         char fmt[256];
1231         va_list args;
1232         int i;
1233         int in_buf = strlen(message_buf);
1234
1235         snprintf(fmt, 256, "%03u %s\r\n", numeric, format);
1236
1237         va_start(args, format);
1238         i = vsnprintf(message_buf + in_buf, 512 - in_buf, fmt, args);
1239         va_end(args);
1240 }
1241
1242 /* flush_numeric():
1243  *              Actually flushes the buffer written by numeric() -- but does
1244  *              NOT erase it. If an error, sets the "free_me" flag in the socket.
1245  */
1246 void flush_numeric(struct conn * const c)
1247 {
1248         if (send(c->sock, message_buf, strlen(message_buf), 0) == -1 && errno == EPIPE)
1249                 c->free_me = 1;
1250 }
1251
1252 /*
1253  * init_file_transfer():
1254  *              Initiate a data connection for sending. This does not open
1255  *              any files etc., just does whatever is needed for the socket,
1256  *              if needed. It does, however, send the 150 reply to the client,
1257  *              and mmap()s if needed.
1258  *
1259  *              Linux systems (others?) define SOL_TCP right away, which saves us
1260  *              some grief and code size. Perhaps using getprotoent() is the `right'
1261  *              way, but it's bigger :-) (Optionally, we could figure it out at
1262  *              configure time, of course...)
1263  *
1264  *              For optimal speed, we use the Linux 2.2.x-only TCP_CORK flag if
1265  *              possible. Note that this is only defined in the first `arm' --
1266  *              we silently assume that Linux is the only OS supporting this
1267  *              flag. This might be an over-generalization, but I it looks like
1268  *              we'll have to depend on it other places as well, so we might
1269  *              just as well be evil here.
1270  */
1271 void init_file_transfer(struct ftran * const f)
1272 {
1273         struct linger ling;
1274         struct conn * const c = f->owner;
1275         const int mode = IPTOS_THROUGHPUT, zero = 0, one = 1;
1276         struct stat buf;
1277         int events;
1278
1279 #ifdef SOL_TCP
1280         /* we want max throughput */
1281         setsockopt(f->sock, SOL_IP, IP_TOS, (void *)&mode, sizeof(mode));
1282         setsockopt(f->sock, SOL_TCP, TCP_NODELAY, (void *)&zero, sizeof(zero));
1283 #ifdef TCP_CORK
1284         setsockopt(f->sock, SOL_TCP, TCP_CORK, (void *)&one, sizeof(one));
1285 #endif
1286 #else
1287         /* should these pointers be freed afterwards? */
1288         {
1289                 getprotoent();  /* legal? */
1290                 {
1291                         const struct protoent * const pe_ip  = getprotobyname("ip");
1292                         const struct protoent * const pe_tcp = getprotobyname("tcp");
1293                         setsockopt(f->sock, pe_ip->p_proto, IP_TOS, (void *)&mode, sizeof(mode));
1294                         setsockopt(f->sock, pe_tcp->p_proto, TCP_NODELAY, (void *)&zero, sizeof(zero));
1295                 }
1296                 endprotoent();
1297         }
1298 #endif
1299
1300         if (f->dir_listing) {
1301                 f->block_size = MAX_BLOCK_SIZE;
1302         } else {
1303 #if WANT_ASCII
1304                 f->ascii_mode = f->owner->ascii_mode;
1305 #endif
1306
1307                 /* find the preferred block size */
1308                 f->block_size = MAX_BLOCK_SIZE;
1309                 if (fstat(f->local_file, &buf) != -1 &&
1310                     buf.st_blksize < MAX_BLOCK_SIZE) {
1311                         f->block_size = buf.st_blksize;
1312                 }
1313         }
1314
1315         f->state = 5;
1316
1317         events = POLLOUT;
1318 #if WANT_UPLOAD
1319         if (f->upload) {
1320                 events = POLLIN;
1321         }
1322 #endif /* WANT_UPLOAD */
1323
1324         TRAP_ERROR(add_fd(f->sock, events), 500, return);
1325
1326         ling.l_onoff = 0;
1327         ling.l_linger = 0;
1328         setsockopt(f->sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
1329
1330 #if !HAVE_POLL && WANT_UPLOAD
1331         /*
1332          * if we let an upload socket stay in master_send_fds, we would
1333          * get data that would fool us into closing the socket... (sigh)
1334          */
1335         if (f->upload) {
1336                 FD_CLR(f->sock, &master_send_fds);
1337                 FD_SET(f->sock, &master_fds);
1338         }
1339 #endif
1340
1341         time(&(f->owner->last_transfer));
1342         
1343         if (f->dir_listing) {
1344                 /* include size? */
1345                 numeric(f->owner, 150, "Opening ASCII mode data connection for directory listing.");
1346         } else {
1347                 /*
1348                  * slightly kludged -- perhaps we should kill the second arm,
1349                  * at the expense of code size? Or perhaps we could collapse
1350                  * the two possible replies into one?
1351                  */
1352 #if WANT_ASCII
1353                 if (f->ascii_mode
1354 #if WANT_UPLOAD
1355                         || f->upload
1356 #endif /* WANT_UPLOAD */
1357                 ) {
1358                         numeric(f->owner, 150, "Opening %s mode data connection for '%s'",
1359                                 (f->ascii_mode) ? "ASCII" : "BINARY", f->filename);
1360                 } else {
1361                         numeric(f->owner, 150, "Opening %s mode data connection for '%s' (%u bytes)",
1362                                 (f->ascii_mode) ? "ASCII" : "BINARY", f->filename,
1363                                 f->size); 
1364                 }
1365 #else /* !WANT_ASCII */
1366 #if WANT_UPLOAD
1367                 if (f->upload) {
1368                         numeric(f->owner, 150, "Opening BINARY mode data connection for '%s'", f->filename);
1369                 } else
1370 #endif /* WANT_UPLOAD */
1371                         numeric(f->owner, 150, "Opening BINARY mode data connection for '%s' (%u bytes)", f->filename, f->size);
1372 #endif /* !WANT_ASCII */
1373         }
1374
1375         /*
1376          * This section _could_ in theory be more optimized, but it's
1377          * much easier this way, and hopefully, the compiler will be
1378          * intelligent enough to optimize most of this away. The idea
1379          * is, some modes _require_ use of mmap (or not). The preferred
1380          * thing is using mmap() when we don't have sendfile(), and not
1381          * using mmap() when we have sendfile().
1382          */
1383 #if HAVE_MMAP
1384         if (f->dir_listing == 0) {
1385 #if HAVE_LINUX_SENDFILE || HAVE_BSD_SENDFILE
1386                 int do_mmap = (sendfile_supported) ? 0 : 1;
1387 #else
1388                 int do_mmap = 1;
1389 #endif
1390 #if WANT_ASCII
1391                 if (f->ascii_mode == 1) do_mmap = 1;
1392 #endif
1393 #if WANT_UPLOAD
1394                 if (f->upload == 1) do_mmap = 0;
1395 #endif
1396  
1397                 if (do_mmap == 1) {
1398                         f->file_data = mmap(NULL, f->size, PROT_READ, MAP_SHARED, f->local_file, 0);
1399                         if (f->file_data == MAP_FAILED) f->file_data = NULL;
1400                 } else {
1401                         f->file_data = NULL;
1402                 }
1403                 f->pos = f->owner->rest_pos;
1404         }
1405 #else /* !HAVE_MMAP */
1406         lseek(f->local_file, f->owner->rest_pos, SEEK_SET);
1407 #endif
1408 }
1409
1410 /*
1411  * create_server_socket():
1412  *              Create and bind a server socket, that we can use to
1413  *              listen to new clients on.
1414  */
1415 int create_server_socket()
1416 {
1417         int server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1418         const unsigned int one = 1;
1419         struct sockaddr_in addr;
1420         int err;
1421         
1422         /*
1423          * In the `perfect' world, if an address was in use, we could
1424          * just wait for the kernel to clear everything up, and everybody
1425          * would be happy. But when you just found out your server socket
1426          * was invalid, it has to be `re-made', and 3000 users are trying
1427          * to access your fileserver, I think it's nice that it comes
1428          * up right away... hence this option.
1429          */
1430         setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1431         ioctl(server_sock, FIONBIO, &one);      /* just in case */
1432
1433         addr.sin_family = AF_INET;
1434         addr.sin_addr.s_addr = INADDR_ANY;
1435         addr.sin_port = htons(FTP_PORT);
1436
1437         do {
1438                 err = bind(server_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
1439
1440                 if (err == -1) {
1441                         perror("bind()");
1442                 
1443                         /* try to recover from recoverable errors... */
1444                         if (errno == ENOMEM || errno == EADDRINUSE) {
1445                                 puts("Waiting 1 sec before trying again...");
1446                                 sleep(1);
1447                         } else {
1448                                 puts("Giving up.");
1449                                 exit(1); 
1450                         }
1451                 }
1452         } while (err == -1);
1453
1454         listen(server_sock, 20);
1455
1456         err = add_fd(server_sock, POLLIN);
1457         if (err) {
1458                 perror("add_fd");
1459                 return -1;
1460         }
1461
1462         return server_sock;
1463 }
1464
1465 #if !HAVE_POLL
1466 /*
1467  * clear_bad_fds():
1468  *              Try to find invalid socket descriptors, and clean them.
1469  *              The methods used are rather UGLY, but I can't think of
1470  *              any good way of checking e.g. server_sock without
1471  *              doing anything to it :-(
1472  *
1473  *              poll() is able to do this in a much cleaner way, which 
1474  *              we use if we use poll(). That checking isn't done here,
1475  *              though.
1476  */
1477 void clear_bad_fds(int * const server_sock)
1478 {
1479         {
1480                 fd_set fds;
1481                 struct timeval tv = { 0, 0 };
1482
1483                 FD_ZERO(&fds);
1484                 FD_SET(*server_sock, &fds); 
1485                 if (select(*server_sock, &fds, NULL, NULL, &tv) == -1) {
1486                         FD_CLR(*server_sock, &master_fds);
1487                         close(*server_sock);
1488                         *server_sock = create_server_socket();
1489                 }
1490         }
1491
1492         /* could do this (conn, ftran) in any order */
1493         {
1494                 struct conn *c = NULL, *next = first_conn->next_conn;
1495         
1496                 /* run through the linked list */
1497                 while (next != NULL) {
1498                         char buf[1];
1499
1500                         c = next;
1501                         next = c->next_conn;
1502
1503                         if (read(c->sock, &buf, 0) == -1 &&
1504                             errno == EBADF) {
1505                                 destroy_conn(c);
1506                         }
1507                 }
1508         }
1509
1510         {
1511                 struct ftran *f = NULL, *next = first_ftran->next_ftran;
1512         
1513                 while (next != NULL) {
1514                         char buf[1];
1515
1516                         f = next;
1517                         next = f->next_ftran;
1518
1519                         if (read(f->sock, &buf, 0) == -1 &&
1520                             errno == EBADF) {
1521                                 destroy_ftran(f);
1522                         }
1523                 }
1524         }       
1525 }
1526 #endif
1527
1528 #if HAVE_BSD_SENDFILE || HAVE_LINUX_SENDFILE
1529 int mysendfile(int sock, int fd, off_t *offset, size_t count)
1530 {
1531 #if HAVE_BSD_SENDFILE
1532         int err;
1533         off_t ssize = 0;
1534         
1535         err = sendfile(fd, sock, *offset, count, NULL, &ssize, 0);
1536         if (ssize > 0) *offset += ssize;
1537 #else /* !HAVE_BSD_SENDFILE */
1538 #if HAVE_LINUX_SENDFILE
1539         return sendfile(sock, fd, offset, count);
1540 #endif /* HAVE_LINUX_SENDFILE */
1541 #endif /* !HAVE_BSD_SENDFILE */
1542 }
1543 #endif /* HAVE_BSD_SENDFILE || HAVE_LINUX_SENDFILE */
1544
1545
1546 #if WANT_MESSAGE
1547 /*
1548  * dump_file(): Dumps a file on the control connection. Used for
1549  *              welcome messages and the likes. Note that outbuf
1550  *              is so big, to prevent any crashing from users creating
1551  *              weird .message files (like 1024 LFs)... The size of
1552  *              the file is limited to 1024 bytes (by truncation).
1553  */
1554 void dump_file(struct conn * const c, const int num, const char * const filename)
1555 {
1556         char buf[1024], outbuf[5121];
1557         char *ptr = outbuf + 4;
1558         int i, j = -1;
1559
1560         const int dumpfile = open(filename, O_RDONLY);
1561         if (dumpfile == -1) return;
1562
1563         i = read(dumpfile, buf, 1024);
1564         if (i <= 0) {
1565                 close(dumpfile);
1566                 return;
1567         }
1568
1569         sprintf(outbuf, "%03u-", num);
1570         while (++j < i) {
1571                 *ptr++ = buf[j];
1572                 if (buf[j] == '\n') {
1573                         sprintf(ptr, "%03u-", num);
1574                         ptr += 4;
1575                 }
1576         }
1577         *ptr++ = '\n';
1578
1579         send(c->sock, outbuf, ptr - outbuf, 0);
1580         close(dumpfile);
1581 }
1582
1583
1584 /*
1585  * list_readme():
1586  *              Lists all README file in the current (ie. OS current)
1587  *              directory, in a 250- message.
1588  */
1589 void list_readmes(struct conn * const c)
1590 {
1591         glob_t pglob;
1592         const time_t now = time(NULL);
1593         int i;
1594
1595         if (glob("README*", 0, NULL, &pglob) != 0) return;
1596
1597         for (i = 0; i < pglob.gl_pathc; i++) {
1598                 struct stat buf;
1599                 char str[256];
1600                 char *tm;
1601
1602                 if (stat(pglob.gl_pathv[i], &buf) == -1) continue;
1603
1604                 /* remove trailing LF */
1605                 tm = ctime(&buf.st_mtime);
1606                 tm[strlen(tm) - 1] = 0;
1607
1608                 snprintf(str, 256, "250-Please read the file %s\r\n"
1609                                    "250-\tIt was last modified %s - %ld days ago\r\n",
1610                         pglob.gl_pathv[i], tm,
1611                         (now - buf.st_mtime) / 86400);
1612                 send(c->sock, str, strlen(str), 0);
1613         }
1614         globfree(&pglob);
1615 }
1616 #endif
1617