📄 pure-ftpwho.c
字号:
if (current_size > (off_t) 0) { unsigned long bandwidth; long double pct; int pcti; if (xfer_since > 0UL && current_size > restartat) { bandwidth = (unsigned long) ((current_size - restartat) / xfer_since); } else { bandwidth = 0UL; } if ((long double) total_size > 0.0L) { pct = ((long double) current_size * 100.0L) / (long double) total_size; pcti = (int) (pct + 0.5L); if (pcti > 100) { pcti = 100; /* should never happen */ } printf(" resume=\"%llu\"", (unsigned long long) restartat); printf(" current_size=\"%llu\"", (unsigned long long) current_size); printf(" total_size=\"%llu\"", (unsigned long long) total_size); printf(" percentage=\"%d\"", pcti); printf(" bandwidth=\"%lu\"", bandwidth); } else { printf(" resume=\"%llu\"", (unsigned long long) restartat); printf(" current_size=\"%llu\"", (unsigned long long) current_size); printf(" bandwidth=\"%lu\"", bandwidth); } } puts(" />");}static void xml_output_footer(void){ puts("</status>");}/* Shell output */static const char *shell_escaped(const char * const s_){ register const unsigned char *s = (const unsigned char *) s_; static char buf[MAXPATHLEN + 32U]; const char * const bufend = &buf[sizeof buf - (size_t) 1U]; register char *bufpnt = buf; while (*s != 0U) { if (ISCTRLCODE(*s)) { *bufpnt = '_'; } else if (*s == '|' || *s == '\\') { if (bufpnt == bufend) { break; } *bufpnt++ = '\\'; if (bufpnt == bufend) { bufpnt--; break; } *bufpnt = (char) *s; } else { *bufpnt = (char) *s; } if (bufpnt == bufend) { break; } bufpnt++; s++; } *bufpnt = 0; return buf;}static void shell_output_header(void){}static void shell_output_line(const pid_t pid, const char * const account, const unsigned long since, const unsigned long xfer_since, const char * const state, const char * const filename, const char * const hbuf, const char * const local_hbuf, const char * const local_port, const off_t restartat, const off_t total_size, const off_t current_size){ unsigned long bandwidth = 0UL; long double pct; int pcti = 0; if (current_size > (off_t) 0) { if (xfer_since > 0UL && current_size > restartat) { bandwidth = (unsigned long) ((current_size - restartat) / (xfer_since * 1024UL)); } if ((long double) total_size > 0.0L) { pct = ((long double) current_size * 100.0L) / (long double) total_size; pcti = (int) (pct + 0.5L); if (pcti > 100) { pcti = 100; /* should never happen */ } } } printf("%lu|", (unsigned long) pid); printf("%s|", shell_escaped(account)); printf("%lu|", since); printf("%s|", shell_escaped(state)); printf("%s|", shell_escaped(filename)); printf("%s|", shell_escaped(hbuf)); printf("%s|", shell_escaped(local_hbuf)); printf("%s|", shell_escaped(local_port)); printf("%llu|", (unsigned long long) (current_size / 1024)); printf("%llu|", (unsigned long long) (total_size / 1024)); printf("%d|", pcti); printf("%lu\n", bandwidth);}static void shell_output_footer(void){}/* function pointers */static void (*output_header)(void) = text_output_header;static void (*output_line)(const pid_t pid, const char * const account, const unsigned long since, const unsigned long xfer_since, const char * const state, const char * const filename, const char * const hbuf, const char * const local_hbuf, const char * const local_port, const off_t restartat, const off_t total_size, const off_t current_size) = text_output_line;static void (*output_footer)(void) = text_output_footer;/* Back to life */static void help(void){ puts("\nUsage :\n\n" "-c : this program is called by a web server (CGI mode)\n" "-h : help\n" "-H : don't resolve host names, only show IP addresses\n" "-n : synonym for -H\n" "-s : easily parsable output for shell scripts\n" " format is :\n" " pid|acct|time|state|file|peer|local|port|current|total|%|bandwidth\n" "-v : output verbose ASCII\n" "-w : output HTML page (web mode)\n" "-W : output HTML page without header/footer (embedded mode)\n" "-x : output XML data\n"); exit(EXIT_SUCCESS);}static int closedesc_but1(void){ int fodder; (void) close(0); if ((fodder = open("/dev/null", O_RDONLY)) == -1) { return -1; } (void) dup2(fodder, 0); if (fodder > 0) { (void) close(fodder); } if (fcntl(1, F_GETFD) == -1) { return -1; } if (fcntl(2, F_GETFD) != -1) { if ((fodder = open("/dev/null", O_WRONLY)) == -1) { return -1; } (void) dup2(fodder, 2); if (fodder > 2) { (void) close(fodder); } } return 0;}int main(int argc, char *argv[]){ DIR *dir; struct dirent *entry; struct stat st; FTPWhoEntry *scanned_entry; int locked; int delete_file; const char *state; time_t now; int fodder;#ifndef NON_ROOT_FTP if (geteuid() != (uid_t) 0) { puts("You must be root to run this. Sorry."); return 1; }#endif if (argc < 0) { return -1; } if (closedesc_but1() < 0) { return -2; }#ifdef HAVE_SETLOCALE# ifdef LC_MESSAGES (void) setlocale(LC_MESSAGES, "");# endif# ifdef LC_CTYPE (void) setlocale(LC_CTYPE, "");# endif# ifdef LC_COLLATE (void) setlocale(LC_COLLATE, "");# endif#endif fixlimits();# ifdef SIGFPE signal(SIGFPE, sigfpe);# endif# ifdef SIGSEGV signal(SIGSEGV, sigsegv);# endif if (getenv("GATEWAY_INTERFACE") != NULL) { html_cgi = 1; output_header = html_output_header; output_line = html_output_line; output_footer = html_output_footer; } while ((fodder = getopt(argc, argv, "CchHnsvwWx")) != -1) { switch(fodder) { case 'h' : help(); /* doesn't return */ case 'n' : case 'H' : dont_resolve_ip++; break; case 'C' : case 'c' : html_cgi++; case 'W' : html_raw++; case 'w' : output_header = html_output_header; output_line = html_output_line; output_footer = html_output_footer; break; case 's' : output_header = shell_output_header; output_line = shell_output_line; output_footer = shell_output_footer; break; case 'x' : output_header = xml_output_header; output_line = xml_output_line; output_footer = xml_output_footer; break; case 'v' : verbose++; break; case '?' : help(); } } now = time(NULL); if (chdir(SCOREBOARD_PATH) != 0 || (dir = opendir(".")) == NULL) { fprintf(stderr, "Unable to open the ftpwho scoreboard.\n" "Make sure that the [" SCOREBOARD_PATH "/] directory exists,\n" "Or wait until a client connects, so that it gets\n" "automatically created. This message doesn't mean that your\n" "server didn't start properly. It probably just means that\n" "you are running it with ftpwho for the first time.\n"); return -1; } lock.l_whence = SEEK_SET; lock.l_start = (off_t) 0; lock.l_len = (off_t) 0; lock.l_pid = getpid(); output_header(); while ((entry = readdir(dir)) != NULL) { mmap_fd = -1; locked = 0; delete_file = 0; scanned_entry = NULL; if (strncmp(entry->d_name, SCOREBOARD_PREFIX, sizeof SCOREBOARD_PREFIX - 1U) != 0) { goto nextone; } if ((mmap_fd = open(entry->d_name, O_RDWR | O_NOFOLLOW)) == -1) { goto nextone; } if (fstat(mmap_fd, &st) != 0 || !S_ISREG(st.st_mode) || (st.st_mode & 0600) != 0600 || st.st_size != (off_t) sizeof (FTPWhoEntry) ||#ifdef NON_ROOT_FTP st.st_uid != geteuid()#else st.st_uid != (uid_t) 0#endif ) { goto nextone; } ftpwho_lock(); locked++; if ((scanned_entry = (FTPWhoEntry *) mmap(NULL, sizeof (FTPWhoEntry), PROT_READ, MAP_SHARED | MAP_FILE, mmap_fd, (off_t) 0)) == NULL) { goto nextone; } if (checkproc(scanned_entry->pid) == 0) { /* still in the scoreboard, but no more process */ delete_file++; goto nextone; } if (scanned_entry->state != FTPWHO_STATE_FREE) { unsigned long since; unsigned long xfer_since; char local_port[NI_MAXSERV]; char local_hbuf[NI_MAXHOST]; char hbuf[NI_MAXHOST]; switch (scanned_entry->state) { case FTPWHO_STATE_IDLE : state = "IDLE"; break; case FTPWHO_STATE_DOWNLOAD : state = " DL "; break; case FTPWHO_STATE_UPLOAD : state = " UL "; break; default : state = "ERR!"; } if (scanned_entry->date < now) { since = (unsigned long) (now - scanned_entry->date); } else { since = 0UL; } if (scanned_entry->xfer_date > (time_t) 0 && scanned_entry->xfer_date < now) { xfer_since = (unsigned long) (now - scanned_entry->xfer_date); } else { xfer_since = 0UL; } for (;;) { int eai; if ((eai = getnameinfo ((struct sockaddr *) &scanned_entry->addr, STORAGE_LEN(scanned_entry->addr), hbuf, sizeof hbuf, NULL, (size_t) 0U, dont_resolve_ip != 0 ? NI_NUMERICHOST : 0)) == 0) { break; }#ifdef EAI_NONAME if (eai == EAI_NONAME && dont_resolve_ip == 0 && getnameinfo ((struct sockaddr *) &scanned_entry->addr, STORAGE_LEN(scanned_entry->addr), hbuf, sizeof hbuf, NULL, (size_t) 0U, NI_NUMERICHOST) == 0) { break; } #endif goto nextone; } for (;;) { int eai; if ((eai = getnameinfo ((struct sockaddr *) &scanned_entry->local_addr, STORAGE_LEN(scanned_entry->addr), local_hbuf, sizeof local_hbuf, local_port, sizeof local_port, dont_resolve_ip != 0 ? (NI_NUMERICHOST | NI_NUMERICSERV) : NI_NUMERICSERV)) == 0) { break; }#ifdef EAI_NONAME if (eai == EAI_NONAME && dont_resolve_ip == 0 && getnameinfo ((struct sockaddr *) &scanned_entry->local_addr, STORAGE_LEN(scanned_entry->addr), local_hbuf, sizeof local_hbuf, local_port, sizeof local_port, NI_NUMERICHOST | NI_NUMERICSERV) == 0) { break; }#endif goto nextone; } output_line(scanned_entry->pid, scanned_entry->account, since, xfer_since, state, scanned_entry->filename, hbuf, local_hbuf, local_port, (scanned_entry->restartat <= scanned_entry->download_current_size) ? scanned_entry->restartat : (off_t) 0, (scanned_entry->state == FTPWHO_STATE_DOWNLOAD) ? scanned_entry->download_total_size : (off_t) 0, (scanned_entry->state == FTPWHO_STATE_DOWNLOAD || scanned_entry->state == FTPWHO_STATE_UPLOAD) ? scanned_entry->download_current_size : (off_t) 0); } nextone: if (locked != 0 && mmap_fd != -1) { ftpwho_unlock(); } if (scanned_entry != NULL) { (void) munmap((void *) scanned_entry, sizeof (FTPWhoEntry)); } if (mmap_fd != -1) { close(mmap_fd); } if (delete_file != 0) { unlink(entry->d_name); } } output_footer(); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -