pwrite - a multi-user "talk" program.
Rob P. and Stan L.
rosenbk at dalcs.UUCP
Tue Apr 30 04:34:23 AEST 1985
Gentlepeople:
After completing a software design course, which involved a
software project using sockets, I decided to do a little spare
time hacking myself in order to produce this multi-user "talk"
program. I thought it would be an interesting project because
I could learn the use of 4.2BSD sockets and because talk(1)
only handles two people and requires a driver.
Do whatever you want with this piece of software, but please leave
the comments in main.c undisturbed.
A few notes:
1) In evals.c, in e_ring(), change the command for pwrite
from ~puchyr/com/pwrite to an appropriate path.
2) The following is a shell archive file. make a directory
and save this file in it. Edit this file and remove
the top portion of this file up to and including the
----cut here---- line. Then use the command:
sh this_file
Do not run this file through csh. It must be fed to the
Bourne shell.
3) You should end up a number of C programs, a Makefile, and
a pwrite.man manual entry. use the command:
make
to compile the programs. An 'a.out' will result.
If anyone comes with bug fixes please post them to the net.
.__ ___. .__ ..
|__\ /___| |__\ ||
|| >> <<__ || >>.. .. __. ||__ .. .. .. __.
||// \__\ ||// || || /__| |._ \ \\ || |'/__|
||\\ .___>> || ||_||<<__. || || \\|| | /
|| \\ |___/ || \__| \__| || || \`| ||
\|
._________________________________________/|
|_________________________________________/
Robert Scott Puchyr; ...dartvax!dalcs!dalcsug!puchyr
Dalhousie University, Halifax, Nova Scotia, Canada.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# Makefile
# evals.c
# goodbye.c
# header.h
# hello.c
# main.c
# pwrite.man
# socket_lib.c
# users.c
# utils.c
# windows.c
cat - << \SHAR_EOF > Makefile
a.out: main.o evals.o goodbye.o hello.o socket_lib.o users.o utils.o windows.o
cc -g main.o evals.o goodbye.o hello.o socket_lib.o users.o utils.o windows.o -lcurses -ltermcap
main.o: header.h main.c
evals.o: header.h evals.c
goodbye.o: header.h goodbye.c
hello.o: header.h hello.c
socket_lib.o: header.h socket_lib.c
users.o: header.h users.c
utils.o: header.h utils.c
windows.o: header.h windows.c
SHAR_EOF
cat - << \SHAR_EOF > evals.c
#include "header.h"
eval_key(c)
char c;
{
int a, k;
switch(c)
{
case 4:
goodbye();
break;
case 12:
wrefresh(curscr);
break;
case 18:
w_redraw(0);
break;
case 23:
if (SNOOPER >= 0)
p_sendch(c);
break;
case ESC:
eval_esc();
break;
case 127:
case 8:
w_writech(0,'\b');
p_sendch('\b');
break;
default:
if (c >= ' ' || c == RET)
{
w_writech(0,c);
p_sendch(c);
}
break;
}
}
eval_esc()
{
int c;
overwrite(curscr,SCREEN);
w_setcorners(CURRENT_WINDOW);
sprintf(STRING,"%c\n\"%s\" --> COMM-MODE.%c",BEGIN_SECRET,T[0].__tty,END_SECRET);
p_sendstr(STRING);
w_corners(1);
do_line("Command Mode. Press ESC to return to Talk Mode.");
while ((c = getchar()) != ESC)
{
w_corners(0);
switch(c)
{
case 12:
wrefresh(curscr);
break;
case 18:
w_redraw(0);
break;
case 'w':
w_who();
break;
case 'a':
e_call();
break;
case 'd':
e_delete();
break;
case 'r':
e_ring();
break;
case '?':
w_help();
break;
case 'h':
w_mvcorners( 0,-2, 0,-2);
break;
case 'j':
w_mvcorners( 1, 0, 1, 0);
break;
case 'k':
w_mvcorners(-1, 0,-1, 0);
break;
case 'l':
w_mvcorners( 0, 2, 0, 2);
break;
case 'H':
w_mvcorners( 0, 0, 0,-2);
break;
case 'J':
w_mvcorners( 0, 0, 1, 0);
break;
case 'K':
w_mvcorners( 0, 0,-1, 0);
break;
case 'L':
w_mvcorners( 0, 0, 0, 2);
break;
case SPC:
w_nextcorners();
break;
case '@':
w_change();
break;
}
w_corners(1);
do_line("Command Mode. Press ESC to return to Talk Mode.");
}
w_corners(0);
w_redraw(1);
sprintf(STRING,"%c\n\"%s\" <-- COMM-MODE.%c",BEGIN_SECRET,T[0].__tty,END_SECRET);
p_sendstr(STRING);
sock_io();
}
e_call()
{
int a;
w_who();
strcpy(STRING,enter_line("Which user do you want? "));
if (*STRING)
{
if (!strcmp(STRING,"**"))
{
if (p_check(STRING,0) < 0)
{
SNOOPER = p_add("**","Super Snooper",-1,0);
w_new_user(SNOOPER);
sprintf(STRING,"%c\n\"%s\" ADD \"**\" %c",BEGIN_SECRET,T[0].__tty,END_SECRET);
p_sendstr(STRING);
}
else
{
panic("How many Super Snoopers do you want?!?!?",2);
}
}
else if ((a = p_check(STRING,1)) < 0)
{
panic("That user is not on the system.",2);
}
else
{
if (p_check(STRING,0) < 0)
{
a = p_add(W[a].W_tty,W[a].W_username,-1,0);
w_new_user(a);
sprintf(STRING,"%c\n\"%s\" ADD \"%s\".%c",BEGIN_SECRET,T[0].__tty,T[a].__tty,END_SECRET);
p_sendstr(STRING);
}
else
{
panic("That user is already on pwrite.",2);
}
}
}
w_redraw(0);
}
e_delete()
{
int a;
w_who();
strcpy(STRING,enter_line("Which user do you want to delete? "));
if (*STRING)
{
if ((a = p_check(STRING,0)) < 0)
{
panic("That user is not on pwrite.",2);
}
else
{
sprintf(STRING,"%c\n\"%s\" DEL \"%s\".%c",BEGIN_SECRET,T[0].__tty,T[a].__tty,END_SECRET);
p_delete(a);
p_sendstr(STRING);
}
}
w_redraw(0);
}
e_ring()
{
int a;
for (a=1; a < NUM_T; a++)
{
if (!T[a].__dead && !T[a].__connected)
{
sprintf(STRING,"/dev/tty%s",T[a].__tty);
if ((fp = fopen(STRING,"w")) != NULL)
{
fprintf(fp,"\n\n\n%c",7);
fprintf(fp,"pwrite: User '%s' on 'tty%s' wishes to talk to you using 'pwrite'.\n",T[0].__username,T[0].__tty);
fprintf(fp,"pwrite: Please respond using: '~puchyr/com/pwrite' and wait 10 seconds.\n");
fprintf(fp,"\n\n%c",7);
fflush(fp);
fclose(fp);
w_writestr(a,"[RING] ");
}
else
{
w_writestr(a,"[NO RING] ");
}
}
}
}
SHAR_EOF
cat - << \SHAR_EOF > goodbye.c
#include "header.h"
goodbye()
{
int a;
for (a=0; a < NUM_T; a++)
{
if (T[a].__sock >= 0 && !T[a].__dead)
s_delete(T[a].__sock);
}
unlink(T[0].__file);
do_line("");
nocrmode(); echo();
endwin();
exit(1);
}
SHAR_EOF
cat - << \SHAR_EOF > header.h
#include <curses.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#define MAX_USERS 12
#define ESC 27
#define RET '\n'
#define SPC ' '
#define BEGIN_SECRET 19
#define END_SECRET 20
WINDOW *SCREEN; /* a full-size work area */
WINDOW *LINE; /* bottom line of screen */
FILE *fp, *fopen();
struct pw__user /* pwrite user structure */
{
WINDOW *__win1; /* user's border window */
WINDOW *__win2; /* user's inner window */
char __file[32]; /* user's socket file name */
char __tty[8]; /* user's tty number (tty??) */
char __username[32]; /* user's username */
int __sock; /* user's socket descriptor */
int __connected; /* is this user connected? */
int __dead; /* is this connection dead? */
int __secret; /* is currently sending secret */
};
struct pw__user T[MAX_USERS]; /* I am T[0] */
struct corners
{
int C_y; /* y coordinate or this corner */
int C_x; /* x coordinate or this corner */
int C_under; /* what was under this corner */
};
struct corners C[4];
int CURRENT_WINDOW; /* The current window */
struct def__loc /* default locations of wins */
{
int D_y; /* default row of this window */
int D_x; /* default col */
int D_ysize; /* default y size */
int D_xsize; /* default x size */
};
struct def__loc D[MAX_USERS]; /* I am D[0] */
struct who__list /* who_list structure */
{
char W_tty[8]; /* tty */
char W_username[32]; /* username */
};
struct who__list W[64]; /* The who_list */
int NUM_W; /* # of users on the system */
char STRING[BUFSIZ]; /* General purpose string */
int NUM_T; /* # of users you have */
int NUM_C; /* # of users connectd to you */
int ACTIVE_MASK; /* mask of active descriptors */
int SMART; /* TRUE if terminal is smart */
int SNOOPER; /* T element for the Snooper */
int errno; /* standard error noumber */
int sock_io(); /* a place to go on SIGURG */
int goodbye(); /* a place to go and die */
int _pipe_(); /* "The Universe is defective" */
int _death_(); /* program bombed badley! */
struct timeval TIMEOUT; /* timeout structure */
extern char *enter_line(); /* input routine */
SHAR_EOF
cat - << \SHAR_EOF > hello.c
#include "header.h"
int DEF_LENGTH, DEF_WIDTH;
int NUM_DOWN, NUM_ACROSS;
hello()
{
int a;
int y, x;
/*
printf("# of lines: "); LINES = atoi(gets(STRING));
printf("# of cols : "); COLS = atoi(gets(STRING));
*/
initscr();
crmode(); noecho();
signal(SIGQUIT,SIG_IGN);
signal(SIGINT, goodbye);
/* signal(SIGPIPE, _pipe_); */
signal(SIGSEGV,_death_);
signal(SIGBUS, _death_);
if (*CM && LINES >= 8 && COLS >= 32)
SMART = 1;
else
SMART = 0;
TIMEOUT.tv_sec = 5; /* 5 seconds */
TIMEOUT.tv_usec = 0; /* 0 microseconds */
SCREEN = newwin(LINES,COLS,0,0);
clearok(SCREEN,0);
LINE = newwin(1,COLS,LINES-1,0);
DEF_LENGTH = 8;
DEF_WIDTH = (COLS - 8) / 2;
if (DEF_WIDTH > 32)
DEF_WIDTH = 32;
NUM_DOWN = LINES / DEF_LENGTH;
NUM_ACROSS = (COLS - 8) / DEF_WIDTH;
for (a=0; a < MAX_USERS; a++)
{
D[a].D_ysize = DEF_LENGTH;
D[a].D_xsize = DEF_WIDTH;
D[a].D_y = LINES - DEF_LENGTH;
D[a].D_x = COLS - DEF_WIDTH;
}
for (x=a=0; x < NUM_ACROSS; x++)
for (y=0; y < NUM_DOWN; y++,a++)
{
D[a].D_y = y * DEF_LENGTH;
D[a].D_x = x * DEF_WIDTH + 8;
}
p_setup_me();
}
SHAR_EOF
cat - << \SHAR_EOF > main.c
#include "header.h"
#define VERSION "2.0"
/***********************************************************************
*
* ____
* | \ o | A multi-user communication
* |___/ _ _ _ __ _. _|_ ___ program by:
* | | | |/ | | /___>
* | |/\| | _|_ |_/ \___ Robert Scott Puchyr,
* Dalhousie University,
* Halifax, Nova Scotia,
* Canada,
* April 9, 1985
*
***********************************************************************/
main(argc,argv)
int argc;
char **argv;
{
printf("Pwrite. version %s.\nPress ESC ? for help.\n\n",VERSION);
hello();
do_pwrite();
goodbye();
}
do_pwrite()
{
while (1)
{
sock_io();
if (NUM_C < NUM_T)
p_beg();
}
}
sock_io()
{
char S[BUFSIZ];
int a, i, m;
m = s_select(ACTIVE_MASK);
if (m & 1)
{
read(0,&a,1);
eval_key(a);
}
if (m <= 1)
return(0);
if (m & (1 << T[0].__sock))
{
p_answer();
}
for (a=1; a < NUM_T; a++)
{
if (m & (1 << T[a].__sock) && T[a].__connected)
{
i = read(T[a].__sock,S,BUFSIZ);
if (i <= 0)
{
sprintf(STRING,"%c\n\"%s\" LOS \"%s\".%c",BEGIN_SECRET,T[0].__tty,T[a].__tty,END_SECRET);
p_delete(a);
p_sendstr(STRING);
}
else
{
S[i] = NULL;
w_writestr(a,S);
}
}
}
}
SHAR_EOF
cat - << \SHAR_EOF > pwrite.man
PWRITE(1) UNIX Programmer's Manual PWRITE(1)
NAME
pwrite - multi-user ``talk'' program
SYNOPSIS
pwrite
DESCRIPTION
_P_w_r_i_t_e allows a user to communicate with a number of other
users who are logged into the computer. There are no command
line arguments for _p_w_r_i_t_e. After entering _p_w_r_i_t_e, a box or
window labeled with your username and terminal tty will
appear in the upper left portion of your screen. There are
two modes in _p_w_r_i_t_e, talk mode, and command mode. The ESCAPE
button functions as a toggle switch between talk mode and
command mode. The following commands are available in com-
mand mode.
a - Add a user. A ``ghost'' window will appear on
the screen. When adding a user, the user's name
or the user's terminal tty number are valid
inputs. Ghost windows, drawn with dotted lines,
are used to indicate incomplete connections.
d - Delete a connection. Deleting yourself will exit
you from the program.
r - Ring. All unanswered connections, ghost windows,
are rung by sending a note to the expected users.
[NO RING] appears if a user has his write permis-
sion off. You are free to ring as frequently or
infrequently as you wish.
w - See who is on the system.
? - Help. A few help windows are displayed in the
lower right area of the screen.
_P_w_r_i_t_e allows a maximun of 12 windows on the screen. You are
free to change the windows within command mode. Included in
command mode are four corner posts, [ [ ] ] , which are
used as sights for changing windows. The window on which
they are placed is called the _c_u_r_r_e_n_t _w_i_n_d_o_w. The commands
for customizing the windows within command mode are:
h j k l - Moves the sights left (h), down (j), up (k), or
right (l) respectively.
H J K L - Changes size by moving the lower right sight
left, down, up, or right while holding the upper
left sight stationary.
SPACE - Select current window. With a number of windows
Printed 4/29/85 9 April 1985 1
PWRITE(1) UNIX Programmer's Manual PWRITE(1)
on your screen, pressing SPACE will allow you to
select a different current window.
@ - Actually move and resize the current window to
fit within the four sights. Moving the sights
alone will not change the current window's loca-
tion or size. The @ command does.
FILES
/tmp/.pw_* - communication sockets
SEE ALSO
talk(1), mesg(1)
BUGS
_P_w_r_i_t_e is heavily dependent on sockets.
The program tends to boldly state that the current Universe
is defective. This is done when an unknown SIGPIPE error
ocurrs with the sockets.
Printed 4/29/85 9 April 1985 2
SHAR_EOF
cat - << \SHAR_EOF > socket_lib.c
#include "header.h"
/*****************************************************************************
*
* SCOKET_ID = make_a_socket();
*
* make_a_socket() creates a socket local to the system and
* binds the name FILE_NAME to it. This function is called
* by new_server_socket() and new_client_socket(). A SOCKET_ID
* is returned on success, -1 if not.
*
*****************************************************************************/
make_a_socket()
{
int SOCKET_ID;
errno = 0;
if ((SOCKET_ID = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
{
return(-1);
}
return(SOCKET_ID);
}
/*****************************************************************************
*
* SOCKET_ID = s_new_server(FILE_NAME);
*
* s_new_server() creates a socket ready for connection
* by connect_server(). This function returns a SOCKET_ID
* if successful, otherwise -1.
*
*****************************************************************************/
s_new_server(FILE_NAME)
char *FILE_NAME;
{
int SOCKET_ID;
struct sockaddr SOCKET_INFO;
errno = 0;
if ((SOCKET_ID = make_a_socket()) < 0)
{
return(-1);
}
SOCKET_INFO.sa_family = AF_UNIX;
strcpy(SOCKET_INFO.sa_data, FILE_NAME);
unlink(SOCKET_INFO.sa_data);
errno = 0;
if (bind(SOCKET_ID, &SOCKET_INFO, sizeof(SOCKET_INFO)) < 0)
{
return(-1);
}
chmod(SOCKET_INFO.sa_data, 0666);
listen(SOCKET_ID,5);
return(SOCKET_ID);
}
/*****************************************************************************
*
* SOCKET_ID = s_new_client();
*
* s_new_client() creates and returns a SOCKET_ID ready
* ready for connrction using connect_client(). A -1 is returned
* if something messed up.
*
*****************************************************************************/
s_new_client()
{
int SOCKET_ID;
errno = 0;
if ((SOCKET_ID = make_a_socket()) < 0)
{
return(-1);
}
return(SOCKET_ID);
}
/*****************************************************************************
*
* s_connect_server(SOCKET_ID, FILE_NAME);
*
* s_connect_server() connects the already created SOCKET_ID
* with a UNIX file. -1 is returned if the connection cannot
* be made. Otherwise, the filename of the client's socket
* placed in FILE_NAME and a SOCKET_ID file descriptor is
* for the newly accpeted socket is returned.
*
*****************************************************************************/
s_connect_server (SOCKET_ID, FILE_NAME)
int SOCKET_ID;
char *FILE_NAME;
{
int NEW_SOCKET;
int namelen;
struct sockaddr SOCKET_INFO;
namelen = sizeof(SOCKET_INFO);
errno = 0;
if ((NEW_SOCKET = accept(SOCKET_ID, &SOCKET_INFO, &namelen)) < 0)
{
return(-1);
}
strcpy(FILE_NAME,SOCKET_INFO.sa_data);
return(NEW_SOCKET);
}
/*****************************************************************************
*
* s_connect_client(SOCKET_ID, FILE_NAME);
*
* s_connect_client() connects a SOCKET_ID already created with
* new_client_socket() and connects it (with the UNIX file
* FILE_NAME). Zero is returned upon success, -1 if you're not
* so fortunate.
*
*****************************************************************************/
s_connect_client (SOCKET_ID, FILE_NAME)
int SOCKET_ID;
char *FILE_NAME;
{
int namelen;
struct sockaddr SOCKET_INFO;
namelen = sizeof(SOCKET_INFO);
SOCKET_INFO.sa_family = AF_UNIX;
strcpy(SOCKET_INFO.sa_data, FILE_NAME);
errno = 0;
return(connect(SOCKET_ID, &SOCKET_INFO, namelen));
}
/*****************************************************************************
*
* s_select(MASK);
*
*****************************************************************************/
s_select (MASK)
int MASK;
{
int mask;
mask = MASK;
select(20, &mask, 0, 0, &TIMEOUT);
return(mask);
}
/*****************************************************************************
*
* s_read(SOCKET_ID, STRING, NUM_CHARS);
*
* s_read() reads NUM_CHARS bytes from the socket SOCKET_ID
* and places them in STRING. This function returns -1 if
* reading is not possible from SOCKET_ID, this means that
* the socket has been closed down from the other end.
* A SOCKET_ID of 0 will read from standard input. If no
* problems occur, the number of characters actually read
* from the socket is returned.
*
*****************************************************************************/
s_read(SOCKET_ID,STRING,NUM_CHARS)
int SOCKET_ID;
char *STRING;
int NUM_CHARS;
{
int num_read;
if (s_select(SOCKET_ID))
{
if ((num_read = read(SOCKET_ID, STRING, NUM_CHARS)) <= 0)
{
return(-1); /* Socket was closed from other side */
}
STRING[num_read] = NULL;
return(num_read);
}
return(0);
}
/*****************************************************************************
*
* s_write(SOCKET_ID, STRING);
*
* s_write() writes a NULL terminated STRING to the socket
* specified by SOCKET_ID. The number of characters written to
* the socket is returned. -1 is returned something goes wrong.
*
*****************************************************************************/
s_write(SOCKET_ID,STRING)
int SOCKET_ID;
char *STRING;
{
return(write(SOCKET_ID, STRING, strlen(STRING)));
}
/*****************************************************************************
*
* s_delete(SOCKET_ID);
*
* s_delete() closes down a socket, as specified by
* SOCKET_ID;
*
*****************************************************************************/
s_delete(SOCKET_ID)
int SOCKET_ID;
{
errno = 0;
shutdown(SOCKET_ID, 2);
return(close(SOCKET_ID));
}
SHAR_EOF
cat - << \SHAR_EOF > users.c
#include "header.h"
FILE *fp;
struct utmp ubuf;
p_setup_me()
{
CURRENT_WINDOW = NUM_T = NUM_C = 0;
SNOOPER = -1;
ACTIVE_MASK = 0 | (1 << 0); /* 0 is stdin */
strcpy(T[0].__tty,rindex(ttyname(0),'/') + 4);
strcpy(T[0].__username,getenv("USER"));
sprintf(T[0].__file,"/tmp/.pw_%s",T[0].__tty);
if ((T[0].__sock = s_new_server(T[0].__file)) < 0)
panic("Error creating your socket.",0);
T[0].__connected = 1;
w_new_user(0);
NUM_T++; NUM_C++;
ACTIVE_MASK |= (1 << T[0].__sock);
}
p_delete(n)
int n;
{
int a;
if (T[n].__connected)
NUM_C--;
delwin(T[n].__win1);
delwin(T[n].__win2);
if (SMART)
{
wclear(T[n].__win1);
wclear(T[n].__win2);
wrefresh(T[n].__win1);
wrefresh(T[n].__win2);
}
else
{
printf("\nUser '%s' on 'tty%s' has disconnected%c\n",T[n].__username,T[n].__tty,7);
}
if (T[n].__sock >= 0)
{
ACTIVE_MASK &= ~(1 << T[n].__sock);
s_delete(T[n].__sock);
}
strcpy(T[n].__tty,"");
strcpy(T[n].__username,"");
strcpy(T[n].__file,"");
T[n].__sock = -1;
T[n].__dead = 1;
T[n].__connected = 0;
if (NUM_C < 1 || n == 0)
goodbye();
if (n == SNOOPER)
SNOOPER = -1;
if (n == CURRENT_WINDOW)
w_nextcorners();
}
p_answer()
{
char t[8], u[32];
int a, c, s;
strcpy(STRING,"");
s = s_connect_server(T[0].__sock,STRING);
if (s < 0)
return(-1);
a = read(s,STRING,BUFSIZ); /* "j6|puchyr|" */
STRING[a] = NULL;
STRING[2] = NULL;
strcpy(t,STRING);
aslstr(STRING,3);
for (a=0; STRING[a] != '|'; u[a] = STRING[a++]);
u[a] = NULL;
a = p_add(t,u,s,1);
w_new_user(a);
sprintf(STRING,"%c\n\"%s\" ANS \"%s\".%c",BEGIN_SECRET,T[0].__tty,T[a].__tty,END_SECRET);
p_sendstr(STRING);
NUM_C++;
}
p_add(t,u,s,c)
char *t, *u;
int s, c;
{
int a;
if (NUM_C >= MAX_USERS)
{
panic("You cannot add any more.",4);
return(0);
}
for (a=1; a < NUM_T; a++)
{
if (T[a].__dead)
break;
}
sprintf(T[a].__file,"/tmp/.pw_%s",t);
strcpy(T[a].__tty,t);
strcpy(T[a].__username,u);
T[a].__dead = 0;
T[a].__secret = 0;
T[a].__sock = s;
T[a].__connected = c;
if (c)
ACTIVE_MASK |= (1 << T[a].__sock);
if (a >= NUM_T)
NUM_T++;
CURRENT_WINDOW = a;
return(a);
}
p_beg()
{
int a;
for (a=0; a < NUM_T; a++)
{
if (!T[a].__dead && !T[a].__connected)
{
if (T[a].__sock < 0)
T[a].__sock = s_new_client();
if (s_connect_client(T[a].__sock,T[a].__file) >= 0)
{
sprintf(STRING,"%s|%s|",T[0].__tty,T[0].__username);
s_write(T[a].__sock,STRING);
T[a].__connected = 1;
delwin(T[a].__win1);
delwin(T[a].__win2);
w_new_user(a);
sprintf(STRING,"%c\n\"%s\" GOT \"%s\".%c",BEGIN_SECRET,T[0].__tty,T[a].__tty,END_SECRET);
p_sendstr(STRING);
NUM_C++;
ACTIVE_MASK |= (1 << T[a].__sock);
}
}
}
}
p_who()
{
if ((fp = fopen("/etc/utmp","r")) == NULL)
{
panic("Can't open /etc/utmp. (Major Bug!!)\n",0);
}
for (NUM_W=0; fread((char *) &ubuf, sizeof(ubuf), 1, fp) == 1; )
{
if (*ubuf.ut_name)
{
strcpy(W[NUM_W].W_username,ubuf.ut_name);
W[NUM_W].W_tty[0] = ubuf.ut_line[3];
W[NUM_W].W_tty[1] = ubuf.ut_line[4];
W[NUM_W].W_tty[2] = NULL;
NUM_W++;
}
}
fclose(fp);
}
p_check(s,how)
char *s;
int how;
{
int a, l;
if (how)
{
p_who();
if ((l = strlen(s)) <= 2)
{
for (a=0; a < NUM_W; a++)
{
if (!strcmp(W[a].W_tty,s))
break;
}
}
else
{
for (a=0; a < NUM_W; a++)
{
if (!strcmp(W[a].W_username,s))
break;
}
}
if (a < NUM_W)
return(a);
else
return(-1);
}
else
{
if ((l = strlen(s)) <= 2)
{
for (a=0; a < NUM_T; a++)
{
if (!strcmp(T[a].__tty,s))
break;
}
}
else
{
for (a=0; a < NUM_T; a++)
{
if (!strcmp(T[a].__username,s))
break;
}
}
if (a < NUM_T)
return(a);
else
return(-1);
}
}
p_sendch(c)
int c;
{
int a;
for (a=1; a < NUM_T; a++)
if (T[a].__connected && !T[a].__dead && T[a].__sock >= 0)
write(T[a].__sock,&c,1);
}
p_sendstr(s)
char *s;
{
int a;
for (a=1; a < NUM_T; a++)
if (T[a].__connected && !T[a].__dead && T[a].__sock >= 0)
write(T[a].__sock,s,strlen(s));
}
p_secretcommand(n,c)
int n, c;
{
char temp[16];
int a;
switch(c)
{
case 23:
sprintf(STRING,"%c\n\"%s\" HAS",BEGIN_SECRET,T[0].__tty);
for (a=0; a < NUM_T; a++)
{
if (!T[a].__dead)
{
strcat(STRING," \"");
strcat(STRING,T[a].__tty);
strcat(STRING,"\"");
}
}
sprintf(temp,".%c",END_SECRET);
strcat(STRING,temp);
write(T[n].__sock,STRING,strlen(STRING));
break;
}
}
SHAR_EOF
cat - << \SHAR_EOF > utils.c
#include "header.h"
panic(s,n)
char *s;
int n;
{
if (SMART)
{
do_line(s);
}
else
{
printf("\n%s\n",s);
}
fflush(stdout);
if (n)
{ sleep(n); }
else
{ sleep(5); goodbye(); }
}
do_line(s)
char *s;
{
int a, l;
if (SMART)
{
wclear(LINE);
if ((l = strlen(s)) < COLS)
{
waddstr(LINE,s);
}
else
{
for (a=16; a > 0; a--)
waddch(LINE,s[l-a]);
}
if (!*s)
touchwin(LINE);
wrefresh(LINE);
}
else
{
printf("\n%s\n",s);
}
}
_pipe_()
{
signal(SIGINT, SIG_IGN);
if (SMART)
mvcur(0,COLS-1,LINES-9,0);
printf("\n");
printf(".----------------------.\n");
printf("| THIS UNIVERSE SEEMS |\n");
printf("| TO BE DEFECTIVE! |\n");
printf("| |\n");
printf("| PLEASE TRY ANOTHER. |\n");
printf("| Press RETURN |\n");
printf("`----------------------'\n");
gets(STRING);
endwin(); exit(0);
}
_death_()
{
signal(SIGINT, SIG_IGN);
if (SMART)
mvcur(0,COLS-1,LINES-9,0);
printf("\n");
printf(".----------------------.\n");
printf("| .-----* A serious |\n");
printf("| _|_ system error |\n");
printf("| / \\ has occurred |\n");
printf("| | TNT | |\n");
printf("| \\___/ Press RETURN |\n");
printf("`----------------------'\n");
gets(STRING);
endwin(); exit(0);
}
char *enter_line(s)
char *s;
{
char e_line[BUFSIZ], c;
int a, no_echo;
if (!SMART)
{
printf("\n%s",s);
echo(); nocrmode();
gets(e_line);
noecho(); crmode();
return(e_line);
}
no_echo = 0;
if (*s == '^')
{ s++; no_echo = 1; }
do_line(s);
a = 0;
for (a=e_line[0]=0; (c=getchar()) != RET && c != ESC; )
{
switch(c)
{
case 127:
case 8: if (a > 0)
e_line[--a] = NULL;
break;
case 21: a = 0; e_line[a] = NULL;
break;
default: if (a < BUFSIZ && c >= ' ')
{
e_line[a++] = c;
e_line[a] = NULL;
}
break;
}
if (!no_echo)
do_line(e_line);
}
if (c == ESC)
strcpy(e_line,"");
return(e_line);
}
aslstr(s,n)
char *s;
int n;
{
int a;
for (a=0; s[a] = s[a+n]; a++);
}
SHAR_EOF
cat - << \SHAR_EOF > windows.c
#include "header.h"
WINDOW *W_WINDOW;
WINDOW *H_WINDOW;
w_new_user(n)
int n;
{
int a, b, c, x, y;
T[n].__win1 = newwin(D[n].D_ysize,D[n].D_xsize,D[n].D_y,D[n].D_x);
T[n].__win2 = newwin(D[n].D_ysize-3,D[n].D_xsize-3,D[n].D_y+2,D[n].D_x+2);
if (T[n].__connected)
{
box(T[n].__win1,'|','-');
}
else
{
for (y=0; y < D[n].D_ysize; y++)
{
mvwaddch(T[n].__win1,y,0,'.');
mvwaddch(T[n].__win1,y,D[n].D_xsize-1,'.');
}
for (x=0; x < D[n].D_xsize; x+=2)
{
mvwaddch(T[n].__win1,D[n].D_ysize-1,x,'-');
mvwaddch(T[n].__win1,0,x+1,'-');
}
}
mvwaddch(T[n].__win1,0,0,'.');
mvwaddch(T[n].__win1,D[n].D_ysize-1,0,'`');
mvwaddch(T[n].__win1,0,D[n].D_xsize-1,'.');
mvwaddch(T[n].__win1,D[n].D_ysize-1,D[n].D_xsize-1,'\'');
sprintf(STRING,"%s %s",T[n].__tty,T[n].__username);
for (a=0; STRING[a] && a+3 < T[n].__win1->_maxx; a++)
mvwaddch(T[n].__win1,0,a+2,STRING[a]);
scrollok(T[n].__win2,1);
w_setcorners(n);
if (SMART)
{
wrefresh(T[n].__win1);
wrefresh(T[n].__win2);
}
else
{
printf("\nUser '%s' on 'tty%s' has joined.%c\n",T[n].__username,T[n].__tty,7);
}
}
w_setcorners(n)
int n;
{
CURRENT_WINDOW = n;
C[0].C_y = C[1].C_y = D[n].D_y;
C[0].C_x = C[2].C_x = D[n].D_x;
C[2].C_y = C[3].C_y = D[n].D_y + D[n].D_ysize-1;
C[1].C_x = C[3].C_x = D[n].D_x + D[n].D_xsize-1;
}
w_addch(n,c)
int n, c;
{
switch(c)
{
case BEGIN_SECRET:
T[n].__secret = 1;
return(0);
break;
case END_SECRET:
T[n].__secret = 0;
return(0);
break;
case 23:
p_secretcommand(n,c);
return(0);
break;
}
if (T[n].__secret)
{
if (SNOOPER < 0)
return(0);
else
n = SNOOPER;
}
if (SMART)
{
if (c == 8)
{
w_backspace(n);
}
else if (T[n].__win2->_curx == T[n].__win2->_maxx-1)
{
if (c == RET || c == SPC)
waddch(T[n].__win2,RET);
else
{
w_wordwrap(n);
waddch(T[n].__win2,c);
}
}
else
{
waddch(T[n].__win2,c);
}
if (n == SNOOPER)
wrefresh(T[SNOOPER].__win2);
}
else
{
putchar(c);
}
}
w_writech(n,c)
int n, c;
{
w_addch(n,c);
if (SMART)
wrefresh(T[n].__win2);
else
fflush(stdout);
}
w_writestr(n,s)
int n;
char *s;
{
for (; *s; w_addch(n,*s++));
if (SMART)
wrefresh(T[n].__win2);
else
fflush(stdout);
}
w_wordwrap(n)
int n;
{
int c, x, y, s;
waddch(T[n].__win2,RET);
y = T[n].__win2->_cury;
x = T[n].__win2->_maxx - 2;
for ( ; x > 0 && T[n].__win2->_y[y-1][x] != SPC; x--);
s = x + 1;
if (x)
{
for (x=0; s < T[n].__win2->_maxx - 1; x++,s++)
{
wmove(T[n].__win2,y-1,s);
c = winch(T[n].__win2);
waddch(T[n].__win2,SPC);
mvwaddch(T[n].__win2,y,x,c);
}
}
}
w_backspace(n)
int n;
{
int y, x;
if (!T[n].__win2->_curx && (y = T[n].__win2->_cury))
{
wmove(T[n].__win2,y-1,T[n].__win2->_maxx-1);
for (x=T[n].__win2->_maxx-2; x >= 0; x--)
{
wmove(T[n].__win2,y-1,x);
if (winch(T[n].__win2) != SPC)
break;
}
wmove(T[n].__win2,y-1,x+1);
}
else
waddch(T[n].__win2,8);
}
w_who()
{
int a, i, j, x, y;
p_who();
y = LINES - 4;
x = NUM_W / y;
if (NUM_W % y)
x++;
if (NUM_W < y)
y = NUM_W;
x *= 16;
if (SMART)
W_WINDOW = newwin(y+3,x+4,LINES-(y+4),0);
else
W_WINDOW = newwin(y+3,x+4,0,0);
box(W_WINDOW,'|','-');
mvwaddch(W_WINDOW,0,0,'.');
mvwaddch(W_WINDOW,y+2,0,'`');
mvwaddch(W_WINDOW,0,x+3,'.');
mvwaddch(W_WINDOW,y+2,x+3,'\'');
mvwaddstr(W_WINDOW,0,2,"who");
for (i=j=a=0; a < NUM_W; a++)
{
if (p_check(W[a].W_tty,0) != -1)
{
wstandout(W_WINDOW);
mvwaddstr(W_WINDOW,j+2,(i*16)+2," <");
}
mvwaddstr(W_WINDOW,j+2,(i*16)+2,W[a].W_tty);
mvwaddstr(W_WINDOW,j+2,(i*16)+6,W[a].W_username);
wstandend(W_WINDOW);
j++;
if (j >= y)
{
j = 0;
i++;
}
}
wrefresh(W_WINDOW);
delwin(W_WINDOW);
}
w_redraw(n)
int n;
{
int a;
if (SMART)
{
werase(SCREEN);
for (a=0; a < NUM_T; a++)
{
if (!T[a].__dead)
{
overwrite(T[a].__win1,SCREEN);
overwrite(T[a].__win2,SCREEN);
}
}
if (n)
touchwin(SCREEN);
wrefresh(SCREEN);
}
}
w_help()
{
if (SMART)
H_WINDOW = newwin(14,40,LINES-15,COLS-40);
else
H_WINDOW = newwin(14,40,0,0);
wprintw(H_WINDOW,".-help---------------------------------.");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| Talk-mode commands: |");
wprintw(H_WINDOW,"| =================== |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| ^L - redraw screen |");
wprintw(H_WINDOW,"| ^D - exit pwrite |");
wprintw(H_WINDOW,"| ESC - enter Command Mode |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"`-Press SPACE for more-----------------'");
wrefresh(H_WINDOW);
while (getchar() != SPC);
wclear(H_WINDOW);
wprintw(H_WINDOW,".-help---------------------------------.");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| Command Mode commands: |");
wprintw(H_WINDOW,"| ====================== |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| a - add a user |");
wprintw(H_WINDOW,"| d - delete a user |");
wprintw(H_WINDOW,"| w - see who is on the system |");
wprintw(H_WINDOW,"| r - ring all unanswered users |");
wprintw(H_WINDOW,"| ^L - redraw screen |");
wprintw(H_WINDOW,"| ESC - return to Talk Mode |");
wprintw(H_WINDOW,"| ? - show these help pages |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"`-Press SPACE for more-----------------'");
wrefresh(H_WINDOW);
while (getchar() != SPC);
wclear(H_WINDOW);
wprintw(H_WINDOW,".-help---------------------------------.");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| Moving windows around: |");
wprintw(H_WINDOW,"| ---------------------- |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"| h j k l - move the four border |");
wprintw(H_WINDOW,"| corners left, down, up, |");
wprintw(H_WINDOW,"| or right. |");
wprintw(H_WINDOW,"| H J K L - change size. |");
wprintw(H_WINDOW,"| SPACE - select another window. |");
wprintw(H_WINDOW,"| @ - move window to fit |");
wprintw(H_WINDOW,"| within the four corners. |");
wprintw(H_WINDOW,"| |");
wprintw(H_WINDOW,"`-Press SPACE--------------------------'");
wrefresh(H_WINDOW);
while (getchar() != SPC);
delwin(H_WINDOW);
w_redraw(1);
}
w_corners(n)
int n;
{
int a;
if (!SMART)
return(0);
if (n)
{
for (a=0; a < 4; a++)
{
wmove(curscr,C[a].C_y,C[a].C_x);
C[a].C_under = winch(curscr);
wmove(SCREEN,C[a].C_y,C[a].C_x);
wstandout(SCREEN);
if (a % 2)
waddch(SCREEN,']');
else
waddch(SCREEN,'[');
wstandend(SCREEN);
}
}
else
{
for (a=0; a < 4; a++)
{
wmove(SCREEN,C[a].C_y,C[a].C_x);
waddch(SCREEN,C[a].C_under);
}
}
wrefresh(SCREEN);
}
w_mvcorners(y,x,j,i)
int y, x, j, i;
{
if (!SMART)
return(0);
C[0].C_y += y; C[0].C_x += x;
C[1].C_y += y; C[1].C_x += i;
C[2].C_y += j; C[2].C_x += x;
C[3].C_y += j; C[3].C_x += i;
if (C[0].C_y < 0 || C[0].C_y >= (LINES - (C[2].C_y - C[0].C_y)))
{
C[0].C_y -= y; C[1].C_y -= y;
}
if (C[0].C_x < 0 || C[0].C_x >= (COLS - (C[1].C_x - C[0].C_x)))
{
C[0].C_x -= x; C[2].C_x -= x;
}
if (C[3].C_y < (C[0].C_y+4) || C[3].C_y >= LINES)
{
C[2].C_y -= j; C[3].C_y -= j;
}
if (C[3].C_x < (C[0].C_x+7) || C[3].C_x >= COLS)
{
C[1].C_x -= i; C[3].C_x -= i;
}
}
w_change()
{
if (!SMART)
return(0);
delwin(T[CURRENT_WINDOW].__win1);
delwin(T[CURRENT_WINDOW].__win2);
D[CURRENT_WINDOW].D_ysize = C[2].C_y - C[0].C_y + 1;
D[CURRENT_WINDOW].D_xsize = C[1].C_x - C[0].C_x + 1;
D[CURRENT_WINDOW].D_y = C[0].C_y;
D[CURRENT_WINDOW].D_x = C[0].C_x;
w_new_user(CURRENT_WINDOW);
w_redraw(1);
}
w_nextcorners()
{
if (!SMART)
return(0);
do
{
if (++CURRENT_WINDOW >= NUM_T)
CURRENT_WINDOW = 0;
}
while (T[CURRENT_WINDOW].__dead);
w_setcorners(CURRENT_WINDOW);
}
SHAR_EOF
#That's all folks!
exit 0
More information about the Comp.sources.unix
mailing list