Back to index

im-sdk  12.3.91
watchdog.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2001 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 
00043 #ifdef HAVE_CONFIG_H
00044 #include <config.h>
00045 #endif
00046 
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <unistd.h>
00050 #include <pwd.h>
00051 #include <signal.h>
00052 #include <sys/wait.h>
00053 #include <sys/stat.h>
00054 #include <sys/types.h>
00055 #include <sys/utsname.h>
00056 #include <locale.h>
00057 #include <nl_types.h>
00058 #include <X11/Intrinsic.h>
00059 #include <X11/Xlibint.h>
00060 #include <X11/StringDefs.h>
00061 #include <X11/Xatom.h>
00062 
00063 #include "watchdog.h"
00064 
00065 #define       HTT_CLASS_NAME "Iiimx"
00066 
00067 #if 0
00068 #include "watchdog_msg.h"
00069 #include "nls_message.h"
00070 #include "htt_server/main.h"
00071 /* For debugging purpose */
00072 #include "htt_debug.h"
00073 #endif
00074 
00075 #ifndef PATH_MAX
00076 #define PATH_MAX 1024
00077 #endif
00078 
00079 #ifndef OPENWINHOME
00080 #define OPENWINHOME "/usr/openwin"
00081 #endif
00082 #define OPENWIN_MOTIF_PRELOAD_ENV "LD_PRELOAD=/usr/dt/lib/libXm.so.3"
00083 
00084 #define IMDIR IIIMLIBDIR
00085 
00086 static void     start_htt_server(int *, char *argv[]);
00087 static void     start_htt_props(int *, char *argv[]);
00088 static void     start_iiimd(int *, char ** argv);
00089 static Bool     build_dir(const char *, mode_t);
00090 static char *   build_uds_filename(Widget);
00091 static char *   build_vardir_dirname(void);
00092 static char **  build_iiimd_arg(char *, char *);
00093 static void     proc_exit(int);
00094 static void     clean_up(int);
00095 static void     parse_command(int, char **);
00096 static char    *build_cmdline_db(Widget toplevel, char *argv[], int argc, Bool replace_mode);
00097 
00098 static char    *htt_props_path = "htt_props";
00099 
00100 #define  NL_HTT_SETD  3
00101 
00102 typedef enum {
00103   RmServerActive = 1,
00104   RmServerReset = 2,
00105   RmServerKilled = 3
00106 } ServerStatus;
00107 
00108 static ServerStatus Server_Status = RmServerActive;
00109 
00110 #if 0
00111 static HttMessage htt_message = (HttMessage) 0;
00112 #endif
00113 
00114 #if 0
00115 #define nl_msg(msg_num, msg) GetNLSMessage(htt_message, msg_num, msg)
00116 #endif
00117 #define nl_msg(msg_num, msg) (msg)
00118 
00119 static int      htt_server_pid, htt_props_pid;
00120 static int      iiimd_pid;
00121 static Atom     htt_atom, server_atom, props_atom, resource_atom;
00122 static Atom     cmdline_atom, htt_server_reset_atom, htt_watchdog_atom,
00123   class_atom;
00124 static Display *display;
00125 static Window   httw_id;
00126 
00127 static Bool     spawn_props = True;       /* htt_props spawned by htt */
00128 static char   **htt_server_arg;
00129 static char   **htt_props_arg;
00130 static char   **iiimd_arg;
00131 static char    *get_home_dir(char *buf);
00132 static char    *get_host(char *buf, int max_len);
00133 static int      htt_server_killed = 0;
00134 
00135 typedef struct _RmDatabase {
00136   char *htt_server_name;
00137   Bool start_props;  /* This bool is used to sense
00138                              * htt_props running or not */
00139   Bool respond_to_sm;
00140   Bool start_iiimd;
00141   char *udsfile;
00142   char *vardir;
00143 } RmDatabase;
00144 
00145 static RmDatabase my_rdb;
00146 
00147 static XtResource rdb_items[] = {
00148   {"inputMethod", "InputMethod", XtRString, sizeof(char *),
00149    offsetof(RmDatabase, htt_server_name), XtRString, (XPointer)"iiim-xbe"},
00150   {"startProps", "StartProps", XtRBool, sizeof(Bool),
00151    offsetof(RmDatabase, start_props), XtRString, (XPointer) "false"},
00152   {"respondToSM", "RespondToSM", XtRBool, sizeof(Bool),
00153    offsetof(RmDatabase, respond_to_sm), XtRString, (XPointer) "false"},
00154   {"startIiimd", "StartIiimd", XtRBool, sizeof(Bool),
00155    offsetof(RmDatabase, start_iiimd), XtRString, (XPointer) "false"},
00156   {"udsFile", "UdsFile", XtRString, sizeof (char *),
00157    offsetof(RmDatabase, udsfile), XtRString, (XPointer) NULL},
00158   {"varDir", "VarDir", XtRString, sizeof (char *),
00159    offsetof(RmDatabase, vardir), XtRString, (XPointer) NULL},
00160 };
00161 
00162 static XrmOptionDescRec rdb_options[] = {
00163   {"-xim", "*inputMethod", XrmoptionSepArg, NULL},
00164   {"-sp", "*startProps", XrmoptionNoArg, (XPointer) "true"},
00165   {"-so", "*startProps", XrmoptionNoArg, (XPointer) "false"},
00166   {"-rsm", "*respondToSM", XrmoptionNoArg, (XPointer) "true"},
00167   {"-iiimd", "*startIiimd", XrmoptionNoArg, (XPointer) "True"},
00168   {"-udsfile", "*udsFile", XrmoptionSepArg, NULL},
00169   {"-vardir", "*varDir", XrmoptionSepArg, NULL},
00170 };
00171 
00172 static int      NUM_RDB_OPTIONS = XtNumber(rdb_options);
00173 
00174 int
00175 main(argc, argv)
00176      int             argc;
00177      char           *argv[];
00178 {
00179   pid_t           grpid;
00180   Atom            ret_type;
00181   int             ret_format;
00182   unsigned long   nitems, bytes_left;
00183   char            htt_name[MAXNAMELEN];
00184   int             screen_no;
00185   XEvent          ev;
00186   unsigned long  *tmp; /* must be 'long' to set pid */
00187   int             i;
00188   char           *locale;
00189   char           *cmdline_prop;
00190   XtAppContext    app;
00191   Widget          toplevel;
00192   Atom            htt_save_atom[3];
00193   int             pid = getpid();
00194   Atom            host_atom;
00195   char            hostname_prop[1024];
00196   Atom            iiim_server_atom;
00197   char *          uds_filename;
00198   char *          vardir_dirname;
00199 
00200   setlocale(LC_ALL, "");
00201 #if 0
00202   htt_message = CreateNLSMessage((char *) 0, NL_HTT_SETD);
00203 #endif
00204 
00205 #if 0
00206   LOG0("watchdog.c:starting htt");
00207 #endif
00208   /*
00209    * Setup the signal handlers to monitor htt_server, htt_props
00210    * abnormal termination
00211    */
00212 #ifdef SETPGRP_VOID
00213   grpid = setpgrp();
00214 #else
00215   grpid = setpgrp(0, 0);
00216 #endif
00217 
00218 #ifdef SunOS
00219   sigset(SIGTERM, clean_up);
00220   sigset(SIGINT, clean_up);
00221   sigset(SIGCHLD, proc_exit);
00222 #else
00223   signal(SIGTERM, clean_up);
00224   signal(SIGINT, clean_up);
00225   signal(SIGCHLD, proc_exit);
00226 #endif
00227 
00228 #if 0
00229   LOG0("watchdog.c:Signal handlers set");
00230 #endif
00231   toplevel = XtVaAppInitialize(&app, HTT_CLASS_NAME,
00232                             rdb_options, NUM_RDB_OPTIONS,
00233                             &argc, argv, NULL,
00234                             NULL);
00235   XtGetApplicationResources(toplevel, (char *) &my_rdb,
00236                          rdb_items, XtNumber(rdb_items),
00237                          0, 0);
00238 
00239   my_rdb.start_props = False;
00240   my_rdb.respond_to_sm = False;
00241 
00242   /* duplicate again this time to build command line db */
00243   cmdline_prop = build_cmdline_db(toplevel, argv, argc, False);
00244 
00245   parse_command(argc, argv);
00246 
00247   strcpy(htt_name, HTT_WINDOW_NAME);
00248   if ((locale = setlocale(LC_CTYPE, NULL)))
00249     strcat(htt_name, locale);
00250   else {
00251     fprintf(stderr,
00252            nl_msg(NL_HTT_LOCALE_FAIL,
00253                  "iiimx : Error - locale not supported\n")
00254            );
00255     exit(1);
00256   }
00257 
00258   htt_server_arg = (char **) malloc(sizeof(char *) * (argc + 1));
00259 
00260   htt_props_arg = (char **) malloc(sizeof(char *) * (argc + 3));
00261 
00262   {
00263     /* htt_server */
00264     char **pargv = htt_server_arg;
00265     *pargv++ = my_rdb.htt_server_name;
00266     for (i = 1; i < argc; i++) {
00267       *pargv++ = argv[i];
00268     }
00269     *pargv = NULL;
00270 
00271     /* htt_props */
00272     pargv = htt_props_arg;
00273     *pargv++ = htt_props_path;
00274     for (i = 1; i < argc; i++) {
00275       *pargv++ = argv[i];
00276     }
00277     *pargv++ = "-lc_basiclocale";
00278     *pargv++ = locale;
00279     *pargv = NULL;
00280   }
00281 
00282   uds_filename = NULL;
00283   vardir_dirname = NULL;
00284   if (True == my_rdb.start_iiimd) {
00285     if (NULL == my_rdb.udsfile) {
00286       uds_filename = build_uds_filename(toplevel);
00287     } else {
00288       uds_filename = my_rdb.udsfile;
00289     }
00290     if (NULL == my_rdb.vardir) {
00291       vardir_dirname = build_vardir_dirname();
00292     } else {
00293       vardir_dirname = my_rdb.vardir;
00294     }
00295     iiimd_arg = build_iiimd_arg(uds_filename, vardir_dirname);
00296   }
00297 
00298   /* Obtain display */
00299   display = XtDisplay(toplevel);
00300   if (display == NULL) {
00301     fprintf(stderr,
00302            nl_msg(NL_HTT_XOPEN_DISPLAY_FAIL,
00303                  "iiimx : Error - Unable to connect with X server\n"));
00304     exit(-1);
00305   }
00306   /* Create the properties in the display */
00307   htt_atom = XInternAtom(display, htt_name, False);
00308   htt_watchdog_atom = XInternAtom(display, HTT_WATCHDOG_PID, False);
00309   server_atom = XInternAtom(display, HTT_SERVER_PID, False);
00310   props_atom = XInternAtom(display, HTT_PROPS_PID, False);
00311   resource_atom = XInternAtom(display, HTT_RESOURCES, False);
00312   cmdline_atom = XInternAtom(display, HTT_CMDLINE_RESOURCES, False);
00313   htt_server_reset_atom = XInternAtom(display, HTT_SERVER_RESET, False);
00314   if (htt_atom == BadAtom)
00315     fprintf(stderr,
00316            nl_msg(NL_ATOM_CREATE_FAIL,
00317                  "iiimx : Warning - Unable to create atom")
00318            );
00319 
00320   iiim_server_atom = None;
00321   if (True == my_rdb.start_iiimd) {
00322     iiim_server_atom = XInternAtom(display, "IIIM_SERVER", False);
00323   }
00324   /*
00325    * If already a version of iiimx is running under same locale , detect
00326    * it by checking SelectionOwner of HTT_ATOM
00327    */
00328   screen_no = DefaultScreen(display);
00329   httw_id = XGetSelectionOwner(display, htt_atom);
00330   if (httw_id != None) {
00331     fprintf(stderr,
00332            nl_msg(NL_HTT_ALREADY_RUNNING,
00333                  "iiimx : Error - iiimx is already running...\n")
00334            );
00335     exit(-1);
00336   }
00337   /* Create the window & make this window as owner of propery htt_atom */
00338   httw_id = XCreateSimpleWindow(display, RootWindow(display, screen_no),
00339                             0, 0, 10, 10, 4, 1, 1);
00340 
00341   /* Register WM Protocol */
00342 #if 0
00343   LOG1("watchdog.c:htt_window_id %x\n", httw_id);
00344 #endif
00345 
00346   htt_save_atom[0] = XInternAtom(display, "_MOTIF_WM_MESSAGES", True);
00347   htt_save_atom[1] = XInternAtom(display, "WM_DELETE_WINDOW", True);
00348   htt_save_atom[2] = XInternAtom(display, "WM_SAVE_YOURSELF", True);
00349 
00350   host_atom = XInternAtom(display, "WM_CLIENT_MACHINE", True);
00351   get_host(hostname_prop, sizeof(hostname_prop));
00352   XChangeProperty(display, httw_id, host_atom, XA_STRING, 8,
00353                 PropModeReplace, hostname_prop, strlen(hostname_prop));
00354 
00355   class_atom = XInternAtom(display, "WM_CLASS", True);
00356   XChangeProperty(display, httw_id, class_atom, XA_STRING, 8,
00357                 PropModeReplace, "iiimx", strlen("iiimx"));
00358 
00359   XSetWMProtocols(display, httw_id, (Atom *)&htt_save_atom, 3);
00360 
00361   XSelectInput(display, httw_id, PropertyChangeMask | StructureNotifyMask);
00362   XSetSelectionOwner(display, htt_atom, httw_id, CurrentTime);
00363 
00364   XChangeProperty(display, httw_id, cmdline_atom, XA_STRING, 8,
00365                 PropModeReplace, cmdline_prop, strlen(cmdline_prop));
00366 
00367   if (True == my_rdb.start_iiimd) {
00368     char * iiim_server;
00369     char * iiim_vardir;
00370     iiim_server = (char *)malloc(PATH_MAX);
00371     iiim_vardir = (char *)malloc(PATH_MAX);
00372     snprintf(iiim_server, PATH_MAX, "uds:%s", uds_filename);
00373     XSetSelectionOwner(display, iiim_server_atom, httw_id, CurrentTime);
00374     XChangeProperty(display, httw_id, iiim_server_atom, XA_STRING, 8,
00375                   PropModeReplace, iiim_server, strlen(iiim_server));
00376     snprintf(iiim_server, PATH_MAX, "IIIM_SERVER=%s,", uds_filename);
00377     putenv(iiim_server);
00378     snprintf(iiim_vardir, PATH_MAX, "IIIMD_OPTION_VARDIR=%s", vardir_dirname);
00379     putenv(iiim_vardir);
00380     putenv("IIIMD_OPTION_DESKTOP=");
00381     /* free(iiim_server); */
00382   }
00383 
00384   XFlush(display);   /* I am not sure it will reach before
00385                       * htt_server starts so flush explicitly */
00386 
00387   /*
00388    * Set the PID property and used by htt_props to verify if it is
00389    * forked from htt
00390    */
00391   XChangeProperty(display, httw_id, htt_watchdog_atom, XA_WINDOW, 32,
00392                 PropModeReplace, (unsigned char *)&pid, sizeof(pid));
00393 
00394   /* fork iiimd */
00395   if (True == my_rdb.start_iiimd) {
00396     start_iiimd(&iiimd_pid, iiimd_arg);
00397   }
00398 
00399   /* fork htt_server */
00400   start_htt_server(&htt_server_pid, htt_server_arg);
00401 
00402   XChangeProperty(display, httw_id, server_atom, XA_WINDOW, 32,
00403                 PropModeReplace,
00404                 (unsigned char *)&htt_server_pid, sizeof(htt_server_pid));
00405   XFlush(display);
00406 
00407 
00408   /* fork htt_props *//* TO DO: conditional fork */
00409     if (my_rdb.start_props) {
00410       start_htt_props(&htt_props_pid, htt_props_arg);
00411       XChangeProperty(display, httw_id, props_atom, XA_WINDOW, 32,
00412                     PropModeReplace, (unsigned char *)&htt_props_pid,
00413                     sizeof(htt_props_pid));
00414       XFlush(display);
00415     }
00416     for (;;) {
00417       XNextEvent(display, &ev);
00418       switch (ev.type) {
00419       case PropertyNotify:
00420        if (ev.xproperty.window == httw_id) {
00421          if (ev.xproperty.atom == props_atom) {
00422 #if 0
00423            LOG2("watchdog.c:  property notify event wid = %x atom = %s\n",
00424                ev.xproperty.window, XGetAtomName(display, ev.xproperty.atom));
00425 #endif
00426            XGetWindowProperty(display, httw_id,
00427                             props_atom, 0, 4, False, XA_WINDOW,
00428                             &ret_type, &ret_format,
00429                             &nitems, &bytes_left, &tmp);
00430            if (ret_type == XA_WINDOW) {
00431              if (*tmp) {
00432               htt_props_pid = *tmp;
00433               my_rdb.start_props = 1;
00434 #if 0
00435               LOG1("watchdog.c:htt_props started pid=%d\n", htt_props_pid);
00436 #endif
00437              } else {
00438               my_rdb.start_props = 0;
00439               htt_props_pid = -1;
00440               spawn_props = False; /* htt_props spawned by
00441                                     * htt is killed */
00442 #if 0
00443               LOG0("watchdog.c:htt_props is killed");
00444 #endif
00445              }
00446            }
00447          } else if (ev.xproperty.atom == server_atom) {
00448            XGetWindowProperty(display, httw_id,
00449                             server_atom, 0, 4, False, XA_WINDOW,
00450                             &ret_type, &ret_format,
00451                             &nitems, &bytes_left, &tmp);
00452            if (ret_type == XA_WINDOW)
00453              if (*tmp) {
00454               if (htt_server_pid == (*tmp));
00455               else
00456                 fprintf(stderr,
00457                        nl_msg(NL_HTT_DUPLAICTED,
00458                              "iiimx : Warning - Duplicate iiim-xbe %ld\n"),
00459                        *tmp);
00460              }
00461          } else if (ev.xproperty.atom == resource_atom) {
00462            cmdline_prop = build_cmdline_db(toplevel, argv, argc, False);
00463            XChangeProperty(display, httw_id, cmdline_atom, XA_STRING,
00464                          8, PropModeReplace, cmdline_prop,
00465                          strlen(cmdline_prop) + 1);
00466            XFlush(display);
00467            XFree(cmdline_prop);
00468          } else if (ev.xproperty.atom == htt_server_reset_atom) {
00469            XGetWindowProperty(display, httw_id, htt_server_reset_atom,
00470                             0, 4,
00471                             False, XA_WINDOW, &ret_type, &ret_format,
00472                             &nitems, &bytes_left, &tmp);
00473            if (*tmp) {
00474              htt_server_killed = *tmp;
00475              /* Kill & start the server */
00476              Server_Status = RmServerReset;
00477              kill(htt_server_pid, SIGTERM);
00478              cmdline_prop = build_cmdline_db(toplevel, argv, argc, True);
00479              XChangeProperty(display, httw_id, cmdline_atom,
00480                            XA_STRING, 8,
00481                            PropModeReplace, cmdline_prop,
00482                            strlen(cmdline_prop) + 1);
00483              XFlush(display);
00484              XFree(cmdline_prop);
00485              start_htt_server(&htt_server_pid, htt_server_arg);
00486              XChangeProperty(display, httw_id, server_atom,
00487                            XA_WINDOW,
00488                            32, PropModeReplace, (unsigned char *)&htt_server_pid,
00489                            sizeof(htt_server_pid));
00490            } else {
00491              /* Kill the server */
00492              Server_Status = RmServerKilled;
00493              kill(htt_server_pid, SIGTERM);
00494            }
00495 
00496          } else
00497 #ifdef HTT_DEBUG
00498            fprintf(stderr,
00499                   "iiimx: Unknown property notify event wid = %x atom = %s\n",
00500                   ev.xproperty.window,
00501                   XGetAtomName(display, ev.xproperty.atom))
00502 #endif
00503            ;
00504        }
00505        break;
00506       case DestroyNotify:
00507        if (ev.xdestroywindow.window == httw_id) {
00508          Server_Status = RmServerKilled;
00509          kill(htt_server_pid, SIGTERM);
00510          if (my_rdb.start_props)
00511            kill(htt_props_pid, SIGTERM);
00512          exit(0);
00513        } else {
00514                             /* don't know what to do.... */
00515        }
00516       case ClientMessage:{
00517 
00518 #if 0
00519        LOG0("watchdog.c:Client Message");
00520        LOG1("watchdog.c:Message type %s\n",
00521             XGetAtomName(display, ev.xclient.message_type));
00522        LOG1("watchdog.c:format %d\n", ev.xclient.format);
00523        LOG1("watchdog.c:Client message data %s \n",
00524             XGetAtomName(display, ev.xclient.data.l[0]));
00525 #endif
00526                             /* Need to tell htt_server to save its state */
00527        if ((ev.xclient.format == 32) && (!strncmp(XGetAtomName(display, ev.xclient.message_type), "WM_PROTOCOLS", 12))) {
00528          if (ev.xclient.data.l[0] == htt_save_atom[1]) {
00529            char           *res = strdup("DeleteWindow:True");
00530            XChangeProperty(display, httw_id,
00531                          resource_atom, XA_STRING,
00532                          8, PropModeAppend,
00533                          (unsigned char *) res, strlen(res) + 1);
00534            free(res);
00535          }
00536          if (ev.xclient.data.l[0] == htt_save_atom[2]) {
00537            char           *res = strdup("SaveState:True");
00538            XChangeProperty(display, httw_id,
00539                          resource_atom, XA_STRING,
00540                          8, PropModeAppend,
00541                          (unsigned char *) res, strlen(res) + 1);
00542            free(res);
00543            if (my_rdb.respond_to_sm)
00544               if (!spawn_props) {
00545                 /* spawn_props = False means  */
00546                 char          **tmp_argv = (char **) XtMalloc((argc + 1) *
00547                                                    sizeof(char *));
00548                 int             tmp_argc;
00549                 for (tmp_argc = 0; tmp_argc < argc; tmp_argc++)
00550                   tmp_argv[tmp_argc] = argv[tmp_argc];
00551                 tmp_argv[tmp_argc] = (char *) XtMalloc(strlen("-so") + 1);
00552                 strcpy(tmp_argv[tmp_argc++], "-so");
00553                 XSetCommand(display, httw_id, tmp_argv, tmp_argc);
00554                 XtFree(tmp_argv[tmp_argc - 1]);
00555                 XtFree((char *)tmp_argv);
00556               } else
00557                 XSetCommand(display, httw_id, argv, argc);
00558             else
00559               XSetCommand(display, httw_id, (char **)0, 0);
00560               /* Ignore WM_SAVEYOURSELF  msg */
00561             }
00562            }
00563        break;
00564       }
00565       }
00566     }
00567 }
00568 
00569 void 
00570 clean_up(int unused)
00571 {
00572 
00573   if (my_rdb.start_props) {
00574     fprintf(stderr,
00575            nl_msg(NL_HTT_PROPS_STILL_RUNNING,
00576                  "iiimx : Warning - htt_props is still running use htt_props to kill this server ...\n")
00577            );
00578 #ifdef SunOS
00579     sigset(SIGINT, (void (*) (int)) clean_up);
00580 #else
00581     signal(SIGINT, (void (*) (int)) clean_up);
00582 #endif
00583     return;
00584   }
00585   /*
00586    * Change server_pid to zero, signal handler sense it that is handled
00587    * by htt
00588    */
00589   htt_server_killed = 1;
00590   Server_Status = RmServerKilled;
00591   kill(htt_server_pid, SIGTERM);
00592   if (my_rdb.start_props)
00593     kill(htt_props_pid, SIGTERM);
00594   exit(1);
00595 }
00596 
00597 void 
00598 proc_exit(int unused)
00599 {
00600   int             pid;
00601   int             wstat;
00602 
00603   for (;;) {
00604     pid = wait3(&wstat, WNOHANG, (struct rusage *) NULL);
00605     if (pid == 0)
00606       return;
00607     else if (pid == -1)
00608       return;
00609     else if (pid == htt_server_pid) {
00610       if (WIFSTOPPED(wstat)) {
00611        fprintf(stderr,
00612               nl_msg(NL_HTT_SUSPENDED,
00613                      "iiim-xbe has been suspended \n")
00614               );
00615       } else if (WIFEXITED(wstat)) {
00616        switch (Server_Status) {
00617        case RmServerKilled:
00618          if (my_rdb.start_props)
00619            kill(htt_props_pid, SIGTERM);
00620          exit(1);
00621          break;      /* Not so useful */
00622        case RmServerReset:
00623          /*
00624           * Don't worry abt it. Watchdog wants
00625           * to reset htt_server
00626           */
00627          break;
00628        case RmServerActive:
00629          fprintf(stderr, nl_msg(NL_HTT_SERVER_EXITED_UNKNOWN,
00630                              "iiimx : Warning - iiim-xbe has been terminated without knowledge of iiimx , restart iiimx again\n"));
00631          if (my_rdb.start_props)
00632            kill(htt_props_pid, SIGTERM);
00633          exit(0);
00634          break;      /* Not so usefule */
00635        }
00636 #if 0
00637        fprintf(stderr,
00638               nl_msg(NL_HTT_SERVER_DIED,
00639                      "htt : Warning - htt_server died and recovered\n"));
00640        start_htt_server(&htt_server_pid, htt_server_arg);
00641 #endif
00642       } else if (WIFSIGNALED(wstat)) {
00643        switch (WTERMSIG(wstat)) {
00644        case SIGTERM:
00645        case SIGKILL: /* there must be a reason */
00646          if (!htt_server_killed) {
00647            /*
00648             * 4049423: In zh_TW.BIG5 and
00649             * ja_JP.PCK, htt prints
00650             * message in garbage when it
00651             * exits
00652             * 
00653             * fprintf(stderr,
00654             * nl_msg(NL_HTT_SERVER_EXITED
00655             * , "htt : htt_server has
00656             * been terminated\n") );
00657             */
00658            if (my_rdb.start_props)
00659              kill(htt_props_pid, SIGTERM);
00660            exit(0);
00661          }
00662          htt_server_killed = 0;
00663          break;
00664        case SIGQUIT:
00665        case SIGILL:
00666 #ifndef       linux
00667        case SIGEMT:
00668 #endif
00669        case SIGSEGV:
00670        case SIGFPE:
00671        case SIGTRAP:
00672        case SIGBUS:
00673 #ifndef       linux
00674        case SIGSYS:
00675 #endif
00676        case SIGIOT:
00677          fprintf(stderr,
00678                 nl_msg(NL_HTT_SERVER_DIED,
00679                       "iiimx : Warning - iiim-xbe died and recovered\n")
00680                 );
00681          start_htt_server(&htt_server_pid, htt_server_arg);
00682          break;
00683        default:
00684          fprintf(stderr,
00685                 nl_msg(NL_HTT_SERVER_DIED_UNKNOWN,
00686                       "iiimx : Error - iiim-xbe died. Don't know how to recover\n")
00687                 );
00688          if (my_rdb.start_props)
00689            kill(htt_props_pid, SIGTERM);
00690          exit(1);
00691        }
00692       }
00693     } else if ((my_rdb.start_props) && (pid == htt_props_pid)) {
00694       /*
00695        * printf("watchdog: htt_props has died, do
00696        * something?\n");
00697        */
00698     }
00699   }
00700 }
00701 
00702 int
00703 check_openwin_path(char *prg, char *oppath, char *result)
00704 {
00705   static char suffix[]="/bin/";
00706   int req;
00707 
00708   if (!oppath) return 0;
00709 
00710   req = strlen(prg) + sizeof(suffix) + 1;
00711 
00712   if (oppath
00713       && ((strlen(oppath) + sizeof (suffix) + req) < MAXNAMELEN))
00714     {
00715       strcpy(result, oppath);
00716       strcat(result, suffix);
00717       strcat(result, prg);
00718       if (access(result, X_OK) == 0) return 1;
00719     }
00720   return 0;
00721 }
00722 
00723 /* If the path in OPENWIN, return 1. */
00724 #define OPENWIN_PATH 1
00725 int
00726 search_program(char *prg, char *path)
00727 {
00728   char *basepath;
00729 
00730   if (check_openwin_path(prg, getenv("OPENWINHOME"), path))
00731     return OPENWIN_PATH;
00732   if (check_openwin_path(prg, OPENWINHOME, path))
00733     return OPENWIN_PATH;
00734     
00735   basepath = IMDIR;
00736   if (basepath
00737       && ((strlen(basepath) + strlen(prg) + 2) < MAXNAMELEN))
00738     {
00739       strcpy(path, basepath);
00740       strcat(path, "/");
00741       strcat(path, prg);
00742       if (access(path, X_OK) == 0) return 0;
00743     }
00744   return -1;
00745 }
00746 
00747 void 
00748 start_htt_server(htt_server_pid, argv)
00749      int            *htt_server_pid;
00750      char           *argv[];
00751 {
00752   char            pathname[MAXNAMELEN];
00753   extern int      errno;
00754   int             pid;
00755   int             flag;
00756 
00757   flag = search_program(my_rdb.htt_server_name, pathname);
00758 
00759   if (flag < 0)
00760     {
00761       perror("iiim-xbe not found\n");
00762       return;
00763     }
00764 
00765   pid = (*htt_server_pid) = fork();
00766   switch (*htt_server_pid) {
00767   case -1:
00768     perror("watchdog:fork\n");
00769     exit(errno);
00770   case 0:
00771     /*
00772      * Note: Forked process sleeps for one second (roughly) in
00773      * order to allow htt to update PID property. It should work
00774      * most of the cases
00775      */
00776     sleep(1);
00777 
00778 #ifdef SETPGRP_VOID
00779     setpgrp();
00780 #else
00781     setpgrp(0, 0);
00782 #endif
00783 
00784 #ifdef SunOS
00785     if (flag == OPENWIN_PATH) {
00786       putenv(OPENWIN_MOTIF_PRELOAD_ENV);
00787     }
00788 #endif
00789     execv(pathname, argv);
00790     perror("execv iiim-xbe failed\n");
00791   }
00792   Server_Status = RmServerActive;
00793 }
00794 
00795 void 
00796 start_htt_props(htt_props_pid, argv)
00797      int            *htt_props_pid;
00798      char           *argv[];
00799 {
00800   char            pathname[MAXNAMELEN];
00801   extern int      errno;
00802 
00803   if (search_program(htt_props_path, pathname) < 0)
00804     {
00805       perror("htt_props not found\n");
00806       return;
00807     }
00808   *htt_props_pid = fork();
00809   switch (*htt_props_pid) {
00810   case -1:
00811     perror("watchdog:fork\n");
00812     exit(errno);
00813   case 0:
00814     setpgrp();
00815     if (!my_rdb.respond_to_sm)
00816       sleep(10);
00817     execv(pathname, argv);
00818     perror("execv htt_props failed\n");
00819   }
00820 }
00821 
00822 void 
00823 start_iiimd(iiimd_pid, argv)
00824      int *    iiimd_pid;
00825      char **  argv;
00826 {
00827   char *      pathname;
00828   extern int  errno;
00829   int         pid;
00830 
00831   pathname = "/usr/bin/iiimd";
00832 
00833   pid = (*iiimd_pid) = fork();
00834   switch (*iiimd_pid) {
00835   case -1:
00836     perror("watchdog:fork\n");
00837     exit(errno);
00838   case 0:
00839 #ifdef SETPGRP_VOID
00840     setpgrp();
00841 #else
00842     setpgrp(0, 0);
00843 #endif
00844 
00845     execv(pathname, argv);
00846     perror("execv iiimd failed\n");
00847   }
00848   sleep(4);
00849 }
00850 
00851 static Bool
00852 build_dir(const char * path, mode_t mode)
00853 {
00854   struct stat st;
00855   if (stat(path, &st) < 0) {
00856     if ((mkdir(path, mode) < 0) || (stat(path, &st) < 0)) {
00857       return False;
00858     }
00859   }
00860   if ((S_ISDIR(st.st_mode))) {
00861     return True;
00862   } else {
00863     return False;
00864   }
00865 }
00866 
00867 static char *
00868 build_uds_filename(Widget toplevel)
00869 {
00870   char *             udsf;
00871   struct passwd *    pw;
00872 
00873   pw = getpwuid(geteuid());
00874   udsf = (char *)malloc(PATH_MAX);
00875 
00876   if ((NULL == pw) || (NULL == udsf)) {
00877     endpwent();
00878     if (NULL != udsf) free(udsf);
00879     return NULL;
00880   }
00881 
00882   snprintf(udsf, PATH_MAX, "/tmp/.iiim-%s", pw->pw_name);
00883   if (False == build_dir(udsf, 0700)){
00884     endpwent();
00885     free(udsf);
00886     return NULL;
00887   }
00888   strncat(udsf, "/", PATH_MAX);
00889   strncat(udsf, DisplayString(XtDisplay(toplevel)), PATH_MAX);
00890 
00891   return udsf;
00892 
00893 #if 0
00894   size_t             len;
00895 
00896   get_home_dir(udsf);
00897 
00898   strncat(udsf, ".iiim", PATH_MAX);
00899   if (False == build_dir(udsf, 0777)){
00900       free(udsf);
00901       return NULL;
00902   }
00903 
00904   strncat(udsf, "/run", PATH_MAX);
00905   if (False == build_dir(udsf, 0700)){
00906       free(udsf);
00907       return NULL;
00908   }
00909 
00910   strncat(udsf, "/", PATH_MAX);
00911   len = strlen(udsf);
00912   get_host(udsf + len, PATH_MAX - len);
00913   strncat(udsf, "-", PATH_MAX);
00914   strncat(udsf, DisplayString(XtDisplay(toplevel)), PATH_MAX);
00915 
00916   return udsf; 
00917 #endif /* 0 */
00918 }
00919 
00920 static char *
00921 build_vardir_dirname(void)
00922 {
00923   char *      vardir;
00924 
00925   vardir = (char *)malloc(PATH_MAX);
00926   if (NULL == vardir) {
00927     return NULL;
00928   }
00929 
00930   get_home_dir(vardir);
00931 
00932   strncat(vardir, ".iiim", PATH_MAX);
00933   if (False == build_dir(vardir, 0777)){
00934       free(vardir);
00935       return NULL;
00936   }
00937 
00938   strncat(vardir, "/le", PATH_MAX);
00939   if (False == build_dir(vardir, 0777)){
00940       free(vardir);
00941       return NULL;
00942   }
00943 
00944   return vardir; 
00945 }
00946 
00947 static char **
00948 build_iiimd_arg(char * udsf, char * vardir)
00949 {
00950   char **     pargv;
00951   char **     p;
00952 
00953   pargv = (char **)malloc((sizeof (char *)) * (7));
00954   p = pargv;
00955 
00956   *(p++) = "iiimd";
00957   *(p++) = "-nodaemon";
00958   if (NULL != udsf) {
00959     *(p++) = "-udsfile";
00960     *(p++) = udsf;
00961   }
00962   if (NULL != vardir) {
00963     *(p++) = "-vardir";
00964     *(p++) = vardir;
00965   }
00966   *(p++) = NULL;
00967 
00968   return pargv;
00969 }
00970 
00971 static void
00972 usage(void) {
00973   printf(
00974         nl_msg(NL_HTT_USAGE_1,
00975               "usage:\n       iiimx [-options ...]\n\nwhere options include:\n")
00976         );
00977   printf(
00978         nl_msg(NL_HTT_USAGE_2,
00979               "    -help                         print out this message\n")
00980         );
00981   printf(
00982         nl_msg(NL_HTT_USAGE_3,
00983               "    -display displayname          X server to contact\n")
00984         );
00985   printf(
00986         nl_msg(NL_HTT_USAGE_4,
00987               "    -xrm file                     additional resource file\n")
00988         );
00989 #if 0
00990   printf(
00991         nl_msg(NL_HTT_USAGE_5,
00992               "    -so                           server only\n")
00993         );
00994   printf(
00995         nl_msg(NL_HTT_USAGE_5,
00996               "    -sp                           start htt_props as well\n")
00997         );
00998   printf(
00999         nl_msg(NL_HTT_USAGE_6,
01000               "    -nosm                         do not respond to session manager\n")
01001         );
01002 #endif
01003   printf(
01004         nl_msg(NL_HTT_USAGE_7,
01005               "    -xim                          xim server name\n")
01006         );
01007 }
01008 
01009 static void
01010 parse_command(int argc, char **argv)
01011 {
01012   int             i;
01013   for (i = 1; i < argc; i++) {
01014     if (!strcmp(argv[i], "-help")) {
01015       usage();
01016       exit(0);
01017     }
01018   }
01019 }
01020 
01021 static char*
01022 build_cmdline_db(Widget toplevel, char *argv[], int argc, Bool replace_mode)
01023 {
01024   char            filenamebuf[PATH_MAX], *filename = filenamebuf;
01025   static XrmDatabase cmd_db;
01026   FILE           *fd;
01027   char           *type_return[20];
01028   XrmValue        val_return;
01029   char           *lang = NULL;
01030   int             count;
01031   int             file_size;
01032   char           *str_return;
01033   static XrmQuark RmQString;
01034 
01035   static XrmDatabase db;
01036   char          **pargv;
01037   int             pargc;
01038   Bool            res_status;
01039 
01040   pargc = argc;
01041   pargv = (char **) Xmalloc(sizeof(char *) * pargc);
01042   for (count = 0; count < pargc; count++) {
01043     pargv[count] = Xmalloc(strlen(argv[count]) + 1);
01044     strcpy(pargv[count], argv[count]);
01045   }
01046 
01047 
01048   RmQString = XrmPermStringToQuark(XtRString);
01049   db = XtDatabase(XtDisplay(toplevel));
01050   /* Create db from command line options */
01051   XrmParseCommand(&cmd_db, rdb_options, NUM_RDB_OPTIONS,
01052                 HTT_CLASS_NAME, &pargc, pargv);
01053 
01054   for (count = 0; count < pargc; count++)
01055     XFree(pargv[count]);
01056   Xfree(pargv);
01057 
01058   /* try to get locale of the program */
01059   res_status = XrmGetResource(db, "iiimx*language",
01060                            "Iiimx*Language", type_return, &val_return);
01061 
01062   if (res_status && (char *) val_return.addr) {
01063     int             len = strlen((char *) val_return.addr);
01064     if (len) {
01065       char            lang_env[256];
01066       lang = Xmalloc(len + 1);
01067       strcpy(lang, (char *) val_return.addr);
01068       setlocale(LC_CTYPE, lang);
01069       strcpy(lang_env, "LC_CTYPE=");
01070       strcat(lang_env, lang);
01071       putenv(lang_env);
01072     }
01073   } else
01074     lang = setlocale(LC_CTYPE, "");
01075 
01076   /* Add options from ~/.httdefaults */
01077   get_home_dir(filename);
01078   strcat(filename, ".httdefaults");
01079   XrmCombineFileDatabase(filename, &cmd_db, False);
01080 
01081   /* Add options from ~/.Xlocale/<lang>/app-defaults/<HTT_CLASS_NAME> */
01082   get_home_dir(filename);
01083   strcat(filename, ".Xlocale/");
01084   strcat(filename, lang);
01085   strcat(filename, "/app-defaults/");
01086   strcat(filename, HTT_CLASS_NAME);
01087   XrmCombineFileDatabase(filename, &cmd_db, replace_mode);
01088 
01089   /* Generate an uniq file name */
01090   strcpy(filename, "/tmp/HTTXXXXXX");
01091   mkstemp(filename);
01092 #if 0
01093   LOG1("resouce file name is %s\n", filename);
01094 #endif
01095 
01096   /* Store the database */
01097   XrmPutFileDatabase(cmd_db, filename);
01098 
01099   /* If there is no resource the file is empty, or it is not created */
01100   if ((fd = fopen(filename, "r"))) {
01101     /* File exists */
01102     fseek(fd, 0, SEEK_END);
01103     file_size = ftell(fd);
01104 
01105     str_return = Xmalloc(file_size + 1);
01106     fseek(fd, 0, SEEK_SET);
01107     fread(str_return, file_size, 1, fd);
01108     str_return[file_size] = '\0';
01109     fclose(fd);
01110     unlink(filename);
01111   } else {
01112     /* File doesn't exist so send empty resource */
01113     str_return = Xmalloc(1);
01114     *str_return = '\0';
01115   }
01116   return str_return;
01117 }
01118 
01119 static char*
01120 get_home_dir(char *buf) {
01121   static char *ptr = NULL;
01122   int len;
01123 
01124   if (ptr == NULL) {
01125     uid_t uid;
01126     struct passwd  *pw;
01127 
01128     if (!(ptr = getenv("HOME"))) {
01129       if ((ptr = getenv("USER"))) {
01130        pw = getpwnam(ptr);
01131       } else {
01132        uid = getuid();
01133        pw = getpwuid(uid);
01134       }
01135       if (pw) {
01136        ptr = pw->pw_dir;
01137       } else {
01138        ptr = NULL;
01139        *buf = '\0';
01140       }
01141     }
01142   }
01143   if (ptr) {
01144     strcpy(buf, ptr);
01145   }
01146   len = strlen(buf);
01147 
01148   if (buf[len - 1] != '/') {
01149     buf[len] = '/';
01150     buf[len + 1] = '\0';
01151   }
01152   return buf;
01153 }
01154 
01155 static char    *
01156 get_host(buf, max_len)
01157      char           *buf;
01158      int             max_len;
01159 {
01160   int             len;
01161   struct utsname  name;
01162 
01163   uname(&name);
01164 
01165   len = strlen(name.nodename);
01166 
01167   if (len >= max_len) {
01168     len = max_len - 1;
01169   }
01170   strncpy(buf, name.nodename, len);
01171   buf[len] = '\0';
01172 
01173   return buf;
01174 }