home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xwall / xwall.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-22  |  10.9 KB  |  353 lines

  1. /*
  2.  * Copyright 1990 University of Wisconsin-Madison
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of the University of Wisconsin-Madison not
  9.  * be used in advertising or publicity pertaining to distribution of the
  10.  * software without specific, written prior permission.  The University of
  11.  * Wisconsin-Madison makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without express or
  13.  * implied warranty.
  14.  *
  15.  * THE UNIVERSITY OF WISCONSIN-MADISON DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17.  * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN-MADISON BE LIABLE FOR
  18.  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  19.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  20.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Tim Theisen             Department of Computer Sciences
  24.  *          tim@cs.wisc.edu         University of Wisconsin-Madison
  25.  *          uwvax!tim               1210 West Dayton Street
  26.  *          (608)262-0438           Madison, WI   53706
  27.  */
  28.  
  29. #include <pwd.h>
  30. #include <signal.h>
  31. #include <stdio.h>
  32. #include <sys/param.h>
  33. #include <sys/socket.h>
  34. #include <X11/Xos.h>
  35. #include <X11/Intrinsic.h>
  36. #include <X11/Xatom.h>
  37. #include <X11/Xproto.h>
  38. #include <X11/Xmu/Atoms.h>
  39. #include "patchlevel.h"
  40.  
  41. /*
  42.  *  Some systems (like UNICOS) don't define MAXPATHLEN in their param.h,
  43.  *  so make a best guess at it.
  44.  */
  45. #ifndef MAXPATHLEN
  46. #ifdef  PATHSIZE
  47. #define MAXPATHLEN PATHSIZE
  48. #else
  49. #define MAXPATHLEN 1024            /* best guess */
  50. #endif
  51. #endif
  52.  
  53. static XrmOptionDescRec options[] = {
  54.     {"-display",    ".display",    XrmoptionSepArg, (caddr_t)NULL},
  55.     {"-timeout",    ".timeout",    XrmoptionSepArg, (caddr_t)NULL},
  56.     {"-user",        ".user",    XrmoptionSepArg, (caddr_t)NULL},
  57. };
  58.  
  59. static void my_sendmsg();
  60. static void makemsg();
  61. static void Syntax();
  62. static void no_message_manager();
  63. static char mesg[3000];
  64. static int msize;
  65. static char *user;
  66. static int timeout;
  67. static char *display;
  68. static Display *dpy;
  69. static char path[MAXPATHLEN];
  70. static int alloc_error;
  71. static XErrorHandler oldhandler;
  72.  
  73. main(argc,argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.     XrmDatabase database = NULL;
  78.     char *str_type;
  79.     XrmValue xrm_value;
  80.     struct passwd *pw;
  81.  
  82. #if defined(sun)
  83.     /* I don't use the toolkit.  But, I use the Atom routines from Xmu
  84.      * which call XtMalloc.  If I do not at least initialize the toolkit,
  85.      * I get a ld.so error on __XtInherit.
  86.      */
  87.     XtToolkitInitialize();
  88. #endif
  89.     XrmInitialize();
  90.     XrmParseCommand(&database, options, XtNumber(options),
  91.             "xwall", &argc, argv);
  92.     XrmGetResource(database,"xwall.display", "Xwall.Display",
  93.            &str_type, &xrm_value);
  94.     display = xrm_value.addr;
  95.     XrmGetResource(database,"xwall.user", "Xwall.User",
  96.            &str_type, &xrm_value);
  97.     user = xrm_value.addr;
  98.     XrmGetResource(database,"xwall.timeout", "Xwall.Timeout",
  99.            &str_type, &xrm_value);
  100.     if (xrm_value.addr) timeout = atoi(xrm_value.addr);
  101.     if (timeout <= 0) timeout = 15;
  102.  
  103.     if (argc != 1)
  104.     Syntax(argv[0]);
  105.  
  106.     makemsg(argc, argv);
  107.  
  108.     if (user) {
  109.     if (pw = getpwnam(user)) {
  110.         setuid(pw->pw_uid);
  111.         strcpy(path,pw->pw_dir);
  112.         strcat(path,"/.Xauthority");
  113.         (void) setenv("XAUTHORITY", path, True);
  114.     }
  115.     }
  116.  
  117.     my_sendmsg(argc, argv);
  118.     exit(0);
  119. }
  120.  
  121. static void
  122. makemsg(argc, argv)
  123. int argc;
  124. char *argv[];
  125. {
  126.     char *whom, hostname[MAXHOSTNAMELEN];
  127.     char *mytty;
  128.     char *getlogin(), *ttyname();
  129.     struct passwd *pw;
  130.     time_t now, time();
  131.     struct tm *lt;
  132.     int i;
  133.  
  134.     if (!(whom = getlogin()))
  135.     whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
  136.     (void)gethostname(hostname, sizeof(hostname));
  137.     (void)time(&now);
  138.     lt = localtime(&now);
  139.     mytty = ttyname(2);
  140.     if (mytty) sprintf(mesg,
  141.     "\nMessage from %s@%s (%s) at %d:%02d ...\n\n",
  142.     whom, hostname, ttyname(2), lt->tm_hour, lt->tm_min);
  143.     else sprintf(mesg,
  144.     "\nMessage from %s@%s at %d:%02d ...\n\n",
  145.     whom, hostname, lt->tm_hour, lt->tm_min);
  146.     msize = strlen(mesg);
  147.     while ((i = getchar()) != EOF) {
  148.     if (msize >= sizeof mesg) {
  149.         fprintf(stderr, "Message too long\n");
  150.         exit(1);
  151.     }
  152.     mesg[msize++] = i;
  153.     }
  154.     fclose(stdin);
  155. }
  156.  
  157. static int
  158. catch_alloc (dpy, err)
  159. Display *dpy;
  160. XErrorEvent *err;
  161. {
  162.     if ((err->error_code == BadAlloc) &&
  163.     (err->request_code == X_ChangeProperty)) {
  164.     alloc_error = True;
  165.     return 0;
  166.     }
  167.     oldhandler(dpy, err);
  168. }
  169.  
  170. static void
  171. my_sendmsg(argc, argv)
  172. int argc;
  173. char *argv[];
  174. {
  175.     Window myw, hisw = None;
  176.     XSetWindowAttributes attributes;
  177.     Atom message, manager, sentprop = None;
  178.     Time now;
  179.     XEvent event, response;
  180.     int sent = False;
  181.     int recvd = False;
  182.  
  183.     dpy = XOpenDisplay(display);
  184.     if (!dpy) {
  185.     fprintf (stderr, "%s:  unable to open display \"%s\"\n",
  186.          argv[0], XDisplayName(display));
  187.     exit(1);
  188.     }
  189.     oldhandler = XSetErrorHandler(catch_alloc);
  190.  
  191.     /* Abort after timeout seconds of no response */
  192.  
  193.     (void) signal (SIGALRM, no_message_manager);
  194.     (void) alarm ((unsigned) timeout);
  195.  
  196.     /* Create an unmapped window, that the window manager will ignore.
  197.      * This invisble window will be used to own selection and receive
  198.      * events pertaining to the selection. */
  199.  
  200.     attributes.override_redirect = True;
  201.     attributes.event_mask = PropertyChangeMask;
  202.     myw = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0,
  203.                 CopyFromParent, CopyFromParent, CopyFromParent,
  204.                 CWOverrideRedirect|CWEventMask, &attributes);
  205.     message = XInternAtom(dpy, "MESSAGE", False);
  206.     manager = XInternAtom(dpy, "MESSAGE_MANAGER", False);
  207.  
  208.     /* If Manager does not own message selection, message transfer is in
  209.        progress.  Wait for it to complete. */
  210.  
  211.     while (XGetSelectionOwner(dpy, manager) != XGetSelectionOwner(dpy, message))
  212.     sleep((myw & 7)+1);
  213.  
  214.     /* Need a TIMESTAMP.  CurrentTime is not acceptable according to ICCCM.
  215.      * Zero length append causes an event and primes the event loop. */
  216.  
  217.     XChangeProperty(dpy, myw, XA_NULL(dpy), XA_NULL(dpy), 8,
  218.             PropModeAppend, NULL, 0);
  219.  
  220.     while (!recvd){
  221.     XNextEvent(dpy, &event);
  222.     switch (event.type) {
  223.         case PropertyNotify:
  224.         if (event.xproperty.window == myw) {
  225.             /* Now that we have the TIMESTAMP, Assert ownership of
  226.              * the selection */
  227.             if (event.xproperty.atom != XA_NULL(dpy)) break;
  228.             now = event.xproperty.time;
  229.             if (XGetSelectionOwner(dpy, manager) ==
  230.                 XGetSelectionOwner(dpy, message))
  231.             XSetSelectionOwner(dpy, message, myw, now);
  232.             if (XGetSelectionOwner(dpy, message) != myw) {
  233.             /* Somebody else grabbed the selection, wait a while
  234.                and try again */
  235.             while (XGetSelectionOwner(dpy, manager) !=
  236.                    XGetSelectionOwner(dpy, message))
  237.                 sleep((myw & 7)+1);
  238.             XChangeProperty(dpy, myw, XA_NULL(dpy), XA_NULL(dpy),
  239.                     8, PropModeAppend, NULL, 0);
  240.             }
  241.             sent = False;
  242.         } else if (event.xproperty.window == hisw) {
  243.             if ((event.xproperty.atom == sentprop) &&
  244.             (event.xproperty.state == PropertyDelete)) {
  245.             recvd = sent;
  246.             }
  247.         }
  248.         break;
  249.         case SelectionClear:
  250.         /* Somebody else grabbed the selection, wait a while and
  251.            try again */
  252.         sent = False;
  253.         while (XGetSelectionOwner(dpy, manager) !=
  254.                XGetSelectionOwner(dpy, message))
  255.             sleep((myw & 7)+1);
  256.             XChangeProperty(dpy, myw, XA_NULL(dpy), XA_NULL(dpy), 8,
  257.                 PropModeAppend, NULL, 0);
  258.         break;
  259.         case SelectionRequest:
  260.         hisw = event.xselectionrequest.requestor;
  261.         response.xselection.type = SelectionNotify;
  262.         response.xselection.display = dpy;
  263.         response.xselection.requestor =
  264.             event.xselectionrequest.requestor;
  265.         response.xselection.selection =
  266.             event.xselectionrequest.selection;
  267.         response.xselection.time = event.xselectionrequest.time;
  268.         response.xselection.target = event.xselectionrequest.target;
  269.  
  270.         if (event.xselectionrequest.property == None)
  271.             response.xselection.property =
  272.             event.xselectionrequest.target;
  273.         else
  274.             response.xselection.property =
  275.             event.xselectionrequest.property;
  276.  
  277.         if (alloc_error) {
  278.             XDeleteProperty(dpy, hisw, response.xselection.property);
  279.             response.xselection.property = None;
  280.             XSendEvent(dpy, hisw, False, 0, &response);
  281.             fprintf(stderr,"Insufficient server memory to send message.\n");
  282.             exit(1);
  283.         }
  284.  
  285.         if ((event.xselectionrequest.target == XA_STRING) ||
  286.             (event.xselectionrequest.target == XA_TEXT(dpy))) {
  287.             sent = True;
  288.             sentprop = response.xselection.property;
  289.             XSelectInput(dpy, hisw, PropertyChangeMask);
  290.             XChangeProperty(dpy, hisw, response.xselection.property,
  291.                     XA_STRING, 8, PropModeReplace,
  292.                     (unsigned char *) mesg, msize);
  293.             XSendEvent(dpy, hisw, False, 0, &response);
  294.         } else if (event.xselectionrequest.target == XA_TARGETS(dpy)) {
  295.             Atom targets[6];
  296.             targets[0] = XA_TIMESTAMP(dpy);
  297.             targets[1] = XA_STRING;
  298.             targets[2] = XA_TEXT(dpy);
  299.             targets[3] = XA_LENGTH(dpy);
  300.             targets[4] = XA_LIST_LENGTH(dpy);
  301.             targets[5] = XA_CHARACTER_POSITION(dpy);
  302.             XChangeProperty(dpy, hisw, response.xselection.property,
  303.                     XA_ATOM, 32, PropModeReplace,
  304.                     (unsigned char *) targets, 6);
  305.             XSendEvent(dpy, hisw, False, 0, &response);
  306.         } else if (event.xselectionrequest.target==XA_TIMESTAMP(dpy)) {
  307.             XChangeProperty(dpy, hisw, response.xselection.property,
  308.                     XA_INTEGER, 32, PropModeReplace,
  309.                     (unsigned char *) &now, 1);
  310.             XSendEvent(dpy, hisw, False, 0, &response);
  311.         } else if (event.xselectionrequest.target == XA_LENGTH(dpy)) {
  312.             XChangeProperty(dpy, hisw, response.xselection.property,
  313.                     XA_INTEGER, 32, PropModeReplace,
  314.                     (unsigned char *) &msize, 1);
  315.             XSendEvent(dpy, hisw, False, 0, &response);
  316.         } else if (event.xselectionrequest.target==XA_LIST_LENGTH(dpy)){
  317.             int one = 1;
  318.             XChangeProperty(dpy, hisw, response.xselection.property,
  319.                     XA_INTEGER, 32, PropModeReplace,
  320.                     (unsigned char *) &one, 1);
  321.             XSendEvent(dpy, hisw, False, 0, &response);
  322.         } else if (event.xselectionrequest.target ==
  323.             XA_CHARACTER_POSITION(dpy)) {
  324.             int cspan[2];
  325.             cspan[0] = 0;
  326.             cspan[1] = msize;
  327.             XChangeProperty(dpy, hisw, response.xselection.property,
  328.                     XA_SPAN(dpy), 32, PropModeReplace,
  329.                     (unsigned char *) cspan, 2);
  330.             XSendEvent(dpy, hisw, False, 0, &response);
  331.         }
  332.     }
  333.     }
  334.     XCloseDisplay(dpy);
  335. }
  336.  
  337. static void
  338. Syntax(call)
  339. char *call;
  340. {
  341.     fprintf(stderr, "Usage: %s\n", call);
  342.     fprintf(stderr, "    [-display <display>] [-user <user>]\n");
  343.     fprintf(stderr, "    [-timeout <timeout>]\n");
  344.     exit(1);
  345. }
  346.  
  347. static void
  348. no_message_manager()
  349. {
  350.     fprintf(stderr, "Sorry, no message daemon running on display\n");
  351.     exit(1);
  352. }
  353.