home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1966 < prev    next >
Internet Message Format  |  1990-12-28  |  41KB

  1. From: ag@cbmvax.commodore.com (Keith Gabryelski)
  2. Newsgroups: alt.sources
  3. Subject: advise (spy) for streams ttys.
  4. Message-ID: <15193@cbmvax.commodore.com>
  5. Date: 16 Oct 90 23:26:25 GMT
  6.  
  7. The included source code includes
  8.  
  9.     advise.c        # a user program to interact with
  10.                 # the advise device and module.
  11.  
  12.     advisedev.c        # the advise device driver.
  13.                 # (requests to attach to a users terminal
  14.                 #  are done through this device)
  15.  
  16.     advisemod.c        # the advise module.
  17.                 # (this module is pushed onto the advisee's
  18.                 #  tty stream so advisedev may attach to
  19.                 #  it.)
  20.  
  21.     advisemod.h        # useful header file.
  22.  
  23.     COPYING Makefile    # Other files.
  24.  
  25. Pax, Keith
  26.  
  27. Ps, This will only work under System V Release 4.0 streams ttys.
  28.  
  29.     With little effort it could be made to work under other streams
  30.     tty subsystems.
  31.  
  32.     No amount of effort (save re-thinking and re-implimenting) will
  33.     make this thing work on non-streams based ttys.
  34.  
  35. #! /bin/sh
  36. # This is a shell archive, meaning:
  37. # 1. Remove everything above the #! /bin/sh line.
  38. # 2. Save the resulting text in a file.
  39. # 3. Execute the file with /bin/sh (not csh) to create the files:
  40. #    COPYING
  41. #    Makefile
  42. #    advise.c
  43. #    advise.man
  44. #    advisedev.c
  45. #    advisemod.c
  46. #    advisemod.h
  47. # This archive created: Tue Oct 16 19:15:42 1990
  48. export PATH; PATH=/bin:$PATH
  49. if test -f 'COPYING'
  50. then
  51.     echo shar: will not over-write existing file "'COPYING'"
  52. else
  53. cat << \SHAR_EOF > 'COPYING'
  54.  
  55.             Advise GENERAL PUBLIC LICENSE
  56.             (Clarified 11 Feb 1988)
  57.  
  58.  Copyright (C) 1988 Free Software Foundation, Inc.
  59.  Everyone is permitted to copy and distribute verbatim copies
  60.  of this license, but changing it is not allowed.  You can also
  61.  use this wording to make the terms for other programs.
  62.  
  63.   The license agreements of most software companies keep you at the
  64. mercy of those companies.  By contrast, our general public license is
  65. intended to give everyone the right to share Advise.  To make sure that
  66. you get the rights we want you to have, we need to make restrictions
  67. that forbid anyone to deny you these rights or to ask you to surrender
  68. the rights.  Hence this license agreement.
  69.  
  70.   Specifically, we want to make sure that you have the right to give
  71. away copies of Advise, that you receive source code or else can get it
  72. if you want it, that you can change Advise or use pieces of it in new
  73. free programs, and that you know you can do these things.
  74.  
  75.   To make sure that everyone has such rights, we have to forbid you to
  76. deprive anyone else of these rights.  For example, if you distribute
  77. copies of Advise, you must give the recipients all the rights that you
  78. have.  You must make sure that they, too, receive or can get the
  79. source code.  And you must tell them their rights.
  80.  
  81.   Also, for our own protection, we must make certain that everyone
  82. finds out that there is no warranty for Advise.  If Advise is modified by
  83. someone else and passed on, we want its recipients to know that what
  84. they have is not what we distributed, so that any problems introduced
  85. by others will not reflect on our reputation.
  86.  
  87.   Therefore we (Richard Stallman and the Free Software Foundation,
  88. Inc.) make the following terms which say what you must do to be
  89. allowed to distribute or change Advise.
  90.  
  91.  
  92.             COPYING POLICIES
  93.  
  94.   1. You may copy and distribute verbatim copies of Advise source code
  95. as you receive it, in any medium, provided that you conspicuously and
  96. appropriately publish on each copy a valid copyright notice "Copyright
  97. (C) 1988 Free Software Foundation, Inc." (or with whatever year is
  98. appropriate); keep intact the notices on all files that refer to this
  99. License Agreement and to the absence of any warranty; and give any
  100. other recipients of the Advise program a copy of this License
  101. Agreement along with the program.  You may charge a distribution fee
  102. for the physical act of transferring a copy.
  103.  
  104.   2. You may modify your copy or copies of Advise or any portion of it,
  105. and copy and distribute such modifications under the terms of
  106. Paragraph 1 above, provided that you also do the following:
  107.  
  108.     a) cause the modified files to carry prominent notices stating
  109.     that you changed the files and the date of any change; and
  110.  
  111.     b) cause the whole of any work that you distribute or publish,
  112.     that in whole or in part contains or is a derivative of Advise or
  113.     any part thereof, to be licensed at no charge to all third
  114.     parties on terms identical to those contained in this License
  115.     Agreement (except that you may choose to grant more extensive
  116.     warranty protection to some or all third parties, at your option).
  117.  
  118.     c) You may charge a distribution fee for the physical act of
  119.     transferring a copy, and you may at your option offer warranty
  120.     protection in exchange for a fee.
  121.  
  122. Mere aggregation of another unrelated program with this program (or its
  123. derivative) on a volume of a storage or distribution medium does not bring
  124. the other program under the scope of these terms.
  125.  
  126.   3. You may copy and distribute Advise (or a portion or derivative of it,
  127. under Paragraph 2) in object code or executable form under the terms of
  128. Paragraphs 1 and 2 above provided that you also do one of the following:
  129.  
  130.     a) accompany it with the complete corresponding machine-readable
  131.     source code, which must be distributed under the terms of
  132.     Paragraphs 1 and 2 above; or,
  133.  
  134.     b) accompany it with a written offer, valid for at least three
  135.     years, to give any third party free (except for a nominal
  136.     shipping charge) a complete machine-readable copy of the
  137.     corresponding source code, to be distributed under the terms of
  138.     Paragraphs 1 and 2 above; or,
  139.  
  140.     c) accompany it with the information you received as to where the
  141.     corresponding source code may be obtained.  (This alternative is
  142.     allowed only for noncommercial distribution and only if you
  143.     received the program in object code or executable form alone.)
  144.  
  145. For an executable file, complete source code means all the source code for
  146. all modules it contains; but, as a special exception, it need not include
  147. source code for modules which are standard libraries that accompany the
  148. operating system on which the executable file runs.
  149.  
  150.   4. You may not copy, sublicense, distribute or transfer Advise
  151. except as expressly provided under this License Agreement.  Any attempt
  152. otherwise to copy, sublicense, distribute or transfer Advise is void and
  153. your rights to use the program under this License agreement shall be
  154. automatically terminated.  However, parties who have received computer
  155. software programs from you with this License Agreement will not have
  156. their licenses terminated so long as such parties remain in full compliance.
  157.  
  158.   5. If you wish to incorporate parts of Advise into other free programs
  159. whose distribution conditions are different, write to the Free Software
  160. Foundation at 675 Mass Ave, Cambridge, MA 02139.  We have not yet worked
  161. out a simple rule that can be stated here, but we will often permit this.
  162. We will be guided by the two goals of preserving the free status of all
  163. derivatives of our free software and of promoting the sharing and reuse of
  164. software.
  165.  
  166. Your comments and suggestions about our licensing policies and our
  167. software are welcome!  Please contact the Free Software Foundation, Inc.,
  168. 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
  169.  
  170.                NO WARRANTY
  171.  
  172.   BECAUSE ADVISE IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO
  173. WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
  174. WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
  175. RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE ADVISE "AS IS" WITHOUT
  176. WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
  177. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  178. A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND
  179. PERFORMANCE OF ADVISE IS WITH YOU.  SHOULD ADVISE PROVE DEFECTIVE, YOU
  180. ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  181.  
  182.  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  183. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
  184. WHO MAY MODIFY AND REDISTRIBUTE GNU SEND AS PERMITTED ABOVE, BE LIABLE TO
  185. YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER
  186. SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  187. INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  188. BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  189. FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GNU SEND, EVEN
  190. IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR
  191. ANY CLAIM BY ANY OTHER PARTY.
  192. SHAR_EOF
  193. fi # end of overwriting check
  194. if test -f 'Makefile'
  195. then
  196.     echo shar: will not over-write existing file "'Makefile'"
  197. else
  198. cat << \SHAR_EOF > 'Makefile'
  199. # Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
  200. #
  201. # This file is part of advise.
  202. #
  203. # advise is distributed in the hope that it will be useful,
  204. # but WITHOUT ANY WARRANTY.  No author or distributor
  205. # accepts responsibility to anyone for the consequences of using it
  206. # or for whether it serves any particular purpose or works at all,
  207. # unless he says so in writing.  Refer to the advise General Public
  208. # License for full details.
  209. # Everyone is granted permission to copy, modify and redistribute
  210. # advise, but only under the conditions described in the
  211. # advise General Public License.   A copy of this license is
  212. # supposed to have been given to you along with advise so you
  213. # can know your rights and responsibilities.  It should be in a
  214. # file named COPYING.  Among other things, the copyright notice
  215. # and this notice must be preserved on all copies.  */
  216. # Author:    Keith Gabryelski    (ag@amix.commodore.com)
  217. #
  218.  
  219. CC=gcc
  220. CFLAGS=-O
  221.  
  222. all: advise
  223.  
  224. advise.o: advisemod.h
  225. SHAR_EOF
  226. fi # end of overwriting check
  227. if test -f 'advise.c'
  228. then
  229.     echo shar: will not over-write existing file "'advise.c'"
  230. else
  231. cat << \SHAR_EOF > 'advise.c'
  232. /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
  233.  
  234. This file is part of advise.
  235.  
  236. advise is distributed in the hope that it will be useful,
  237. but WITHOUT ANY WARRANTY.  No author or distributor
  238. accepts responsibility to anyone for the consequences of using it
  239. or for whether it serves any particular purpose or works at all,
  240. unless he says so in writing.  Refer to the advise General Public
  241. License for full details.
  242.  
  243. Everyone is granted permission to copy, modify and redistribute
  244. advise, but only under the conditions described in the
  245. advise General Public License.   A copy of this license is
  246. supposed to have been given to you along with advise so you
  247. can know your rights and responsibilities.  It should be in a
  248. file named COPYING.  Among other things, the copyright notice
  249. and this notice must be preserved on all copies.  */
  250.  
  251. /*
  252. ** Author:    Keith Gabryelski    (ag@amix.commodore.com)
  253. */
  254.  
  255. #include <sys/types.h>
  256. #include <sys/stat.h>
  257. #include <signal.h>
  258. #include <stdio.h>
  259. #include <stdlib.h>
  260. #include <unistd.h>
  261. #include <fcntl.h>
  262. #include <stropts.h>
  263. #include <poll.h>
  264. #include <sys/stream.h>
  265. #include <errno.h>
  266. #include <utmp.h>
  267. #include <pwd.h>
  268. #include <termios.h>
  269. #include <string.h>
  270. #include <ctype.h>
  271. #include "advisemod.h"
  272.  
  273. extern char *optarg;
  274.  
  275. #define max(a,b) ((a)>(b)?(a):(b))
  276.  
  277. static struct module_list
  278. {
  279.     char *name;            /* name of module */
  280.     struct module_list *next;    /* next module to be pushed */
  281. } advise_module_list =
  282. {
  283.     "advise", NULL,
  284. };
  285.  
  286. static void usage(void), advise(char *);
  287. static char *strchar(char);
  288. static struct module_list *list_modules(int, char *);
  289.  
  290. static int allow_deny_p, allow_deny;
  291. static int allow_advise_p, allow_advise;
  292. static int error_flag;
  293. static int secret, spy;
  294. static int meta_character = '~';
  295. static char *progname;
  296. static char *module = "ldterm";
  297.  
  298. int
  299. main(int argc, char **argv)
  300. {
  301.     int c, error = 0;
  302.     struct termios termios;
  303.     struct module_list *modules;
  304.  
  305.     progname = *argv;
  306.  
  307.     while((c = getopt(argc, argv, "ADM:Sadm:s?")) != EOF)
  308.     {
  309.     switch(c)
  310.     {
  311.     case 's':
  312.         spy++;
  313.         break;
  314.  
  315.     case 'S':
  316.         if (!getuid())
  317.         secret++;
  318.         break;
  319.  
  320.     case 'a':
  321.         allow_deny_p++;
  322.         allow_deny=ADVISE_ALLOW;
  323.         allow_advise_p++;
  324.         allow_advise++;
  325.         break;
  326.  
  327.     case 'd':
  328.         allow_advise_p++;
  329.         allow_advise=0;
  330.         break;
  331.  
  332.     case 'A':
  333.         allow_deny_p++;
  334.         allow_deny=ADVISE_ALLOW;
  335.         break;
  336.  
  337.     case 'D':
  338.         allow_deny_p++;
  339.         allow_deny=ADVISE_DENY;
  340.         break;
  341.  
  342.     case 'm':
  343.         meta_character = optarg[0];
  344.         break;
  345.  
  346.     case 'M':
  347.         module = optarg;
  348.         break;
  349.  
  350.     case '?':
  351.         error_flag++;
  352.         break;
  353.     }
  354.  
  355.     if (error_flag)
  356.     {
  357.         usage();
  358.     }
  359.     }
  360.  
  361.     if (allow_advise_p)
  362.     {
  363.     int status = ioctl(0, ADVISE_STATUS, &status);
  364.  
  365.     if (allow_advise && status)
  366.     {
  367.         int advise_module_pushed = 0;
  368.  
  369.         /* Push advise module on stream */
  370.         (void) ioctl(0, TCGETS, &termios);
  371.  
  372.         modules = list_modules(0, module);
  373.  
  374.         advise_module_list.next = modules;
  375.  
  376.         for (modules = &advise_module_list;
  377.          modules != NULL;
  378.          modules = modules->next)
  379.         {
  380.  
  381.         if (!strcmp(modules->name, "advise"))
  382.         {
  383.             if (advise_module_pushed)
  384.             continue;
  385.  
  386.             advise_module_pushed = 1;
  387.         }
  388.  
  389.         if (ioctl(0, I_PUSH, modules->name))
  390.         {
  391.             (void) fprintf(stderr, "%s: Couldn't I_PUSH: %s (%s).\n",
  392.                    progname, modules->name, strerror(errno));
  393.             error++;
  394.         }
  395.         }
  396.  
  397.         (void) ioctl(0, TCSETS, &termios);
  398.     }
  399.  
  400.     if (!allow_advise && !status)
  401.     {
  402.         (void) ioctl(0, TCGETS, &termios);
  403.  
  404.         modules = list_modules(0, "advise");
  405.  
  406.         while (modules != NULL)
  407.         {
  408.         if (strcmp(modules->name, "advise"))
  409.         {
  410.             if (ioctl(0, I_PUSH, modules->name))
  411.             {
  412.             (void) fprintf(stderr,
  413.                        "%s: Couldn't I_PUSH: %s (%s).\n",
  414.                        progname, modules->name,
  415.                        strerror(errno));
  416.             error++;
  417.             }
  418.         }
  419.  
  420.         modules = modules->next;
  421.         }
  422.  
  423.         (void) ioctl(0, TCSETS, &termios);
  424.     }
  425.  
  426.     if (!allow_deny_p)
  427.         return error ? 1 : 0;
  428.     }
  429.  
  430.     if (allow_deny_p)
  431.     {
  432.     if (ioctl(0, allow_deny, 0))
  433.     {
  434.         if (errno == EINVAL)
  435.         {
  436.         (void) fprintf(stderr, "%s: module \"advise\" not in stream.\n",
  437.                    progname);
  438.         }
  439.         else
  440.         {
  441.         (void) fprintf(stderr, "%s: Couldn't set advisory mode (%s).\n",
  442.                    progname, strerror(errno));
  443.         }
  444.  
  445.         return 1;
  446.     }
  447.  
  448.     return 0;
  449.     }
  450.  
  451.     /* All switches have been handled */
  452.  
  453.     argc -= optind;
  454.     argv += optind;
  455.  
  456.     if (argc > 1)
  457.     {
  458.     usage();
  459.     }
  460.  
  461.     if (argc == 0)
  462.     {
  463.     int status;
  464.  
  465.     /*
  466.     ** Status of advise.
  467.     */
  468.  
  469.     if (ioctl(0, ADVISE_STATUS, &status))
  470.     {
  471.         printf("Module \"advise\" not pushed on stream.\n");
  472.     }
  473.     else
  474.     {
  475.         printf("Advise access %s\n", status ? "allowed" : "denied");
  476.     }
  477.  
  478.     return 0;
  479.     }
  480.  
  481.     advise(*argv);
  482.  
  483.     return 0;
  484. }
  485.  
  486. void
  487. usage()
  488. {
  489.     (void) fprintf(stderr, "usage: %s [-ADad?] [-M module] | [-Ss] [-m char] [ device | username ]\n",
  490.            progname);
  491.     exit(1);
  492. }
  493.  
  494. static void
  495. advise(char *who)
  496. {
  497.     int ret, fd, metad=0;
  498.     char buf[1024], *device, *devname, *login_name, *tty_name;
  499.     struct pollfd pfds[2];
  500.     struct termios termios, oldtermios;
  501.     struct stat stbuf;
  502.     struct utmp *ut, uts;
  503.     char username[sizeof(ut->ut_name) + 1];
  504.  
  505.     username[0] = '\0';
  506.  
  507.     if (*who == '/') /* full path name */
  508.     device = who;
  509.     else
  510.     {
  511.     /* Either this is /dev/ + who OR a username */
  512.  
  513.     setutent();
  514.  
  515.     while ((ut = getutent()) != NULL)
  516.     {
  517.         if (!strncmp(who, ut->ut_name, sizeof(ut->ut_name)))
  518.         {
  519.         device = (char *)malloc(sizeof("/dev/") +
  520.                     sizeof(ut->ut_name));
  521.  
  522.         if (device == NULL)
  523.         {
  524.             (void) fprintf(stderr,
  525.                 "%s: malloc failed (Out of Memory)\n",
  526.                 progname);
  527.  
  528.             exit(1);
  529.         }
  530.  
  531.         strcpy(device, "/dev/");
  532.         strncat(device, ut->ut_name, sizeof(ut->ut_name));
  533.         device[sizeof("/dev/")+sizeof(ut->ut_name)] = '\0';
  534.  
  535.         strncpy(username, ut->ut_name, sizeof(ut->ut_name));
  536.         username[sizeof(ut->ut_name)] = '\0';
  537.         break;
  538.         }
  539.     }
  540.  
  541.     if (ut == NULL) /* Is /dev/ + who */
  542.     {
  543.         device = (char *)malloc(sizeof("/dev/") + strlen(who));
  544.  
  545.         if (device == NULL)
  546.         {
  547.         (void) fprintf(stderr, "%s: malloc failed (Out of Memory)\n",
  548.                 progname);
  549.  
  550.         exit(1);
  551.         }
  552.  
  553.         strcpy(device, "/dev/");
  554.         strcat(device, who);
  555.     }
  556.  
  557.     endutent();
  558.     }
  559.  
  560.     devname = device + sizeof("/dev/") - 1;
  561.  
  562.     if (username[0] == '\0')
  563.     {
  564.     setutent();
  565.  
  566.     strncpy(uts.ut_line, devname, sizeof(uts.ut_line));
  567.  
  568.     if ((ut = getutline(&uts)) != NULL)
  569.     {
  570.         strncpy(username, ut->ut_name, sizeof(ut->ut_name));
  571.         username[sizeof(ut->ut_name)] = '\0';
  572.     }
  573.     else
  574.     {
  575.         strcpy(username, "unknown");
  576.     }
  577.  
  578.     endutent();
  579.     }
  580.  
  581.     if (stat(device, &stbuf) < 0)
  582.     {
  583.     if (errno == ENOENT)
  584.     {
  585.         (void) fprintf(stderr, "%s: no advisee device: %s\n", progname,
  586.                device);
  587.     }
  588.     else
  589.     {
  590.         (void) fprintf(stderr,
  591.                "%s: Couldn't stat() advisee device: %s (%s)\n",
  592.                progname, device, strerror(errno));
  593.     }
  594.     exit(1);
  595.     }
  596.  
  597.     if ((fd = open("/dev/advise", O_RDWR)) < 0)
  598.     {
  599.     (void) fprintf(stderr,
  600.            "%s: Couldn't open advisory device: /dev/advise (%s)\n",
  601.            progname, strerror(errno));
  602.     exit(1);
  603.     }
  604.  
  605.     if (ioctl(fd, ADVISE_SETADVISEE, stbuf.st_rdev))
  606.     {
  607.     if (errno == EUNATCH)
  608.     {
  609.         (void) fprintf(stderr,
  610.                "%s: module \"advise\" not in place for %s\n",
  611.                progname, device);
  612.     } else if (errno == EACCES)
  613.     {
  614.         (void) fprintf(stderr, "%s: permission denied.\n", progname);
  615.     } else
  616.     {
  617.         (void) fprintf(stderr,
  618.                "%s: Couldn't set advisee: %s (%lu, %lu) (%s)\n",
  619.             progname, device, ((stbuf.st_rdev >> 16) &0xFFFF),
  620.             (stbuf.st_rdev&0xFFFF), strerror(errno));
  621.     }
  622.     exit(1);
  623.     }
  624.  
  625.     if (!secret)
  626.     {
  627.     char *str;
  628.     struct passwd *pt;
  629.  
  630.     if ((login_name = getlogin()) == NULL)
  631.     {
  632.         pt = getpwuid(getuid());
  633.  
  634.         if (pt == NULL || pt->pw_name == NULL)
  635.         {
  636.         login_name = "somebody";
  637.         }
  638.         else
  639.         {
  640.         login_name = pt->pw_name;
  641.         }
  642.     }
  643.  
  644.     if ((tty_name = ttyname(2)) != NULL)
  645.     {
  646.         if (!strncmp(tty_name, "/dev/", sizeof("/dev/")-1))
  647.         tty_name += sizeof("/dev/")-1;
  648.     }
  649.     else
  650.         tty_name = "somewhere";
  651.  
  652.     str = malloc(strlen(login_name) + strlen(tty_name) +
  653.              sizeof("[: advising :]\n\r") + strlen(username) +
  654.              strlen(devname));
  655.  
  656.     if (str)
  657.     {
  658.         struct advise_message m;
  659.         struct strbuf ctl, data;
  660.  
  661.         m.type = ADVISE_READDATA;
  662.  
  663.         ctl.len = sizeof(m);
  664.         ctl.buf = (void *)&m;
  665.  
  666.         sprintf(str, "[%s:%s %s %s:%s]\n\r", login_name,
  667.             tty_name, spy ? "spying" : "advising", username, devname);
  668.  
  669.         data.len = strlen(str);
  670.         data.buf = str;
  671.  
  672.         (void) putmsg(fd, &ctl, &data, 0);
  673.  
  674.         free(str);
  675.     }
  676.     }
  677.  
  678.  
  679.     if (!spy)
  680.     {
  681.     (void) ioctl(0, TCGETS, &termios);
  682.  
  683.     oldtermios = termios;
  684.     termios.c_cc[VMIN] = 1;
  685.     termios.c_cc[VTIME] = 0;
  686.     termios.c_lflag &= ~(ISIG|ICANON|ECHO);
  687.  
  688.     (void) ioctl(0, TCSETS, &termios);
  689.     }
  690.  
  691.     pfds[0].fd = fd;
  692.     pfds[0].events = POLLIN;
  693.  
  694.     pfds[1].fd = 0;
  695.     pfds[1].events = POLLIN;
  696.  
  697.     for (;;)
  698.     {
  699.     if (poll(pfds, 2, INFTIM) < 0)
  700.         continue;
  701.  
  702.     if ((pfds[0].revents&POLLIN) != 0) /* data from advisee ready */
  703.     {
  704.         if ((ret = read(fd, buf, sizeof(buf))) > 0)
  705.         write(1, buf, ret);
  706.     }
  707.  
  708.     if ((pfds[1].revents&POLLIN) != 0) /* data from advisor ready */
  709.     {
  710.         if ((ret = read(0, buf, sizeof(buf))) > 0)
  711.         {
  712.         if (!spy)
  713.         {
  714.             register int i;
  715.             register char *p = buf, *pp=buf;
  716.  
  717.             for (i=0; i < ret; ++i, p++)
  718.             {
  719.             if (metad)
  720.             {
  721.                 if (metad == 2)
  722.                 {
  723.                 meta_character = *p;
  724.                 printf("The meta character is now: %s\n",
  725.                        strchar(meta_character));
  726.                 pp++;
  727.                 metad = 0;
  728.                 continue;
  729.                 }
  730.  
  731.                 switch (*p)
  732.                 {
  733.                 case '=':
  734.                 metad=2;
  735.                 pp++;
  736.                 break;
  737.  
  738.                 case '?':
  739.                 {
  740.                 char *escstr = strchar(meta_character);
  741.  
  742.                 printf("Help for meta character <%s>:\n",
  743.                        escstr);
  744.                 printf("%s?\t-- This help message.\n", escstr);
  745.                 printf("%s~\t-- Send a single meta character.\n",
  746.                        escstr);
  747.                 printf("%s.\t-- Disconnect advise session.\n",
  748.                        escstr);
  749.                 printf("%s=C\t-- Change meta character to C.\n",
  750.                        escstr);
  751.                 printf("%s^Z\t-- Suspend advise session.\n",
  752.                        escstr);
  753.                 pp++;
  754.                 metad=0;
  755.                 break;
  756.                 }
  757.  
  758.                 case '.':
  759.                 {
  760.                 if (!secret)
  761.                 {
  762.                     char *str;
  763.  
  764.                     str = malloc(strlen(login_name) +
  765.                       strlen(tty_name) +
  766.                       sizeof("[/ disconnecting from :]\n") +
  767.                            strlen(username) + strlen(devname));
  768.  
  769.                     if (str)
  770.                     {
  771.                     struct advise_message m;
  772.                     struct strbuf ctl, data;
  773.  
  774.                     m.type = ADVISE_READDATA;
  775.  
  776.                     ctl.len = sizeof(m);
  777.                     ctl.buf = (void *)&m;
  778.  
  779.                     sprintf(str, "[%s/%s disconnecting from %s:%s]\n\r",
  780.                         login_name, tty_name, username,
  781.                         devname);
  782.  
  783.                     data.len = strlen(str);
  784.                     data.buf = str;
  785.  
  786.                     (void) putmsg(fd, &ctl, &data, 0);
  787.  
  788.                     free(str);
  789.                     }
  790.                 }
  791.  
  792.                 close(fd);
  793.  
  794.                 (void) ioctl(0, TCSETS, &oldtermios);
  795.  
  796.                 exit(0);
  797.                 }
  798.  
  799.                 case CTRL('Z'):
  800.                 {
  801.                 (void) ioctl(0, TCSETS, &oldtermios);
  802.                 (void) signal(SIGTSTP, SIG_DFL);
  803.                 (void) kill(0, SIGTSTP);
  804.                 (void) ioctl(0, TCSETS, &termios);
  805.                 metad=0;
  806.                 break;
  807.                 }
  808.  
  809.                 default:
  810.                 metad=0;
  811.                 break;
  812.                 }
  813.             }
  814.             else
  815.             {
  816.                 if (*p == meta_character)
  817.                 {
  818.                 int d = p - pp;
  819.  
  820.                 metad=1;
  821.  
  822.                 if (d)
  823.                     write(fd, pp, d);
  824.  
  825.                 pp += d + 1;
  826.                 i += d;
  827.                 }
  828.             }
  829.             }
  830.  
  831.             if (p - pp)
  832.             {
  833.             struct advise_message m;
  834.             struct strbuf ctl, data;
  835.  
  836.             m.type = ADVISE_DATA;
  837.  
  838.             ctl.len = sizeof(m);
  839.             ctl.buf = (void *)&m;
  840.  
  841.             data.len = p - pp;
  842.             data.buf = p;
  843.  
  844.             (void) putmsg(fd, &ctl, &data, 0);
  845.             }
  846.         }
  847.         }
  848.     }
  849.     }
  850. }
  851.  
  852. static struct module_list *
  853. list_modules(int fd, char *push_below)
  854. {
  855.     char lookbuf[max(FMNAMESZ+1,256)];
  856.     struct module_list *mp, *mpp;
  857.  
  858.     mp = NULL;
  859.  
  860.     while (ioctl(fd, I_LOOK, lookbuf) == 0)
  861.     {
  862.     if (ioctl(fd, I_POP, 0))
  863.     {
  864.         (void) fprintf(stderr, "%s: Couldn't I_POP: %s (%s).\n", progname,
  865.                lookbuf, strerror(errno));
  866.         return mp;
  867.     }
  868.  
  869.     if ((mpp = malloc(sizeof(struct module_list))) == NULL ||
  870.         (mpp->name = malloc(strlen(lookbuf) + 1)) == NULL)
  871.     {
  872.         (void) fprintf(stderr, "%s: Couldn't malloc (out of memory).\n",
  873.                progname);
  874.         return mp;
  875.     }
  876.  
  877.     mpp->next = mp;
  878.     mp = mpp;
  879.  
  880.     strcpy(mp->name, lookbuf);
  881.  
  882.     if (!strcmp(push_below, lookbuf))
  883.         break;
  884.     }
  885.  
  886.     return mp;
  887. }
  888.  
  889. static char *
  890. strchar(char character)
  891. {
  892.     static char retbuf[4];
  893.     char *p = retbuf;
  894.     int capit = 0;
  895.  
  896.     if (!isascii(character))
  897.     {
  898.     *p++ = '~';
  899.     capit = 1;
  900.     character = toascii(character);
  901.     }
  902.  
  903.     if (iscntrl(character))
  904.     {
  905.     *p++ = '^';
  906.     capit = 1;
  907.     character += '@';
  908.     }
  909.  
  910.     if (capit)
  911.     *p++ = toupper(character);
  912.     else
  913.     *p++ = character;
  914.  
  915.     *p = '\0';
  916.  
  917.     return retbuf;
  918. }
  919. SHAR_EOF
  920. fi # end of overwriting check
  921. if test -f 'advise.man'
  922. then
  923.     echo shar: will not over-write existing file "'advise.man'"
  924. else
  925. cat << \SHAR_EOF > 'advise.man'
  926. .TH advise 1
  927. .SH NAME
  928. advise \- Attach to another user.
  929. .SH SYNOPSIS
  930. .B advise
  931. [-ADad?] [-M module] | [-Ss] [-m char] [ device | username ]
  932. .SH DESCRIPTION
  933. .B Advise
  934. attaches a user (the advisor) to another user's (the advisee) terminal in
  935. such a way the the advisor can type for the advisee and view what
  936. the advisee's terminal is displaying.
  937. .PP
  938. The advisee would typically type ``advise -a'' to allow advise attaches;
  939. the advisor would then type ``advise username'' which would connect the
  940. advisors terminal the the advisee's.
  941. .PP
  942. All characters the advisor types are sent to the advisee's terminal
  943. as if the advisee typed them save the meta character.
  944. .PP
  945. The default meta character is tilde (~).  The advisor uses the meta
  946. character to disconnect or suspend the advise session.  The meta
  947. commands that are available to the advisor are:
  948. .PP
  949. .RS
  950. .TP
  951. ~?
  952. Meta character help message.
  953. .TP
  954. ~~
  955. Send the meta character to the advisee's terminal.
  956. .TP
  957. ~.
  958. Disconnect advise session.
  959. .TP
  960. ~=C
  961. Change the meta character to C.
  962. .TP
  963. ~^Z
  964. Suspend this advise session.
  965. .RE
  966. .PP
  967. In Advise mode the advisor uses ``~.'' to disconnect the advise session
  968. (Note: the advisor should use ``~~'' to send one tilde to the advisee's
  969. terminal).
  970. .PP
  971. In ``spy mode'' the advisor should use an interrupt is use to disconnect
  972. the advise session.
  973. .PP
  974. ``advise -d'' can be used by the advisee to disconnect the advise
  975. session.
  976. .SH OPTIONS
  977. .TP
  978. -A
  979. Allow advise attaches to this terminal.
  980. .TP
  981. -D
  982. Disallow advise attaches to this terminal.
  983. .TP
  984. -M module
  985. Name of module to place advise module under.
  986. .TP
  987. -S
  988. When attaching to another user, don't send the attach message.
  989. (available to the super user, only).
  990. .TP
  991. -a
  992. Push advise module on standard input stream and allow advise
  993. attaches.
  994. .TP
  995. -d
  996. Push advise module on standard input stream and disallow advise
  997. attaches.
  998. .TP
  999. -m char
  1000. Change the meta character to ``char''.  The default meta character
  1001. is tilde (~).
  1002. .TP
  1003. -s
  1004. Spy mode only (ie, input from the advisor is not passed to the
  1005. advisee).
  1006. .TP
  1007. device
  1008. The name of the tty device to advise.
  1009. .TP
  1010. username
  1011. The name of the user to advise.
  1012. .SH AUTHOR
  1013. .RS
  1014. .PP
  1015. Keith M. Gabryelski (ag@amix.commodore.com)
  1016. .RE
  1017. SHAR_EOF
  1018. fi # end of overwriting check
  1019. if test -f 'advisedev.c'
  1020. then
  1021.     echo shar: will not over-write existing file "'advisedev.c'"
  1022. else
  1023. cat << \SHAR_EOF > 'advisedev.c'
  1024. /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
  1025.  
  1026. This file is part of advise.
  1027.  
  1028. advise is distributed in the hope that it will be useful,
  1029. but WITHOUT ANY WARRANTY.  No author or distributor
  1030. accepts responsibility to anyone for the consequences of using it
  1031. or for whether it serves any particular purpose or works at all,
  1032. unless he says so in writing.  Refer to the advise General Public
  1033. License for full details.
  1034.  
  1035. Everyone is granted permission to copy, modify and redistribute
  1036. advise, but only under the conditions described in the
  1037. advise General Public License.   A copy of this license is
  1038. supposed to have been given to you along with advise so you
  1039. can know your rights and responsibilities.  It should be in a
  1040. file named COPYING.  Among other things, the copyright notice
  1041. and this notice must be preserved on all copies.  */
  1042.  
  1043. /*
  1044. ** Author:    Keith Gabryelski    (ag@amix.commodore.com)
  1045. */
  1046.  
  1047. #include <sys/types.h>
  1048. #include <sys/param.h>
  1049. #include <sys/sysmacros.h>
  1050. #include <sys/signal.h>
  1051. #include <sys/file.h>
  1052. #include <sys/user.h>
  1053. #include <sys/proc.h>
  1054. #include <sys/termios.h>
  1055. #include <sys/ttold.h>
  1056. #include <sys/cmn_err.h>
  1057. #include <sys/stream.h>
  1058. #include <sys/stropts.h>
  1059. #include <sys/errno.h>
  1060. #include <sys/debug.h>
  1061. #include "advisemod.h"
  1062. #include <sys/inline.h>
  1063.  
  1064. int adviseopen(), adviseclose(), adviserput(), advisewput();
  1065. void advisesrvioc();
  1066.  
  1067. static struct module_info advisemiinfo =
  1068. {
  1069.     0, "advise", 0, INFPSZ, 2048, 128,
  1070. };
  1071.  
  1072. static struct qinit adviserinit =
  1073. {
  1074.     adviserput, NULL, adviseopen, adviseclose, NULL, &advisemiinfo,
  1075. };
  1076.  
  1077. static struct module_info advisemoinfo =
  1078. {
  1079.     42, "advise", 0, INFPSZ, 300, 200,
  1080. };
  1081.  
  1082. static struct qinit advisewinit =
  1083. {
  1084.     advisewput, NULL, adviseopen, adviseclose, NULL, &advisemoinfo,
  1085. };
  1086.  
  1087. struct streamtab adviseinfo =
  1088. {
  1089.     &adviserinit, &advisewinit, NULL, NULL,
  1090. };
  1091.  
  1092. extern struct advise_state advise_table;
  1093.  
  1094. /*ARGSUSED*/
  1095. static int
  1096. adviseopen(q, devp, flag, sflag, credp)
  1097. register queue_t *q;
  1098. dev_t *devp;
  1099. int flag, sflag;
  1100. cred_t *credp;
  1101. {
  1102.     register mblk_t *bp;
  1103.     struct advise_queue_list *ql;
  1104.     struct advise_state  *sp;
  1105.     int i;
  1106.  
  1107.     if (sflag == MODOPEN)
  1108.     return EINVAL;
  1109.  
  1110.     for (i=1; i < L_MAXMIN; ++i)
  1111.     {
  1112.     sp = &advise_table;
  1113.  
  1114.     while (sp->next != NULL)
  1115.     {
  1116.         ql = sp->next->q_list;
  1117.  
  1118.         while (ql != NULL)
  1119.         {
  1120.         if (ql->minord == i)
  1121.             break;
  1122.  
  1123.         ql = ql->next;
  1124.         }
  1125.  
  1126.         if (ql != NULL)
  1127.         break;
  1128.  
  1129.         sp = sp->next;
  1130.     }
  1131.  
  1132.     if (sp->next == NULL)
  1133.         break;
  1134.     }
  1135.  
  1136.     if (i == L_MAXMIN)
  1137.     {
  1138.     return ENOMEM;        /* no more resources */
  1139.     }
  1140.  
  1141.     *devp = makedevice(getmajor(*devp), i);
  1142.  
  1143.     if ((bp = allocb((int)sizeof(struct advise_queue_list), BPRI_MED)) == NULL)
  1144.     {
  1145.     return ENOMEM;
  1146.     }
  1147.  
  1148.     bp->b_wptr += sizeof(struct advise_queue_list);
  1149.     ql = (struct advise_queue_list *)bp->b_rptr;
  1150.     ql->savbp = bp;
  1151.     ql->next = NULL;
  1152.     ql->q = q;
  1153.     ql->state = NULL;
  1154.     ql->minord = i;
  1155.  
  1156.     q->q_ptr = (caddr_t)ql;
  1157.     WR(q)->q_ptr = (caddr_t)ql;
  1158.  
  1159.     return 0;
  1160. }
  1161.  
  1162. static
  1163. adviseclose(q)
  1164. register queue_t *q;
  1165. {
  1166.     struct advise_state *llist = &advise_table;
  1167.     struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
  1168.     struct advise_queue_list *ql, *qlp;
  1169.  
  1170.     /* Remove us from the advisor's list */
  1171.  
  1172.     if (qp->state != NULL)
  1173.     {
  1174.     while (llist != NULL && llist->next != qp->state)
  1175.         llist = llist->next;
  1176.  
  1177.     if (llist != NULL)
  1178.     {
  1179.         ql = llist->next->q_list;
  1180.  
  1181.         if (ql->q == q)
  1182.         {
  1183.         llist->next->q_list = ql->next;
  1184.         }
  1185.         else
  1186.         {
  1187.         while (ql->next != NULL && ql->next->q != q)
  1188.             ql = ql->next;
  1189.  
  1190.         if (ql->next != NULL)
  1191.         {
  1192.             ql->next = ql->next->next;
  1193.         }
  1194.         }
  1195.     }
  1196.     }
  1197.  
  1198.     qp->state = NULL;
  1199.     freeb(qp->savbp);
  1200.  
  1201.     q->q_ptr = NULL;
  1202. }
  1203.  
  1204. static int
  1205. adviserput(q, bp)
  1206. struct queue *q;
  1207. mblk_t *bp;
  1208. {
  1209.     putnext(q, bp);
  1210. }
  1211.  
  1212. static int
  1213. advisewput(q, bp)
  1214. struct queue *q;
  1215. mblk_t *bp;
  1216. {
  1217.     struct advise_queue_list *qp = (struct advise_queue_list *)q->q_ptr;
  1218.     struct advise_state *sp = qp->state;
  1219.  
  1220.     switch (bp->b_datap->db_type)
  1221.     {
  1222.     case M_PROTO:
  1223.     {
  1224.     struct advise_message *ms = (struct advise_message *)bp->b_rptr;
  1225.     mblk_t *bp2 = unlinkb(bp);
  1226.  
  1227.     if (bp2)
  1228.     {
  1229.         if (sp != NULL && sp->q != NULL)
  1230.         {
  1231.         if (ms->type == ADVISE_READDATA)
  1232.         {
  1233.             putnext(WR(sp->q), bp2);
  1234.         }
  1235.         else
  1236.         {
  1237.             putnext(sp->q, bp2);
  1238.         }
  1239.         }
  1240.         else
  1241.         freemsg(bp2);
  1242.     }
  1243.  
  1244.     freemsg(bp);
  1245.  
  1246.     break;
  1247.     }
  1248.  
  1249.     case M_DATA:
  1250.     /*
  1251.     ** Write data to advisee.
  1252.     */
  1253.     if (sp != NULL && sp->q != NULL)
  1254.         putnext(sp->q, bp);
  1255.     else
  1256.         freemsg(bp);
  1257.     break;
  1258.  
  1259.     case M_IOCTL:
  1260.     case M_IOCDATA:
  1261.     advisesrvioc(q, bp);
  1262.     break;
  1263.  
  1264.     default:
  1265.     freemsg(bp);
  1266.     break;
  1267.     }
  1268. }
  1269.  
  1270. static void
  1271. advisesrvioc(q, mp)
  1272. queue_t *q;
  1273. mblk_t *mp;
  1274. {
  1275.     mblk_t *mp1;
  1276.     struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
  1277.     struct advise_queue_list *qp=(struct advise_queue_list *)q->q_ptr; 
  1278.     int s;
  1279.  
  1280.     if (mp->b_datap->db_type == M_IOCDATA)
  1281.     {
  1282.     /* For copyin/copyout failures, just free message. */
  1283.     if (((struct copyresp *)mp->b_rptr)->cp_rval)
  1284.     {
  1285.         freemsg(mp);
  1286.         return;
  1287.     }
  1288.  
  1289.     if (!((struct copyresp *)mp->b_rptr)->cp_private)
  1290.     {
  1291.         mp->b_datap->db_type = M_IOCACK;
  1292.         freemsg(unlinkb(mp));
  1293.         iocbp->ioc_count = 0;
  1294.         iocbp->ioc_rval = 0;
  1295.         iocbp->ioc_error = 0;
  1296.         putnext(RD(q), mp);
  1297.         return;
  1298.     }
  1299.     }
  1300.  
  1301.     switch (iocbp->ioc_cmd)
  1302.     {
  1303.     case ADVISE_SETADVISEE:
  1304.     {
  1305.         register dev_t p;
  1306.         struct advise_queue_list *qlp;
  1307.         struct advise_state *llist;
  1308.  
  1309.         if (qp->state != NULL) /* already advising someone */
  1310.         {
  1311.         iocbp->ioc_error = EBUSY;
  1312.         mp->b_datap->db_type = M_IOCNAK;
  1313.         iocbp->ioc_count = 0;
  1314.         putnext(RD(q), mp);
  1315.         break;
  1316.         }
  1317.  
  1318.         if (!mp->b_cont)
  1319.         {
  1320.         iocbp->ioc_error = EINVAL;
  1321.         mp->b_datap->db_type = M_IOCNAK;
  1322.         iocbp->ioc_count = 0;
  1323.         putnext(RD(q), mp);
  1324.         break;
  1325.         }
  1326.  
  1327.         p = *(dev_t *)mp->b_cont->b_rptr;
  1328.         
  1329.         s = spladvise();
  1330.  
  1331.         llist = advise_table.next;
  1332.  
  1333.         while (llist != NULL && llist->dev != p)
  1334.         {
  1335.         llist = llist->next;
  1336.         }
  1337.  
  1338.         if (llist == NULL)
  1339.         {
  1340.         splx(s);
  1341.         iocbp->ioc_error = EUNATCH;
  1342.         mp->b_datap->db_type = M_IOCNAK;
  1343.         iocbp->ioc_count = 0;
  1344.         putnext(RD(q), mp);
  1345.         break;
  1346.         }
  1347.  
  1348.         if ((llist->status & ALLOW_ADVICE) == 0 && (!suser(u.u_cred)))
  1349.         {
  1350.         splx(s);
  1351.         iocbp->ioc_error = EACCES;
  1352.         mp->b_datap->db_type = M_IOCNAK;
  1353.         iocbp->ioc_count = 0;
  1354.         putnext(RD(q), mp);
  1355.         break;
  1356.         }
  1357.  
  1358.         /*
  1359.         ** Add ourself to the list of advisors for this advisee.
  1360.         */
  1361.  
  1362.         if (llist->q_list == NULL)
  1363.         {
  1364.         qlp = llist->q_list = qp;
  1365.         }
  1366.         else
  1367.         {
  1368.         qlp = llist->q_list;
  1369.  
  1370.         while (qlp->next != NULL)
  1371.             qlp = qlp->next;
  1372.  
  1373.         qlp->next = qp;
  1374.         qlp = qp;
  1375.         }
  1376.  
  1377.         qlp->state = llist;
  1378.  
  1379.         splx(s);
  1380.  
  1381.         mp->b_datap->db_type = M_IOCACK;
  1382.         mp1 = unlinkb(mp);
  1383.         if (mp1)
  1384.         freeb(mp1);
  1385.         iocbp->ioc_count = 0;
  1386.         putnext(RD(q), mp);
  1387.         break;
  1388.     }
  1389.  
  1390.     default:
  1391.     /* Unrecognized ioctl command */
  1392.     if (canput(RD(q)->q_next))
  1393.     {
  1394.         mp->b_datap->db_type = M_IOCNAK;
  1395.         putnext(RD(q), mp);
  1396.     }
  1397.     else
  1398.         putbq(q, mp);
  1399.     break;
  1400.     }
  1401. }
  1402. SHAR_EOF
  1403. fi # end of overwriting check
  1404. if test -f 'advisemod.c'
  1405. then
  1406.     echo shar: will not over-write existing file "'advisemod.c'"
  1407. else
  1408. cat << \SHAR_EOF > 'advisemod.c'
  1409. /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
  1410.  
  1411. This file is part of advise.
  1412.  
  1413. advise is distributed in the hope that it will be useful,
  1414. but WITHOUT ANY WARRANTY.  No author or distributor
  1415. accepts responsibility to anyone for the consequences of using it
  1416. or for whether it serves any particular purpose or works at all,
  1417. unless he says so in writing.  Refer to the advise General Public
  1418. License for full details.
  1419.  
  1420. Everyone is granted permission to copy, modify and redistribute
  1421. advise, but only under the conditions described in the
  1422. advise General Public License.   A copy of this license is
  1423. supposed to have been given to you along with advise so you
  1424. can know your rights and responsibilities.  It should be in a
  1425. file named COPYING.  Among other things, the copyright notice
  1426. and this notice must be preserved on all copies.  */
  1427.  
  1428. /*
  1429. ** Author:    Keith Gabryelski    (ag@amix.commodore.com)
  1430. */
  1431.  
  1432. #include <sys/types.h>
  1433. #include <sys/param.h>
  1434. #include <sys/signal.h>
  1435. #include <sys/file.h>
  1436. #include <sys/user.h>
  1437. #include <sys/proc.h>
  1438. #include <sys/termios.h>
  1439. #include <sys/ttold.h>
  1440. #include <sys/cmn_err.h>
  1441. #include <sys/stream.h>
  1442. #include <sys/stropts.h>
  1443. #include <sys/errno.h>
  1444. #include <sys/debug.h>
  1445. #include "advisemod.h"
  1446. #include <sys/inline.h>
  1447.  
  1448. int advisemopen(), advisemclose(), advisemrput(), advisemwput();
  1449.  
  1450. static struct module_info advisemiinfo =
  1451. {
  1452.     0, "advisemod", 0, INFPSZ, 2048, 128,
  1453. };
  1454.  
  1455. static struct qinit adviserinit =
  1456. {
  1457.     advisemrput, NULL, advisemopen, advisemclose, NULL, &advisemiinfo,
  1458. };
  1459.  
  1460. static struct module_info advisemoinfo =
  1461. {
  1462.     42, "advisemod", 0, INFPSZ, 300, 200,
  1463. };
  1464.  
  1465. static struct qinit advisewinit =
  1466. {
  1467.     advisemwput, NULL, advisemopen, advisemclose, NULL, &advisemoinfo,
  1468. };
  1469.  
  1470. struct streamtab advisemodinfo =
  1471. {
  1472.     &adviserinit, &advisewinit, NULL, NULL,
  1473. };
  1474.  
  1475. struct advise_state advise_table;
  1476.  
  1477. /*ARGSUSED*/
  1478. static int
  1479. advisemopen(q, devp, flag, sflag, credp)
  1480. register queue_t *q;
  1481. dev_t *devp;
  1482. int flag, sflag;
  1483. cred_t *credp;
  1484. {
  1485.     register struct advise_state *sp;
  1486.     register mblk_t *bp;
  1487.     struct advise_state *llist = &advise_table;
  1488.  
  1489.     if (sflag != MODOPEN)
  1490.     return EINVAL;
  1491.  
  1492.     if ((bp = allocb((int)sizeof(struct advise_state), BPRI_MED)) == NULL)
  1493.     {
  1494.     return ENOMEM;
  1495.     }
  1496.  
  1497.     bp->b_wptr += sizeof(struct advise_state);
  1498.     sp = (struct advise_state *)bp->b_rptr;
  1499.     sp->savbp = bp;
  1500.  
  1501.     sp->dev = *devp;
  1502.     sp->status = 0;        /* Deny access by default */
  1503.     sp->next = NULL;
  1504.     sp->q_list = NULL;
  1505.     sp->q = q;
  1506.  
  1507.     while (llist->next != NULL)
  1508.     {
  1509.     if (llist->next->dev == *devp)
  1510.     {
  1511.         /*
  1512.         ** We are already pushed on this stream.
  1513.         */
  1514.         freeb(bp);
  1515.  
  1516.         sp = llist->next;
  1517.  
  1518.         break;
  1519.     }
  1520.  
  1521.     llist = llist->next;
  1522.     }
  1523.  
  1524.     llist->next = sp;
  1525.  
  1526.     q->q_ptr = (caddr_t)sp;
  1527.     WR(q)->q_ptr = (caddr_t)sp;
  1528.  
  1529.     return 0;
  1530. }
  1531.  
  1532. static
  1533. advisemclose(q)
  1534. register queue_t *q;
  1535. {
  1536.     register struct advise_state *sp = (struct advise_state *)q->q_ptr;
  1537.     struct advise_state *llist = &advise_table;
  1538.     struct advise_queue_list *qp = sp->q_list;
  1539.  
  1540.     sp->status = 0;
  1541.  
  1542.     /* unlink us from the state table */
  1543.  
  1544.     while (llist->next != sp)
  1545.     llist = llist->next;
  1546.  
  1547.     llist->next = llist->next->next;
  1548.  
  1549.     while (sp->next != NULL)
  1550.     {
  1551.     /* tell each advisor that we're shutting down */
  1552.  
  1553.     flushq(sp->q, FLUSHDATA);
  1554.     putctl(sp->q->q_next, M_HANGUP);
  1555.     
  1556.     sp = sp->next;
  1557.     }
  1558.  
  1559.     freeb(sp->savbp);
  1560.  
  1561.     q->q_ptr = NULL;
  1562. }
  1563.  
  1564. static
  1565. advisemrput(q, mp)
  1566. register queue_t *q;
  1567. register mblk_t *mp;
  1568. {
  1569.     putnext(q, mp);
  1570. }
  1571.  
  1572. static
  1573. advisemwput(q, mp)
  1574. register queue_t *q;
  1575. register mblk_t *mp;
  1576. {
  1577.     struct advise_state *sp = (struct advise_state *)q->q_ptr;
  1578.     register struct advise_queue_list *qp;
  1579.     int s;
  1580.  
  1581.     switch (mp->b_datap->db_type)
  1582.     {
  1583.     case M_DATA:
  1584.     /*
  1585.     ** Write data to advisors.
  1586.     */
  1587.     s = spladvise();
  1588.     for (qp = sp->q_list; qp != NULL; qp = qp->next)
  1589.     {
  1590.         mblk_t *mp1 = copymsg(mp);
  1591.  
  1592.         if (mp1 != NULL)
  1593.         putnext(qp->q, mp1);
  1594.     }
  1595.  
  1596.     splx(s);
  1597.     break;
  1598.  
  1599.     case M_IOCTL:
  1600.     case M_IOCDATA:
  1601.     if (advisemsrvioc(q, mp)) /* handled? */
  1602.         return;
  1603.     break;
  1604.     }
  1605.  
  1606.     putnext(q, mp);
  1607. }
  1608.  
  1609. static int
  1610. advisemsrvioc(q, mp)
  1611. queue_t *q;
  1612. mblk_t *mp;
  1613. {
  1614.     mblk_t *mp1;
  1615.     struct iocblk *iocbp = (struct iocblk *)mp->b_rptr;
  1616.     struct advise_state *sp = (struct advise_state *)q->q_ptr;
  1617.  
  1618.     if (mp->b_datap->db_type == M_IOCDATA)
  1619.     {
  1620.     struct copyresp *csp = (struct copyresp *)mp->b_rptr;
  1621.  
  1622.     switch(csp->cp_cmd)
  1623.     {
  1624.     case ADVISE_STATUS:
  1625.     case ADVISE_ALLOW:
  1626.     case ADVISE_DENY:
  1627.         /* For copyin/copyout failures, just free message. */
  1628.  
  1629.         if (csp->cp_rval)
  1630.         freemsg(mp);
  1631.         else if (!csp->cp_private)
  1632.         {
  1633.         mp->b_datap->db_type = M_IOCACK;
  1634.         freemsg(unlinkb(mp));
  1635.         iocbp->ioc_count = 0;
  1636.         iocbp->ioc_rval = 0;
  1637.         iocbp->ioc_error = 0;
  1638.         putnext(RD(q), mp);
  1639.         }
  1640.  
  1641.         return 1;
  1642.         }
  1643.     }
  1644.  
  1645.     switch (iocbp->ioc_cmd)
  1646.     {
  1647.     case ADVISE_STATUS:
  1648.         {
  1649.         int *status;
  1650.         caddr_t arg = *(caddr_t *)mp->b_cont->b_rptr;
  1651.  
  1652.         freemsg(mp->b_cont);
  1653.  
  1654.         mp->b_cont = allocb(sizeof(int), BPRI_MED);
  1655.         if (!mp->b_cont)
  1656.         {
  1657.         mp->b_datap->db_type = M_IOCNAK;
  1658.         freemsg(unlinkb(mp));
  1659.         iocbp->ioc_count = 0;
  1660.         iocbp->ioc_rval = 0;
  1661.         iocbp->ioc_error = ENOMEM;
  1662.         putnext(RD(q), mp);
  1663.         return 1;
  1664.         }
  1665.  
  1666.         status = (int *)mp->b_cont->b_rptr;
  1667.         mp->b_cont->b_wptr += sizeof(int);
  1668.  
  1669.         *status = sp->status;
  1670.  
  1671.         if (mp->b_datap->db_type == M_IOCTL &&
  1672.         iocbp->ioc_count == TRANSPARENT)
  1673.         {
  1674.         struct copyreq *creq = (struct copyreq *)mp->b_rptr;
  1675.         mp->b_datap->db_type = M_COPYOUT;
  1676.         creq->cq_addr = arg;
  1677.         mp->b_wptr = mp->b_rptr + sizeof *creq;
  1678.         mp->b_cont->b_wptr = mp->b_cont->b_rptr + sizeof(int);
  1679.         creq->cq_size = sizeof(int);
  1680.         creq->cq_flag = 0;
  1681.         creq->cq_private = (mblk_t *)NULL;
  1682.         putnext(RD(q), mp);
  1683.         return 1;
  1684.         }
  1685.     }
  1686.     break;
  1687.  
  1688.     case ADVISE_ALLOW:
  1689.     sp->status |= ALLOW_ADVICE;
  1690.  
  1691.     mp->b_datap->db_type = M_IOCACK;
  1692.     mp1 = unlinkb(mp);
  1693.     if (mp1)
  1694.         freeb(mp1);
  1695.     iocbp->ioc_count = 0;
  1696.     putnext(RD(q), mp);
  1697.     break;
  1698.  
  1699.     case ADVISE_DENY:
  1700.     sp->status &= ~(ALLOW_ADVICE);
  1701.  
  1702.     mp->b_datap->db_type = M_IOCACK;
  1703.     mp1 = unlinkb(mp);
  1704.     if (mp1)
  1705.         freeb(mp1);
  1706.     iocbp->ioc_count = 0;
  1707.     putnext(RD(q), mp);
  1708.     break;
  1709.  
  1710.     default:
  1711.     return 0;
  1712.     }
  1713.  
  1714.     return 1;
  1715. }
  1716. SHAR_EOF
  1717. fi # end of overwriting check
  1718. if test -f 'advisemod.h'
  1719. then
  1720.     echo shar: will not over-write existing file "'advisemod.h'"
  1721. else
  1722. cat << \SHAR_EOF > 'advisemod.h'
  1723. /* Copyright (C) 1990 Keith Gabryelski (ag@amix.commodore.com)
  1724.  
  1725. This file is part of advise.
  1726.  
  1727. advise is distributed in the hope that it will be useful,
  1728. but WITHOUT ANY WARRANTY.  No author or distributor
  1729. accepts responsibility to anyone for the consequences of using it
  1730. or for whether it serves any particular purpose or works at all,
  1731. unless he says so in writing.  Refer to the advise General Public
  1732. License for full details.
  1733.  
  1734. Everyone is granted permission to copy, modify and redistribute
  1735. advise, but only under the conditions described in the
  1736. advise General Public License.   A copy of this license is
  1737. supposed to have been given to you along with advise so you
  1738. can know your rights and responsibilities.  It should be in a
  1739. file named COPYING.  Among other things, the copyright notice
  1740. and this notice must be preserved on all copies.  */
  1741.  
  1742. /*
  1743. ** Author:    Keith Gabryelski    (ag@amix.commodore.com)
  1744. */
  1745.  
  1746. struct advise_queue_list
  1747. {
  1748.     mblk_t            *savbp;    /* ptr to this mblk for freeb()ing */
  1749.     queue_t            *q;    /* advisor's queue */
  1750.     int                minord; /* minor device for this advisor */
  1751.     struct advise_state        *state; /* ptr back to advise_state struct */
  1752.     struct advise_queue_list    *next;  /* ptr to next advisor */
  1753. };
  1754.  
  1755. struct advise_state
  1756. {
  1757.     mblk_t            *savbp;    /* ptr to this mblk for freeb()ing */
  1758.     int                status;    /* current status */
  1759.     dev_t            dev;    /* our device */
  1760.     queue_t            *q;    /* queue for advisor writing */
  1761.     struct advise_queue_list    *q_list;/* list of spies */
  1762.     struct advise_state        *next;  /* next in advise_table */
  1763. };
  1764.  
  1765. #define ALLOW_ADVICE        (0x01)
  1766.  
  1767. struct advise_message
  1768. {
  1769.     int                type;   /* What type of data is this? */
  1770. };
  1771.  
  1772. #define ADVISE_DATA        (0x00)
  1773. #define ADVISE_READDATA        (0x01)
  1774.  
  1775. #define ADVISE            ('z'<<16)
  1776. #define ADVISE_SETADVISEE    (ADVISE|0x01)
  1777. #define    ADVISE_ALLOW        (ADVISE|0x02)
  1778. #define    ADVISE_DENY        (ADVISE|0x03)
  1779. #define ADVISE_STATUS        (ADVISE|0x04)
  1780.  
  1781. #define spladvise    spltty
  1782. SHAR_EOF
  1783. fi # end of overwriting check
  1784. #    End of shell archive
  1785. exit 0
  1786.