ds2.9a12/bin/
ds2.9a12/extra/
ds2.9a12/extra/crat/
ds2.9a12/extra/creremote/
ds2.9a12/extra/mingw/
ds2.9a12/extra/wolfpaw/
ds2.9a12/fluffos-2.14-ds13/
ds2.9a12/fluffos-2.14-ds13/Win32/
ds2.9a12/fluffos-2.14-ds13/compat/
ds2.9a12/fluffos-2.14-ds13/compat/simuls/
ds2.9a12/fluffos-2.14-ds13/include/
ds2.9a12/fluffos-2.14-ds13/testsuite/
ds2.9a12/fluffos-2.14-ds13/testsuite/clone/
ds2.9a12/fluffos-2.14-ds13/testsuite/command/
ds2.9a12/fluffos-2.14-ds13/testsuite/data/
ds2.9a12/fluffos-2.14-ds13/testsuite/etc/
ds2.9a12/fluffos-2.14-ds13/testsuite/include/
ds2.9a12/fluffos-2.14-ds13/testsuite/inherit/
ds2.9a12/fluffos-2.14-ds13/testsuite/inherit/master/
ds2.9a12/fluffos-2.14-ds13/testsuite/log/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/tests/compiler/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/tests/efuns/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/tests/operators/
ds2.9a12/fluffos-2.14-ds13/testsuite/u/
ds2.9a12/lib/cmds/admins/
ds2.9a12/lib/cmds/common/
ds2.9a12/lib/cmds/creators/include/
ds2.9a12/lib/daemon/services/
ds2.9a12/lib/daemon/tmp/
ds2.9a12/lib/doc/
ds2.9a12/lib/doc/bguide/
ds2.9a12/lib/doc/efun/all/
ds2.9a12/lib/doc/efun/arrays/
ds2.9a12/lib/doc/efun/buffers/
ds2.9a12/lib/doc/efun/compile/
ds2.9a12/lib/doc/efun/floats/
ds2.9a12/lib/doc/efun/functions/
ds2.9a12/lib/doc/efun/general/
ds2.9a12/lib/doc/efun/mixed/
ds2.9a12/lib/doc/efun/numbers/
ds2.9a12/lib/doc/efun/parsing/
ds2.9a12/lib/doc/hbook/
ds2.9a12/lib/doc/help/classes/
ds2.9a12/lib/doc/help/races/
ds2.9a12/lib/doc/lfun/
ds2.9a12/lib/doc/lfun/all/
ds2.9a12/lib/doc/lfun/lib/abilities/
ds2.9a12/lib/doc/lfun/lib/armor/
ds2.9a12/lib/doc/lfun/lib/bank/
ds2.9a12/lib/doc/lfun/lib/bot/
ds2.9a12/lib/doc/lfun/lib/clay/
ds2.9a12/lib/doc/lfun/lib/clean/
ds2.9a12/lib/doc/lfun/lib/clerk/
ds2.9a12/lib/doc/lfun/lib/client/
ds2.9a12/lib/doc/lfun/lib/combat/
ds2.9a12/lib/doc/lfun/lib/connect/
ds2.9a12/lib/doc/lfun/lib/container/
ds2.9a12/lib/doc/lfun/lib/corpse/
ds2.9a12/lib/doc/lfun/lib/creator/
ds2.9a12/lib/doc/lfun/lib/daemon/
ds2.9a12/lib/doc/lfun/lib/damage/
ds2.9a12/lib/doc/lfun/lib/deterioration/
ds2.9a12/lib/doc/lfun/lib/donate/
ds2.9a12/lib/doc/lfun/lib/door/
ds2.9a12/lib/doc/lfun/lib/equip/
ds2.9a12/lib/doc/lfun/lib/file/
ds2.9a12/lib/doc/lfun/lib/fish/
ds2.9a12/lib/doc/lfun/lib/fishing/
ds2.9a12/lib/doc/lfun/lib/flashlight/
ds2.9a12/lib/doc/lfun/lib/follow/
ds2.9a12/lib/doc/lfun/lib/ftp_client/
ds2.9a12/lib/doc/lfun/lib/ftp_data_connection/
ds2.9a12/lib/doc/lfun/lib/fuel/
ds2.9a12/lib/doc/lfun/lib/furnace/
ds2.9a12/lib/doc/lfun/lib/genetics/
ds2.9a12/lib/doc/lfun/lib/holder/
ds2.9a12/lib/doc/lfun/lib/id/
ds2.9a12/lib/doc/lfun/lib/interactive/
ds2.9a12/lib/doc/lfun/lib/lamp/
ds2.9a12/lib/doc/lfun/lib/leader/
ds2.9a12/lib/doc/lfun/lib/light/
ds2.9a12/lib/doc/lfun/lib/limb/
ds2.9a12/lib/doc/lfun/lib/living/
ds2.9a12/lib/doc/lfun/lib/load/
ds2.9a12/lib/doc/lfun/lib/look/
ds2.9a12/lib/doc/lfun/lib/manipulate/
ds2.9a12/lib/doc/lfun/lib/meal/
ds2.9a12/lib/doc/lfun/lib/messages/
ds2.9a12/lib/doc/lfun/lib/player/
ds2.9a12/lib/doc/lfun/lib/poison/
ds2.9a12/lib/doc/lfun/lib/position/
ds2.9a12/lib/doc/lfun/lib/post_office/
ds2.9a12/lib/doc/lfun/lib/potion/
ds2.9a12/lib/doc/lfun/lib/room/
ds2.9a12/lib/doc/lfun/lib/server/
ds2.9a12/lib/doc/lfun/lib/spell/
ds2.9a12/lib/doc/lfun/lib/torch/
ds2.9a12/lib/doc/lfun/lib/vendor/
ds2.9a12/lib/doc/lfun/lib/virt_sky/
ds2.9a12/lib/doc/lfun/lib/weapon/
ds2.9a12/lib/doc/lfun/lib/worn_storage/
ds2.9a12/lib/doc/lpc/basic/
ds2.9a12/lib/doc/lpc/concepts/
ds2.9a12/lib/doc/lpc/constructs/
ds2.9a12/lib/doc/lpc/etc/
ds2.9a12/lib/doc/lpc/intermediate/
ds2.9a12/lib/doc/lpc/types/
ds2.9a12/lib/doc/misc/
ds2.9a12/lib/doc/old/
ds2.9a12/lib/domains/
ds2.9a12/lib/domains/Praxis/adm/
ds2.9a12/lib/domains/Praxis/attic/
ds2.9a12/lib/domains/Praxis/cemetery/mon/
ds2.9a12/lib/domains/Praxis/data/
ds2.9a12/lib/domains/Praxis/death/
ds2.9a12/lib/domains/Praxis/mountains/
ds2.9a12/lib/domains/Praxis/obj/armour/
ds2.9a12/lib/domains/Praxis/obj/magic/
ds2.9a12/lib/domains/Praxis/obj/weapon/
ds2.9a12/lib/domains/Praxis/orc_valley/
ds2.9a12/lib/domains/Ylsrim/
ds2.9a12/lib/domains/Ylsrim/adm/
ds2.9a12/lib/domains/Ylsrim/armor/
ds2.9a12/lib/domains/Ylsrim/broken/
ds2.9a12/lib/domains/Ylsrim/fish/
ds2.9a12/lib/domains/Ylsrim/meal/
ds2.9a12/lib/domains/Ylsrim/npc/
ds2.9a12/lib/domains/Ylsrim/obj/
ds2.9a12/lib/domains/Ylsrim/virtual/
ds2.9a12/lib/domains/Ylsrim/weapon/
ds2.9a12/lib/domains/campus/adm/
ds2.9a12/lib/domains/campus/etc/
ds2.9a12/lib/domains/campus/meals/
ds2.9a12/lib/domains/campus/save/
ds2.9a12/lib/domains/campus/txt/ai/charles/
ds2.9a12/lib/domains/campus/txt/ai/charles/bak2/
ds2.9a12/lib/domains/campus/txt/ai/charles/bak2/bak1/
ds2.9a12/lib/domains/campus/txt/ai/charly/
ds2.9a12/lib/domains/campus/txt/ai/charly/bak/
ds2.9a12/lib/domains/campus/txt/jenny/
ds2.9a12/lib/domains/cave/doors/
ds2.9a12/lib/domains/cave/etc/
ds2.9a12/lib/domains/cave/meals/
ds2.9a12/lib/domains/cave/weap/
ds2.9a12/lib/domains/default/creator/
ds2.9a12/lib/domains/default/doors/
ds2.9a12/lib/domains/default/etc/
ds2.9a12/lib/domains/default/vehicles/
ds2.9a12/lib/domains/default/virtual/
ds2.9a12/lib/domains/default/weap/
ds2.9a12/lib/domains/town/txt/shame/
ds2.9a12/lib/domains/town/virtual/
ds2.9a12/lib/domains/town/virtual/bottom/
ds2.9a12/lib/domains/town/virtual/space/
ds2.9a12/lib/estates/
ds2.9a12/lib/ftp/
ds2.9a12/lib/lib/comp/
ds2.9a12/lib/lib/daemons/
ds2.9a12/lib/lib/daemons/include/
ds2.9a12/lib/lib/lvs/
ds2.9a12/lib/lib/user/
ds2.9a12/lib/lib/virtual/
ds2.9a12/lib/log/
ds2.9a12/lib/log/adm/
ds2.9a12/lib/log/archive/
ds2.9a12/lib/log/chan/
ds2.9a12/lib/log/errors/
ds2.9a12/lib/log/law/adm/
ds2.9a12/lib/log/law/email/
ds2.9a12/lib/log/law/names/
ds2.9a12/lib/log/law/sites-misc/
ds2.9a12/lib/log/law/sites-register/
ds2.9a12/lib/log/law/sites-tempban/
ds2.9a12/lib/log/law/sites-watch/
ds2.9a12/lib/log/open/
ds2.9a12/lib/log/reports/
ds2.9a12/lib/log/router/
ds2.9a12/lib/log/secure/
ds2.9a12/lib/log/watch/
ds2.9a12/lib/obj/book_source/
ds2.9a12/lib/obj/include/
ds2.9a12/lib/powers/prayers/
ds2.9a12/lib/powers/spells/
ds2.9a12/lib/realms/template/adm/
ds2.9a12/lib/realms/template/area/armor/
ds2.9a12/lib/realms/template/area/npc/
ds2.9a12/lib/realms/template/area/obj/
ds2.9a12/lib/realms/template/area/room/
ds2.9a12/lib/realms/template/area/weap/
ds2.9a12/lib/realms/template/bak/
ds2.9a12/lib/realms/template/cmds/
ds2.9a12/lib/save/kills/o/
ds2.9a12/lib/secure/cfg/classes/
ds2.9a12/lib/secure/cmds/builders/
ds2.9a12/lib/secure/cmds/creators/include/
ds2.9a12/lib/secure/cmds/players/
ds2.9a12/lib/secure/cmds/players/include/
ds2.9a12/lib/secure/daemon/imc2server/
ds2.9a12/lib/secure/daemon/include/
ds2.9a12/lib/secure/lib/
ds2.9a12/lib/secure/lib/include/
ds2.9a12/lib/secure/lib/net/include/
ds2.9a12/lib/secure/lib/std/
ds2.9a12/lib/secure/log/adm/
ds2.9a12/lib/secure/log/bak/
ds2.9a12/lib/secure/log/intermud/
ds2.9a12/lib/secure/log/network/
ds2.9a12/lib/secure/modules/
ds2.9a12/lib/secure/npc/
ds2.9a12/lib/secure/obj/include/
ds2.9a12/lib/secure/room/
ds2.9a12/lib/secure/save/
ds2.9a12/lib/secure/save/backup/
ds2.9a12/lib/secure/save/boards/
ds2.9a12/lib/secure/tmp/
ds2.9a12/lib/secure/upgrades/files/
ds2.9a12/lib/secure/verbs/creators/
ds2.9a12/lib/std/board/
ds2.9a12/lib/std/lib/
ds2.9a12/lib/tmp/
ds2.9a12/lib/verbs/admins/include/
ds2.9a12/lib/verbs/builders/
ds2.9a12/lib/verbs/common/
ds2.9a12/lib/verbs/common/include/
ds2.9a12/lib/verbs/creators/
ds2.9a12/lib/verbs/creators/include/
ds2.9a12/lib/verbs/rooms/
ds2.9a12/lib/verbs/rooms/include/
ds2.9a12/lib/www/client/
ds2.9a12/lib/www/errors/
ds2.9a12/lib/www/images/
ds2.9a12/lib/www/lpmuds/downloads_files/
ds2.9a12/lib/www/lpmuds/intermud_files/
ds2.9a12/lib/www/lpmuds/links_files/
ds2.9a12/win32/
/*    /cmd *    from Foundation II
 *    a faster, newer ls command
 *    created by Descartes of Borg 940724
 */

#include <lib.h>

inherit LIB_DAEMON;

static private mapping file_mapping(string *files);
static private string display_ls(mixed targ, int aflag, int lflag, int tflag,
  int nflag, int bflag, int sflag);
static private string long_list(string dir, mixed *files);
static private string short_list(string dir, mixed *files, int n, int s);

int cmd(string str) {
    string *args, *paths, *options, *files, *tmp, *dirs;
    string show;
    int moref, brief, size;
    int all_files, long_details, time_sort, no_load_info, i, x, maxi;

    if(str == "" || !str) str = (string)previous_object()->query_cwd();
    if(!str) return notify_fail("No current working directory.\n");
    i = sizeof(args = explode(str, " "));
    if(args[0][0] == '-') {
        if((x = strlen(args[0])) > 1) options = explode(args[0][1..x-1], "");
        else options = ({});
        if(i == 1) paths = ({ (string)previous_object()->query_cwd() });
        else paths = args[1..i-1];
    }
    else {
        options = ({});
        paths = args;
    }
    i = sizeof(options);
    while(i--) {
        switch(options[i]) {
        case "a": all_files = 1; break;
        case "l": long_details = 1; break;
        case "t": time_sort = 1; break;
        case "m": moref = 1; break;
        case "n": no_load_info = 1; break;
        case "b": brief = 1; break;
        case "s": size = 1; break;
        }
    }
    for(i=0, maxi = sizeof(paths), files = ({}); i<maxi; i++)
        if(tmp = (string *)wild_card(paths[i])) files += tmp;
    if(!sizeof(files)) { 
        message("error", "No such file or directory.", this_player());
        return 1;
    }
    dirs = filter(files, "is_dir", this_object());
    if(sizeof(files = files - dirs))
        show = display_ls(file_mapping(files),all_files,long_details, time_sort,
          no_load_info, brief, size);
    else show = "";
    if(!(maxi = sizeof(dirs))) {
        if(moref) previous_object()->more(explode(show, "\n"), "system");
        else message("system", show, previous_object());
        return 1;
    }
    for(i=0; i<maxi; i++){
        show += display_ls(dirs[i], all_files, long_details, time_sort, 
          no_load_info, brief, size);
    }
    if(!moref && check_string_length(show)) previous_object()->eventPrint(show);
    else print_long_string(this_player(),show);
    return 1;
}

static int is_dir(string str) { return (file_size(str) == -2); }

static private mapping file_mapping(string *files) {
    mapping borg;
    string *tmp;
    string dir;
    int i, maxi, x;

    for(i=0, maxi = sizeof(files), borg = ([]); i<maxi; i++) {
        x = sizeof(tmp = explode(files[i], "/"));
        if(x == 1) dir = "/";
        else dir = "/"+implode(tmp[0..x-2], "/")+"/";
        if(borg[dir]) borg[dir] += get_dir(dir+tmp[x-1], -1);
        else borg[dir] = get_dir(dir+tmp[x-1], -1);
    }
    return borg;
}

static private string display_ls(mixed targ, int aflag, int lflag, int tflag,
  int nflag, int bflag, int sflag) {
    string *cles;
    string ret = "";
    int i, maxi;

    if(stringp(targ) && targ == "/") targ = ([ "/" : get_dir("/", -1) ]);
else if(stringp(targ)){
    targ = "/"+implode(explode(targ,"/"),"/");
    targ = ([ targ : get_dir(targ+"/", -1) ]);
}
for(i=0, maxi = sizeof(cles = keys(targ)); i<maxi; i++) {
    if(!bflag) ret = cles[i]+":\n";
    if(!aflag) targ[cles[i]] = filter(targ[cles[i]], "filter_dots",
          this_object());
    if(tflag) 
        targ[cles[i]]=sort_array(targ[cles[i]],"time_sort",this_object());
    if(lflag) ret += long_list(cles[i], targ[cles[i]]);
    else ret += short_list(cles[i], targ[cles[i]], nflag, sflag);
    ret += "\n";
}
return ret;
}

static int filter_dots(mixed *file) { return (file[0][0] != '.'); }

static int time_sort(mixed *alpha, mixed *beta) {
    if(alpha[2] < beta[2]) return 1;
    else if(alpha[2] > beta[2]) return -1;
    else return 0;
}

static private string long_list(string dir, mixed *files) {
    string ret, acc, loaded;
    int i, maxi;

    if(!(maxi = sizeof(files))) return "";
    else ret = "";
    if((int)master()->valid_read(dir, previous_object())) acc = "r";
    else acc = "-";
    if((int)master()->valid_write(dir, previous_object())) acc += "w";
    else acc += "-";
    if(member_array(dir[0..strlen(dir)-2],
        (string *)previous_object()->GetSearchPath()) != -1) acc += "x";
    else acc += "-";
    for(i=0, maxi=sizeof(files); i<maxi; i++) {
        if(files[i][1] == -2) loaded = "";
        else loaded = (find_object(dir+files[i][0]) ? "*" : "");
        ret += sprintf("%:-3s%:-5s%:-30s %d\t%s", 
          loaded, acc, ctime(files[i][2]),
          files[i][1], files[i][0]);
        if(files[i][1] == -2) ret += "/\n";
        else ret += "\n";
    }
    return ret;
}

static private string short_list(string dir, mixed *files, int n, int s) {
    string *newfiles;
    string ret, tmp;
    int i, j, max, x, long, ind, cols, rows;

    i = sizeof(newfiles=map_array(files,"map_files",this_object(),({dir,n,s})));
    while(i--) if((x=strlen(newfiles[i])) > long) long = x;
    tmp = (string)previous_object()->GetEnvVar("SCREEN");
    if(!tmp || !sscanf(tmp, "%d", x) || !x) x = 80;
    x = x-2;
    if(long > x/3-3) long = x/3-3;
    cols = x/(long+3);
    rows = (max = sizeof(newfiles))/cols;
    if(max % cols) rows++;
    ret = "";
    for(i=0; i<rows; i++) {
        for(j=0; j<cols; j++) {
            ind = (rows * j) + i;
            if(ind < max) ret += sprintf("%:-"+(long+3)+"s", newfiles[ind]);
            else ret += sprintf("%:-"+(long+3)+"s", "");
        }
        ret += "\n";
    }
    return ret;
}

static string map_files(mixed *file, int *flags) {
    string tmp;

    if(flags[1] && flags[2]) {
        if(file[1] == -2) return file[0]+"/";
        else return file[0];
    }
    if(!flags[1]) {
        if(find_object((string)flags[0]+file[0]) && file[1] != -2) tmp = "*";
        else tmp = " ";
    }
    else tmp = "";
    if(!flags[2]) {
        if(file[1] == -2) tmp = tmp + "    ";
        else if(!file[1]) tmp = tmp + "0   ";
        else if(file[1] < 1024) tmp = " 1   ";
        else tmp = sprintf("%s%:-3d ", tmp, (file[1]/1024));
    }
    return tmp + file[0] + ((file[1] == -2) ? "/" : "");
}

void help() {
    message("help", "Syntax: <ls [-ablmnst] (directories|files)>\n\n"
      "If you pass a single directory as an argument, it will list all "
      "files and directories in that directory.  If you list a single "
      "file, then information about that file will be displayed.  If you "
      "use special characters like wild cards, then relevant information "
      "regarding those files and/or directories will be displayed.  The "
      "options have the following meanings:\n"
      "    -a List all files, including files beginning with a '.'\n"
      "    -b Brief listing, leaving out the directory name\n"
      "    -l Long listing of all details about a file\n"
      "    -m Page the output through more\n"
      "    -n No display of loaded object information\n"
      "    -s No display of size information\n"
      "    -t Sort directory listings by time last modified\n\n"
      "The -l option overrides the -n and -s options.  The columns "
      "in the -l listing break down in the following manner:\n"
      "    * if loaded, blank space if not loaded\n"
      "    Access permissions, in the form of rwx\n"
      "    Time last modified\n"
      "    Size of the file\n"
      "    File name\n\nSee also: cd, mkdir, mv, pwd, rm, rmdir", 
      this_player());
}