Repost of hotkey program for 7300/3B1

David H. Brierley dave at galaxia.Newport.RI.US
Wed Jun 7 12:30:22 AEST 1989


This is a repost of the hotkey program for the ATT 7300/3B1 that I
posted a few weeks ago.  I originally posted the source to
unix-pc.sources and a short note to comp.sys.att saying that I posted
the source.  Since then I have been flooded with requests saying "we
dont get unix-pc.*, sould you send me a copy?".  The first few requests
that I got I replied to via mail but eventually it got to the point
where I decided it was worthwhile to just post the source to
comp.sys.att.  So here it is.  Following is an excerpt from the README
file and then the full shar file.  One thing that I forgot to mention in
the documentation is that if you move the mouse pointer into the window
that hotkey creates on the status line the mouse pointer will disappear.
This was done to give me a nice permanent place to hide the mouse
pointer without going to a lot of fuss.

===== Begin extract from README file =====
This program provides a function similar to the IBM-PC TSR programs which
use a "hot key" to activate the program.  When the program is activated it
is given a list of commands that are to be bound to the 8 shifted function
keys.  When a shifted function key is pressed a new window is created and
the requested program is run from within the new window.

----- cut here and feed to sh -----
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  MANIFEST README hotkey.1 hotkey.c hotkey.sample makefile
# Wrapped by dave at galaxia on Sun May 21 22:32:51 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(282 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	
X README                     1	
X hotkey.1                   1	
X hotkey.c                   1	
X hotkey.sample              1	
X makefile                   1	
END_OF_FILE
if test 282 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1197 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis program provides a function similar to the IBM-PC TSR programs which
Xuse a "hot key" to activate the program.  When the program is activated it
Xis given a list of commands that are to be bound to the 8 shifted function
Xkeys.  When a shifted function key is pressed a new window is created and
Xthe requested program is run from within the new window.  Note that this
Xprogram allocates a window for its own use which means that there is one
Xless window available to the user.  Since there are a total of 12 windows
Xavailable on the system and there are only 8 function keys, this should not
Xpresent any problems to the average user.
X
XFor more information about the program, read the man page.  For even more
Xinformation, read the source.
X
XNote that this program does not require any super user priveleges.
X
X---- Installation Instructions ----
X
X1. Edit the makefile to correctly reflect the name of the directory you want
X   the program installed in.
X2. Type "make".
X3. Try it out before installing it, if you are paranoid.
X4. Type "make install".
X5. Let me know if you have any suggestions for improvements.
X
XDavid H. Brierley
Xdave at galaxia.newport.ri.us
X{mirror,rayssd,xanth,att} !galaxia!dave
END_OF_FILE
if test 1197 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'hotkey.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hotkey.1'\"
else
echo shar: Extracting \"'hotkey.1'\" \(5939 characters\)
sed "s/^X//" >'hotkey.1' <<'END_OF_FILE'
X.TH HOTKEY 1 LOCAL
X.UC
X.SH NAME
Xhotkey \- set hotkey-like actions on function keys
X.SH SYNOPSIS
X.nf
Xhotkey [-fFILE] [-r] [-k] [-u#] [-b#] [-n] [-h#] [-w#] [command]
X.fi 
X.SH DESCRIPTION
XThe
X.I hotkey
Xprogram takes over control of the shifted function keys which are normally
Xused by the
X.I "Phone Manager"
Xand allows you to specify a program that is to be run when any of the
Xfunction keys are pressed.  Each time a function key is pressed a new
Xwindow is created and the specified program is run inside the window.
XThe user has control over the size of the created window, the smallest
Xwindow allowed being four lines by twenty columns and the largest window
Xallowed being full screen borderless.  Each function key may be defined
Xusing a separate invocation of the
X.I hotkey
Xprogram, but it is far easier to create a key definition file and simply
Xrun
X.I hotkey
Xonce using the
X.I -f
Xoption.
X.P
XA list showing which function keys are currently mapped will be displayed
Xon the top line of the screen, using the window normally used by the
X.I "Phone Manager"
Xto display the status of the phone lines.  The format of the display is:
X.sp
X.ti +3
XFunction Keys Active: 12345678
X.sp
XIf a particular function keys is not currently mapped, a period will be
Xdisplayed in place of the key number.  After you log off, or if you
Xexplicitly kill the hotkey process using the
X.I -k
Xoption (see below), the display area will be blanked out.
X.SH "INTERACTIONS WITH THE PHONE MANAGER"
XSince this program uses the same display are on the screen as the
X.I "Phone Manager,"
Xand since it usurps control of the shifted function keys, it is not
Xrecomended that this program be used on systems which are actively using the
X.I "Phone Manager."
XThis is not to say that it cant be done, just that it is not recommended.
XIf you do try to run this program and the
X.I "Phone Manager"
Xat the same time they will fight for control of the function keys and will
Xfight over whose message gets displayed on the status line.  The
X.I "Phone Manager"
Xwakes up every time something happens on one of the phone lines (i.e.
Xincoming call, outgoing call, call termination) and reregisters for control
Xof the function keys and updates the display.  The
X.I hotkey
Xprogram wakes up at time intervals that are set at compile time and
Xreregisters for control of the function keys.  If the key definitions have
Xchanged since the last time the display was changed the the display is
Xupdated.  The
X.I hotkey
Xprogram is also woken up by running the program again.
X.SH "METHOD OF OPERATION"
XThe first time this program is run it will fork itself into the background,
Xallocate the window on the status line, and register for control of the
Xshifted function keys.
XThe key definitions are recorded in the
X.I bind
Xfile (see below) and the process id of the background process is recorded in
Xthe
X.I pid
Xfile.  The program determines that it should go into background mode by one
Xof the following conditions being satisfied: a) there is no pid file; b) the
Xprocess id listed in the pid file does not exist; c) the bind file is not
Xowned by the current user.
XEach time one of the shifted function keys are
Xpressed the key definition file is read, a new window is created, and the
Xrequested command is run within the new window.  When the program receives a
Xhangup signal, either because you logged off or because you ran the program
Xagain specifying the -k option, it will blank out the window, change the
Xownership of the bind file to -1, and then go to sleep.  The next time
Xsomeone runs the program the new copy of the program will see that the bind
Xfile is owned by uid -1 and will automatically go into background mode and
Xcreate a new bind file owned by the new user.  The old copy of the program
Xwill see that the bind file is no longer owned by uid -1 and will exit.
XThe reason for all of this nonsense is that if the background process simply
Xexits when it receives the hangup signal the display area on the status line
Xwill revert to the ugly dots pattern.  For this reason you should never kill
Xthe
X.I hotkey
Xprocess using the
X.I kill
Xcommand but instead you should instruct the program to go into idle mode by
Xusing the command
X.I "hotkey -k."
X.SH "OPTIONS"
XThe following options are recognized on the command line:
X.TP 8
X-b#
XSpecifies the key number to be bound (1 thru 8).
X.TP
X-u#
XSpecifies a key number to be unbound.
X.TP
X-k
XKill the
X.I hotkey
Xprocess.
X.TP
X-r
XRefresh the
X.I hotkey
Xwindow on the top line of the screen.
X.TP
X-h#
XSpecifies the height (in rows) of the window to be created.
X.TP
X-w#
XSpecifies the width (in columns) of the window to be created.
X.TP
X-n
XSpecifies that the window to be created should be a full screen
Xborderless window.
X.TP
X-fFILE
XThe contents of the file are read in and used to define the function
Xkeys (see below).
X.P
XAny remaining arguments on the command line are taken to be the command
Xto be executed.
X.SH "FORMAT OF KEY DEFINITION FILE"
XThe key definition file, for use with the
X.I -f
Xoption, consists of one to eight lines in the following format:
X.sp
X.ti +3
Xkeynum,height,width command [arguments]
X.sp
XThe keynum values are the same as those defined above.  The height and
Xwidht values specify the size of the window in rows and columns.  For a
Xfull screen borderless window specify a size of 24,80.  The key
Xdefinitions may be in any order.
X.SH "EXAMPLES"
X.in +3
X.nf
X# start a new shell process
Xhotkey -b1 -h24 -w80 /bin/ksh
X# read the news
Xhotkey -b2 -h24 -w80 rn
X# calculator
Xhotkey -b3 -h12 -w20 calculatr
X.in -3
X.fi
X.SH "SAMPLE KEY DEFINITION FILE"
X.nf
X.in +3
X1,15,72 ksh
X2,15,72 /u/dave/cmd/root.sh
X3,15,72 /u/dave/cmd/uucp.sh
X4,04,20 uusnap
X5,04,20 scrtoggle
X6,04,20 calculatr
X7,24,80 pcomm.sh -f rayssdb
X8,24,80 /u/dave/cmd/rn
X.in -3
X.fi
X.SH FILES
X/usr/local/hotkey/pid	- pid of active hotkey process
X.br
X/usr/local/hotkey/bind	- current key bindings
X.SH "SEE ALSO"
Xwindow(7)
X.SH "BUGS"
XHopefully, none. 
X.SH "AUTHOR"
XDavid H. Brierley 
END_OF_FILE
if test 5939 -ne `wc -c <'hotkey.1'`; then
    echo shar: \"'hotkey.1'\" unpacked with wrong size!
fi
# end of 'hotkey.1'
fi
if test -f 'hotkey.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hotkey.c'\"
else
echo shar: Extracting \"'hotkey.c'\" \(14790 characters\)
sed "s/^X//" >'hotkey.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char    *SccsId = "@(#) hotkey.c: version 1.14 5/21/89 (dhb at galaxia)";
X#endif
X
X#include <stdio.h>
X#include <sys/font.h>
X#include <sys/window.h>
X#include <termio.h>
X#include <signal.h>
X#include <malloc.h>
X#include <string.h>
X#include <setjmp.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/wd.h>
X#include <track.h>
X
X#define ALARM_LIMIT	90
X
X#define PID_FILE	"/usr/local/hotkey/pid"
X#define KEY_FILE	"/usr/local/hotkey/bind"
X
Xstruct hotkey {
X    struct hotkey  *h_next;
X    int             h_key;
X    int             h_height;
X    int             h_width;
X    char            h_cmd[256];
X};
X
Xint             getmaster ();
Xvoid            set_master ();
Xint             mk_window ();
Xstruct hotkey  *read_keyfile ();
Xvoid            write_keyfile ();
Xvoid            unbind ();
Xint             kcount ();
Xvoid            free_list ();
Xstruct hotkey  *insert ();
Xstruct hotkey  *bind ();
Xint             die ();
Xvoid            terminate ();
Xvoid            do_hotkey ();
Xint             atrap ();
Xint             refresh ();
Xvoid            zapmouse ();
X
Xvoid            exit ();
Xvoid            _exit ();
Xchar           *getenv ();
Xvoid            longjmp ();
Xunsigned        alarm ();
X
Xjmp_buf         abuff;
Xint             user_id;
Xint             need_wiocsys = 1;
X
Xmain (argc, argv)
Xint             argc;
Xchar           *argv[];
X{
X    int             keynum;
X    int             mpid;
X    int             wd;
X    int             fd;
X    int             signo;
X    int             oldwd;
X    int             wheight;
X    int             wwidth;
X    time_t          bind_time;
X    time_t          new_bind;
X    char            buffer[1];
X    int             bufpos;
X    char           *home;
X    struct hotkey  *head;
X    int             optch;
X    extern char    *optarg;
X    extern int      optind;
X
X    user_id = getuid ();
X    mpid = getmaster ();
X    keynum = -1;
X    wheight = 12;
X    wwidth = 60;
X
X    if (mpid != 0) {
X	head = read_keyfile (KEY_FILE);
X    }
X    else {
X	head = NULL;
X    }
X
X    while ((optch = getopt (argc, argv, "rknh:w:f:b:u:")) != EOF) {
X	switch (optch) {
X	case 'b':
X	    keynum = atoi (optarg);
X	    break;
X	case 'u':
X	    unbind (optarg, head);
X	    break;
X	case 'k':
X	    free_list (head);
X	    head = NULL;
X	    break;
X	case 'h':
X	    wheight = atoi (optarg);
X	    break;
X	case 'w':
X	    wwidth = atoi (optarg);
X	    break;
X	case 'n':
X	    wheight = 24;
X	    wwidth = 80;
X	    break;
X	case 'f':
X	    free_list (head);
X	    head = read_keyfile (optarg);
X	    break;
X	case 'r':
X	    if (mpid != 0) {
X		(void) kill (mpid, SIGUSR1);
X	    }
X	    exit (0);
X	}
X    }
X
X    if (keynum >= 0) {
X	head = bind (keynum, wheight, wwidth, argc, argv, optind, head);
X    }
X
X    if ((head == NULL) || (kcount (head) == 0)) {
X	if (mpid != 0) {
X	    (void) kill (mpid, SIGHUP);
X	    exit (0);
X	}
X    }
X
X    write_keyfile (head);
X
X    if (mpid != 0) {
X	(void) kill (mpid, SIGALRM);
X	exit (0);
X    }
X
X    wd = mk_window ();
X    oldwd = ioctl (wd, WIOCGPREV, NULL);
X    if (oldwd == -1) {
X	oldwd = 0;
X    }
X
X    if (fork () != 0) {
X	(void) ioctl (oldwd, WIOCSELECT, NULL);
X	exit (0);
X    }
X
X    if ((home = getenv ("HOME")) != NULL) {
X	(void) chdir (home);
X    }
X
X    for (fd = 0; fd < _NFILE; ++fd) {
X	if (fd != wd) {
X	    (void) close (fd);
X	}
X    }
X
X    for (signo = 1; signo < NSIG; ++signo) {
X	(void) signal (signo, SIG_IGN);
X    }
X    (void) signal (SIGALRM, atrap);
X    (void) signal (SIGHUP, die);
X    (void) signal (SIGTERM, die);
X    (void) signal (SIGUSR1, refresh);
X    free_list (head);
X
X    bufpos = 0;
X    set_master ();
X
X    while (1) {
X	(void) setjmp (abuff);
X	if (is_owner (KEY_FILE, &new_bind) == 0) {
X	    terminate ();
X	}
X	if (need_wiocsys) {
X	    (void) ioctl (wd, WIOCSYS, 1);
X	    zapmouse (wd);
X	    bind_time = 0;
X	    need_wiocsys = 0;
X	}
X	if (new_bind != bind_time) {
X	    display_keys (wd);
X	    bind_time = new_bind;
X	}
X	(void) alarm (ALARM_LIMIT);
X	if (read (wd, buffer, 1) != 1) {
X	    continue;
X	}
X	switch (bufpos) {
X	case 0:
X	    if ((buffer[0] & 0x7f) == 0x1b) {
X		++bufpos;
X	    } break;
X	case 1:
X	    if ((buffer[0] & 0x7f) == 0x4f) {
X		bufpos = 2;
X	    }
X	    else {
X		bufpos = 0;
X	    }
X	    break;
X	case 2:
X	    keynum = (buffer[0] & 0x7f) - 'B';
X	    do_hotkey (keynum);
X	    bufpos = 0;
X	    break;
X	}
X    }
X
X}
X
Xint
Xgetmaster ()
X{
X    int             fd;
X    int             pid;
X
X    if (is_owner (PID_FILE, NULL) == 0) {
X	return (0);
X    }
X
X    if ((fd = open (PID_FILE, 0)) == -1) {
X	return (0);
X    }
X
X    if (read (fd, (char *) &pid, sizeof (int)) != sizeof (int)) {
X	pid = 0;
X    }
X    (void) close (0);
X
X    if (pid != 0) {
X	if (kill (pid, 0) == -1) {
X	    pid = 0;
X	}
X    }
X    return (pid);
X
X}
X
Xvoid
Xset_master ()
X{
X    int             fd;
X    int             pid;
X
X    (void) unlink (PID_FILE);
X    if ((fd = creat (PID_FILE, 0666)) == -1) {
X	exit (1);
X    }
X
X    pid = getpid ();
X    if (write (fd, (char *) &pid, sizeof (int)) != sizeof (int)) {
X	exit (1);
X    }
X
X    if (close (fd) == -1) {
X	exit (1);
X    }
X
X}
X
Xint
Xmk_window ()
X{
X    int             wd;
X    int             wnum;
X    int             fd;
X    char           *wname;
X    struct uwdata   uwdata;
X    struct utdata   utdata;
X    struct termio   tty;
X    char           *ttyname ();
X
X    wnum = 0;
X    wd = -1;
X    while (wnum < 8) {
X	fd = open ("/dev/window", 2);
X	if (fd == -1) {
X	    if (wd != -1) {
X		break;
X	    }
X	    exit (1);
X	}
X	wd = fd;
X	wname = ttyname (wd);
X	wnum = atoi (wname + 6);
X    }
X
X    if (ioctl (wd, WIOCGETD, &uwdata) == -1) {
X	exit (1);
X    }
X
X    uwdata.uw_x = 0;
X    uwdata.uw_y = 0;
X    uwdata.uw_width = 9 * 32;
X    uwdata.uw_height = 12;
X    uwdata.uw_uflags = NBORDER;
X
X    if (ioctl (wd, WIOCSETD, &uwdata) == -1) {
X	exit (1);
X    }
X
X    utdata.ut_num = WTXTUSER;
X    (void) strcpy (utdata.ut_text, "Status Manager");
X    (void) ioctl (wd, WIOCSETTEXT, &utdata);
X
X    if (ioctl (wd, WIOCPGRP, NULL) == -1) {
X	exit (1);
X    }
X
X    if (ioctl (wd, WIOCSYS, 1) == -1) {
X	exit (1);
X    }
X
X    if (ioctl (wd, TCGETA, &tty) == -1) {
X	exit (1);
X    }
X
X    tty.c_lflag = 0;
X    tty.c_cc[VMIN] = 1;
X    tty.c_cc[VTIME] = 0;
X
X    if (ioctl (wd, TCSETA, &tty) == -1) {
X	exit (1);
X    }
X
X    return (wd);
X
X}
X
Xstruct hotkey  *
Xread_keyfile (filename)
Xchar           *filename;
X{
X    int             keynum;
X    int             height;
X    int             width;
X    int             n;
X    struct hotkey  *head;
X    char            line[BUFSIZ];
X    FILE           *fp;
X    char           *cmd;
X
X    head = NULL;
X    if ((fp = fopen (filename, "r")) == NULL) {
X	return (head);
X    }
X
X    while (fgets (line, BUFSIZ - 1, fp) != NULL) {
X	cmd = line + strlen (line) - 1;
X	*cmd = '\0';
X	if ((cmd = strchr (line, ' ')) == NULL) {
X	    continue;
X	}
X	*cmd++ = '\0';
X	while (*cmd == ' ') {
X	    ++cmd;
X	}
X	n = sscanf (line, "%d,%d,%d", &keynum, &height, &width);
X	switch (n) {
X	case 3:
X	    break;
X	case 1:
X	    height = 12;
X	    width = 60;
X	    break;
X	default:
X	    continue;
X	}
X	head = insert (head, keynum, height, width, cmd);
X    }
X    (void) fclose (fp);
X    return (head);
X
X}
X
Xvoid
Xwrite_keyfile (head)
Xstruct hotkey  *head;
X{
X    struct hotkey  *ptr;
X    FILE           *fp;
X
X    (void) unlink (KEY_FILE);
X    if ((fp = fopen (KEY_FILE, "w")) == NULL) {
X	exit (1);
X    }
X
X    for (ptr = head; ptr != NULL; ptr = ptr -> h_next) {
X	if (ptr -> h_key != -1) {
X	    (void) fprintf (fp, "%d,%d,%d %s\n",
X			    ptr -> h_key, ptr -> h_height, ptr -> h_width, ptr -> h_cmd);
X	}
X    }
X
X    if (fclose (fp) == -1) {
X	exit (1);
X    }
X
X}
X
Xvoid
Xunbind (key, head)
Xchar           *key;
Xstruct hotkey  *head;
X{
X    struct hotkey  *ptr;
X    int             keynum;
X
X    keynum = atoi (key);
X    for (ptr = head; ptr != NULL; ptr = ptr -> h_next) {
X	if (ptr -> h_key == keynum) {
X	    ptr -> h_key = -1;
X	}
X    }
X
X}
X
Xint
Xkcount (head)
Xstruct hotkey  *head;
X{
X    struct hotkey  *ptr;
X    int             knum;
X
X    for (knum = 0, ptr = head; ptr != NULL; ptr = ptr -> h_next) {
X	if (ptr -> h_key != -1) {
X	    ++knum;
X	}
X    }
X
X    return (knum);
X
X}
X
Xvoid
Xfree_list (head)
Xstruct hotkey  *head;
X{
X    struct hotkey  *ptr;
X    struct hotkey  *tmp;
X
X    ptr = head;
X    while (ptr != NULL) {
X	tmp = ptr;
X	ptr = ptr -> h_next;
X	(void) free (tmp);
X    }
X
X}
X
Xstruct hotkey  *
Xinsert (head, key, height, width, cmd)
Xstruct hotkey  *head;
Xint             key;
Xint             height;
Xint             width;
Xchar           *cmd;
X{
X    struct hotkey  *ptr;
X
X    for (ptr = head; ptr != NULL; ptr = ptr -> h_next) {
X	if (ptr -> h_key == key) {
X	    ptr -> h_key = -1;
X	}
X    }
X
X    if (strlen (cmd) >= sizeof (ptr -> h_cmd)) {
X	(void) fprintf (stderr,
X			"Command string for key %d is too long, max = %d\n",
X			key, sizeof (ptr -> h_cmd));
X	exit (1);
X    }
X
X    ptr = (struct hotkey *) malloc (sizeof (struct hotkey));
X    if (ptr == NULL) {
X	exit (1);
X    }
X
X    if (height > 24) {
X	height = 24;
X    }
X    if (height < 6) {
X	height = 6;
X    }
X    if (width > 80) {
X	width = 80;
X    }
X    if (width < 20) {
X	width = 20;
X    }
X
X    ptr -> h_key = key;
X    ptr -> h_height = height;
X    ptr -> h_width = width;
X    (void) strcpy (ptr -> h_cmd, cmd);
X    ptr -> h_next = head;
X    return (ptr);
X
X}
X
Xstruct hotkey  *
Xbind (key, height, width, ac, av, a0, head)
Xint             key;
Xint             height;
Xint             width;
Xint             ac;
Xchar           *av[];
Xint             a0;
Xstruct hotkey  *head;
X{
X    struct hotkey  *ptr;
X    char            cmd[BUFSIZ];
X    int             n;
X    char           *buf;
X    int             maxlen;
X    int             len0;
X
X    (void) strcpy (cmd, av[a0]);
X    buf = cmd + strlen (cmd);
X    maxlen = BUFSIZ - strlen (cmd);
X
X    for (n = a0 + 1; n < ac; ++n) {
X	len0 = strlen (av[n]) + 1;
X	if (len0 >= maxlen) {
X	    (void) fprintf (stderr,
X			    "Command string for key %d is too long\n", key);
X	    exit (1);
X	}
X	(void) sprintf (buf, " %s", av[n]);
X	buf += len0;
X	maxlen -= len0;
X    }
X
X    ptr = insert (head, key, height, width, cmd);
X    return (ptr);
X
X}
X
Xint
Xdie (code)
Xint             code;
X{
X
X    write_keyfile ((struct hotkey *) NULL);
X    (void) chown (KEY_FILE, 1, 1);
X    (void) chown (PID_FILE, 1, 1);
X    user_id = 1;
X    (void) signal (code, die);
X
X}
X
Xvoid
Xterminate ()
X{
X    int             fd;
X
X    for (fd = 0; fd < _NFILE; ++fd) {
X	(void) close (fd);
X    }
X
X    exit (0);
X
X}
X
Xstatic int      xloc = 0;
Xstatic int      yloc = 0;
X
Xvoid
Xdo_hotkey (code)
Xint             code;
X{
X    int             wd;
X    char           *argv[BUFSIZ / 2];
X    char           *blank;
X    int             argc;
X    int             signo;
X    int             temp;
X    char            cmdbuf[BUFSIZ];
X    struct uwdata   uwdata;
X    struct utdata   utdata;
X    struct hotkey  *head;
X    struct hotkey  *ptr;
X
X    head = read_keyfile (KEY_FILE);
X    for (ptr = head; ptr != NULL; ptr = ptr -> h_next) {
X	if (ptr -> h_key == code) {
X	    break;
X	}
X    }
X
X    if (ptr == NULL) {
X	free_list (head);
X	return;
X    }
X
X    wd = open ("/dev/window", 2);
X    if (wd == -1) {
X	free_list (head);
X	return;
X    }
X
X    if (ioctl (wd, WIOCGETD, &uwdata) == -1) {
X	(void) close (wd);
X	free_list (head);
X	return;
X    }
X
X    uwdata.uw_height = ptr -> h_height * uwdata.uw_vs;
X    uwdata.uw_width = ptr -> h_width * uwdata.uw_hs;
X    if (yloc == 0) {
X	yloc = uwdata.uw_vs;
X    }
X    uwdata.uw_x = xloc;
X    uwdata.uw_y = yloc;
X    xloc += (2 * uwdata.uw_hs);
X    yloc += (2 * uwdata.uw_vs);
X    if (xloc > (8 * uwdata.uw_hs)) {
X	xloc = 0;
X	yloc = 0;
X    }
X    if ((ptr -> h_height == 24) && (ptr -> h_width == 80)) {
X	uwdata.uw_uflags = NBORDER;
X	uwdata.uw_x = 0;
X	uwdata.uw_y = uwdata.uw_vs;
X    }
X    else {
X	uwdata.uw_uflags = BORDRESIZE;
X	if (uwdata.uw_x + uwdata.uw_width > WINWIDTH - (3 * uwdata.uw_hs)) {
X	    temp = WINWIDTH - (3 * uwdata.uw_hs) - uwdata.uw_width;
X	    if (temp < 0) {
X		temp = 0;
X	    }
X	    uwdata.uw_x = temp;
X	    uwdata.uw_width = WINWIDTH - (3 * uwdata.uw_hs) - uwdata.uw_x;
X	}
X	if (uwdata.uw_y + uwdata.uw_height > WINHEIGHT - (4 * uwdata.uw_vs)) {
X	    temp = WINHEIGHT - (4 * uwdata.uw_vs) - uwdata.uw_height;
X	    if (temp < uwdata.uw_vs) {
X		temp = uwdata.uw_vs;
X	    }
X	    uwdata.uw_y = temp;
X	    uwdata.uw_height = WINHEIGHT - (4 * uwdata.uw_vs) - uwdata.uw_y;
X	}
X    }
X
X    if (ioctl (wd, WIOCSETD, &uwdata) == -1) {
X	(void) close (wd);
X	free_list (head);
X	return;
X    }
X
X    utdata.ut_num = WTXTLABEL;
X    (void) strncpy (utdata.ut_text, ptr -> h_cmd, 40);
X    (void) ioctl (wd, WIOCSETTEXT, &utdata);
X
X    (void) strcpy (cmdbuf, ptr -> h_cmd);
X    argc = 0;
X    blank = cmdbuf;
X
X    while (blank != NULL) {
X	argv[argc++] = blank;
X	blank = strchr (blank, ' ');
X	if (blank != NULL) {
X	    while (*blank == ' ') {
X		*blank++ = '\0';
X	    }
X	}
X    }
X    argv[argc] = NULL;
X
X    if (fork () != 0) {
X	(void) close (wd);
X	free_list (head);
X	return;
X    }
X
X    if (fork () != 0) {
X	_exit (0);
X    }
X
X    (void) setpgrp ();
X    if (wd != 0) {
X	(void) close (0);
X	(void) dup (wd);
X    }
X    (void) close (1);
X    (void) dup (0);
X    (void) close (2);
X    (void) dup (0);
X    for (wd = 3; wd < _NFILE; ++wd) {
X	(void) close (wd);
X    }
X    (void) ioctl (0, WIOCPGRP, NULL);
X    for (signo = 1; signo < NSIG; ++signo) {
X	(void) signal (signo, SIG_DFL);
X    }
X
X    (void) execvp (argv[0], argv);
X    (void) execl ("/bin/sh", "sh", "-c", ptr -> h_cmd, 0);
X    _exit (0);
X
X}
X
Xint
Xatrap (code)
Xint             code;
X{
X
X    (void) signal (code, atrap);
X    longjmp (abuff, 1);
X
X}
X
Xint
Xrefresh (code)
Xint             code;
X{
X
X    (void) signal (code, refresh);
X    need_wiocsys = 1;
X    longjmp (abuff, 1);
X
X}
X
X/*			"12345678901234567890123456789012" */
X#define FKEY_MSG	"Function Keys Active: ........  "
X#define	BLANKS		"                                "
X
Xdisplay_keys (wd)
Xint             wd;
X{
X    struct hotkey  *head;
X    struct hotkey  *ptr;
X    char            buf[33];
X    int             n;
X    int             keys;
X
X    head = read_keyfile (KEY_FILE);
X
X    (void) strcpy (buf, FKEY_MSG);
X    keys = 0;
X
X    for (ptr = head; ptr != NULL; ptr = ptr -> h_next) {
X	n = ptr -> h_key;
X	if ((n <= 0) || (n > 8)) {
X	    continue;
X	}
X	buf[n + 21] = '0' + n;
X	++keys;
X    }
X    if (keys == 0) {
X	(void) strcpy (buf, BLANKS);
X    }
X    (void) write (wd, "\r\n", 2);
X    (void) write (wd, buf, 31);
X    free_list (head);
X
X}
X
Xint
Xis_owner (file, mod_time)
Xchar           *file;
Xtime_t         *mod_time;
X{
X    struct stat     sbuf;
X
X    if (stat (file, &sbuf) == -1) {
X	return (0);
X    }
X
X    if (sbuf.st_uid != user_id) {
X	return (0);
X    }
X
X    if (mod_time != NULL) {
X	*mod_time = sbuf.st_mtime;
X    }
X
X    return (1);
X
X}
X
X/* mouse.c */
X
X
Xstruct umdata   mouseinfo;
Xstruct icon     myicon;
X
Xvoid
Xzapmouse (wd)
Xint             wd;
X{
X
X    if (ioctl (wd, WIOCGETMOUSE, &mouseinfo) == -1) {
X	return;
X    }
X
X    mouseinfo.um_icon = &myicon;
X
X    (void) ioctl (wd, WIOCSETMOUSE, &mouseinfo);
X}
END_OF_FILE
if test 14790 -ne `wc -c <'hotkey.c'`; then
    echo shar: \"'hotkey.c'\" unpacked with wrong size!
fi
# end of 'hotkey.c'
fi
if test -f 'hotkey.sample' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hotkey.sample'\"
else
echo shar: Extracting \"'hotkey.sample'\" \(170 characters\)
sed "s/^X//" >'hotkey.sample' <<'END_OF_FILE'
X1,15,72 ksh
X2,15,72 /u/dave/cmd/root.sh
X3,15,72 /u/dave/cmd/uucp.sh
X4,04,20 uusnap
X5,04,20 scrtoggle
X6,04,20 calculatr
X7,24,80 pcomm.sh -f rayssdb
X8,24,80 /u/dave/cmd/rn
END_OF_FILE
if test 170 -ne `wc -c <'hotkey.sample'`; then
    echo shar: \"'hotkey.sample'\" unpacked with wrong size!
fi
# end of 'hotkey.sample'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(479 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
X# Makefile for hotkey program
X# David H. Brierley - dave at galaxia.newport.ri.us
X
XINSDIR = /usr/local/bin
XCFLAGS = -O
X
X# No attempt is made here to link with shared libraries.  If you have ccc,
X# ccs, shcc, etc then simply build the program by typing "make CC=ccc" and
X# the shared libaries will automatically be used.
X
Xhotkey:	hotkey.o
X	$(CC) hotkey.o
X	mv a.out hotkey
X
Xinstall: hotkey
X	rm -f $(INSDIR)/hotkey
X	strip hotkey
X	mv hotkey $(INSDIR)/hotkey
X	chmod 711 $(INSDIR)/hotkey
END_OF_FILE
if test 479 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
David H. Brierley
Home: dave at galaxia.Newport.RI.US   {rayssd,xanth,lazlo,mirror}!galaxia!dave
Work: dhb at rayssd.ray.com           {sun,decuac,gatech,necntc,ukma}!rayssd!dhb



More information about the Unix-pc.sources mailing list