2.9BSD/usr/contrib/notes/access.c

Compare this file to the similar file:
Show the results in this format:

static char *sccsid = "@(#)access.c	1.2 2/1/83";

#include "parms.h"
#include "structs.h"
/*
 *	access - process access list editing
 *
 *	functions include:
 *	(1) display access lists
 *	(2) insert new entries
 *	(3) delete old entries
 *	(4) modify existing entries
 *
 *	Original Coding: Ray Essick	January 1982
 */
#include <pwd.h>
#include <grp.h>			/* /etc/passwd and /etc/group formats */

char   *kmap[] =			/* mapping for name types */
{
    "usr:", "grp:", "sys:"
};
char   *map[] =
{
     /* ---- */ "Null",
     /* ---r */ "Read Only",
     /* --w- */ "(02)",
     /* --wr */ "(03)",
     /* -d-- */ "(04)",					/* nonsense */
     /* -d-r */ "(05)",					/* nonsense */
     /* -dw- */ "(06)",					/* nonsense */
     /* -dwr */ "(07)",
     /* a--- */ "Answer Only",				/* nonsense */
     /* a--r */ "Read/Answer",
     /* a-w- */ "Write only",
     /* a-wr */ "Read/Write",
     /* ad-- */ "(014)",				/* nonsense */
     /* ad-r */ "(015)",				/* nonsense */
     /* adw- */ "(016)",				/* nonsense */
     /* adwr */ "Director/R/W"
};

struct perm_f   entry;
struct perm_f   alist[NPERMS];		/* hold the access list */
access (io)
struct io_f *io;			/* notefile working with */
{
    struct passwd  *getpwnam ();
    struct group   *getgrnam ();	/* check validity of name/group */
    FILE * acs, *fopen ();		/* stream I/O */
    char    fn[WDLEN];
    struct auth_f   me;			/* for detecting suicidals */

    int     items,
            base,
            i,
            which,
            changed;
    char    c;
    short ptype;
    char    zname[NAMESZ + 1];		/* hold new user */


    sprintf(fn, "%s/%s/%s", MSTDIR, io->nf, ACCESS); /* file name */
    x ((acs = fopen(fn, "r")) == NULL, "access: no access file");
    x ((items = fread(alist, sizeof entry, NPERMS, acs)) == 0, "access: empty file");
    fclose(acs);			/* and close the file */
    changed = 0;			/* no changes made to the list yet */
    base = 0;				/* which part are we displaying */
    erase();
    plotit(base, items);
    while(1) {
	cmdprompt();
	c = gchar();					/* grab command */
	switch(c) {
	    case '?': 
	    case 'h': 
		help(ACCHLP);			/* print the help page */
		goto redraw;			/* redraw the screen */

	    case '!': 				/* fork a shell for him */
		gshell();
		goto redraw;

	    case 'K':
	    case 'Q': 
		return(0);			/* return to the caller */

	    case '\004': 			/* abort notefiles */
		return(QUITFAST);

	    case 'k':
	    case 'q': 		/* update lists (if changed) and leave) */
		if (changed) {
		    acssort(items);			/* order them */
		    ignsigs++;
		    x ((acs = fopen(fn, "w")) == NULL, "access: reopen");
		    x (fwrite(alist, sizeof entry, items, acs) != items,
			"access:update write");
		    fclose(acs);		/* and close the file */
		    ignsigs--;
		}
		return(0);

	    case '-': 				/* scroll display backwards */
		base -= (nrows - 6);		/* back a half sreen */
		if (base < 0) {
		    base = 0;			/* don't pass zero */
		}
		goto redraw;

	    case '+': 				/* scroll display forwards */
		base += (nrows - 6);		/* up half screen */
		if (base >= items) {
		    base = items - (nrows - 6);		/* don't over-run */
		}
		goto redraw;

	    case 's': 				/* sort and redraw the list */
		acssort (items);		/* do the sort */
						/* and fall through to ... */
		break;

	    case 'r': 		/* redraw the lists */
	    case '\014': 	/* everyone else uses ^L, might as well */
	redraw: 
		erase();
		plotit(base, items);
		break;			/* back to command sucker */

	    case 'i': 			/* enter a bunch of permissions */
		while (items < NPERMS) {		/* not if all full */
	    reget:  at(-4, 40);
		    putstr("Entry type:  \b");
		    c = gchar();
		    if (c == '\n' || c == '\r' || c == 'q')
			break;				/* get out */
		    switch (c) {
			case 'u': 
			    ptype = PUSER;
			    break;

			case 'g': 
			    ptype = PGROUP;
			    break;
			     
			case 's': 
			    ptype = PSYSTEM;
			    break;

			default: 
			    putstr("\07  (u,g,s,q,<cr>)");
			    goto reget;
		    }
		    putch(c);
		    at(-3, 40);
		    putstr("Name: ");
		    clear_eol();
		    if (gline(zname, NAMESZ) == 1)
			continue;			/* null name */
		    if (ptype == PUSER && strcmp ("Other", zname) != 0)
		    {
			if (getpwnam (zname) == NULL)
			{
			    at (-2, 40);
			    putstr("--No such user-- ");
			    continue;
			}
		    }
		    if (ptype == PGROUP && strcmp ("Other", zname) != 0)
		    {
			if (getgrnam (zname) == NULL)
			{
			    at (-2, 40);
			    putstr("--No such group--");
			    continue;
			}
		    }

		    alist[items].perms = DFLTPERMS;     /* give him default */
		    getmode(&alist[items].perms);
		    alist[items].ptype = ptype;
		    strmove(zname, alist[items].pname); /* copy things over */
		    items++;
		    changed = 1;			/* and set flags */
		    acssort(items);
		    erase();				/* clean screen */
		    plotit(base, items);		/* show new list */
		}
		endpwent();
		endgrent();				/* close passwd and group files */
		break;


	    case 'd': 					/* delete some permissions */
		prompt("Delete entry #: ");
		if ((c = gchar()) == '\n' || c == '\r')
		    break;				/* null */
		which = getnum(c);			/* grab number */
		if (which <= 0)
		    break;				/* don't update */
		if (which > items || c < '0' || c > '9')
		{
		    warn("Bad entry");
		    break;
		}
		which--;				/* adjust to zero base */
		getname(&me, 0);			/* grab my name */
		if ((alist[which].ptype = PUSER) && strcmp (me.aname, alist[which].pname) == 0)
		{
		    warn("Can't Delete self");
		    break;
		}
		items--;			/* decrement count  and */
		for (i = which; i < items; i++) {	/* tamp down list */
		    alist[i].ptype = alist[i + 1].ptype;
		    strmove(alist[i + 1].pname, alist[i].pname);
		    alist[i].perms = alist[i + 1].perms;
		}
		changed = 1;			/* mark it as changed */
		goto redraw;			/* show updated screen */

	    case 'm': 				/* modify someones permission */
		prompt("Modify entry #: ");
		if ((c = gchar()) == '\n' || c == '\r') {
		    break;				/* null entry */
		}
		which = getnum(c);
		if (which <= 0) {
		    break;
		}
		/* check its validity */
		if (which > items || c < '0' || c > '9') {
		    warn("Bad entry");
		    break;
		}
		which--;			/* adjust to zero base */
		getmode(&alist[which].perms);
		changed = 1;			/* set changed flag */
		goto redraw;			/* repaint screen */

	    default: 				/* wrong key dummy */
		putch('\07');
		break;
	}
    }
}

acscmp(a, b)
struct perm_f  *a,
               *b;
{
		/* people before groups and systems */
    if (a->ptype < b->ptype) {
	return(-1);
    }
    if (a->ptype > b->ptype) {
	return(1);
    }
    if (strcmp ("Other", a->pname) == 0) {
	if (strcmp ("Other", b->pname) == 0) {
	    return(0);
	} else {
	    return(1);					/* put "Other" last */
	}
    }
    if (strcmp ("Other", b->pname) == 0) {
	return - 1;					/* is correct */
    }
    return(strcmp(a->pname, b->pname));
}

acssort(items)					/* sort the access list */
{
    qsort(alist, items, sizeof entry, acscmp);
}

getmode(zmode)
short *zmode;
{						/* grab a mode from the tty */
    char    c;
    short mode;					/* resulting mode */
    char buf[80];

    mode = *zmode;				/* set to what passed in */

    while (1) {
	at(-2, 40);
	sprintf(buf, "Mode: %s", map[mode]);
	putstr(buf);
	clear_eol();
	at(-1, 40);
	putstr("Mods: ");
again:
	c = gchar();
	switch(c) {
	    case 'a': 				/* toggle answer */
		if (mode & WRITOK) {
		    break;			/* write supersedese */
		}
		if (mode & RESPOK) {
		    mode &= NOT RESPOK;
		} else {
		    mode |= RESPOK;
		}
		break;

	    case 'r': 				/* toggle read */
		if (mode & DRCTOK) {
		    break;			/* director supersedes */
		}
		if (mode & READOK) {
		    mode &= NOT READOK;
		} else {
		    mode |= READOK;
		}
		break;

	    case 'w': 				/* toggle write */
		if (mode & DRCTOK) {
		    break;			/* director supersedes */
		}
		if (mode & WRITOK) {
		    mode &= NOT WRITOK;
		} else {
		    mode |= WRITOK + RESPOK;
		}
		break;

	    case 'd': 				/* toggle director */
		if (mode & DRCTOK) {
		    mode &= NOT DRCTOK;
		} else {
		    mode |= DRCTOK + READOK + WRITOK + RESPOK;
		}
		break;

	    case 'n': 				/* set to null */
		mode = 0;
		break;

	    case '\n':				/* acceptable to him, return */
	    case 'q': 
		return(*zmode = mode);		/* do both ways */

	    default: 
		putstr("\07  (d,r,w,a,n,q,<cr>)");
		goto again;
	}
	putch(c);
    }
}

plotit (base, items)					/* plot the list */
{
    register int    atrow,
                    length,
                    atcol,
                    i;

    atrow = 1;
    atcol = 1;
    length = nrows - 6;					/* maximum in a col */
    for (i = base; i < items && i - base < 2 * length; i++) {
	at(atrow++, atcol);
	printf("%2d %s%-*s %s", i + 1, kmap[alist[i].ptype], NAMESZ,
		alist[i].pname, map[alist[i].perms]);
	if (atrow > length) {
	    atrow = 1;
	    atcol += 40;
	}
    }
}