176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Display directory contents 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h> 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <console.h> 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <com32.h> 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <dirent.h> 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <minmax.h> 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <unistd.h> 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <getkey.h> 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int rows, cols; /* Screen parameters */ 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define DIR_CHUNK 1024 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char *type_str(int type) 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (type) { 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_FIFO: 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[fif]"; 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_CHR: 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[chr]"; 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_DIR: 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[dir]"; 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_BLK: 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[blk]"; 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_UNKNOWN: 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_REG: 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return ""; 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_LNK: 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[lnk]"; 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_SOCK: 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[sck]"; 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DT_WHT: 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[wht]"; 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return "[???]"; 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void free_dirents(struct dirent **dex, size_t n_de) 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t i; 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < n_de; i++) 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman free(dex[i]); 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman free(dex); 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int compare_dirent(const void *p_de1, const void *p_de2) 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const struct dirent *de1 = *(const struct dirent **)p_de1; 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const struct dirent *de2 = *(const struct dirent **)p_de2; 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ndir1, ndir2; 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ndir1 = de1->d_type != DT_DIR; 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ndir2 = de2->d_type != DT_DIR; 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ndir1 != ndir2) 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return ndir1 - ndir2; 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return strcmp(de1->d_name, de2->d_name); 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int display_directory(const char *dirname) 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DIR *dir; 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct dirent *de; 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct dirent **dex = NULL; 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t n_dex = 0, n_de = 0; 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t i, j, k; 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t nrows, ncols, perpage; 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman size_t endpage; 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int maxlen = 0; 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int pos, tpos, colwidth; 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dir = opendir(dirname); 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!dir) { 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("Unable to read directory: %s\n", dirname); 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while ((de = readdir(dir)) != NULL) { 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct dirent *nde; 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (n_de >= n_dex) { 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct dirent **ndex; 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ndex = realloc(dex, (n_dex + DIR_CHUNK) * sizeof *dex); 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!ndex) 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto nomem; 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dex = ndex; 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman n_dex += DIR_CHUNK; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nde = malloc(de->d_reclen); 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!nde) 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto nomem; 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(nde, de, de->d_reclen); 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dex[n_de++] = nde; 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman maxlen = max(maxlen, de->d_reclen); 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman closedir(dir); 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman qsort(dex, n_de, sizeof *dex, compare_dirent); 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman maxlen -= offsetof(struct dirent, d_name) + 1; 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ncols = (cols + 2)/(maxlen + 8); 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ncols = min(ncols, n_de); 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ncols = max(ncols, 1U); 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman colwidth = (cols + 2)/ncols; 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman perpage = ncols * (rows - 1); 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < n_de; i += perpage) { 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Rows on this page */ 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman endpage = min(i+perpage, n_de); 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nrows = ((endpage-i) + ncols - 1)/ncols; 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (j = 0; j < nrows; j++) { 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pos = tpos = 0; 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (k = i+j; k < endpage; k += nrows) { 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pos += printf("%*s%-5s %s", 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (tpos - pos), "", 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman type_str(dex[k]->d_type), 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dex[k]->d_name); 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tpos += colwidth; 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("\n"); 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (endpage >= n_de) 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman get_key(stdin, 0); 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman free_dirents(dex, n_de); 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmannomem: 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman closedir(dir); 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("Out of memory error!\n"); 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman free_dirents(dex, n_de); 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -1; 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint main(int argc, char *argv[]) 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rv; 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (getscreensize(1, &rows, &cols)) { 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Unknown screen size? */ 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rows = 24; 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cols = 80; 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (argc < 2) 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = display_directory("."); 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (argc == 2) 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = display_directory(argv[1]); 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else { 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("Usage: dir directory\n"); 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = 1; 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rv ? 1 : 0; 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 176