#! /usr/bin/icmake -t.

// This script implements a non-destructive rm (am: attic move)

#define YEAR    "1994--2016"
#define VERSION "1.14.01"

#define ATTIC_DIR   "/.attic"	    // append after $HOME
#define ATTIC_ZIP   "attic.zip"	    // the zip-name
int
    flags_done,
    extract,
    viewmode,
    debug;

string
    home,
    attic,
    cwd,
    progname,
    recurs,
    forced,
    unzipflag;

void kill(string s)
{
    printf(s, "\n\n");
    exit(1);
}

void preamble(list argv, list envp)
{
    int
        index;

    cwd = chdir(".");                       // get cwd

    for (index = 0; home = element(index, envp); index += 2)
    {
        if (home == "HOME")                 // HOME found
        {                                   // get it
            home = element(index + 1, envp);
            break;                          // and done
        }
    }
    if (!home)
        kill("$HOME not found");

    progname = change_ext(element(0, argv), "");

    attic = home + ATTIC_DIR;                // set $HOME/.attic, change to
}

void check_attic()
{
    if (!exists(attic))                     // attic should exist
    {
        printf(attic, " does not exist. Create it [y/n] ? ");
        if (getch() != "y")                 // not a "y" ?
            kill("ok.");
        system("mkdir " + attic);           // make the attic subdir
        exec("chmod", 700, attic);          // private use
    }                                       // else attic must be dir
    else if (!((int)element(0, stat(attic)) & S_IFDIR))
        kill("'" + attic + "' is not a directory");

    attic += "/" + ATTIC_ZIP;               // append the zip-name
    chdir("/");                             // go to the root
}

void set_flags(string arg)
{
    int
        index;
    string
        flag;

                                            // process all arguments
    for (index = 1; flag = element(index, arg); index++)
    {
        if (flag == "r")                    // process encountered options
            recurs = "-r";
        else if (flag == "d")
            debug++;
        else if (flag == "f")
            forced = "-f";
        else if (flag == "x")
            extract++;
        else if (flag == "v")
        {
            extract++;
            viewmode++;
            unzipflag = "-l ";
        }
        else
            kill("Unrecognized flag '-" +
                 flag +
                 "': " +
                 progname +
                 "aborted");
    }

    if (extract && unzipflag == "")
        unzipflag = "-u ";                  // use proper unzip flag
}

list options(int argc, list argv)
{
    int
        index;
    list
        ret;
    string
        arg;

    for (index = 0; index < argc; index++)
    {
        arg = element(index, argv);         // get next argument
        if (element(0, arg) == "-")         // first element is a - ?
            set_flags(arg);                 // then set flags
        else
            ret += (list)arg;               // or add to list to return
    }

    return (ret);                           // returned list
}

void usage()
{
    printf
    (
        "\n"
        "ICCE AM (Attic Move) non-destructive remove. Version " VERSION "\n"
        "Copyright (c) ICCE " YEAR ". All Rights Reserved\n"
        "\n"
        "AM by Frank B. Brokken\n"
        "\n"
        "Usage: ", progname, " [options] file(s)\n"
        "Where:\n"
        "   options:\n"
        "       -d: Debug mode: no execution but display of commands\n"
        "       -f: Forced processing of indicated files\n"
        "       -r: Recursive removal of directory contents\n"
        "       -v: View current contents of the attic\n"
        "       -x: Extract files from the attic to their original place\n"
        "           (i.e., if you are permitted to do so...\n"
        "\n"
        "   file(s): names of files and directories to move to/from the attic\n"
        "\n"
        "   ", home, ATTIC_DIR, "/",  ATTIC_ZIP, " is used to store the files.\n"
        "\n"
    );
    exit (1);
}

string prefix_path(string file)
{
    string
        el,
        ret;
    int
        index;

    if (element(0, file) != "/")            // if file isn't an absolute path
        file = cwd + file;                  // then make an absolute path

    for (index = 1; el = element(index, file); index++)
        ret += el;                          // remove first char from abs path

    return (ret);                           // return modified string
}

void retrieve(string file)
{
    string
        cmd;

    cmd = "unzip "                          // update only
        + unzipflag
        + attic;

    if (!viewmode)
        cmd += " "
             + prefix_path(file);           // and the file (+ path prefix)

    if (debug)
        printf("( cd /; ", cmd, " )\n");    // debug: show command
    else
        system(cmd);                        // else exec cmd
}

void remove(string file)
{
    string
        cmd;

    cmd = "zip -my "                        // remove, remove links as links
        + forced                            // maybe forced
        + " "
        + recurs                            // maybe recursive
        + " "
        + attic                             // target zip
        + " "
        + prefix_path(file);                // and the file (+ path prefix)

    if (debug)
        printf("( cd /; ", cmd, " )\n");    // debug: show command
    else
        system(cmd);                        // else exec cmd
}

void one_file(string file)
{
    if (extract)                            // either retrieve or remove
        retrieve(file);                     // the file
    else
        remove(file);
}

void process(int argc, list argv)
{
    int
        index;

    for (index = 1; index < argc; index++)
        one_file(element(index, argv));     // process one file
}

int main(int argc, list argv, list envp)
{
    echo (OFF);

    preamble(argv, envp);                   // set progname and attic dir.

    argv = options(argc, argv);             // get the options
    argc = listlen(argv);                    // determine remaining arguments

    if (argc == 1 && !viewmode)             // none left and no viewmode ?
        usage();                            // give usage and exit 1

    check_attic();                          // check accessability of attic

    if (viewmode)                           // view contents
        retrieve("");
    else                                    // or
        process(argc, argv);                // process remaining arguments
    return (0);                             // done
}
