static char *calc_percent_done(off_t size, off_t done) { static char sbuf[32]; memset(sbuf, '\0', sizeof(sbuf)); if (done == 0) { util_sstrncpy(sbuf, "0", sizeof(sbuf)); } else if (size == 0) { util_sstrncpy(sbuf, "Inf", sizeof(sbuf)); } else if (done >= size) { util_sstrncpy(sbuf, "100", sizeof(sbuf)); } else { snprintf(sbuf, sizeof(sbuf), "%.0f", ((double) done / (double) size) * 100.0); sbuf[sizeof(sbuf)-1] = '\0'; } return sbuf; }
int util_set_scoreboard(const char *path) { char dir[PR_TUNABLE_PATH_MAX] = {'\0'}; struct stat st; char *tmp = NULL; util_sstrncpy(dir, path, sizeof(dir)); tmp = strrchr(dir, '/'); if (tmp == NULL) { errno = EINVAL; return -1; } *tmp = '\0'; /* Parent directory must not be world-writable. */ if (stat(dir, &st) < 0) return -1; if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return -1; } if (st.st_mode & S_IWOTH) { errno = EPERM; return -1; } *tmp = '/'; /* Make sure file exists. */ if (stat(dir, &st) < 0) return -1; util_sstrncpy(util_scoreboard_file, path, sizeof(util_scoreboard_file)); return 0; }
static void read_scoreboard(void) { /* NOTE: this buffer should probably be limited to the maximum window * width, as it is used for display purposes. */ static char buf[PR_TUNABLE_BUFFER_SIZE] = {'\0'}; pr_scoreboard_entry_t *score = NULL; ftp_sessions = calloc(chunklen, sizeof(char *)); if (ftp_sessions == NULL) exit(1); if (scoreboard_open() < 0) return; /* Iterate through the scoreboard. */ while ((score = util_scoreboard_entry_read()) != NULL) { /* Default status: "A" for "authenticating" */ char *status = "A"; /* If a ServerName was given, skip unless the scoreboard entry matches. */ if (server_name != NULL && strcmp(server_name, score->sce_server_label) != 0) { continue; } /* Clear the buffer for this run. */ memset(buf, '\0', sizeof(buf)); /* Has the user authenticated yet? */ if (strcmp(score->sce_user, "(none)") != 0) { /* Determine the status symbol to display. */ if (strcmp(score->sce_cmd, "idle") == 0) { status = "I"; ftp_nidles++; if (display_mode != FTPTOP_SHOW_RATES && !(display_mode & FTPTOP_SHOW_IDLE)) continue; } else if (strcmp(score->sce_cmd, "RETR") == 0 || strcmp(score->sce_cmd, "READ") == 0 || strcmp(score->sce_cmd, "scp download") == 0) { status = "D"; ftp_ndownloads++; if (display_mode != FTPTOP_SHOW_RATES && !(display_mode & FTPTOP_SHOW_DOWNLOAD)) continue; } else if (strcmp(score->sce_cmd, "STOR") == 0 || strcmp(score->sce_cmd, "APPE") == 0 || strcmp(score->sce_cmd, "STOU") == 0 || strcmp(score->sce_cmd, "WRITE") == 0 || strcmp(score->sce_cmd, "scp upload") == 0) { status = "U"; ftp_nuploads++; if (display_mode != FTPTOP_SHOW_RATES && !(display_mode & FTPTOP_SHOW_UPLOAD)) continue; } else if (strcmp(score->sce_cmd, "LIST") == 0 || strcmp(score->sce_cmd, "NLST") == 0 || strcmp(score->sce_cmd, "MLST") == 0 || strcmp(score->sce_cmd, "MLSD") == 0 || strcmp(score->sce_cmd, "READDIR") == 0) { status = "L"; } } else { status = "A"; /* Overwrite the "command", for display purposes */ util_sstrncpy(score->sce_cmd, "(authenticating)", sizeof(score->sce_cmd)); } if (display_mode != FTPTOP_SHOW_RATES) { int user_namelen, client_namelen, cmd_arglen; user_namelen = str_getscreenlen(score->sce_user, 8); client_namelen = str_getscreenlen(score->sce_client_name, 20); cmd_arglen = str_getscreenlen(score->sce_cmd_arg, FTPTOP_REG_ARG_SIZE); snprintf(buf, sizeof(buf), FTPTOP_REG_DISPLAY_FMT, (unsigned int) score->sce_pid, status, user_namelen, user_namelen, score->sce_user, client_namelen, client_namelen, score->sce_client_name, score->sce_server_addr, show_time(&score->sce_begin_session), score->sce_cmd, cmd_arglen, cmd_arglen, score->sce_cmd_arg); buf[sizeof(buf)-1] = '\0'; } else { int user_namelen, client_namelen; user_namelen = str_getscreenlen(score->sce_user, 8); client_namelen = str_getscreenlen(score->sce_client_name, 44); /* Skip sessions unless they are actually transferring data */ if (*status != 'U' && *status != 'D') continue; snprintf(buf, sizeof(buf), FTPTOP_XFER_DISPLAY_FMT, (unsigned int) score->sce_pid, status, user_namelen, user_namelen, score->sce_user, client_namelen, client_namelen, score->sce_client_name, (score->sce_xfer_len / 1024.0) / (score->sce_xfer_elapsed / 1000), FTPTOP_XFER_DONE_SIZE, FTPTOP_XFER_DONE_SIZE, *status == 'D' ? calc_percent_done(score->sce_xfer_size, score->sce_xfer_done) : "(n/a)"); buf[sizeof(buf)-1] = '\0'; } /* Make sure there is enough memory allocated in the session list. * Allocate more if needed. */ if (ftp_nsessions && ftp_nsessions % chunklen == 0) { ftp_sessions = realloc(ftp_sessions, (ftp_nsessions + chunklen) * sizeof(char *)); if (ftp_sessions == NULL) { exit(1); } } ftp_sessions[ftp_nsessions] = calloc(1, strlen(buf) + 1); if (ftp_sessions[ftp_nsessions] == NULL) { exit(1); } util_sstrncpy(ftp_sessions[ftp_nsessions++], buf, strlen(buf) + 1); } scoreboard_close(); }