home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
ytalk-3.0
/
part01
/
user.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-20
|
7KB
|
328 lines
/* user.c -- user database */
/* NOTICE
*
* Copyright (c) 1990,1992,1993 Britt Yenne. All rights reserved.
*
* This software is provided AS-IS. The author gives no warranty,
* real or assumed, and takes no responsibility whatsoever for any
* use or misuse of this software, or any damage created by its use
* or misuse.
*
* This software may be freely copied and distributed provided that
* no part of this NOTICE is deleted or edited in any manner.
*
*/
/* Mail comments or questions to ytalk@austin.eds.com */
#include "header.h"
#include <pwd.h>
extern char *getlogin();
yuser *me; /* my user information */
yuser *user_list; /* list of invited/connected users */
yuser *connect_list; /* list of connected users */
yuser *wait_list; /* list of connected users */
yuser *fd_to_user[MAX_FILES]; /* convert file descriptors to users */
yuser *key_to_user[128]; /* convert menu ident chars to users */
u_long def_flags = 0L; /* default FL_* flags */
static u_long daemon_id; /* running daemon ID counter */
/* ---- local functions ----- */
static int passwd_opened = 0;
static int
user_id(name)
char *name;
{
register struct passwd *pw;
passwd_opened = 1;
if((pw = getpwnam(name)) == NULL)
return -1;
return pw->pw_uid;
}
static char *
user_name(uid)
int uid;
{
register struct passwd *pw;
passwd_opened = 1;
if((pw = getpwuid(uid)) == NULL)
return NULL;
return pw->pw_name;
}
static void
close_passwd()
{
extern void endpwent();
if(passwd_opened)
{
endpwent();
passwd_opened = 0;
}
}
static void
generate_full_name(user)
yuser *user;
{
register char *c, *d, *ce;
if(user->full_name == NULL)
user->full_name = get_mem(50);
c = user->full_name, ce = user->full_name + 49;
for(d = user->user_name; *d && c < ce; d++)
*(c++) = *d;
if(c < ce)
*(c++) = '@';
for(d = user->host_name; *d && c < ce; d++)
*(c++) = *d;
if(user->tty_name[0])
{
if(c < ce)
*(c++) = '#';
for(d = user->tty_name; *d && c < ce; d++)
*(c++) = *d;
}
*c = '\0';
}
static void
assign_key(user)
yuser *user;
{
register ychar old;
static ychar key = 'a';
if(user->key != '\0' || user == me || user_list == NULL)
return;
old = key;
do {
if(key_to_user[key] == NULL)
{
key_to_user[key] = user;
user->key = key;
return;
}
if(key == 'z')
key = 'A';
else if(key == 'Z')
key = 'a';
else
key++;
} while(old != key);
user->key = '\0';
}
/* ---- global functions ----- */
/* Initialize user data structures.
*/
void
init_user()
{
int my_uid;
char *my_name;
char my_host[100];
user_list = NULL;
connect_list = NULL;
wait_list = NULL;
daemon_id = getpid() << 10;
(void)memset(fd_to_user, 0, MAX_FILES * sizeof(yuser *));
(void)memset(key_to_user, 0, 128 * sizeof(yuser *));
my_uid = getuid();
/* get my username */
if((my_name = getlogin()) != NULL)
if(my_uid < 0 || user_id(my_name) != my_uid)
my_name = NULL;
if(my_name == NULL)
my_name = user_name(getuid());
if(my_name == NULL)
{
show_error("Who are you?");
bail(YTE_ERROR);
}
/* get my hostname */
if(gethostname(my_host, 100) < 0)
{
show_error("init_user: gethostname() failed");
bail(YTE_ERROR);
}
/* get my user record */
if((me = new_user(my_name, my_host, NULL)) == NULL)
bail(YTE_ERROR);
me->remote.protocol = YTP_NEW;
me->remote.vmajor = VMAJOR;
me->remote.vminor = VMINOR;
me->remote.pid = getpid();
close_passwd();
}
/* Create a new user record.
*/
yuser *
new_user(name, hostname, tty)
char *name, *hostname, *tty;
{
register yuser *out, *u;
u_long addr;
/* find the host address */
if(hostname == NULL || *hostname == '\0')
{
hostname = me->host_name;
addr = me->host_addr;
}
else if((addr = get_host_addr(hostname)) == (u_long)-1)
{
sprintf(errstr, "new_user: bad host: '%s'\n", hostname);
show_error(errstr);
return NULL;
}
/* create the user record */
out = (yuser *)get_mem(sizeof(yuser));
(void)memset(out, 0, sizeof(yuser));
out->user_name = str_copy(name);
out->host_name = str_copy(hostname);
out->host_addr = addr;
if(tty)
out->tty_name = str_copy(tty);
else
out->tty_name = str_copy("");
out->d_id = daemon_id++;
generate_full_name(out);
assign_key(out);
out->flags = def_flags;
/* Actually make an effort to keep the user list in order */
if(user_list == NULL || out->key <= user_list->key)
{
out->unext = user_list;
user_list = out;
}
else
{
for(u = user_list; u->unext != NULL; u = u->unext)
if(out->key <= u->unext->key)
break;
out->unext = u->unext;
u->unext = out;
}
return out;
}
void
free_user(user)
yuser *user;
{
register yuser *u;
/* remove him from the various blacklists */
if(user == user_list)
user_list = user->unext;
else
for(u = user_list; u; u = u->unext)
if(u->unext == user)
{
u->unext = user->unext;
break;
}
if(user == connect_list)
connect_list = user->next;
else
for(u = connect_list; u; u = u->next)
if(u->next == user)
{
u->next = user->next;
break;
}
if(user == wait_list)
wait_list = user->next;
else
for(u = wait_list; u; u = u->next)
if(u->next == user)
{
u->next = user->next;
break;
}
/* close him down */
close_term(user);
free(user->full_name);
free(user->user_name);
free(user->host_name);
free(user->tty_name);
if(user->dbuf)
free(user->dbuf);
if(user->output_fd > 0)
close(user->output_fd);
if(user->fd)
{
remove_fd(user->fd);
fd_to_user[user->fd] = NULL;
close(user->fd);
}
if(user->key != '\0')
key_to_user[user->key] = NULL;
free(user);
if(connect_list == NULL && wait_list != NULL)
msg_term(me, "Waiting for connection...");
user_winch = 1;
}
/* Find a user by name/host/pid. If name is NULL, then it is not checked.
* If host_addr is (u_long)-1 then it is not checked. If pid is (u_long)-1
* then it is not checked.
*/
yuser *
find_user(name, host_addr, pid)
char *name;
u_long host_addr, pid;
{
register yuser *u;
for(u = user_list; u; u = u->unext)
if(name == NULL || strcmp(u->user_name, name) == 0)
if(host_addr == (u_long)-1 || u->host_addr == host_addr)
if(pid == (u_long)-1 || u->remote.pid == pid)
return u;
/* it could be _me_! */
if(name == NULL || strcmp(me->user_name, name) == 0)
if(host_addr == (u_long)-1 || me->host_addr == host_addr)
if(pid == (u_long)-1 || me->remote.pid == pid)
return me;
/* nobody I know */
return NULL;
}