
/*
 *  SECURITY.C
 *
 *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
 *
 *  Checks whether a given file should be allowed to be read or written
 *
 *  Lock directory containing file
 *  Generate directory path
 *  Check path against allowed list (UULIB:Security)
 *
 *  If type == 'c' return  1 if file name begins with a C.
 *		   return -1 if file name does not begin with a C.
 *		   return  0 if file name begins with a C. but is for
 *		    a directory other than the current one.
 */

#include <proto/all.h>
#include <libraries/dosextens.h>
#include <stdio.h>

typedef struct FileLock FileLock;

static char TmpBuf[128];

SecurityDisallow(file, type)
char *file;
{
    char *fs;
    char c;
    int  disallow = 1;
    BPTR lock;
    BPTR slock;

    for (fs = file + strlen(file); fs >= file && *fs != '/' && *fs != ':'; --fs);
    ++fs;
    if (fs == file) {           /*  just a file name    */
	if (type == 'c') {
	    if ((file[0]|0x20) == 'c' && file[1] == '.')
		return(1);
	    return(-1);
	}
	return(0);              /*  type r or w, current dir, allow. */
    }
    if (type == 'c')            /*  not just a file name, allow C.   */
	return(0);
    c = *fs;
    *fs = 0;		/*  keep just the path	    */

    lock = Lock(file, SHARED_LOCK);
    if (lock) {
	FILE *fi = fopen("UULIB:Security", "r");
	if (fi) {
	    while (fgets(TmpBuf, sizeof(TmpBuf), fi)) {
		char *ptr;
		if (TmpBuf[0] == '#' || TmpBuf[0] == '\n' || TmpBuf[0] == 0)
		    continue;

		/*
		 *  breakout the directory name and permissions
		 */

		for (ptr = TmpBuf; *ptr != '\n' && *ptr != ' ' && *ptr != 9; ++ptr);
		*ptr = 0;

		/*
		 *  permissions allowed?
		 */

		for (++ptr; *ptr && *ptr != type; ++ptr);
		if (*ptr == 0)      /*  sorry   */
		    continue;

		if (slock = Lock(TmpBuf, SHARED_LOCK)) {
		    if (SameLock(lock, slock))
			disallow = 0;
		    UnLock(slock);
		}
		if (disallow == 0)
		    break;
	    }
	    fclose(fi);
	}
	UnLock(lock);
    }

    *fs = c;		/*  restore path    */

    return(disallow);
}

SameLock(lock, slock)
BPTR lock, slock;
{
    FileLock *fl1 = (FileLock *)((long)lock << 2);
    FileLock *fl2 = (FileLock *)((long)slock << 2);

    if (fl1->fl_Task == fl2->fl_Task && fl1->fl_Key == fl2->fl_Key)
	return(1);
    return(0);
}

