#	$RCSfile: handle.pl,v $
#	$Revision: 0.13 $
#	$Author: marten $
#	$Date: 1994/01/14 14:21:55 $

# handle.pl - all nichandle generation and lookup routines.

require "entype.pl";
require "defines.pl";
require "adderror.pl";
require "syslog.pl";

sub OpenHandleDB {

    local($name, *db) = @_;

    open(DB, ">$name") || warn "$!" || return 0;
    dbmopen(%db, "$name", 0666) || warn "$!" || return 0;

    return 1;
}

sub CloseHandleDB {

    local(*db) = @_;

    close(DB);
    dbmclose(db);
}

sub LockHandleDB {

    local(*db) = @_;

    flock(DB, $LOCK_EX);
}

sub UnlockHandleDB {

    local(*db) = @_;

    flock(DB, $LOCK_UN);
}

sub LookupHandle {

    # Will lookup either handle associated
    # with a name, or name associated with
    # handle. Returns an array with the
    # values, and the number of elements in
    # the array.
    # Needs a objecttype to find the correct database

    local($lookupstring, $objecttype) = @_;
    local($stat) = 0;
    local(%handle) = ();
    local($value) = "";

    $stat = &OpenHandleDB($HANDLEDB{$objecttype}, *handle);

    if (!$stat) {
	return -1;
    }

    $value = $handle{$lookupstring};

    &CloseHandleDB(*handle);
    
    local(@tmp) = split(/,/, $value);

    return $#tmp+1, @tmp;
}

sub GenInitials {

    # Will generate initials for a new nic handle

    local($string) = @_;
    local($initials) = "";

    local(@tmp) = split(/\s+/, $string);

    if ($tmp[0] =~ /^(.).*-(.)/) {
	$initials = $1.$2;
    } elsif ($tmp[0] =~ /^(.)/) {
	$initials = $1;
    }

    if (($#tmp > 1) && (length($initials) < 2)) {
	if ($tmp[$#tmp-1] =~ /^(.)/) {
	    $initials .= $1;
	}
    }

    if ($tmp[$#tmp] =~ /^(.)/) {
	$initials .= $1;
    }

    $initials =~ tr/a-z/A-Z/;

    return $initials;

}

sub DeleteHandle {

    local(*object) = @_;
    local($person, $handle) = "";
    local(%db) = ();

    local($type) = &entype(*object);
    
    return 0 if (!$HANDLEATTR{$type});

    $stat = &OpenHandleDB($HANDLEDB{$type}, *db);

    if (!$stat) {
	&syslog("ERRLOG", "error opening handle database: $!");
        &CloseHandleDB(*db);
        &adderror(*object, "Unable to open handle database");
	return -1;
    }

    $handle = $object{$HANDLEATTR{$type}};
    $key = $object{$type};

    &LockHandleDB(*db);

    delete $db{$handle};

    if ($db{$key} =~ /^$handle$/) { delete $db{$key};}
    elsif ($db{$key} =~ s/^$handle,//) {}
    elsif ($db{$key} =~ s/,$handle,/,/) {}
    elsif ($db{$key} =~ s/,$handle$//) {}

    &UnlockHandleDB(*db);

    &CloseHandleDB(*db);

    return 1;
}

#
# AssignHandle
#
# Assigns a NIC handle to a person object
# Returns nic handle and inserts handle in
# person object.
# Does not use LookupHandle, because doing
# it ourself is faster.

sub AssignHandle {

    local(*object, $choice) = @_;
    local($i) = 0;
    local($initials) = "";
    local(%db)= ();
    local($stat) = 0;
    local($nichandle) = "";

    local($type) = &entype(*object);
    
    return 0 if (!$HANDLEATTR{$type});

    $stat = &OpenHandleDB($HANDLEDB{$type}, *db);

    if (!$stat) {
	&syslog("ERRLOG", "error opening handle database: $!");
        &CloseHandleDB(*db);
	&adderror(*object, "Unable to open handle database");
	return -1;
    }

    if ($choice ne "") {
	if ($choice !~ /\-$HANDLEPOSTFIX$/) {
	    &adderror(*object,
		      "Requested handle must end in \"-$HANDLEPOSTFIX\"");
	    return -1;
	}
	if ($db{$choice}) {
	    &adderror(*object, "Requested nic handle already exists");
	    return -2;		# requested nic handle already exists
	} else {
	    $nichandle = $choice;
	}
    } else {
	$initials = &GenInitials($object{$type});

	for $i (1..$MAXHANDLE) {
	    $nichandle = "$initials"."$i"."-$HANDLEPOSTFIX";
	    next if $db{$nichandle};
	    last;
	}

	if ($i == $MAXHANDLE) {
	    &syslog("ERRLOG", "Maxhandle exceeded for $nichandle");
	    &adderror(*object, "cannot assign new handle, contact NCC");
	    return -1;
	}
    }

    &LockHandleDB(*db);

    local($handlename) = $object{$type};
    $handlename =~ tr/A-Z/a-z/;
    $db{$nichandle} = $handlename;
    if ($db{$handlename}) {
	&addwarning(*object, "Please check that this person is different from people with handles:\n   $db{$handlename}");
	$db{$handlename} .= ",".$nichandle;
    } else {
	$db{$handlename} = $nichandle;
    }

    &UnlockHandleDB(*db);

    &CloseHandleDB(*db);

    $object{$HANDLEATTR{$type}} = $nichandle;
    &addwarning(*object, "nic handle \"$nichandle\" assigned");

    return $nichandle;
}


sub AddHandle {

    local(*entry) = @_;
    local(%db) = ();

    local($type) = &entype(*entry);

    return 1 if (!$HANDLEATTR{$type});

    $stat = &OpenHandleDB($HANDLEDB{$type}, *db);

    if (!$stat) {
	&syslog("ERRLOG", "error opening handle database: $!");
	&CloseHandleDB(*db);
	return -1;
    }

    $nichandle = $entry{$HANDLEATTR{$type}};

    # nichandle is already in our database, check to see if this person
    # is already in. If the nic handle is already in, but the person is
    # different, an error will be generated, stating that this is a
    # person with the same nic handle. This can go, if we ever make just
    # the nic handle the unique key for a person.

    if ($db{$nichandle}) {
	local($thisname) = $entry{$type};
	$thisname =~ tr/A-Z/a-z/;
	if ($db{$nichandle} ne $thisname) {
	    &adderror(*entry, "$ATTL{$HANDLEATTR{$type}} appears to be assigned to \"$db{$nichandle}\"");
	    return -1;
	} else {
	    return 1;
	}
    }

    local($handlename) = $entry{$type};
    $handlename =~ tr/A-Z/a-z/;

    
    &LockHandleDB(*db);
    $db{$nichandle} = $handlename;
    if ($db{$handlename}) {
	$db{$handlename} .= ",".$nichandle;
    } else {
	$db{$handlename} = $nichandle;
    }
    &UnlockHandleDB(*db);

    &CloseHandleDB(*db);

    return 1;
}
1;




