
/*
 * rmf.c -- remove a folder
 *
 * $Id$
 */

#include <h/mh.h>

static struct swit switches[] = {
#define	INTRSW            0
    { "interactive", 0 },
#define	NINTRSW           1
    { "nointeractive", 0 },
#define VERSIONSW         2
    { "version", 0 },
#define	HELPSW            3
    { "help", 4 },
    { NULL, 0 }
};

/*
 * static prototypes
 */
static int rmf(char *);
static void rma (char *);


main (int argc, char **argv)
{
    int defolder = 0, interactive = -1;
    char *cp, *folder = NULL, newfolder[BUFSIZ];
    char buf[100], **ap, **argp, *arguments[MAXARGS];

#ifdef LOCALE
	setlocale(LC_ALL, "");
#endif
    invo_name = r1bindex (argv[0], '/');
    if ((cp = m_find (invo_name)) != NULL) {
	ap = brkstring (cp = getcpy (cp), " ", "\n");
	ap = copyip (ap, arguments);
    }
    else
	ap = arguments;
    copyip (argv + 1, ap);
    argp = arguments;

    while ((cp = *argp++)) {
	if (*cp == '-')
	    switch (smatch (++cp, switches)) {
		case AMBIGSW: 
		    ambigsw (cp, switches);
		    done (1);
		case UNKWNSW: 
		    adios (NULL, "-%s unknown", cp);

		case HELPSW: 
		    sprintf (buf, "%s [+folder] [switches]", invo_name);
		    print_help (buf, switches);
		    done (1);
		case VERSIONSW:
		    print_version(invo_name);
		    done (1);

		case INTRSW: 
		    interactive = 1;
		    continue;
		case NINTRSW: 
		    interactive = 0;
		    continue;
	    }
	if (*cp == '+' || *cp == '@') {
	    if (folder)
		adios (NULL, "only one folder at a time!");
	    else
		folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
	}
	else
	    adios (NULL, "usage: %s [+folder] [switches]", invo_name);
    }

    if (!m_find ("path"))
	free (path ("./", TFOLDER));
    if (!folder) {
	folder = m_getfolder ();
	defolder++;
    }
    if (strcmp (m_mailpath (folder), pwd ()) == 0)
	adios (NULL, "sorry, you can't remove the current working directory");

    if (interactive == -1)
	interactive = defolder;

    if (strchr (folder, '/') && (*folder != '/') && (*folder != '.')) {
	for (cp = copy (folder, newfolder); cp > newfolder && *cp != '/'; cp--)
	    continue;
	if (cp > newfolder)
	    *cp = '\0';
	else
	    strcpy (newfolder, (cp = m_find (inbox)) ? cp : defalt);
    }
    else
	strcpy (newfolder, (cp = m_find (inbox)) ? cp : defalt);

    if (interactive) {
	cp = concat ("Remove folder \"", folder, "\"? ", NULL);
	if (!getanswer (cp))
	    done (0);
	free (cp);
    }

    if (rmf (folder) == OK && strcmp (m_find (pfolder), newfolder)) {
	printf ("[+%s now current]\n", newfolder);
	m_replace (pfolder, newfolder);
    }
    m_update ();

    done (0);
}

static int
rmf (char *folder)
{
    int i, j, others;
    register char *maildir;
    char cur[BUFSIZ];
    register struct dirent *dp;
    register DIR *dd;

    switch (i = chdir (maildir = m_maildir (folder))) {
	case OK: 
	    if (access (".", W_OK) != NOTOK && access ("..", W_OK) != NOTOK)
		break;		/* fall otherwise */

	case NOTOK: 
	    sprintf (cur, "atr-%s-%s", current, m_mailpath (folder));
	    if (!m_delete (cur)) {
		printf ("[+%s de-referenced]\n", folder);
		return OK;
	    }
	    advise (NULL, "you have no profile entry for the %s folder +%s",
		    i == NOTOK ? "unreadable" : "read-only", folder);
	    return NOTOK;
    }

    if ((dd = opendir (".")) == NULL)
	adios (NULL, "unable to read folder +%s", folder);
    others = 0;

    j = strlen(BACKUP_PREFIX);
    while ((dp = readdir (dd))) {
	switch (dp->d_name[0]) {
	    case '.': 
		if (strcmp (dp->d_name, ".") == 0
			|| strcmp (dp->d_name, "..") == 0)
		    continue;	/* else fall */

	    case ',': 
#ifdef	MHE
	    case '+': 
#endif	/* MHE */
#ifdef	UCI
	    case '_': 
	    case '#': 
#endif	/* UCI */
		break;

	    default: 
		if (m_atoi (dp->d_name))
		    break;
		if (strcmp (dp->d_name, LINK) == 0
			|| strncmp (dp->d_name, BACKUP_PREFIX, j) == 0)
		    break;

		admonish (NULL, "file \"%s/%s\" not deleted",
			folder, dp->d_name);
		others++;
		continue;
	}
	if (unlink (dp->d_name) == NOTOK) {
	    admonish (dp->d_name, "unable to unlink %s:", folder);
	    others++;
	}
    }

    closedir (dd);

    rma (folder);

    chdir ("..");
    if (others == 0 && remdir (maildir))
	return OK;

    advise (NULL, "folder +%s not removed", folder);
    return NOTOK;
}


static void
rma (char *folder)
{
    register int alen, j, plen;
    register char *cp;
    register struct node *np, *pp;

    alen = strlen ("atr-");
    plen = strlen (cp = m_mailpath (folder)) + 1;

    m_getdefs ();
    for (np = m_defs, pp = NULL; np; np = np->n_next)
	if (ssequal ("atr-", np->n_name)
		&& (j = strlen (np->n_name) - plen) > alen
		&& *(np->n_name + j) == '-'
		&& strcmp (cp, np->n_name + j + 1) == 0) {
	    if (!np->n_context)
		admonish (NULL, "bug: m_delete(key=\"%s\")", np->n_name);
	    if (pp) {
		pp->n_next = np->n_next;
		np = pp;
	    }
	    else
		m_defs = np->n_next;
	    ctxflags |= CTXMOD;
	}
	else
	    pp = np;
}
