/* This file is part of the Project Athena Zephyr Notification System.
 * It contains code for the "znol" command.
 *
 *	Created by:	Robert French
 *
 *      $Id: znol.c,v 1.11 2001/01/11 05:27:54 lha Exp $
 *
 *	Copyright (c) 1987 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */

#include <sysdep.h>
#include <zephyr/zephyr.h>
#include <roken.h>

#include <pwd.h>

RCSID("$Id: znol.c,v 1.11 2001/01/11 05:27:54 lha Exp $");

#define SUBSATONCE 7
#define ON 1
#define OFF 0

static int verbose = 0;


static void
usage(const char *progname)
{
    fprintf(stderr,
	    "Usage: %s [on|off] "
	    "[-q | -l] [-R realm] [-f file | -u username]\n",
	    progname);
    exit (1);
}

/*
 *
 */

int
main(int argc, char **argv)
{
    char *cp;
    ZSubscription_t subs[SUBSATONCE];
    FILE *fp;
    struct passwd *pwd;
    char anyonename[BUFSIZ],name[BUFSIZ],
	cleanname[BUFSIZ],realmname[BUFSIZ],*envptr;
    char *zrealm = realmname;
    char *comment_ptr;
    int onoff = ON,quiet = 0,justlist = 0,useronly = 0, filenamed = 0;
    int retval,arg,ind,one,numlocs;
    short wgport;
    
    if ((retval = ZInitialize()) != ZERR_NONE) {
	com_err(argv[0],retval,"initializing");
	exit (1);
    }
    
    strlcpy (realmname, ZGetDefaultRealm(), sizeof(realmname));
    
    for (arg=1;arg<argc;arg++) {
	if (!strcmp(argv[arg],"on")) {
	    onoff = ON;
	    continue;
	}
	if (!strcmp(argv[arg],"off")) {
	    onoff = OFF;
	    continue;
	} 
	if (argv[arg][0] == '-') {
	    char opt = argv[arg][1];
	    if (opt == 0 || argv[arg][2] != 0)
		usage (argv[0]);
	    switch (argv[arg][1]) {
	    case 'q':
		quiet = 1;
		break;
	    case 'l':
		justlist = 1;
		break;
	    case 'v':
		verbose = 1;
		break;
	    case 'f':
		if (arg == argc-1) {
		    fprintf(stderr,"No file name specified\n");
		    usage (argv[0]);
		}
		(void) strcpy(anyonename,argv[++arg]);
		filenamed = 1;
		break;
	    case 'u':
		if (arg == argc-1) {
		    fprintf(stderr,"No username specified\n");
		    usage (argv[0]);
		}
		(void) strcpy(cleanname,argv[++arg]);
		useronly = 1;
		break;
	    case 'R':
		if (arg == argc-1) {
		    fprintf(stderr,"No realm name specified\n");
		    usage (argv[0]);
		}
		(void) strcpy(realmname,argv[++arg]);
		useronly = 1;
		break;
	    default:
		usage (argv[0]);
	    }
	    continue;
	}
    }
    
    if (quiet && justlist) {
	fprintf(stderr,"-q and -l cannot both be used\n");
	usage (argv[0]);
    } 
    if (useronly && filenamed) {
	fprintf(stderr,"-u and -f cannot both be used\n");
	usage (argv[0]);
    } 
    if (!justlist)
	if ((wgport = ZGetWGPort()) == -1) {
	    com_err(argv[0],errno,"while getting WindowGram port");
	    exit(1);
	}
    
    if (!useronly) {
	/* If no filename specified, get the default */
	if (!filenamed) {
	    envptr = getenv("HOME");
	    if (envptr)
		(void) strcpy(anyonename,envptr);
	    else {
		if (!(pwd = getpwuid(getuid()))) {
		    fprintf(stderr,"You are not listed in the password file.\n");
		    exit (1);
		}
		(void) strcpy(anyonename,pwd->pw_dir);
	    }
	    (void) strcat(anyonename,"/.anyone");
	}
	
	/* if the filename is "-", read stdin */
	if (strcmp(anyonename,"-") == 0) {
	    fp = stdin;
	} else if (!(fp = fopen(anyonename,"r"))) {
	    fprintf(stderr,"Can't open %s for input\n",anyonename);
	    exit (1);
	}
    }
    
    ind = 0;
    
    for (;;) {
	zrealm = realmname;

	if (!useronly) {
	    if (!fgets(cleanname,sizeof cleanname,fp))
		break;
	    if (cleanname[0] == '#' || cleanname[0] == '\0' ||
		cleanname[0] == '\n')
		continue;	/* ignore comment and empty lines */
	    if ((comment_ptr = strchr(cleanname, '#')) != NULL)
		*comment_ptr = '\0'; /* Ignore from # onwards */
	    /* Get rid of old-style nol entries, just in case */
	    cp = cleanname + strlen(cleanname) - 1;
	    if (*cp == '\n')
		*cp = '\0';
	    while(*--cp == ' ')
		*cp = '\0';
	    if (strncmp(cleanname, "%REALM", 6) == 0) {
		cp = cleanname + 6;
		while (isspace((unsigned char)*cp))
		    cp++;
		if (*cp == '\0') {
		    fprintf (stderr, "WARN: strange realname");
		    continue;
		}
		strlcpy (realmname, cp, sizeof(realmname));
	    }
	    if ((cp = strchr(cleanname, '%')) != NULL) {
		*cp = '\0';
		if (cp[1] != '\0')
		    zrealm = cp + 1;
	    }
	    if (*cleanname == '@' || !*cleanname)
		continue;
	} else if (ind)
	    break;		/* only do the one name */
	
	subs[ind].zsub_class = LOGIN_CLASS;
	if (strchr (cleanname, '@') != NULL)
	    strlcpy (name, cleanname, sizeof(name));
	else
	    snprintf (name, sizeof(name), "%s@%s", cleanname, ZGetRhs(zrealm));
	subs[ind].zsub_classinst = estrdup(name);
	subs[ind++].zsub_recipient = "";
	
	if (!quiet && onoff == ON) {
	    if ((retval = ZNewLocateUser (zrealm,name,&numlocs,ZAUTH))
		!= ZERR_NONE) {
		com_err(argv[0],retval,"locating user");
		exit(1);
	    }
	    one = 1;
	    if (numlocs) {
		if (strcmp(zrealm, ZGetDefaultRealm()) == 0) {
		    printf("%s", cleanname);
		} else {
		    /*
		     * If zrealm and user is in the same realm
		     * print it as user%REALM
		     */
		    cp = strchr(name, '@');
		    if (cp != NULL && strcmp (cp + 1, zrealm) == 0) {
			*cp = '\0';
		    }

		    printf ("%s%%%s", name, zrealm);
		}
		printf ("\n");
	    }
	}
	
	if (ind == SUBSATONCE) {
	    if (!justlist)
		if ((retval = (onoff==ON)?
		     ZSubscribeToSansDefaults(zrealm,subs,ind,(u_short)wgport):
		     ZUnsubscribeTo(zrealm,subs,ind,(u_short)wgport)) !=
		    ZERR_NONE) {
		    com_err(argv[0],retval,(onoff==ON)?
			    "subscribing":
			    "unsubscribing");
		    exit(1);
		} 
	    for (ind=0;ind<SUBSATONCE;ind++)
		free(subs[ind].zsub_classinst);
	    ind = 0;
	}
    }
    
    if (ind && !justlist)
	if ((retval = (onoff==ON)?
	     ZSubscribeTo(zrealm,subs,ind,(u_short)wgport):
	     ZUnsubscribeTo(zrealm,subs,ind,(u_short)wgport)) !=
	    ZERR_NONE) {
	    com_err(argv[0],retval,(onoff==ON)?
		    "subscribing":
		    "unsubscribing");
	    exit(1);
	} 
    
    if (!useronly)
	(void) fclose(fp);		/* file is open read-only,
					   ignore errs */
    exit(0);
}
