home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!gatech!bloom-beacon!husc6!spdcc!ima!necntc!ncoast!allbery
- From: jack@swlabs.UUCP (Jack Bonn)
- Newsgroups: comp.sources.misc
- Subject: v03i086: VAX-like Phone Utility for SysV
- Message-ID: <1551@swlabs.UUCP>
- Date: 17 Jul 88 16:46:08 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: jack@swlabs.UUCP (Jack Bonn)
- Organization: Software Labs, Ltd. Easton, CT USA
- Lines: 466
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 3, Issue 86
- Submitted-by: "Jack Bonn" <jack@swlabs.UUCP>
- Archive-name: sys5-phone
-
- [Another "talk" clone. ++bsa]
-
- #!/bin/sh
- # shar: Shell Archiver (v1.22)
- #
- # Run the following text with /bin/sh to create:
- # phone.1
- # phone.c
- # Makefile
- #
- sed 's/^X//' << 'SHAR_EOF' > phone.1 &&
- X.TH PHONE 1 "July 17, 1988"
- X.UC 4
- X.SH NAME
- Xphone \- phone another user, typing screen to screen.
- X.SH SYNOPSIS
- Xphone user
- X.SH DESCRIPTION
- X.I Phone
- Xcauses a message to appear on the terminal being used by
- X.I user
- Xthat indicates that someone is trying to phone him.
- XIf the other user also executes phone, then both screens are cleared
- Xand the users are set up in a two way conversation.
- X.PP
- XEach user's input is displayed at the bottom of their own
- Xscreen and at the top of the other user's screen. The
- Xfollowing control characters are handled:
- X.TP 20
- X.BI "ERASE\ (Control\ H)"
- XErase the character before the cursor.
- X.TP
- X.BI "KILL\ (Control\ U)"
- XErase the line the cursor is on and move the cursor to the beginning
- Xof the (now blank) line.
- X.TP
- X.BI "Control\ L"
- XRefresh your own screen.
- X.TP
- X.BI "Control\ G"
- XEither flash (preferably) or ring the bell on other user's terminal.
- X.TP
- X.BI "EOF\ (Control\ D)"
- XDiscontinue execution. The other user is informed.
- X.PP
- X(The characters in parenthesis above are typical assignments
- Xfor these control characters. Those assigned by the user
- Xwill be used. See STTY(1)).
- X.SH BUGS
- X.I Phone
- Xhandles only two users. If a third user attempts entry into
- Xa conversation, strange things happen.
- X.PP
- XWorks only when each user is logged in once. An error
- Xmessage is indicated otherwise (although a "-d tty" option
- Xwould be an obvious extension).
- X.PP
- XRequires System V, since it uses Sys V IPC.
- X.SH AUTHOR
- XJack Bonn
- X.br
- XSoftware Labs, Ltd.
- X.br
- XBox 451
- X.br
- XEaston, CT 06612
- X.PP
- Xjack@swlabs.UUCP
- X.br
- Xuunet!swlabs!jack
- SHAR_EOF
- chmod 0640 phone.1 || echo "restore of phone.1 fails"
- sed 's/^X//' << 'SHAR_EOF' > phone.c &&
- X#include <sys/param.h>
- X#include <sys/types.h>
- X#include <sys/ipc.h>
- X#include <sys/msg.h>
- X#include <utmp.h>
- X#include <signal.h>
- X#include <curses.h>
- X#include <stdio.h>
- X#include <string.h>
- X
- X#define SAME 0 /* For calls to strcmp */
- X#define CTRL_G ('G'-'A'+1)
- X#define CTRL_L ('L'-'A'+1)
- X
- X/*
- X packet.type is one of these --
- X*/
- X#define ERASE 1 /* Erase previous character */
- X#define KILL 2 /* Erase line cursor is on */
- X#define DISPLAY 3 /* Display character on screen */
- X#define ADIOS 4 /* Hang up/disolve connection */
- X#define REFRESH 5 /* Redraw screen on CTL-L */
- X#define FLASH 6 /* Ring bell/flash screen */
- X
- X/*
- X packet.origin is one of these --
- X*/
- X#define LOCAL 0
- X#define REMOTE 1
- X
- X#define IPC_ID 230 /* Upper part of key (for uniqueness) */
- X#define RING_TIME 10 /* Ring cadence in seconds */
- X
- Xint pid = 0; /* pid for offspring, if non-zero */
- X
- Xint loc_q, rem_q; /* message queue id's */
- Xkey_t my_key, other_key; /* keys for the two queues */
- Xkey_t ftok(); /* convert a file to a key */
- X
- Xchar *my_name, *other_name; /* Both user names */
- X
- Xchar *my_tty; /* Path of my device */
- Xchar other_tty[24]; /* Path of other users device */
- X
- Xint erase_ch, kill_ch, eof_ch; /* Special control chars for user */
- X
- XWINDOW *topwin, *botwin; /* curses windows */
- XWINDOW *topleg, *botleg; /* windows for legends */
- Xstruct utmp *u_elem, *getutent();
- Xstruct termio new_ioargs, old_ioargs;
- X
- Xstruct packet /* This is the packet that we ipc */
- X{
- X long type;
- X int origin;
- X char keypress;
- X} s_pkt, r_pkt;
- X
- Xvoid wrapup(); /* Forward reference */
- Xvoid wrapup_child(); /* Forward reference */
- Xvoid exit();
- X
- Xmain(argc,argv)
- X int argc;
- X char *argv[];
- X {
- X
- X if (argc != 2) {
- X printf ("usage: phone user\n");
- X exit(1);
- X }
- X
- X signal (SIGINT, wrapup);
- X
- X get_names(argv[1]); /* Get our name and other user's */
- X
- X if (!get_ttys()) /* Get our tty and other user's */
- X wrapup();
- X
- X get_keys();
- X
- X if (!open_queues())
- X wrapup();
- X
- X init_screen();
- X
- X if (pid=fork()) {
- X scrn_proc(); /* Returns when ADIOS packet received */
- X wrapup();
- X } else {
- X signal (SIGQUIT, wrapup_child);
- X key_proc(); /* Never returns, must be killed */
- X }
- X /* NOTREACHED */
- X}
- X
- Xvoid wrapup () {
- X int ret_code; /* Wait insists on an argument */
- X struct msqid_ds buf;
- X
- X if (pid) { /* Kill sibbling if present */
- X kill (pid, SIGQUIT);
- X wait (&ret_code);
- X }
- X
- X endwin(); /* Clean up curses windows */
- X msgctl (loc_q, IPC_RMID, &buf); /* Remove our message queue */
- X send_remote (ADIOS, 0); /* In case other side is still up */
- X exit(0);
- X}
- X
- Xkey_proc() {
- X int ch;
- X
- X /* Keyboard process */
- X
- X init_kbd();
- X
- X for (;;) {
- X ch=getchar();
- X
- X if (ch == erase_ch)
- X send_both (ERASE, 0);
- X
- X else if (ch == kill_ch)
- X send_both (KILL, 0);
- X
- X else if (ch == CTRL_L)
- X send_local (REFRESH, 0);
- X
- X else if (ch == CTRL_G)
- X send_both (FLASH, 0);
- X
- X else if (ch == eof_ch)
- X send_local (ADIOS, 0);
- X
- X else {
- X if (ch == '\r')
- X ch = '\n';
- X send_both (DISPLAY, ch);
- X
- X }
- X }
- X}
- X
- Xvoid wrapup_child () {
- X reset_kbd(); /* Put ioctl stuff where it was */
- X exit(0);
- X}
- X
- Xscrn_proc() {
- X int y, x;
- X int ch;
- X WINDOW *window; /* temp curses windows */
- X
- X /* Screen process */
- X
- X scrn_legend (topleg, other_name, other_tty);
- X scrn_legend (botleg, my_name, my_tty);
- X
- X wrefresh (topwin);
- X wrefresh (botwin);
- X
- X do {
- X msgrcv (loc_q, &r_pkt, sizeof(r_pkt) - sizeof(r_pkt.type), 0L, 0);
- X
- X if (r_pkt.origin == LOCAL)
- X window = botwin;
- X else
- X window = topwin;
- X
- X ch = r_pkt.keypress;
- X
- X switch ((int)r_pkt.type) {
- X
- X case ERASE:
- X waddch(window, '\b');
- X wdelch(window);
- X break;
- X
- X case KILL:
- X wdeleteln(window);
- X getyx(window, y, x);
- X wmove(window, y, 0);
- X break;
- X
- X case DISPLAY:
- X waddch (window, (char)ch);
- X break;
- X
- X case ADIOS:
- X if (r_pkt.origin == REMOTE)
- X wprintw(botwin, "\n*** %s has hung up. ***\n", other_name);
- X break;
- X
- X case REFRESH:
- X clearok(curscr, TRUE);
- X break;
- X
- X case FLASH:
- X flash();
- X break;
- X
- X }
- X
- X if (r_pkt.origin == REMOTE)
- X wrefresh (topwin);
- X
- X wrefresh (botwin);
- X
- X } while (r_pkt.type != ADIOS);
- X}
- X
- Xint open_queues()
- X {
- X int seconds;
- X
- X loc_q = msgget (my_key, 0666 | IPC_CREAT);
- X
- X if (loc_q == -1) {
- X printf ("Unable to create my queue\n");
- X return (FALSE);
- X }
- X
- X /*
- X Stand on our head to test creation of rem_q more often
- X than when we ring the other user.
- X */
- X for (seconds=RING_TIME; ; seconds++) {
- X rem_q = msgget (other_key, 0);
- X
- X if (rem_q != -1)
- X break;
- X
- X if (seconds == RING_TIME) {
- X seconds = 0;
- X if (!ring (other_tty)) {
- X printf ("%s's phone is off the hook (mesg -n).\n\n", other_name);
- X return (FALSE);
- X }
- X printf ("Ringing %s on %.14s\n\n", other_name, other_tty);
- X }
- X if (sleep (1)) /* != 0 if interrupted by other signal */
- X return (FALSE);
- X }
- X return (TRUE);
- X}
- X
- Xinit_screen() {
- X initscr();
- X topleg = newwin(1,0,0,0);
- X topwin = newwin(10,0,1,0);
- X botleg = newwin(1,0,12,0);
- X botwin = newwin(10,0,13,0);
- X idlok(topwin,TRUE);
- X idlok(botwin,TRUE);
- X scrollok(topwin,TRUE);
- X scrollok(botwin,TRUE);
- X}
- X
- Xinit_kbd() {
- X ioctl (0, TCGETA, &old_ioargs);
- X erase_ch = old_ioargs.c_cc[VERASE];
- X kill_ch = old_ioargs.c_cc[VKILL];
- X eof_ch = old_ioargs.c_cc[VEOF];
- X new_ioargs = old_ioargs;
- X new_ioargs.c_lflag &= ~(ICANON | ECHO);
- X new_ioargs.c_cc[VMIN] = (char)1;
- X ioctl (0, TCSETA, &new_ioargs);
- X}
- X
- Xreset_kbd() {
- X ioctl (0, TCSETA, &old_ioargs);
- X}
- X
- Xget_names(cmd_arg)
- X char *cmd_arg;
- X {
- X char *getenv();
- X
- X my_name = getenv("LOGNAME");
- X other_name = cmd_arg;
- X }
- X
- Xint get_ttys()
- X{
- X int found;
- X char *ttyname();
- X
- X my_tty = ttyname(0);
- X found=0;
- X while(u_elem=getutent()) {
- X
- X if (strcmp(u_elem->ut_user, other_name) == SAME) {
- X found++;
- X strcpy(other_tty, "/dev/");
- X strncpy(&other_tty[5], u_elem->ut_line, sizeof(u_elem->ut_line));
- X }
- X }
- X if (found != 1) {
- X if (found == 0)
- X printf("User %s is not logged in.\n", other_name);
- X else
- X printf("User %s is logged in more than once.\n", other_name);
- X return (FALSE);
- X }
- X return (TRUE);
- X}
- X
- Xget_keys() /* Get unique keys for naming message queues */
- X{
- X my_key = ftok (my_tty, IPC_ID);
- X other_key = ftok (other_tty, IPC_ID);
- X}
- X
- Xint ring (device)
- X char *device;
- X {
- X FILE *out_s;
- X
- X if (!(out_s = fopen (device, "w")))
- X return (FALSE);
- X
- X fprintf (out_s, "\n%s is phoning you.\n", my_name);
- X fprintf (out_s, "Type 'phone %s' to answer.\007\n\n", my_name);
- X fclose (out_s);
- X return (TRUE);
- X}
- X
- Xscrn_legend (window, user, terminal)
- X WINDOW *window;
- X char *user;
- X char *terminal;
- X {
- X char buffer[40];
- X
- X wattron (window, A_REVERSE | A_BOLD);
- X sprintf (buffer, "%s (%s):", user, terminal);
- X wprintw (window, "%-*s", COLS, buffer);
- X wrefresh (window);
- X }
- X
- Xsend_local (type, ch)
- X int type;
- X int ch;
- X {
- X s_pkt.type = type;
- X s_pkt.keypress = ch;
- X s_pkt.origin = LOCAL;
- X msgsnd (loc_q, &s_pkt, sizeof(s_pkt) - sizeof(s_pkt.type), 0);
- X }
- X
- Xsend_remote (type, ch)
- X int type;
- X int ch;
- X {
- X s_pkt.type = type;
- X s_pkt.keypress = ch;
- X s_pkt.origin = REMOTE;
- X msgsnd (rem_q, &s_pkt, sizeof(s_pkt) - sizeof(s_pkt.type), 0);
- X }
- X
- Xsend_both (type, ch)
- X int type;
- X int ch;
- X {
- X send_local (type, ch);
- X send_remote (type, ch);
- X }
- SHAR_EOF
- chmod 0644 phone.c || echo "restore of phone.c fails"
- sed 's/^X//' << 'SHAR_EOF' > Makefile &&
- Xphone: phone.c
- X cc phone.c -o phone -lcurses
- X
- Xlint:
- X lint phone.c -lcurses
- X
- Xinstall:
- X cp phone /usr/lbin
- X
- Xshar:
- X shar phone.1 phone.c Makefile >phone.sh
- SHAR_EOF
- chmod 0640 Makefile || echo "restore of Makefile fails"
- exit 0
- --
- Jack Bonn, <> Software Labs, Ltd, Box 451, Easton CT 06612
- uunet!swlabs!jack
-