ICMAKE Part 4

In part 1, Brokken and Kubat explained where the ideas for icmake came from, the basics of the program and where you can get a copy. In Parts 2 and 3 we covered the grammar of icmake source files. In this final part of the article we show examples of the use of icmake.
5.3. The Attic Move script.
#! /usr/local/bin/icmake -qi
/*
       This script is used to implement a non-destructive rm
*/
#define YEAR    "1993, 1994"
#define VERSION "1.10"
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";      // 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";              // 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";
        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/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 = sizeof(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
}
______________________

Geek Guide
The DevOps Toolbox

Tools and Technologies for Scale and Reliability
by Linux Journal Editor Bill Childers

Get your free copy today

Sponsored by IBM

Webcast
8 Signs You're Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
On Demand
Moderated by Linux Journal Contributor Mike Diehl

Sign up and watch now

Sponsored by Skybot