home *** CD-ROM | disk | FTP | other *** search
- From: ag@cbmvax.commodore.com (Keith Gabryelski)
- Newsgroups: alt.sources
- Subject: advise (spy) for streams ttys.
- Message-ID: <15193@cbmvax.commodore.com>
- Date: 16 Oct 90 23:26:25 GMT
-
- The included source code includes
-
- advise.c # a user program to interact with
- # the advise device and module.
-
- advisedev.c # the advise device driver.
- # (requests to attach to a users terminal
- # are done through this device)
-
- advisemod.c # the advise module.
- # (this module is pushed onto the advisee's
- # tty stream so advisedev may attach to
- # it.)
-
- advisemod.h # useful header file.
-
- COPYING Makefile # Other files.
-
- Pax, Keith
-
- Ps, This will only work under System V Release 4.0 streams ttys.
-
- With little effort it could be made to work under other streams
- tty subsystems.
-
- No amount of effort (save re-thinking and re-implimenting) will
- make this thing work on non-streams based ttys.
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # COPYING
- # Makefile
- # advise.c
- # advise.man
- # advisedev.c
- # advisemod.c
- # advisemod.h
- # This archive created: Tue Oct 16 19:15:42 1990
- export PATH; PATH=/bin:$PATH
- if test -f 'COPYING'
- then
- echo shar: will not over-write existing file "'COPYING'"
- else
- cat << \SHAR_EOF > 'COPYING'
-
- Advise GENERAL PUBLIC LICENSE
- (Clarified 11 Feb 1988)
-
- Copyright (C) 1988 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license, but changing it is not allowed. You can also
- use this wording to make the terms for other programs.
-
- The license agreements of most software companies keep you at the
- mercy of those companies. By contrast, our general public license is
- intended to give everyone the right to share Advise. To make sure that
- you get the rights we want you to have, we need to make restrictions
- that forbid anyone to deny you these rights or to ask you to surrender
- the rights. Hence this license agreement.
-
- Specifically, we want to make sure that you have the right to give
- away copies of Advise, that you receive source code or else can get it
- if you want it, that you can change Advise or use pieces of it in new
- free programs, and that you know you can do these things.
-
- To make sure that everyone has such rights, we have to forbid you to
- deprive anyone else of these rights. For example, if you distribute
- copies of Advise, you must give the recipients all the rights that you
- have. You must make sure that they, too, receive or can get the
- source code. And you must tell them their rights.
-
- Also, for our own protection, we must make certain that everyone
- finds out that there is no warranty for Advise. If Advise is modified by
- someone else and passed on, we want its recipients to know that what
- they have is not what we distributed, so that any problems introduced
- by others will not reflect on our reputation.
-
- Therefore we (Richard Stallman and the Free Software Foundation,
- Inc.) make the following terms which say what you must do to be
- allowed to distribute or change Advise.
-
-
- COPYING POLICIES
-
- 1. You may copy and distribute verbatim copies of Advise source code
- as you receive it, in any medium, provided that you conspicuously and
- appropriately publish on each copy a valid copyright notice "Copyright
- (C) 1988 Free Software Foundation, Inc." (or with whatever year is
- appropriate); keep intact the notices on all files that refer to this
- License Agreement and to the absence of any warranty; and give any
- other recipients of the Advise program a copy of this License
- Agreement along with the program. You may charge a distribution fee
- for the physical act of transferring a copy.
-
- 2. You may modify your copy or copies of Advise or any portion of it,
- and copy and distribute such modifications under the terms of
- Paragraph 1 above, provided that you also do the following:
-
- a) cause the modified files to carry prominent notices stating
- that you changed the files and the date of any change; and
-
- b) cause the whole of any work that you distribute or publish,
- that in whole or in part contains or is a derivative of Advise or
- any part thereof, to be licensed at no charge to all third
- parties on terms identical to those contained in this License
- Agreement (except that you may choose to grant more extensive
- warranty protection to some or all third parties, at your option).
-
- c) You may charge a distribution fee for the physical act of
- transferring a copy, and you may at your option offer warranty
- protection in exchange for a fee.
-
- Mere aggregation of another unrelated program with this program (or its
- derivative) on a volume of a storage or distribution medium does not bring
- the other program under the scope of these terms.
-
- 3. You may copy and distribute Advise (or a portion or derivative of it,
- under Paragraph 2) in object code or executable form under the terms of
- Paragraphs 1 and 2 above provided that you also do one of the following:
-
- a) accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- b) accompany it with a written offer, valid for at least three
- years, to give any third party free (except for a nominal
- shipping charge) a complete machine-readable copy of the
- corresponding source code, to be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- c) accompany it with the information you received as to where the
- corresponding source code may be obtained. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form alone.)
-
- For an executable file, complete source code means all the source code for
- all modules it contains; but, as a special exception, it need not include
- source code for modules which are standard libraries that accompany the
- operating system on which the executable file runs.
-
- 4. You may not copy, sublicense, distribute or transfer Advise
- except as expressly provided under this License Agreement. Any attempt
- otherwise to copy, sublicense, distribute or transfer Advise is void and
- your rights to use the program under this License agreement shall be
- automatically terminated. However, parties who have received computer
- software programs from you with this License Agreement will not have
- their licenses terminated so long as such parties remain in full compliance.
-
- 5. If you wish to incorporate parts of Advise into other free programs
- whose distribution conditions are different, write to the Free Software
- Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked
- out a simple rule that can be stated here, but we will often permit this.
- We will be guided by the two goals of preserving the free status of all
- derivatives of our free software and of promoting the sharing and reuse of
- software.
-
- Your comments and suggestions about our licensing policies and our
- software are welcome! Please contact the Free Software Foundation, Inc.,
- 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
-
- NO WARRANTY
-
- BECAUSE ADVISE IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO
- WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
- WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
- RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE ADVISE "AS IS" WITHOUT
- WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
- PERFORMANCE OF ADVISE IS WITH YOU. SHOULD ADVISE PROVE DEFECTIVE, YOU
- ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
- STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
- WHO MAY MODIFY AND REDISTRIBUTE GNU SEND AS PERMITTED ABOVE, BE LIABLE TO
- YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER
- SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
- BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
- FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GNU SEND, EVEN
- IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR
- ANY CLAIM BY ANY OTHER PARTY.
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- # Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
- #
- # This file is part of advise.
- #
- # advise is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY. No author or distributor
- # accepts responsibility to anyone for the consequences of using it
- # or for whether it serves any particular purpose or works at all,
- # unless he says so in writing. Refer to the advise General Public
- # License for full details.
- #
- # Everyone is granted permission to copy, modify and redistribute
- # advise, but only under the conditions described in the
- # advise General Public License. A copy of this license is
- # supposed to have been given to you along with advise so you
- # can know your rights and responsibilities. It should be in a
- # file named COPYING. Among other things, the copyright notice
- # and this notice must be preserved on all copies. */
- #
- # Author: Keith Gabryelski (ag@amix.commodore.com)
- #
-
- CC=gcc
- CFLAGS=-O
-
- all: advise
-
- advise.o: advisemod.h
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'advise.c'
- then
- echo shar: will not over-write existing file "'advise.c'"
- else
- cat << \SHAR_EOF > 'advise.c'
- /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
-
- This file is part of advise.
-
- advise is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the advise General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- advise, but only under the conditions described in the
- advise General Public License. A copy of this license is
- supposed to have been given to you along with advise so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
-
- /*
- ** Author: Keith Gabryelski (ag@amix.commodore.com)
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <stropts.h>
- #include <poll.h>
- #include <sys/stream.h>
- #include <errno.h>
- #include <utmp.h>
- #include <pwd.h>
- #include <termios.h>
- #include <string.h>
- #include <ctype.h>
- #include "advisemod.h"
-
- extern char *optarg;
-
- #define max(a,b) ((a)>(b)?(a):(b))
-
- static struct module_list
- {
- char *name; /* name of module */
- struct module_list *next; /* next module to be pushed */
- } advise_module_list =
- {
- "advise", NULL,
- };
-
- static void usage(void), advise(char *);
- static char *strchar(char);
- static struct module_list *list_modules(int, char *);
-
- static int allow_deny_p, allow_deny;
- static int allow_advise_p, allow_advise;
- static int error_flag;
- static int secret, spy;
- static int meta_character = '~';
- static char *progname;
- static char *module = "ldterm";
-
- int
- main(int argc, char **argv)
- {
- int c, error = 0;
- struct termios termios;
- struct module_list *modules;
-
- progname = *argv;
-
- while((c = getopt(argc, argv, "ADM:Sadm:s?")) != EOF)
- {
- switch(c)
- {
- case 's':
- spy++;
- break;
-
- case 'S':
- if (!getuid())
- secret++;
- break;
-
- case 'a':
- allow_deny_p++;
- allow_deny=ADVISE_ALLOW;
- allow_advise_p++;
- allow_advise++;
- break;
-
- case 'd':
- allow_advise_p++;
- allow_advise=0;
- break;
-
- case 'A':
- allow_deny_p++;
- allow_deny=ADVISE_ALLOW;
- break;
-
- case 'D':
- allow_deny_p++;
- allow_deny=ADVISE_DENY;
- break;
-
- case 'm':
- meta_character = optarg[0];
- break;
-
- case 'M':
- module = optarg;
- break;
-
- case '?':
- error_flag++;
- break;
- }
-
- if (error_flag)
- {
- usage();
- }
- }
-
- if (allow_advise_p)
- {
- int status = ioctl(0, ADVISE_STATUS, &status);
-
- if (allow_advise && status)
- {
- int advise_module_pushed = 0;
-
- /* Push advise module on stream */
- (void) ioctl(0, TCGETS, &termios);
-
- modules = list_modules(0, module);
-
- advise_module_list.next = modules;
-
- for (modules = &advise_module_list;
- modules != NULL;
- modules = modules->next)
- {
-
- if (!strcmp(modules->name, "advise"))
- {
- if (advise_module_pushed)
- continue;
-
- advise_module_pushed = 1;
- }
-
- if (ioctl(0, I_PUSH, modules->name))
- {
- (void) fprintf(stderr, "%s: Couldn't I_PUSH: %s (%s).\n",
- progname, modules->name, strerror(errno));
- error++;
- }
- }
-
- (void) ioctl(0, TCSETS, &termios);
- }
-
- if (!allow_advise && !status)
- {
- (void) ioctl(0, TCGETS, &termios);
-
- modules = list_modules(0, "advise");
-
- while (modules != NULL)
- {
- if (strcmp(modules->name, "advise"))
- {
- if (ioctl(0, I_PUSH, modules->name))
- {
- (void) fprintf(stderr,
- "%s: Couldn't I_PUSH: %s (%s).\n",
- progname, modules->name,
- strerror(errno));
- error++;
- }
- }
-
- modules = modules->next;
- }
-
- (void) ioctl(0, TCSETS, &termios);
- }
-
- if (!allow_deny_p)
- return error ? 1 : 0;
- }
-
- if (allow_deny_p)
- {
- if (ioctl(0, allow_deny, 0))
- {
- if (errno == EINVAL)
- {
- (void) fprintf(stderr, "%s: module \"advise\" not in stream.\n",
- progname);
- }
- else
- {
- (void) fprintf(stderr, "%s: Couldn't set advisory mode (%s).\n",
- progname, strerror(errno));
- }
-
- return 1;
- }
-
- return 0;
- }
-
- /* All switches have been handled */
-
- argc -= optind;
- argv += optind;
-
- if (argc > 1)
- {
- usage();
- }
-
- if (argc == 0)
- {
- int status;
-
- /*
- ** Status of advise.
- */
-
- if (ioctl(0, ADVISE_STATUS, &status))
- {
- printf("Module \"advise\" not pushed on stream.\n");
- }
- else
- {
- printf("Advise access %s\n", status ? "allowed" : "denied");
- }
-
- return 0;
- }
-
- advise(*argv);
-
- return 0;
- }
-
- void
- usage()
- {
- (void) fprintf(stderr, "usage: %s [-ADad?] [-M module] | [-Ss] [-m char] [ device | username ]\n",
- progname);
- exit(1);
- }
-
- static void
- advise(char *who)
- {
- int ret, fd, metad=0;
- char buf[1024], *device, *devname, *login_name, *tty_name;
- struct pollfd pfds[2];
- struct termios termios, oldtermios;
- struct stat stbuf;
- struct utmp *ut, uts;
- char username[sizeof(ut->ut_name) + 1];
-
- username[0] = '\0';
-
- if (*who == '/') /* full path name */
- device = who;
- else
- {
- /* Either this is /dev/ + who OR a username */
-
- setutent();
-
- while ((ut = getutent()) != NULL)
- {
- if (!strncmp(who, ut->ut_name, sizeof(ut->ut_name)))
- {
- device = (char *)malloc(sizeof("/dev/") +
- sizeof(ut->ut_name));
-
- if (device == NULL)
- {
- (void) fprintf(stderr,
- "%s: malloc failed (Out of Memory)\n",
- progname);
-
- exit(1);
- }
-
- strcpy(device, "/dev/");
- strncat(device, ut->ut_name, sizeof(ut->ut_name));
- device[sizeof("/dev/")+sizeof(ut->ut_name)] = '\0';
-
- strncpy(username, ut->ut_name, sizeof(ut->ut_name));
- username[sizeof(ut->ut_name)] = '\0';
- break;
- }
- }
-
- if (ut == NULL) /* Is /dev/ + who */
- {
- device = (char *)malloc(sizeof("/dev/") + strlen(who));
-
- if (device == NULL)
- {
- (void) fprintf(stderr, "%s: malloc failed (Out of Memory)\n",
- progname);
-
- exit(1);
- }
-
- strcpy(device, "/dev/");
- strcat(device, who);
- }
-
- endutent();
- }
-
- devname = device + sizeof("/dev/") - 1;
-
- if (username[0] == '\0')
- {
- setutent();
-
- strncpy(uts.ut_line, devname, sizeof(uts.ut_line));
-
- if ((ut = getutline(&uts)) != NULL)
- {
- strncpy(username, ut->ut_name, sizeof(ut->ut_name));
- username[sizeof(ut->ut_name)] = '\0';
- }
- else
- {
- strcpy(username, "unknown");
- }
-
- endutent();
- }
-
- if (stat(device, &stbuf) < 0)
- {
- if (errno == ENOENT)
- {
- (void) fprintf(stderr, "%s: no advisee device: %s\n", progname,
- device);
- }
- else
- {
- (void) fprintf(stderr,
- "%s: Couldn't stat() advisee device: %s (%s)\n",
- progname, device, strerror(errno));
- }
- exit(1);
- }
-
- if ((fd = open("/dev/advise", O_RDWR)) < 0)
- {
- (void) fprintf(stderr,
- "%s: Couldn't open advisory device: /dev/advise (%s)\n",
- progname, strerror(errno));
- exit(1);
- }
-
- if (ioctl(fd, ADVISE_SETADVISEE, stbuf.st_rdev))
- {
- if (errno == EUNATCH)
- {
- (void) fprintf(stderr,
- "%s: module \"advise\" not in place for %s\n",
- progname, device);
- } else if (errno == EACCES)
- {
- (void) fprintf(stderr, "%s: permission denied.\n", progname);
- } else
- {
- (void) fprintf(stderr,
- "%s: Couldn't set advisee: %s (%lu, %lu) (%s)\n",
- progname, device, ((stbuf.st_rdev >> 16) &0xFFFF),
- (stbuf.st_rdev&0xFFFF), strerror(errno));
- }
- exit(1);
- }
-
- if (!secret)
- {
- char *str;
- struct passwd *pt;
-
- if ((login_name = getlogin()) == NULL)
- {
- pt = getpwuid(getuid());
-
- if (pt == NULL || pt->pw_name == NULL)
- {
- login_name = "somebody";
- }
- else
- {
- login_name = pt->pw_name;
- }
- }
-
- if ((tty_name = ttyname(2)) != NULL)
- {
- if (!strncmp(tty_name, "/dev/", sizeof("/dev/")-1))
- tty_name += sizeof("/dev/")-1;
- }
- else
- tty_name = "somewhere";
-
- str = malloc(strlen(login_name) + strlen(tty_name) +
- sizeof("[: advising :]\n\r") + strlen(username) +
- strlen(devname));
-
- if (str)
- {
- struct advise_message m;
- struct strbuf ctl, data;
-
- m.type = ADVISE_READDATA;
-
- ctl.len = sizeof(m);
- ctl.buf = (void *)&m;
-
- sprintf(str, "[%s:%s %s %s:%s]\n\r", login_name,
- tty_name, spy ? "spying" : "advising", username, devname);
-
- data.len = strlen(str);
- data.buf = str;
-
- (void) putmsg(fd, &ctl, &data, 0);
-
- free(str);
- }
- }
-
-
- if (!spy)
- {
- (void) ioctl(0, TCGETS, &termios);
-
- oldtermios = termios;
- termios.c_cc[VMIN] = 1;
- termios.c_cc[VTIME] = 0;
- termios.c_lflag &= ~(ISIG|ICANON|ECHO);
-
- (void) ioctl(0, TCSETS, &termios);
- }
-
- pfds[0].fd = fd;
- pfds[0].events = POLLIN;
-
- pfds[1].fd = 0;
- pfds[1].events = POLLIN;
-
- for (;;)
- {
- if (poll(pfds, 2, INFTIM) < 0)
- continue;
-
- if ((pfds[0].revents&POLLIN) != 0) /* data from advisee ready */
- {
- if ((ret = read(fd, buf, sizeof(buf))) > 0)
- write(1, buf, ret);
- }
-
- if ((pfds[1].revents&POLLIN) != 0) /* data from advisor ready */
- {
- if ((ret = read(0, buf, sizeof(buf))) > 0)
- {
- if (!spy)
- {
- register int i;
- register char *p = buf, *pp=buf;
-
- for (i=0; i < ret; ++i, p++)
- {
- if (metad)
- {
- if (metad == 2)
- {
- meta_character = *p;
- printf("The meta character is now: %s\n",
- strchar(meta_character));
- pp++;
- metad = 0;
- continue;
- }
-
- switch (*p)
- {
- case '=':
- metad=2;
- pp++;
- break;
-
- case '?':
- {
- char *escstr = strchar(meta_character);
-
- printf("Help for meta character <%s>:\n",
- escstr);
- printf("%s?\t-- This help message.\n", escstr);
- printf("%s~\t-- Send a single meta character.\n",
- escstr);
- printf("%s.\t-- Disconnect advise session.\n",
- escstr);
- printf("%s=C\t-- Change meta character to C.\n",
- escstr);
- printf("%s^Z\t-- Suspend advise session.\n",
- escstr);
- pp++;
- metad=0;
- break;
- }
-
- case '.':
- {
- if (!secret)
- {
- char *str;
-
- str = malloc(strlen(login_name) +
- strlen(tty_name) +
- sizeof("[/ disconnecting from :]\n") +
- strlen(username) + strlen(devname));
-
- if (str)
- {
- struct advise_message m;
- struct strbuf ctl, data;
-
- m.type = ADVISE_READDATA;
-
- ctl.len = sizeof(m);
- ctl.buf = (void *)&m;
-
- sprintf(str, "[%s/%s disconnecting from %s:%s]\n\r",
- login_name, tty_name, username,
- devname);
-
- data.len = strlen(str);
- data.buf = str;
-
- (void) putmsg(fd, &ctl, &data, 0);
-
- free(str);
- }
- }
-
- close(fd);
-
- (void) ioctl(0, TCSETS, &oldtermios);
-
- exit(0);
- }
-
- case CTRL('Z'):
- {
- (void) ioctl(0, TCSETS, &oldtermios);
- (void) signal(SIGTSTP, SIG_DFL);
- (void) kill(0, SIGTSTP);
- (void) ioctl(0, TCSETS, &termios);
- metad=0;
- break;
- }
-
- default:
- metad=0;
- break;
- }
- }
- else
- {
- if (*p == meta_character)
- {
- int d = p - pp;
-
- metad=1;
-
- if (d)
- write(fd, pp, d);
-
- pp += d + 1;
- i += d;
- }
- }
- }
-
- if (p - pp)
- {
- struct advise_message m;
- struct strbuf ctl, data;
-
- m.type = ADVISE_DATA;
-
- ctl.len = sizeof(m);
- ctl.buf = (void *)&m;
-
- data.len = p - pp;
- data.buf = p;
-
- (void) putmsg(fd, &ctl, &data, 0);
- }
- }
- }
- }
- }
- }
-
- static struct module_list *
- list_modules(int fd, char *push_below)
- {
- char lookbuf[max(FMNAMESZ+1,256)];
- struct module_list *mp, *mpp;
-
- mp = NULL;
-
- while (ioctl(fd, I_LOOK, lookbuf) == 0)
- {
- if (ioctl(fd, I_POP, 0))
- {
- (void) fprintf(stderr, "%s: Couldn't I_POP: %s (%s).\n", progname,
- lookbuf, strerror(errno));
- return mp;
- }
-
- if ((mpp = malloc(sizeof(struct module_list))) == NULL ||
- (mpp->name = malloc(strlen(lookbuf) + 1)) == NULL)
- {
- (void) fprintf(stderr, "%s: Couldn't malloc (out of memory).\n",
- progname);
- return mp;
- }
-
- mpp->next = mp;
- mp = mpp;
-
- strcpy(mp->name, lookbuf);
-
- if (!strcmp(push_below, lookbuf))
- break;
- }
-
- return mp;
- }
-
- static char *
- strchar(char character)
- {
- static char retbuf[4];
- char *p = retbuf;
- int capit = 0;
-
- if (!isascii(character))
- {
- *p++ = '~';
- capit = 1;
- character = toascii(character);
- }
-
- if (iscntrl(character))
- {
- *p++ = '^';
- capit = 1;
- character += '@';
- }
-
- if (capit)
- *p++ = toupper(character);
- else
- *p++ = character;
-
- *p = '\0';
-
- return retbuf;
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'advise.man'
- then
- echo shar: will not over-write existing file "'advise.man'"
- else
- cat << \SHAR_EOF > 'advise.man'
- .TH advise 1
- .SH NAME
- advise \- Attach to another user.
- .SH SYNOPSIS
- .B advise
- [-ADad?] [-M module] | [-Ss] [-m char] [ device | username ]
- .SH DESCRIPTION
- .B Advise
- attaches a user (the advisor) to another user's (the advisee) terminal in
- such a way the the advisor can type for the advisee and view what
- the advisee's terminal is displaying.
- .PP
- The advisee would typically type ``advise -a'' to allow advise attaches;
- the advisor would then type ``advise username'' which would connect the
- advisors terminal the the advisee's.
- .PP
- All characters the advisor types are sent to the advisee's terminal
- as if the advisee typed them save the meta character.
- .PP
- The default meta character is tilde (~). The advisor uses the meta
- character to disconnect or suspend the advise session. The meta
- commands that are available to the advisor are:
- .PP
- .RS
- .TP
- ~?
- Meta character help message.
- .TP
- ~~
- Send the meta character to the advisee's terminal.
- .TP
- ~.
- Disconnect advise session.
- .TP
- ~=C
- Change the meta character to C.
- .TP
- ~^Z
- Suspend this advise session.
- .RE
- .PP
- In Advise mode the advisor uses ``~.'' to disconnect the advise session
- (Note: the advisor should use ``~~'' to send one tilde to the advisee's
- terminal).
- .PP
- In ``spy mode'' the advisor should use an interrupt is use to disconnect
- the advise session.
- .PP
- ``advise -d'' can be used by the advisee to disconnect the advise
- session.
- .SH OPTIONS
- .TP
- -A
- Allow advise attaches to this terminal.
- .TP
- -D
- Disallow advise attaches to this terminal.
- .TP
- -M module
- Name of module to place advise module under.
- .TP
- -S
- When attaching to another user, don't send the attach message.
- (available to the super user, only).
- .TP
- -a
- Push advise module on standard input stream and allow advise
- attaches.
- .TP
- -d
- Push advise module on standard input stream and disallow advise
- attaches.
- .TP
- -m char
- Change the meta character to ``char''. The default meta character
- is tilde (~).
- .TP
- -s
- Spy mode only (ie, input from the advisor is not passed to the
- advisee).
- .TP
- device
- The name of the tty device to advise.
- .TP
- username
- The name of the user to advise.
- .SH AUTHOR
- .RS
- .PP
- Keith M. Gabryelski (ag@amix.commodore.com)
- .RE
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'advisedev.c'
- then
- echo shar: will not over-write existing file "'advisedev.c'"
- else
- cat << \SHAR_EOF > 'advisedev.c'
- /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
-
- This file is part of advise.
-
- advise is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the advise General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- advise, but only under the conditions described in the
- advise General Public License. A copy of this license is
- supposed to have been given to you along with advise so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
-
- /*
- ** Author: Keith Gabryelski (ag@amix.commodore.com)
- */
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/sysmacros.h>
- #include <sys/signal.h>
- #include <sys/file.h>
- #include <sys/user.h>
- #include <sys/proc.h>
- #include <sys/termios.h>
- #include <sys/ttold.h>
- #include <sys/cmn_err.h>
- #include <sys/stream.h>
- #include <sys/stropts.h>
- #include <sys/errno.h>
- #include <sys/debug.h>
- #include "advisemod.h"
- #include <sys/inline.h>
-
- int adviseopen(), adviseclose(), adviserput(), advisewput();
- void advisesrvioc();
-
- static struct module_info advisemiinfo =
- {
- 0, "advise", 0, INFPSZ, 2048, 128,
- };
-
- static struct qinit adviserinit =
- {
- adviserput, NULL, adviseopen, adviseclose, NULL, &advisemiinfo,
- };
-
- static struct module_info advisemoinfo =
- {
- 42, "advise", 0, INFPSZ, 300, 200,
- };
-
- static struct qinit advisewinit =
- {
- advisewput, NULL, adviseopen, adviseclose, NULL, &advisemoinfo,
- };
-
- struct streamtab adviseinfo =
- {
- &adviserinit, &advisewinit, NULL, NULL,
- };
-
- extern struct advise_state advise_table;
-
- /*ARGSUSED*/
- static int
- adviseopen(q, devp, flag, sflag, credp)
- register queue_t *q;
- dev_t *devp;
- int flag, sflag;
- cred_t *credp;
- {
- register mblk_t *bp;
- struct advise_queue_list *ql;
- struct advise_state *sp;
- int i;
-
- if (sflag == MODOPEN)
- return EINVAL;
-
- for (i=1; i < L_MAXMIN; ++i)
- {
- sp = &advise_table;
-
- while (sp->next != NULL)
- {
- ql = sp->next->q_list;
-
- while (ql != NULL)
- {
- if (ql->minord == i)
- break;
-
- ql = ql->next;
- }
-
- if (ql != NULL)
- break;
-
- sp = sp->next;
- }
-
- if (sp->next == NULL)
- break;
- }
-
- if (i == L_MAXMIN)
- {
- return ENOMEM; /* no more resources */
- }
-
- *devp = makedevice(getmajor(*devp), i);
-
- if ((bp = allocb((int)sizeof(struct advise_queue_list), BPRI_MED)) == NULL)
- {
- return ENOMEM;
- }
-
- bp->b_wptr += sizeof(struct advise_queue_list);
- ql = (struct advise_queue_list *)bp->b_rptr;
- ql->savbp = bp;
- ql->next = NULL;
- ql->q = q;
- ql->state = NULL;
- ql->minord = i;
-
- q->q_ptr = (caddr_t)ql;
- WR(q)->q_ptr = (caddr_t)ql;
-
- return 0;
- }
-
- static
- adviseclose(q)
- register queue_t *q;
- {
- struct advise_state *llist = &advise_table;
- struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
- struct advise_queue_list *ql, *qlp;
-
- /* Remove us from the advisor's list */
-
- if (qp->state != NULL)
- {
- while (llist != NULL && llist->next != qp->state)
- llist = llist->next;
-
- if (llist != NULL)
- {
- ql = llist->next->q_list;
-
- if (ql->q == q)
- {
- llist->next->q_list = ql->next;
- }
- else
- {
- while (ql->next != NULL && ql->next->q != q)
- ql = ql->next;
-
- if (ql->next != NULL)
- {
- ql->next = ql->next->next;
- }
- }
- }
- }
-
- qp->state = NULL;
- freeb(qp->savbp);
-
- q->q_ptr = NULL;
- }
-
- static int
- adviserput(q, bp)
- struct queue *q;
- mblk_t *bp;
- {
- putnext(q, bp);
- }
-
- static int
- advisewput(q, bp)
- struct queue *q;
- mblk_t *bp;
- {
- struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
- struct advise_state *sp = qp->state;
-
- switch (bp->b_datap->db_type)
- {
- case M_PROTO:
- {
- struct advise_message *ms = (struct advise_message *)bp->b_rptr;
- mblk_t *bp2 = unlinkb(bp);
-
- if (bp2)
- {
- if (sp != NULL && sp->q != NULL)
- {
- if (ms->type == ADVISE_READDATA)
- {
- putnext(WR(sp->q), bp2);
- }
- else
- {
- putnext(sp->q, bp2);
- }
- }
- else
- freemsg(bp2);
- }
-
- freemsg(bp);
-
- break;
- }
-
- case M_DATA:
- /*
- ** Write data to advisee.
- */
- if (sp != NULL && sp->q != NULL)
- putnext(sp->q, bp);
- else
- freemsg(bp);
- break;
-
- case M_IOCTL:
- case M_IOCDATA:
- advisesrvioc(q, bp);
- break;
-
- default:
- freemsg(bp);
- break;
- }
- }
-
- static void
- advisesrvioc(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- mblk_t *mp1;
- struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
- struct advise_queue_list *qp=(struct advise_queue_list *)q->q_ptr;
- int s;
-
- if (mp->b_datap->db_type == M_IOCDATA)
- {
- /* For copyin/copyout failures, just free message. */
- if (((struct copyresp *)mp->b_rptr)->cp_rval)
- {
- freemsg(mp);
- return;
- }
-
- if (!((struct copyresp *)mp->b_rptr)->cp_private)
- {
- mp->b_datap->db_type = M_IOCACK;
- freemsg(unlinkb(mp));
- iocbp->ioc_count = 0;
- iocbp->ioc_rval = 0;
- iocbp->ioc_error = 0;
- putnext(RD(q), mp);
- return;
- }
- }
-
- switch (iocbp->ioc_cmd)
- {
- case ADVISE_SETADVISEE:
- {
- register dev_t p;
- struct advise_queue_list *qlp;
- struct advise_state *llist;
-
- if (qp->state != NULL) /* already advising someone */
- {
- iocbp->ioc_error = EBUSY;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- if (!mp->b_cont)
- {
- iocbp->ioc_error = EINVAL;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- p = *(dev_t *)mp->b_cont->b_rptr;
-
- s = spladvise();
-
- llist = advise_table.next;
-
- while (llist != NULL && llist->dev != p)
- {
- llist = llist->next;
- }
-
- if (llist == NULL)
- {
- splx(s);
- iocbp->ioc_error = EUNATCH;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- if ((llist->status & ALLOW_ADVICE) == 0 && (!suser(u.u_cred)))
- {
- splx(s);
- iocbp->ioc_error = EACCES;
- mp->b_datap->db_type = M_IOCNAK;
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- /*
- ** Add ourself to the list of advisors for this advisee.
- */
-
- if (llist->q_list == NULL)
- {
- qlp = llist->q_list = qp;
- }
- else
- {
- qlp = llist->q_list;
-
- while (qlp->next != NULL)
- qlp = qlp->next;
-
- qlp->next = qp;
- qlp = qp;
- }
-
- qlp->state = llist;
-
- splx(s);
-
- mp->b_datap->db_type = M_IOCACK;
- mp1 = unlinkb(mp);
- if (mp1)
- freeb(mp1);
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
- }
-
- default:
- /* Unrecognized ioctl command */
- if (canput(RD(q)->q_next))
- {
- mp->b_datap->db_type = M_IOCNAK;
- putnext(RD(q), mp);
- }
- else
- putbq(q, mp);
- break;
- }
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'advisemod.c'
- then
- echo shar: will not over-write existing file "'advisemod.c'"
- else
- cat << \SHAR_EOF > 'advisemod.c'
- /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
-
- This file is part of advise.
-
- advise is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the advise General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- advise, but only under the conditions described in the
- advise General Public License. A copy of this license is
- supposed to have been given to you along with advise so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
-
- /*
- ** Author: Keith Gabryelski (ag@amix.commodore.com)
- */
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/signal.h>
- #include <sys/file.h>
- #include <sys/user.h>
- #include <sys/proc.h>
- #include <sys/termios.h>
- #include <sys/ttold.h>
- #include <sys/cmn_err.h>
- #include <sys/stream.h>
- #include <sys/stropts.h>
- #include <sys/errno.h>
- #include <sys/debug.h>
- #include "advisemod.h"
- #include <sys/inline.h>
-
- int advisemopen(), advisemclose(), advisemrput(), advisemwput();
-
- static struct module_info advisemiinfo =
- {
- 0, "advisemod", 0, INFPSZ, 2048, 128,
- };
-
- static struct qinit adviserinit =
- {
- advisemrput, NULL, advisemopen, advisemclose, NULL, &advisemiinfo,
- };
-
- static struct module_info advisemoinfo =
- {
- 42, "advisemod", 0, INFPSZ, 300, 200,
- };
-
- static struct qinit advisewinit =
- {
- advisemwput, NULL, advisemopen, advisemclose, NULL, &advisemoinfo,
- };
-
- struct streamtab advisemodinfo =
- {
- &adviserinit, &advisewinit, NULL, NULL,
- };
-
- struct advise_state advise_table;
-
- /*ARGSUSED*/
- static int
- advisemopen(q, devp, flag, sflag, credp)
- register queue_t *q;
- dev_t *devp;
- int flag, sflag;
- cred_t *credp;
- {
- register struct advise_state *sp;
- register mblk_t *bp;
- struct advise_state *llist = &advise_table;
-
- if (sflag != MODOPEN)
- return EINVAL;
-
- if ((bp = allocb((int)sizeof(struct advise_state), BPRI_MED)) == NULL)
- {
- return ENOMEM;
- }
-
- bp->b_wptr += sizeof(struct advise_state);
- sp = (struct advise_state *)bp->b_rptr;
- sp->savbp = bp;
-
- sp->dev = *devp;
- sp->status = 0; /* Deny access by default */
- sp->next = NULL;
- sp->q_list = NULL;
- sp->q = q;
-
- while (llist->next != NULL)
- {
- if (llist->next->dev == *devp)
- {
- /*
- ** We are already pushed on this stream.
- */
- freeb(bp);
-
- sp = llist->next;
-
- break;
- }
-
- llist = llist->next;
- }
-
- llist->next = sp;
-
- q->q_ptr = (caddr_t)sp;
- WR(q)->q_ptr = (caddr_t)sp;
-
- return 0;
- }
-
- static
- advisemclose(q)
- register queue_t *q;
- {
- register struct advise_state *sp = (struct advise_state *)q->q_ptr;
- struct advise_state *llist = &advise_table;
- struct advise_queue_list *qp = sp->q_list;
-
- sp->status = 0;
-
- /* unlink us from the state table */
-
- while (llist->next != sp)
- llist = llist->next;
-
- llist->next = llist->next->next;
-
- while (sp->next != NULL)
- {
- /* tell each advisor that we're shutting down */
-
- flushq(sp->q, FLUSHDATA);
- putctl(sp->q->q_next, M_HANGUP);
-
- sp = sp->next;
- }
-
- freeb(sp->savbp);
-
- q->q_ptr = NULL;
- }
-
- static
- advisemrput(q, mp)
- register queue_t *q;
- register mblk_t *mp;
- {
- putnext(q, mp);
- }
-
- static
- advisemwput(q, mp)
- register queue_t *q;
- register mblk_t *mp;
- {
- struct advise_state *sp = (struct advise_state *)q->q_ptr;
- register struct advise_queue_list *qp;
- int s;
-
- switch (mp->b_datap->db_type)
- {
- case M_DATA:
- /*
- ** Write data to advisors.
- */
- s = spladvise();
- for (qp = sp->q_list; qp != NULL; qp = qp->next)
- {
- mblk_t *mp1 = copymsg(mp);
-
- if (mp1 != NULL)
- putnext(qp->q, mp1);
- }
-
- splx(s);
- break;
-
- case M_IOCTL:
- case M_IOCDATA:
- if (advisemsrvioc(q, mp)) /* handled? */
- return;
- break;
- }
-
- putnext(q, mp);
- }
-
- static int
- advisemsrvioc(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- mblk_t *mp1;
- struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
- struct advise_state *sp = (struct advise_state *)q->q_ptr;
-
- if (mp->b_datap->db_type == M_IOCDATA)
- {
- struct copyresp *csp = (struct copyresp *)mp->b_rptr;
-
- switch(csp->cp_cmd)
- {
- case ADVISE_STATUS:
- case ADVISE_ALLOW:
- case ADVISE_DENY:
- /* For copyin/copyout failures, just free message. */
-
- if (csp->cp_rval)
- freemsg(mp);
- else if (!csp->cp_private)
- {
- mp->b_datap->db_type = M_IOCACK;
- freemsg(unlinkb(mp));
- iocbp->ioc_count = 0;
- iocbp->ioc_rval = 0;
- iocbp->ioc_error = 0;
- putnext(RD(q), mp);
- }
-
- return 1;
- }
- }
-
- switch (iocbp->ioc_cmd)
- {
- case ADVISE_STATUS:
- {
- int *status;
- caddr_t arg = *(caddr_t *)mp->b_cont->b_rptr;
-
- freemsg(mp->b_cont);
-
- mp->b_cont = allocb(sizeof(int), BPRI_MED);
- if (!mp->b_cont)
- {
- mp->b_datap->db_type = M_IOCNAK;
- freemsg(unlinkb(mp));
- iocbp->ioc_count = 0;
- iocbp->ioc_rval = 0;
- iocbp->ioc_error = ENOMEM;
- putnext(RD(q), mp);
- return 1;
- }
-
- status = (int *)mp->b_cont->b_rptr;
- mp->b_cont->b_wptr += sizeof(int);
-
- *status = sp->status;
-
- if (mp->b_datap->db_type == M_IOCTL &&
- iocbp->ioc_count == TRANSPARENT)
- {
- struct copyreq *creq = (struct copyreq *)mp->b_rptr;
- mp->b_datap->db_type = M_COPYOUT;
- creq->cq_addr = arg;
- mp->b_wptr = mp->b_rptr + sizeof *creq;
- mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
- creq->cq_size = sizeof(int);
- creq->cq_flag = 0;
- creq->cq_private = (mblk_t *)NULL;
- putnext(RD(q), mp);
- return 1;
- }
- }
- break;
-
- case ADVISE_ALLOW:
- sp->status |= ALLOW_ADVICE;
-
- mp->b_datap->db_type = M_IOCACK;
- mp1 = unlinkb(mp);
- if (mp1)
- freeb(mp1);
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
-
- case ADVISE_DENY:
- sp->status &= ~(ALLOW_ADVICE);
-
- mp->b_datap->db_type = M_IOCACK;
- mp1 = unlinkb(mp);
- if (mp1)
- freeb(mp1);
- iocbp->ioc_count = 0;
- putnext(RD(q), mp);
- break;
-
- default:
- return 0;
- }
-
- return 1;
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'advisemod.h'
- then
- echo shar: will not over-write existing file "'advisemod.h'"
- else
- cat << \SHAR_EOF > 'advisemod.h'
- /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
-
- This file is part of advise.
-
- advise is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the advise General Public
- License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- advise, but only under the conditions described in the
- advise General Public License. A copy of this license is
- supposed to have been given to you along with advise so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
-
- /*
- ** Author: Keith Gabryelski (ag@amix.commodore.com)
- */
-
- struct advise_queue_list
- {
- mblk_t *savbp; /* ptr to this mblk for freeb()ing */
- queue_t *q; /* advisor's queue */
- int minord; /* minor device for this advisor */
- struct advise_state *state; /* ptr back to advise_state struct */
- struct advise_queue_list *next; /* ptr to next advisor */
- };
-
- struct advise_state
- {
- mblk_t *savbp; /* ptr to this mblk for freeb()ing */
- int status; /* current status */
- dev_t dev; /* our device */
- queue_t *q; /* queue for advisor writing */
- struct advise_queue_list *q_list;/* list of spies */
- struct advise_state *next; /* next in advise_table */
- };
-
- #define ALLOW_ADVICE (0x01)
-
- struct advise_message
- {
- int type; /* What type of data is this? */
- };
-
- #define ADVISE_DATA (0x00)
- #define ADVISE_READDATA (0x01)
-
- #define ADVISE ('z'<<16)
- #define ADVISE_SETADVISEE (ADVISE|0x01)
- #define ADVISE_ALLOW (ADVISE|0x02)
- #define ADVISE_DENY (ADVISE|0x03)
- #define ADVISE_STATUS (ADVISE|0x04)
-
- #define spladvise spltty
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-