home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1990 University of Wisconsin-Madison
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the University of Wisconsin-Madison not
- * be used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. The University of
- * Wisconsin-Madison makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * THE UNIVERSITY OF WISCONSIN-MADISON DISCLAIMS ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN-MADISON BE LIABLE FOR
- * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Tim Theisen Department of Computer Sciences
- * tim@cs.wisc.edu University of Wisconsin-Madison
- * uwvax!tim 1210 West Dayton Street
- * (608)262-0438 Madison, WI 53706
- */
-
- #include <pwd.h>
- #include <signal.h>
- #include <stdio.h>
- #include <sys/param.h>
- #include <sys/socket.h>
- #include <X11/Xos.h>
- #include <X11/Intrinsic.h>
- #include <X11/Xatom.h>
- #include <X11/Xproto.h>
- #include <X11/Xmu/Atoms.h>
- #include "patchlevel.h"
-
- /*
- * Some systems (like UNICOS) don't define MAXPATHLEN in their param.h,
- * so make a best guess at it.
- */
- #ifndef MAXPATHLEN
- #ifdef PATHSIZE
- #define MAXPATHLEN PATHSIZE
- #else
- #define MAXPATHLEN 1024 /* best guess */
- #endif
- #endif
-
- static XrmOptionDescRec options[] = {
- {"-display", ".display", XrmoptionSepArg, (caddr_t)NULL},
- {"-timeout", ".timeout", XrmoptionSepArg, (caddr_t)NULL},
- {"-user", ".user", XrmoptionSepArg, (caddr_t)NULL},
- };
-
- static void my_sendmsg();
- static void makemsg();
- static void Syntax();
- static void no_message_manager();
- static char mesg[3000];
- static int msize;
- static char *user;
- static int timeout;
- static char *display;
- static Display *dpy;
- static char path[MAXPATHLEN];
- static int alloc_error;
- static XErrorHandler oldhandler;
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- XrmDatabase database = NULL;
- char *str_type;
- XrmValue xrm_value;
- struct passwd *pw;
-
- #if defined(sun)
- /* I don't use the toolkit. But, I use the Atom routines from Xmu
- * which call XtMalloc. If I do not at least initialize the toolkit,
- * I get a ld.so error on __XtInherit.
- */
- XtToolkitInitialize();
- #endif
- XrmInitialize();
- XrmParseCommand(&database, options, XtNumber(options),
- "xwall", &argc, argv);
- XrmGetResource(database,"xwall.display", "Xwall.Display",
- &str_type, &xrm_value);
- display = xrm_value.addr;
- XrmGetResource(database,"xwall.user", "Xwall.User",
- &str_type, &xrm_value);
- user = xrm_value.addr;
- XrmGetResource(database,"xwall.timeout", "Xwall.Timeout",
- &str_type, &xrm_value);
- if (xrm_value.addr) timeout = atoi(xrm_value.addr);
- if (timeout <= 0) timeout = 15;
-
- if (argc != 1)
- Syntax(argv[0]);
-
- makemsg(argc, argv);
-
- if (user) {
- if (pw = getpwnam(user)) {
- setuid(pw->pw_uid);
- strcpy(path,pw->pw_dir);
- strcat(path,"/.Xauthority");
- (void) setenv("XAUTHORITY", path, True);
- }
- }
-
- my_sendmsg(argc, argv);
- exit(0);
- }
-
- static void
- makemsg(argc, argv)
- int argc;
- char *argv[];
- {
- char *whom, hostname[MAXHOSTNAMELEN];
- char *mytty;
- char *getlogin(), *ttyname();
- struct passwd *pw;
- time_t now, time();
- struct tm *lt;
- int i;
-
- if (!(whom = getlogin()))
- whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
- (void)gethostname(hostname, sizeof(hostname));
- (void)time(&now);
- lt = localtime(&now);
- mytty = ttyname(2);
- if (mytty) sprintf(mesg,
- "\nMessage from %s@%s (%s) at %d:%02d ...\n\n",
- whom, hostname, ttyname(2), lt->tm_hour, lt->tm_min);
- else sprintf(mesg,
- "\nMessage from %s@%s at %d:%02d ...\n\n",
- whom, hostname, lt->tm_hour, lt->tm_min);
- msize = strlen(mesg);
- while ((i = getchar()) != EOF) {
- if (msize >= sizeof mesg) {
- fprintf(stderr, "Message too long\n");
- exit(1);
- }
- mesg[msize++] = i;
- }
- fclose(stdin);
- }
-
- static int
- catch_alloc (dpy, err)
- Display *dpy;
- XErrorEvent *err;
- {
- if ((err->error_code == BadAlloc) &&
- (err->request_code == X_ChangeProperty)) {
- alloc_error = True;
- return 0;
- }
- oldhandler(dpy, err);
- }
-
- static void
- my_sendmsg(argc, argv)
- int argc;
- char *argv[];
- {
- Window myw, hisw = None;
- XSetWindowAttributes attributes;
- Atom message, manager, sentprop = None;
- Time now;
- XEvent event, response;
- int sent = False;
- int recvd = False;
-
- dpy = XOpenDisplay(display);
- if (!dpy) {
- fprintf (stderr, "%s: unable to open display \"%s\"\n",
- argv[0], XDisplayName(display));
- exit(1);
- }
- oldhandler = XSetErrorHandler(catch_alloc);
-
- /* Abort after timeout seconds of no response */
-
- (void) signal (SIGALRM, no_message_manager);
- (void) alarm ((unsigned) timeout);
-
- /* Create an unmapped window, that the window manager will ignore.
- * This invisble window will be used to own selection and receive
- * events pertaining to the selection. */
-
- attributes.override_redirect = True;
- attributes.event_mask = PropertyChangeMask;
- myw = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0,
- CopyFromParent, CopyFromParent, CopyFromParent,
- CWOverrideRedirect|CWEventMask, &attributes);
- message = XInternAtom(dpy, "MESSAGE", False);
- manager = XInternAtom(dpy, "MESSAGE_MANAGER", False);
-
- /* If Manager does not own message selection, message transfer is in
- progress. Wait for it to complete. */
-
- while (XGetSelectionOwner(dpy, manager) != XGetSelectionOwner(dpy, message))
- sleep((myw & 7)+1);
-
- /* Need a TIMESTAMP. CurrentTime is not acceptable according to ICCCM.
- * Zero length append causes an event and primes the event loop. */
-
- XChangeProperty(dpy, myw, XA_NULL(dpy), XA_NULL(dpy), 8,
- PropModeAppend, NULL, 0);
-
- while (!recvd){
- XNextEvent(dpy, &event);
- switch (event.type) {
- case PropertyNotify:
- if (event.xproperty.window == myw) {
- /* Now that we have the TIMESTAMP, Assert ownership of
- * the selection */
- if (event.xproperty.atom != XA_NULL(dpy)) break;
- now = event.xproperty.time;
- if (XGetSelectionOwner(dpy, manager) ==
- XGetSelectionOwner(dpy, message))
- XSetSelectionOwner(dpy, message, myw, now);
- if (XGetSelectionOwner(dpy, message) != myw) {
- /* Somebody else grabbed the selection, wait a while
- and try again */
- while (XGetSelectionOwner(dpy, manager) !=
- XGetSelectionOwner(dpy, message))
- sleep((myw & 7)+1);
- XChangeProperty(dpy, myw, XA_NULL(dpy), XA_NULL(dpy),
- 8, PropModeAppend, NULL, 0);
- }
- sent = False;
- } else if (event.xproperty.window == hisw) {
- if ((event.xproperty.atom == sentprop) &&
- (event.xproperty.state == PropertyDelete)) {
- recvd = sent;
- }
- }
- break;
- case SelectionClear:
- /* Somebody else grabbed the selection, wait a while and
- try again */
- sent = False;
- while (XGetSelectionOwner(dpy, manager) !=
- XGetSelectionOwner(dpy, message))
- sleep((myw & 7)+1);
- XChangeProperty(dpy, myw, XA_NULL(dpy), XA_NULL(dpy), 8,
- PropModeAppend, NULL, 0);
- break;
- case SelectionRequest:
- hisw = event.xselectionrequest.requestor;
- response.xselection.type = SelectionNotify;
- response.xselection.display = dpy;
- response.xselection.requestor =
- event.xselectionrequest.requestor;
- response.xselection.selection =
- event.xselectionrequest.selection;
- response.xselection.time = event.xselectionrequest.time;
- response.xselection.target = event.xselectionrequest.target;
-
- if (event.xselectionrequest.property == None)
- response.xselection.property =
- event.xselectionrequest.target;
- else
- response.xselection.property =
- event.xselectionrequest.property;
-
- if (alloc_error) {
- XDeleteProperty(dpy, hisw, response.xselection.property);
- response.xselection.property = None;
- XSendEvent(dpy, hisw, False, 0, &response);
- fprintf(stderr,"Insufficient server memory to send message.\n");
- exit(1);
- }
-
- if ((event.xselectionrequest.target == XA_STRING) ||
- (event.xselectionrequest.target == XA_TEXT(dpy))) {
- sent = True;
- sentprop = response.xselection.property;
- XSelectInput(dpy, hisw, PropertyChangeMask);
- XChangeProperty(dpy, hisw, response.xselection.property,
- XA_STRING, 8, PropModeReplace,
- (unsigned char *) mesg, msize);
- XSendEvent(dpy, hisw, False, 0, &response);
- } else if (event.xselectionrequest.target == XA_TARGETS(dpy)) {
- Atom targets[6];
- targets[0] = XA_TIMESTAMP(dpy);
- targets[1] = XA_STRING;
- targets[2] = XA_TEXT(dpy);
- targets[3] = XA_LENGTH(dpy);
- targets[4] = XA_LIST_LENGTH(dpy);
- targets[5] = XA_CHARACTER_POSITION(dpy);
- XChangeProperty(dpy, hisw, response.xselection.property,
- XA_ATOM, 32, PropModeReplace,
- (unsigned char *) targets, 6);
- XSendEvent(dpy, hisw, False, 0, &response);
- } else if (event.xselectionrequest.target==XA_TIMESTAMP(dpy)) {
- XChangeProperty(dpy, hisw, response.xselection.property,
- XA_INTEGER, 32, PropModeReplace,
- (unsigned char *) &now, 1);
- XSendEvent(dpy, hisw, False, 0, &response);
- } else if (event.xselectionrequest.target == XA_LENGTH(dpy)) {
- XChangeProperty(dpy, hisw, response.xselection.property,
- XA_INTEGER, 32, PropModeReplace,
- (unsigned char *) &msize, 1);
- XSendEvent(dpy, hisw, False, 0, &response);
- } else if (event.xselectionrequest.target==XA_LIST_LENGTH(dpy)){
- int one = 1;
- XChangeProperty(dpy, hisw, response.xselection.property,
- XA_INTEGER, 32, PropModeReplace,
- (unsigned char *) &one, 1);
- XSendEvent(dpy, hisw, False, 0, &response);
- } else if (event.xselectionrequest.target ==
- XA_CHARACTER_POSITION(dpy)) {
- int cspan[2];
- cspan[0] = 0;
- cspan[1] = msize;
- XChangeProperty(dpy, hisw, response.xselection.property,
- XA_SPAN(dpy), 32, PropModeReplace,
- (unsigned char *) cspan, 2);
- XSendEvent(dpy, hisw, False, 0, &response);
- }
- }
- }
- XCloseDisplay(dpy);
- }
-
- static void
- Syntax(call)
- char *call;
- {
- fprintf(stderr, "Usage: %s\n", call);
- fprintf(stderr, " [-display <display>] [-user <user>]\n");
- fprintf(stderr, " [-timeout <timeout>]\n");
- exit(1);
- }
-
- static void
- no_message_manager()
- {
- fprintf(stderr, "Sorry, no message daemon running on display\n");
- exit(1);
- }
-