Article 159696 of comp.os.vms:
This is a multi-part message in MIME format.

--------------167E2781446B
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Please excuse the dup posting but I am trying to determine if
there is a bug in the attachment code of the Netscape news server for
OpenVMS.  So I'm going to attach the code here (running Netscape from 
Digital UNIX)

--
-----------------------------------------------------------------------
Brian J. McCarthy                  | mailto:mccarthy@hndymn.zko.dec.com
Digital Equipment Corp. Nashua, NH | DEC CRTL/DEC C++ Class Libraries
-----------------------------------------------------------------------

--------------167E2781446B
Content-Type: text/plain; charset=iso-8859-1; name="netscape_remote.c"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline; filename="netscape_remote.c"

/* -*- Mode:C; tab-width: 8 -*-
 * remote.c --- remote control of Netscape Navigator for Unix and OpenVMS
 * version 1.1.3, for Netscape Navigator 1.1 and newer.
 *
 * Copyright © 1996 Netscape Communications Corporation, all rights reserved.
 * Created: Jamie Zawinski <jwz@netscape.com>, 24-Dec-94.
 *
 * 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.  No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or 
 * implied warranty.
 *
 * To compile (UNIX):
 *
 *    cc -o netscape-remote remote.c -DSTANDALONE -lXmu -lX11
 *
 * To use (UNIX):
 *
 *    netscape-remote -help
 *
 * To compile: (OpenVMS Alpha)
 *    cc /define=standalone netscape_remote/prefi=all
 *    link netscape_remote,sys$input:/opt
 *    sys$share:decw$xlibshr/share
 *    sys$share:decw$xmulibshr/share
 *    <ctrl/z>
 *
 * To compile: (OpenVMS VAX)
 *   cc /define=standalone netscape_remote/prefi=all/stand=vaxc
 *   link netscape_remote,sys$input:/opt
 *   sys$share:decw$xlibshr/share
 *   sys$share:decw$xmulibshr/share
 *  <ctrl/z>
 *
 * To use (OpenVMS):
 *
 *   $ NETSCAPE_REMOTE :== $SYS$DISK:[]NETSCAPE_REMOTE.EXE 
 *                       OR on V6.2 systems and greater:
 *   $ DEFINE DCL$PATH SYS$DISK:[]
 * 
 *   $ netscape_remote -help
 *
 * Documentation for the protocol which this code implements may be found at:
 *
 *    http://home.netscape.com/newsref/std/x-remote.html
 *
 * Bugs and commentary to x_cbug@netscape.com.
 *
 * Modified by:
 *
 *   x.x		mccarthy@hndymn.zko.dec.com		Oct, 1996
 *	- Added support and comments for compiling on OpenVMS platforms.
 *	- Added check for number of command options == 0 before trying to 
 *	  execute commands (resulted in locked window and access violation)
 *	- Added WARN_VERSION define (I don't care if its running something
 *	  besides 1.1, hell 3.0 is out the door now)
 *	- Changed exit() calls (most of them) to use EXIT_SUCCESS or
 * 	  EXIT_FAILURE
 *	- Added call to get icon name to make sure the message
 *	  was being sent to the browser and not the news or
 *	  mail windows (which caused a new browser window
 *	  to be displayed).
 *	- Added help for -sync option 
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifdef __VMS
#if __VMS_VER >= 70000000
#include <strings.h>		/* strcasecmp */
#else
#define strcasecmp my_strcasecmp
#include <types.h>
static const u_char charmap[] = {
	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
	'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
	'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
	'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
	'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
};

typedef char * __wide_char_ptr;
typedef const char * __wide_const_char_ptr;
typedef unsigned char   __u_char;
typedef __u_char * __wide_u_char_ptr;
typedef const __u_char * __wide_const_u_char_ptr;

int
my_strcasecmp(__wide_const_char_ptr s1, __wide_const_char_ptr s2)
{
register __wide_const_u_char_ptr cm = charmap,
   us1 = (const u_char *)s1,
   us2 = (const u_char *)s2;

   while (cm[*us1] == cm[*us2++])
	if (*us1++ == '\0')
	   return (0);
   return (cm[*us1] - cm[*--us2]);
}

#endif		/* vms version less than 7.0 */
#endif

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#ifndef __VMS
#include <X11/Xmu/WinUtil.h>	/* for XmuClientWindow() */
#else
/* bring header right in line */
/* xmuclientwindow() exists in decw$xmulibshrr5 and decw$xmulibshr */
/* so be sure to add that to your linker options file */
/*
 * $XConsortium: WinUtil.h,v 1.3 89/09/22 12:10:20 jim Exp $
 *
 * Copyright 1988 by the Massachusetts Institute of Technology
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, 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 M.I.T. not be used in advertising
 * or publicity pertaining to distribution of the software without specific, 
 * written prior permission. M.I.T. makes no representations about the 
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * The X Window System is a Trademark of MIT.
 *
 * The interfaces described by this header file are for miscellaneous utilities
 * and are not part of the Xlib standard.
 */

#ifndef _XMU_WINDOWUTIL_H_
#define _XMU_WINDOWUTIL_H_

extern Window XmuClientWindow();
extern Bool XmuUpdateMapHints();
extern Screen *XmuScreenOfWindow();

#endif /* _XMU_WINDOWUTIL_H_ */

#endif


/* vroot.h is a header file which lets a client get along with `virtual root'
   window managers like swm, tvtwm, olvwm, etc.  If you don't have this header
   file, you can find it at "http://home.netscape.com/newsref/std/vroot.h".
   If you don't care about supporting virtual root window managers, you can
   comment this line out.
 */
#ifndef __VMS
#include "vroot.h"
#endif

#ifdef STANDALONE
 static const char *progname = 0;
 static const char *expected_mozilla_version = "1.1";
#else  /* !STANDALONE */
 extern const char *progname;
 extern const char *expected_mozilla_version;
#endif /* !STANDALONE */

#define MOZILLA_VERSION_PROP   "_MOZILLA_VERSION"
#define MOZILLA_LOCK_PROP      "_MOZILLA_LOCK"
#define MOZILLA_COMMAND_PROP   "_MOZILLA_COMMAND"
#define MOZILLA_RESPONSE_PROP  "_MOZILLA_RESPONSE"
static Atom XA_MOZILLA_VERSION  = 0;
static Atom XA_MOZILLA_LOCK     = 0;
static Atom XA_MOZILLA_COMMAND  = 0;
static Atom XA_MOZILLA_RESPONSE = 0;

static void
mozilla_remote_init_atoms (Display *dpy)
{
  if (! XA_MOZILLA_VERSION)
    XA_MOZILLA_VERSION = XInternAtom (dpy, MOZILLA_VERSION_PROP, False);
  if (! XA_MOZILLA_LOCK)
    XA_MOZILLA_LOCK = XInternAtom (dpy, MOZILLA_LOCK_PROP, False);
  if (! XA_MOZILLA_COMMAND)
    XA_MOZILLA_COMMAND = XInternAtom (dpy, MOZILLA_COMMAND_PROP, False);
  if (! XA_MOZILLA_RESPONSE)
    XA_MOZILLA_RESPONSE = XInternAtom (dpy, MOZILLA_RESPONSE_PROP, False);
}

static Window
mozilla_remote_find_window (Display *dpy)
{
  int i;
  Window root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy));
  Window root2, parent, *kids;
  unsigned int nkids;
  Window result = 0;
  Window tenative = 0;
  Window non_netscape = 0;
  unsigned char *tenative_version = 0;

  if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
    {
      fprintf (stderr, "%s: XQueryTree failed on display %s\n", progname,
	       DisplayString (dpy));
      exit (2);
    }

  /* root != root2 is possible with virtual root WMs. */

  if (! (kids && nkids))
    {
      fprintf (stderr, "%s: root window has no children on display %s\n",
	       progname, DisplayString (dpy));
      exit (2);
    }

  for (i = nkids-1; i >= 0; i--) {
    Atom type;
    int format;
    unsigned long nitems, bytesafter;
    unsigned char *version = 0;
    char *icon_name = 0;
    Window w = XmuClientWindow (dpy, kids[i]);
    int status = XGetWindowProperty (dpy, w, XA_MOZILLA_VERSION,
				       0, (65536 / sizeof (long)),
				       False, XA_STRING,
				       &type, &format, &nitems, &bytesafter,
				       &version);
    if (! version)
      /* Didn't get the XA_MOZILLA_VERSION atom back */
      continue;

    if (XGetIconName (dpy, w, &icon_name) ) {
      if (strncmp (icon_name, "Netscape:", strlen("Netscape:")) != 0) {
	/* 
	** If the icon name is not Netscape, skip it
	** it could be "News" or "Mail" or some other window 
	** that Netscape created, store away its value though,
	** because if we don't find a Netscape browser window
	** around, this window will do.
	*/
	non_netscape = w;
	XFree (icon_name);
	continue;
      } else {
	/* The icon name started with Netscape */
	XFree (icon_name);
      }
    } /* end of check for getting icon name */

    if (strcmp ((char *) version, expected_mozilla_version) &&
	      !tenative) {
      tenative = w;
      tenative_version = version;
      continue;
    }
    XFree (version);
    if (status == Success && type != None) {
      result = w;
      break;
    }
  } /* End of loop for all the children */

  if (result && tenative) {
      fprintf (stderr,
	       "%s: warning: \nboth version %s (0x%x) and version\n"
	       "\t%s (0x%x) are running.\n  Using version %s.\n",
	       progname, tenative_version, (unsigned int) tenative,
	       expected_mozilla_version, (unsigned int) result,
	       expected_mozilla_version);
      XFree (tenative_version);
      return result;
  } else {
    if (tenative) {
#ifdef WARN_VERSION
        fprintf (stderr,
	       "%s: warning: expected version %s but found version\n"
	       "\t%s (0x%x) instead.\n",
	       progname, expected_mozilla_version,
	       tenative_version, (unsigned int) tenative);
#endif
      XFree (tenative_version);
      return tenative;
    } else {
      if (result) {
        return result;
      } else {
        if (non_netscape) {
	  /* 
	  ** Found a non-browser window, sending
	  ** the command to that window will
	  ** have the desired effect.
	  */
          return non_netscape;
	} else {
	  fprintf (stderr, "%s: netscape not running on display %s\n", progname,
	       DisplayString (dpy));
	  exit (EXIT_SUCCESS);
	}
      }
    }
  }
}

static void
mozilla_remote_check_window (Display *dpy, Window window)
{
  Atom type;
  int format;
  unsigned long nitems, bytesafter;
  unsigned char *version = 0;
  int status = XGetWindowProperty (dpy, window, XA_MOZILLA_VERSION,
				   0, (65536 / sizeof (long)),
				   False, XA_STRING,
				   &type, &format, &nitems, &bytesafter,
				   &version);
  if (status != Success || !version)
    {
      fprintf (stderr, "%s: window 0x%x is not a Netscape window.\n",
	       progname, (unsigned int) window);
      exit (6);
    }
  else if (strcmp ((char *) version, expected_mozilla_version))
    {
#ifdef WARN_VERSION
      fprintf (stderr,
	       "%s: warning: window 0x%x is Netscape version %s;\n"
	       "\texpected version %s.\n",
	       progname, (unsigned int) window,
	       version, expected_mozilla_version);
#endif
    }
  XFree (version);
}


static char *lock_data = 0;

static void
mozilla_remote_obtain_lock (Display *dpy, Window window)
{
  Bool locked = False;
  Bool waited = False;

  if (! lock_data)
    {
      lock_data = (char *) malloc (255);
      sprintf (lock_data, "pid%d@", getpid ());
      if (gethostname (lock_data + strlen (lock_data), 100))
	{
	  perror ("gethostname");
	  exit (EXIT_FAILURE);
	}
    }

  do
    {
      int result;
      Atom actual_type;
      int actual_format;
      unsigned long nitems, bytes_after;
      unsigned char *data = 0;

      XGrabServer (dpy);   /* ################################# DANGER! */

      result = XGetWindowProperty (dpy, window, XA_MOZILLA_LOCK,
				   0, (65536 / sizeof (long)),
				   False, /* don't delete */
				   XA_STRING,
				   &actual_type, &actual_format,
				   &nitems, &bytes_after,
				   &data);
      if (result != Success || actual_type == None)
	{
	  /* It's not now locked - lock it. */
#ifdef DEBUG_PROPS
	  fprintf (stderr, "%s: (writing " MOZILLA_LOCK_PROP
		   " \"%s\" to 0x%x)\n",
		   progname, lock_data, (unsigned int) window);
#endif
	  XChangeProperty (dpy, window, XA_MOZILLA_LOCK, XA_STRING, 8,
			   PropModeReplace, (unsigned char *) lock_data,
			   strlen (lock_data));
	  locked = True;
	}

      XUngrabServer (dpy); /* ################################# danger over */
      XSync (dpy, False);

      if (! locked)
	{
	  /* We tried to grab the lock this time, and failed because someone
	     else is holding it already.  So, wait for a PropertyDelete event
	     to come in, and try again. */

	  fprintf (stderr, "%s: window 0x%x is locked by %s; waiting...\n",
		   progname, (unsigned int) window, data);
	  waited = True;

	  while (1)
	    {
	      XEvent event;
	      XNextEvent (dpy, &event);
	      if (event.xany.type == DestroyNotify &&
		  event.xdestroywindow.window == window)
		{
		  fprintf (stderr, "%s: window 0x%x unexpectedly destroyed.\n",
			   progname, (unsigned int) window);
		  exit (6);
		}
	      else if (event.xany.type == PropertyNotify &&
		       event.xproperty.state == PropertyDelete &&
		       event.xproperty.window == window &&
		       event.xproperty.atom == XA_MOZILLA_LOCK)
		{
		  /* Ok!  Someone deleted their lock, so now we can try
		     again. */
#ifdef DEBUG_PROPS
		  fprintf (stderr, "%s: (0x%x unlocked, trying again...)\n",
			   progname, (unsigned int) window);
#endif
		  break;
		}
	    }
	}
      if (data)
	XFree (data);
    }
  while (! locked);

  if (waited)
    fprintf (stderr, "%s: obtained lock.\n", progname);
}


static void
mozilla_remote_free_lock (Display *dpy, Window window)
{
  int result;
  Atom actual_type;
  int actual_format;
  unsigned long nitems, bytes_after;
  unsigned char *data = 0;

#ifdef DEBUG_PROPS
	  fprintf (stderr, "%s: (deleting " MOZILLA_LOCK_PROP
		   " \"%s\" from 0x%x)\n",
		   progname, lock_data, (unsigned int) window);
#endif

  result = XGetWindowProperty (dpy, window, XA_MOZILLA_LOCK,
			       0, (65536 / sizeof (long)),
			       True, /* atomic delete after */
			       XA_STRING,
			       &actual_type, &actual_format,
			       &nitems, &bytes_after,
			       &data);
  if (result != Success)
    {
      fprintf (stderr, "%s: unable to read and delete " MOZILLA_LOCK_PROP
	       " property\n",
	       progname);
      return;
    }
  else if (!data || !*data)
    {
      fprintf (stderr, "%s: invalid data on " MOZILLA_LOCK_PROP
	       " of window 0x%x.\n",
	       progname, (unsigned int) window);
      return;
    }
  else if (strcmp ((char *) data, lock_data))
    {
      fprintf (stderr, "%s: " MOZILLA_LOCK_PROP
	       " was stolen!  Expected \"%s\", saw \"%s\"!\n",
	       progname, lock_data, data);
      return;
    }

  if (data)
    XFree (data);
}


static int
mozilla_remote_command (Display *dpy, Window window, const char *command,
			Bool raise_p)
{
  int result;
  Bool done = False;
  char *new_command = 0;

  /* The -noraise option is implemented by passing a "noraise" argument
     to each command to which it should apply.
   */
  if (! raise_p)
    {
      char *close;
      new_command = (char *) malloc (strlen (command) + 20);
      strcpy (new_command, command);
      close = strrchr (new_command, ')');
      if (close)
	strcpy (close, ", noraise)");
      else
	strcat (new_command, "(noraise)");
      command = new_command;
    }

#ifdef DEBUG_PROPS
  fprintf (stderr, "%s: (writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x)\n",
	   progname, command, (unsigned int) window);
#endif

  XChangeProperty (dpy, window, XA_MOZILLA_COMMAND, XA_STRING, 8,
		   PropModeReplace, (unsigned char *) command,
		   strlen (command));

  while (!done)
    {
      XEvent event;
      XNextEvent (dpy, &event);
      if (event.xany.type == DestroyNotify &&
	  event.xdestroywindow.window == window)
	{
	  /* Print to warn user...*/
	  fprintf (stderr, "%s: window 0x%x was destroyed.\n",
		   progname, (unsigned int) window);
	  result = 6;
	  goto DONE;
	}
      else if (event.xany.type == PropertyNotify &&
	       event.xproperty.state == PropertyNewValue &&
	       event.xproperty.window == window &&
	       event.xproperty.atom == XA_MOZILLA_RESPONSE)
	{
	  Atom actual_type;
	  int actual_format;
	  unsigned long nitems, bytes_after;
	  unsigned char *data = 0;

	  result = XGetWindowProperty (dpy, window, XA_MOZILLA_RESPONSE,
				       0, (65536 / sizeof (long)),
				       True, /* atomic delete after */
				       XA_STRING,
				       &actual_type, &actual_format,
				       &nitems, &bytes_after,
				       &data);
#ifdef DEBUG_PROPS
	  if (result == Success && data && *data)
	    {
	      fprintf (stderr, "%s: (server sent " MOZILLA_RESPONSE_PROP
		       " \"%s\" to 0x%x.)\n",
		       progname, data, (unsigned int) window);
	    }
#endif

	  if (result != Success)
	    {
	      fprintf (stderr, "%s: failed reading " MOZILLA_RESPONSE_PROP
		       " from window 0x%0x.\n",
		       progname, (unsigned int) window);
	      result = 6;
	      done = True;
	    }
	  else if (!data || strlen((char *) data) < 5)
	    {
	      fprintf (stderr, "%s: invalid data on " MOZILLA_RESPONSE_PROP
		       " property of window 0x%0x.\n",
		       progname, (unsigned int) window);
	      result = 6;
	      done = True;
	    }
	  else if (*data == '1')	/* positive preliminary reply */
	    {
	      fprintf (stderr, "%s: %s\n", progname, data + 4);
	      /* keep going */
	      done = False;
	    }
#if 1
	  else if (!strncmp ((char *)data, "200", 3)) /* positive completion */
	    {
	      result = 0;
	      done = True;
	    }
#endif
	  else if (*data == '2')		/* positive completion */
	    {
	      fprintf (stderr, "%s: %s\n", progname, data + 4);
	      result = 0;
	      done = True;
	    }
	  else if (*data == '3')	/* positive intermediate reply */
	    {
	      fprintf (stderr, "%s: internal error: "
		       "server wants more information?  (%s)\n",
		       progname, data);
	      result = 3;
	      done = True;
	    }
	  else if (*data == '4' ||	/* transient negative completion */
		   *data == '5')	/* permanent negative completion */
	    {
	      fprintf (stderr, "%s: %s\n", progname, data + 4);
	      result = (*data - '0');
	      done = True;
	    }
	  else
	    {
	      fprintf (stderr,
		       "%s: unrecognised " MOZILLA_RESPONSE_PROP
		       " from window 0x%x: %s\n",
		       progname, (unsigned int) window, data);
	      result = 6;
	      done = True;
	    }

	  if (data)
	    XFree (data);
	}
#ifdef DEBUG_PROPS
      else if (event.xany.type == PropertyNotify &&
	       event.xproperty.window == window &&
	       event.xproperty.state == PropertyDelete &&
	       event.xproperty.atom == XA_MOZILLA_COMMAND)
	{
	  fprintf (stderr, "%s: (server 0x%x has accepted "
		   MOZILLA_COMMAND_PROP ".)\n",
		   progname, (unsigned int) window);
	}
#endif /* DEBUG_PROPS */
    }

 DONE:

  if (new_command)
    free (new_command);

  return result;
}

int
mozilla_remote_commands (Display *dpy, Window window, char **commands)
{
  Bool raise_p = True;
  int status = 0;

  mozilla_remote_init_atoms (dpy);

  if (window == 0)
    window = mozilla_remote_find_window (dpy);
  else
    mozilla_remote_check_window (dpy, window);

  XSelectInput (dpy, window, (PropertyChangeMask|StructureNotifyMask));

  mozilla_remote_obtain_lock (dpy, window);

  while (*commands)
    {
      if (!strcmp (*commands, "-raise"))
	raise_p = True;
      else if (!strcmp (*commands, "-noraise"))
	raise_p = False;
      else
	status = mozilla_remote_command (dpy, window, *commands, raise_p);

      if (status != 0)
	break;
      commands++;
    }

  /* When status = 6, it means the window has been destroyed */
  /* It is invalid to free the lock when window is destroyed. */

  if ( status != 6 )
    mozilla_remote_free_lock (dpy, window);

  return status;
}


#ifdef STANDALONE

static void
usage (void)
{
  fprintf (stderr, "usage: %s [ options ... ]\n\
       where options include:\n\
\n\
       -help                     to show this message.\n\
       -display <dpy>            to specify the X server to use.\n\
       -remote <remote-command>  to execute a command in an already-running\n\
                                 Netscape process.  See \n\
                           http://home.netscape.com/newsref/std/x-remote.html\n\
                                 list of valid commands.\n\
       -id <window-id>           the id of an X window to which the -remote\n\
                                 commands should be sent; if unspecified,\n\
                                 the first window found will be used.\n\
       -sync\n\
       -synchronize              Calls XSynchronize () after opening the\n\
                                 display\n\
       -raise                    whether following -remote commands should\n\
                                 cause the window to raise itself to the top\n\
                                 (this is the default.)\n\
       -noraise                  the opposite of -raise: following -remote\n\
                                 commands will not auto-raise the window.\n\
",
	   progname);
}


void
main (int argc, char **argv)
{
  Display *dpy;
  char *dpy_string = 0;
  char **remote_commands = 0;
  int remote_command_count = 0;
  int remote_command_size = 0;
  unsigned long remote_window = 0;
  Bool sync_p = False;
  int i;

  progname = strrchr (argv[0], '/');
  if (progname)
    progname++;
  else
    progname = argv[0];

  /* Hack the -help and -version arguments before opening the display. */
  for (i = 1; i < argc; i++)
    {
      if (!strcasecmp (argv [i], "-h") ||
	  !strcasecmp (argv [i], "-help"))
	{
	  usage ();
	  exit (EXIT_SUCCESS);
	}
      else if (!strcmp (argv [i], "-d") ||
	       !strcmp (argv [i], "-dpy") ||
	       !strcmp (argv [i], "-disp") ||
	       !strcmp (argv [i], "-display"))
	{
	  i++;
	  dpy_string = argv [i];
	}
      else if (!strcmp (argv [i], "-sync") ||
	       !strcmp (argv [i], "-synchronize"))
	{
	  sync_p = True;
	}
      else if (!strcmp (argv [i], "-remote"))
	{
	  if (remote_command_count == remote_command_size)
	    {
	      remote_command_size += 20;
	      remote_commands =
		(remote_commands
		 ? realloc (remote_commands,
			    remote_command_size * sizeof (char *))
		 : calloc (remote_command_size, sizeof (char *)));
	    }
	  i++;
	  if (!argv[i] || *argv[i] == '-' || *argv[i] == 0)
	    {
	      fprintf (stderr, "%s: invalid `-remote' option \"%s\"\n",
		       progname, argv[i] ? argv[i] : "");
	      usage ();
	      exit (EXIT_FAILURE);
	    }
	  remote_commands [remote_command_count++] = argv[i];
	}
      else if (!strcmp (argv [i], "-raise") ||
	       !strcmp (argv [i], "-noraise"))
	{
	  char *r = argv [i];
	  if (remote_command_count == remote_command_size)
	    {
	      remote_command_size += 20;
	      remote_commands =
		(remote_commands
		 ? realloc (remote_commands,
			    remote_command_size * sizeof (char *))
		 : calloc (remote_command_size, sizeof (char *)));
	    }
	  remote_commands [remote_command_count++] = r;
	}
      else if (!strcmp (argv [i], "-id"))
	{
	  char c;
	  if (remote_command_count > 0)
	    {
	      fprintf (stderr,
		"%s: the `-id' option must preceed all `-remote' options.\n",
		       progname);
	      usage ();
	      exit (EXIT_FAILURE);
	    }
	  else if (remote_window != 0)
	    {
	      fprintf (stderr, "%s: only one `-id' option may be used.\n",
		       progname);
	      usage ();
	      exit (EXIT_FAILURE);
	    }
	  i++;
	  if (argv[i] &&
	      1 == sscanf (argv[i], " %ld %c", &remote_window, &c))
	    ;
	  else if (argv[i] &&
		   1 == sscanf (argv[i], " 0x%lx %c", &remote_window, &c))
	    ;
	  else
	    {
	      fprintf (stderr, "%s: invalid `-id' option \"%s\"\n",
		       progname, argv[i] ? argv[i] : "");
	      usage ();
	      exit (EXIT_FAILURE);
	    }
	}
    }

    if ( remote_command_count == 0)  {
	fprintf (stderr, "No options on command line\n");
	usage ();
	exit (EXIT_FAILURE);
    }

  dpy = XOpenDisplay (dpy_string);
  if (! dpy)
    exit (EXIT_FAILURE);

  if (sync_p)
    XSynchronize (dpy, True);

  exit (mozilla_remote_commands (dpy, (Window) remote_window,
				 remote_commands));
}

#endif /* STANDALONE */

--------------167E2781446B--



