static void verify_scoreboard_file(void) { struct stat sbuf; if (stat(util_get_scoreboard(), &sbuf) < 0) { fprintf(stderr, "%s: unable to stat '%s': %s\n", program, util_get_scoreboard(), strerror(errno)); exit(1); } }
static int check_scoreboard_file(void) { struct stat sbuf; if (stat(util_get_scoreboard(), &sbuf) < 0) return -1; return 0; }
static int check_scoreboard_file(void) { struct stat st; if (stat(util_get_scoreboard(), &st) < 0) { return -1; } return 0; }
static void process_opts(int argc, char *argv[]) { int optc = 0; const char *prgopts = "DS:d:f:hIiUV"; while ((optc = getopt(argc, argv, prgopts)) != -1) { switch (optc) { case 'D': display_mode = 0U; display_mode |= FTPTOP_SHOW_DOWNLOAD; break; case 'S': server_name = strdup(optarg); break; case 'd': delay = atoi(optarg); if (delay < 0) { fprintf(stderr, "%s: negative delay illegal: %d\n", program, delay); exit(1); } if (delay > 15) { fprintf(stderr, "%s: delay of 0-15 seconds only supported\n", program); exit(1); } break; case 'f': if (util_set_scoreboard(optarg) < 0) { fprintf(stderr, "%s: unable to use scoreboard '%s': %s\n", program, optarg, strerror(errno)); exit(1); } break; case 'h': usage(); break; case 'I': display_mode = 0U; display_mode |= FTPTOP_SHOW_IDLE; break; case 'i': display_mode &= ~FTPTOP_SHOW_IDLE; break; case 'U': display_mode = 0U; display_mode |= FTPTOP_SHOW_UPLOAD; break; case 'V': show_version(); break; case '?': break; default: break; } } /* First attempt to check the supplied/default scoreboard path. If this is * incorrect, try the config file kludge. */ if (check_scoreboard_file() < 0) { scan_config_file(); if (check_scoreboard_file() < 0) { fprintf(stderr, "%s: %s\n", util_get_scoreboard(), strerror(errno)); fprintf(stderr, "(Perhaps you need to specify the ScoreboardFile with -f, or change\n"); fprintf(stderr," the compile-time default directory?)\n"); exit(1); } } }
int main(int argc, char **argv) { int c = 0, res = 0; int verbose = FALSE; char *cp, *progname = *argv; const char *cmdopts = "c:f:hv"; cp = strrchr(progname, '/'); if (cp != NULL) progname = cp+1; opterr = 0; while ((c = #ifdef HAVE_GETOPT_LONG getopt_long(argc, argv, cmdopts, opts, NULL) #else /* HAVE_GETOPT_LONG */ getopt(argc, argv, cmdopts) #endif /* HAVE_GETOPT_LONG */ ) != -1) { switch (c) { case 'h': show_usage(progname, 0); break; case 'f': util_set_scoreboard(optarg); break; case 'c': config_filename = strdup(optarg); break; case 'v': verbose = TRUE; break; case '?': fprintf(stderr, "unknown option: %c\n", (char) optopt); show_usage(progname, 1); break; } } /* First attempt to check the supplied/default scoreboard path. If this is * incorrect, try the config file kludge. */ if (check_scoreboard_file() < 0) { char *path; path = util_scan_config(config_filename, "ScoreboardFile"); if (path) { util_set_scoreboard(path); free(path); } if (check_scoreboard_file() < 0) { fprintf(stderr, "%s: %s\n", util_get_scoreboard(), strerror(errno)); fprintf(stderr, "(Perhaps you need to specify the ScoreboardFile with -f, or change\n"); fprintf(stderr," the compile-time default directory?)\n"); exit(1); } } res = util_scoreboard_scrub(verbose); if (res < 0) { fprintf(stderr, "error scrubbing scoreboard %s: %s\n", util_get_scoreboard(), strerror(errno)); return 1; } return 0; }
int main(int argc, char **argv) { pr_scoreboard_entry_t *score = NULL; pid_t mpid = 0; time_t uptime = 0; unsigned int count = 0, total = 0; int c = 0, res = 0; char *server_name = NULL; struct scoreboard_class classes[MAX_CLASSES]; char *cp, *progname = *argv; const char *cmdopts = "S:c:f:ho:v"; unsigned char verbose = FALSE; unsigned long outform = 0; memset(classes, 0, MAX_CLASSES * sizeof(struct scoreboard_class)); cp = strrchr(progname, '/'); if (cp != NULL) progname = cp+1; opterr = 0; while ((c = #ifdef HAVE_GETOPT_LONG getopt_long(argc, argv, cmdopts, opts, NULL) #else /* HAVE_GETOPT_LONG */ getopt(argc, argv, cmdopts) #endif /* HAVE_GETOPT_LONG */ ) != -1) { switch (c) { case 'h': show_usage(progname, 0); case 'v': verbose = TRUE; break; case 'f': util_set_scoreboard(optarg); break; case 'c': config_filename = strdup(optarg); break; case 'o': /* Check the given outform parameter. */ if (strcmp(optarg, "compat") == 0) { outform |= OF_COMPAT; break; } else if (strcmp(optarg, "oneline") == 0) { outform |= OF_ONELINE; break; } fprintf(stderr, "unknown outform value: '%s'\n", optarg); return 1; case 'S': server_name = strdup(optarg); break; case '?': fprintf(stderr, "unknown option: %c\n", (char) optopt); show_usage(progname, 1); } } /* First attempt to check the supplied/default scoreboard path. If this is * incorrect, try the config file kludge. */ if (check_scoreboard_file() < 0) { char *path; path = util_scan_config(config_filename, "ScoreboardFile"); if (path) { util_set_scoreboard(path); free(path); } if (check_scoreboard_file() < 0) { fprintf(stderr, "%s: %s\n", util_get_scoreboard(), strerror(errno)); fprintf(stderr, "(Perhaps you need to specify the ScoreboardFile with -f, or change\n"); fprintf(stderr," the compile-time default directory?)\n"); exit(1); } } count = 0; if ((res = util_open_scoreboard(O_RDONLY)) < 0) { switch (res) { case -1: fprintf(stderr, "unable to open scoreboard: %s\n", strerror(errno)); return 1; case UTIL_SCORE_ERR_BAD_MAGIC: fprintf(stderr, "scoreboard is corrupted or old\n"); return 1; case UTIL_SCORE_ERR_OLDER_VERSION: fprintf(stderr, "scoreboard version is too old\n"); return 1; case UTIL_SCORE_ERR_NEWER_VERSION: fprintf(stderr, "scoreboard version is too new\n"); return 1; } } mpid = util_scoreboard_get_daemon_pid(); uptime = util_scoreboard_get_daemon_uptime(); if (!mpid) { printf("inetd FTP daemon:\n"); } else { printf("standalone FTP daemon [%u], up for %s\n", (unsigned int) mpid, show_uptime(uptime)); } if (server_name) printf("ProFTPD Server '%s'\n", server_name); while ((score = util_scoreboard_entry_read()) != NULL) { int downloading = FALSE, uploading = FALSE; register unsigned int i = 0; /* If a ServerName was given, skip unless the scoreboard entry matches. */ if (server_name && strcmp(server_name, score->sce_server_label) != 0) continue; if (!count++) { if (total) printf(" - %d user%s\n\n", total, total > 1 ? "s" : ""); total = 0; } /* Tally up per-Class counters. */ for (i = 0; i != MAX_CLASSES; i++) { if (classes[i].score_class == 0) { classes[i].score_class = strdup(score->sce_class); classes[i].score_count++; break; } if (strcasecmp(classes[i].score_class, score->sce_class) == 0) { classes[i].score_count++; break; } } total++; if (strcmp(score->sce_cmd, "RETR") == 0 || strcmp(score->sce_cmd, "READ") == 0 || strcmp(score->sce_cmd, "scp download") == 0) { downloading = TRUE; } else { if (strcmp(score->sce_cmd, "STOR") == 0 || strcmp(score->sce_cmd, "STOU") == 0 || strcmp(score->sce_cmd, "APPE") == 0 || strcmp(score->sce_cmd, "WRITE") == 0 || strcmp(score->sce_cmd, "scp upload") == 0) { uploading = TRUE; } } if (outform & OF_COMPAT) { if ((downloading || uploading) && score->sce_xfer_size > 0) { if (downloading) { printf("%5d %-6s (%s%%) %s %s\n", (int) score->sce_pid, show_time(&score->sce_begin_idle), percent_complete(score->sce_xfer_size, score->sce_xfer_done), score->sce_cmd, score->sce_cmd_arg); } else { printf("%5d %-6s (n/a) %s %s\n", (int) score->sce_pid, show_time(&score->sce_begin_idle), score->sce_cmd, score->sce_cmd_arg); } } else { printf("%5d %-6s %s %s\n", (int) score->sce_pid, show_time(&score->sce_begin_idle), score->sce_cmd, score->sce_cmd_arg); } if (verbose) { if (score->sce_client_addr[0]) { printf(" (host: %s [%s])\n", score->sce_client_name, score->sce_client_addr); } if (score->sce_protocol[0]) { printf(" (protocol: %s)\n", score->sce_protocol); } if (score->sce_cwd[0]) { printf(" (cwd: %s)\n", score->sce_cwd); } if (score->sce_class[0]) { printf(" (class: %s)\n", score->sce_class); } } continue; } /* Has the client authenticated yet, or not? */ if (strcmp(score->sce_user, "(none)")) { /* Is the client idle? */ if (strcmp(score->sce_cmd, "idle") == 0) { /* These printf() calls needs to be split up, as show_time() returns * a pointer to a static buffer, and pushing two invocations onto * the stack means that the times thus formatted will be incorrect. */ printf("%5d %-8s [%6s] ", (int) score->sce_pid, score->sce_user, show_time(&score->sce_begin_session)); printf("%6s %s", show_time(&score->sce_begin_idle), score->sce_cmd); if (verbose && !(outform & OF_ONELINE)) printf("\n"); } else { if (downloading) { printf("%5d %-8s [%6s] (%3s%%) %s %s", (int) score->sce_pid, score->sce_user, show_time(&score->sce_begin_session), percent_complete(score->sce_xfer_size, score->sce_xfer_done), score->sce_cmd, score->sce_cmd_arg); } else { printf("%5d %-8s [%6s] (n/a) %s %s", (int) score->sce_pid, score->sce_user, show_time(&score->sce_begin_session), score->sce_cmd, score->sce_cmd_arg); } if (verbose) { printf("%sKB/s: %3.2f%s", (outform & OF_ONELINE) ? " " : "\n\t", (score->sce_xfer_len / 1024.0) / (score->sce_xfer_elapsed / 1000), (outform & OF_ONELINE) ? "" : "\n"); } } /* Display additional information, if requested. */ if (verbose) { if (score->sce_client_addr[0]) { printf("%sclient: %s [%s]%s", (outform & OF_ONELINE) ? " " : "\t", score->sce_client_name, score->sce_client_addr, (outform & OF_ONELINE) ? "" : "\n"); } if (score->sce_server_addr[0]) { printf("%sserver: %s (%s)%s", (outform & OF_ONELINE) ? " " : "\t", score->sce_server_addr, score->sce_server_label, (outform & OF_ONELINE) ? "" : "\n"); } if (score->sce_protocol[0]) { printf("%sprotocol: %s%s", (outform & OF_ONELINE) ? " " : "\t", score->sce_protocol, (outform & OF_ONELINE) ? "" : "\n"); } if (score->sce_cwd[0]) { printf("%slocation: %s%s", (outform & OF_ONELINE) ? " " : "\t", score->sce_cwd, (outform & OF_ONELINE) ? "" : "\n"); } if (score->sce_class[0]) { printf("%sclass: %s", (outform & OF_ONELINE) ? " " : "\t", score->sce_class); } printf("%s", "\n"); } else { printf("%s", "\n"); } } else { printf("%5d %-8s [%6s] (authenticating)", (int) score->sce_pid, score->sce_user, show_time(&score->sce_begin_session)); /* Display additional information, if requested. */ if (verbose) { if (score->sce_client_addr[0]) { printf("%sclient: %s [%s]%s", (outform & OF_ONELINE) ? " " : "\n\t", score->sce_client_name, score->sce_client_addr, (outform & OF_ONELINE) ? "" : "\n"); } if (score->sce_server_addr[0]) { printf("%sserver: %s (%s)%s", (outform & OF_ONELINE) ? " " : "\t", score->sce_server_addr, score->sce_server_label, (outform & OF_ONELINE) ? "" : "\n"); } if (score->sce_protocol[0]) { printf("%sprotocol: %s%s", (outform & OF_ONELINE) ? " " : "\t", score->sce_protocol, (outform & OF_ONELINE) ? "" : "\n"); } if (score->sce_class[0]) { printf("%sclass: %s", (outform & OF_ONELINE) ? " " : "\t", score->sce_class); } } printf("%s", "\n"); } } util_close_scoreboard(); if (total) { register unsigned int i = 0; for (i = 0; i != MAX_CLASSES; i++) { if (classes[i].score_class == 0) break; printf("Service class %-20s - %3lu user%s\n", classes[i].score_class, classes[i].score_count, classes[i].score_count > 1 ? "s" : ""); } } else { printf("no users connected\n"); } if (server_name) { free(server_name); server_name = NULL; } return 0; }
int main(int argc, char **argv) { pr_scoreboard_entry_t *score = NULL; pid_t oldpid = 0, mpid; unsigned int count = 0, total = 0; int c = 0, res = 0; char *server_name = NULL; struct scoreboard_class classes[MAX_CLASSES]; char *cp, *progname = *argv; const char *cmdopts = "S:c:f:h"; register unsigned int i; memset(classes, 0, MAX_CLASSES * sizeof(struct scoreboard_class)); cp = strrchr(progname, '/'); if (cp != NULL) progname = cp + 1; opterr = 0; while ((c = #ifdef HAVE_GETOPT_LONG getopt_long(argc, argv, cmdopts, opts, NULL) #else /* HAVE_GETOPT_LONG */ getopt(argc, argv, cmdopts) #endif /* HAVE_GETOPT_LONG */ ) != -1) { switch (c) { case 'h': show_usage(progname, 0); break; case 'f': util_set_scoreboard(optarg); break; case 'c': config_filename = strdup(optarg); break; case 'S': server_name = strdup(optarg); break; case '?': fprintf(stderr, "unknown option: %c\n", (char) optopt); show_usage(progname, 1); break; } } /* First attempt to check the supplied/default scoreboard path. If this is * incorrect, try the config file kludge. */ if (check_scoreboard_file() < 0) { char *path; path = util_scan_config(config_filename, "ScoreboardFile"); if (path) { util_set_scoreboard(path); free(path); } if (check_scoreboard_file() < 0) { fprintf(stderr, "%s: %s\n", util_get_scoreboard(), strerror(errno)); fprintf(stderr, "(Perhaps you need to specify the ScoreboardFile with -f, or change\n"); fprintf(stderr," the compile-time default directory?)\n"); exit(1); } } count = 0; res = util_open_scoreboard(O_RDONLY); if (res < 0) { switch (res) { case UTIL_SCORE_ERR_BAD_MAGIC: fprintf(stderr, "error opening scoreboard: bad/corrupted file\n"); return 1; case UTIL_SCORE_ERR_OLDER_VERSION: fprintf(stderr, "error opening scoreboard: bad version (too old)\n"); return 1; case UTIL_SCORE_ERR_NEWER_VERSION: fprintf(stderr, "error opening scoreboard: bad version (too new)\n"); return 1; default: fprintf(stderr, "error opening scoreboard: %s\n", strerror(errno)); return 1; } } mpid = util_scoreboard_get_daemon_pid(); errno = 0; while ((score = util_scoreboard_entry_read()) != NULL) { if (errno) break; if (!count++ || oldpid != mpid) { if (total) printf(" - %d user%s\n\n", total, total > 1 ? "s" : ""); if (!mpid) { printf("inetd FTP connections:\n"); } else { printf("Master proftpd process %u:\n", (unsigned int) mpid); } if (server_name) printf("ProFTPD Server '%s'\n", server_name); oldpid = mpid; total = 0; } /* If a ServerName was given, skip unless the scoreboard entry matches. */ if (server_name && strcmp(server_name, score->sce_server_label) != 0) { continue; } for (i = 0; i != MAX_CLASSES; i++) { if (classes[i].score_class == 0) { classes[i].score_class = strdup(score->sce_class); classes[i].score_count++; break; } if (strcasecmp(classes[i].score_class, score->sce_class) == 0) { classes[i].score_count++; break; } } total++; } util_close_scoreboard(); /* Print out the total. */ if (total) { for (i = 0; i != MAX_CLASSES; i++) { if (classes[i].score_class == 0) break; printf("Service class %-20s - %3lu %s\n", classes[i].score_class, classes[i].score_count, classes[i].score_count > 1 ? "users" : "user"); } } else { if (!mpid) { printf("inetd FTP connections:\n"); } else { printf("Master proftpd process %u:\n", (unsigned int) mpid); } printf("0 users\n"); } if (server_name) { free(server_name); } return 0; }
int util_scoreboard_scrub(int verbose) { int fd = -1, res = 0; off_t curr_offset = 0; struct flock lock; pr_scoreboard_entry_t sce; if (verbose) { fprintf(stdout, "scrubbing ScoreboardFile %s\n", util_get_scoreboard()); } /* Manually open the scoreboard. It won't hurt if the process already * has a descriptor opened on the scoreboard file. */ fd = open(util_get_scoreboard(), O_RDWR); if (fd < 0) { if (verbose) { fprintf(stdout, "error opening scoreboard: %s", strerror(errno)); } return -1; } /* Lock the entire scoreboard. */ lock.l_type = F_WRLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; /* We can afford to block/wait until we obtain our lock on the file. */ while (fcntl(fd, F_SETLKW, &lock) < 0) { int xerrno = errno; if (xerrno == EINTR) { continue; } (void) close(fd); errno = xerrno; return -1; } /* Skip past the scoreboard header. */ curr_offset = lseek(fd, (off_t) sizeof(pr_scoreboard_header_t), SEEK_SET); if (curr_offset < 0) { int xerrno = errno; /* Release the scoreboard. */ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; while (fcntl(fd, F_SETLKW, &lock) < 0) { if (errno == EINTR) { continue; } } /* Don't need the descriptor anymore. */ (void) close(fd); errno = xerrno; return -1; } memset(&sce, 0, sizeof(sce)); while (read(fd, &sce, sizeof(sce)) == sizeof(sce)) { /* Check to see if the PID in this entry is valid. If not, erase * the slot. */ if (sce.sce_pid && kill(sce.sce_pid, 0) < 0 && errno == ESRCH) { /* OK, the recorded PID is no longer valid. */ if (verbose) { fprintf(stdout, "scrubbing scoreboard slot for PID %u", (unsigned int) sce.sce_pid); } /* Rewind to the start of this slot. */ if (lseek(fd, curr_offset, SEEK_SET) < 0) { if (verbose) { fprintf(stdout, "error scrubbing scoreboard: %s", strerror(errno)); } } memset(&sce, 0, sizeof(sce)); while (write(fd, &sce, sizeof(sce)) != sizeof(sce)) { if (errno == EINTR) { continue; } if (verbose) { fprintf(stdout, "error scrubbing scoreboard: %s", strerror(errno)); } } } /* Mark the current offset. */ curr_offset = lseek(fd, (off_t) 0, SEEK_CUR); if (curr_offset < 0) { res = -1; break; } } /* Release the scoreboard. */ lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; while (fcntl(fd, F_SETLKW, &lock) < 0) { if (errno == EINTR) { continue; } } /* Don't need the descriptor anymore. */ (void) close(fd); return res; }