Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / programs / dtimsstart / main.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: main.c /main/10 1996/10/28 12:41:03 cde-hp $ */
24
25 /*
26  * (c) Copyright 1996 Digital Equipment Corporation.
27  * (c) Copyright 1996 Hewlett-Packard Company.
28  * (c) Copyright 1996 International Business Machines Corp.
29  * (c) Copyright 1996 Sun Microsystems, Inc.
30  * (c) Copyright 1996 Novell, Inc. 
31  * (c) Copyright 1996 FUJITSU LIMITED.
32  * (c) Copyright 1996 Hitachi.
33  */
34
35 #ifndef lint
36 static char     *RCS_ID = "@(#)dtimsstart $Revision: /main/10 $ $Date: 1996/10/28 12:41:03 $";
37 #endif
38
39 char    *ProgramRevision = "dtimsstart $Revision: /main/10 $";
40
41 #define _EXTERN_DEFINE_
42 #include        "xims.h"
43 #undef  _EXTERN_DEFINE_
44
45 #include        <signal.h>
46 #include        <locale.h>
47
48 #ifndef NLS
49 #define catgets(i, sn,mn,s) (s)
50 #else
51 #define NL_SETN 1       /* set number */
52 #include <nl_types.h>
53 static nl_catd  catd = (nl_catd) -1;
54 #endif  /* NLS */
55
56 extern char *find_system_locale_name(char *);
57
58     /* local functions */
59 static int      IsNoError(/* error */);
60 static int      EnvNeeded(/* error */);
61 static int      ErrMsgDisabled(/* error */);
62 static int      ximsShowImsList(/*  */);
63 static int      ximsShowCurrentIms(/*  */);
64 static int      prepare_remote(/* win_st */);
65 static int      ximsRemoteConf(/*  */);
66 static int      ximsSetMode(/*  */);
67 static void     show_select_mode(/* mode */);
68 static int      set_locale_env(/* locale */);
69 static void     init_command(/* progname */);
70 static bool     optname_match(/* name, str, minlen */);
71 static int      parse_options(/* argc, argv */);
72 static void     usage(/* force */);
73
74 static int      exitSignalNumber = 0;
75 static bool     do_usage = False;
76
77
78 int main (int argc, char **argv)
79 {
80     int         ret = NoError;
81     int         ret2;
82
83     init_command(argv[0]);
84
85     ret = parse_options(argc, argv);
86
87     ret2 = set_locale_env(Opt.LocaleName);      /* set LANG, LC_ALL, msg cat */
88         /* get_user_environ() does check ErrNoLocale */
89
90     if (do_usage) {     /* '-help' option */
91         usage(True);
92         Exit(NoError);
93     }
94     if (ret != NoError)
95         Exit(ret);
96
97     if (OpMode == MODE_START && getenv(ENV_NO_DTIMSSTART))
98         Exit(ErrDisabled);
99
100     if ((ret = set_cmd_env()) != NoError) {
101             /* get_user_environ()) & read_cmd_conf()) */
102         Exit(ret);
103     }
104
105 #ifdef  DEBUG
106     if (DebugLvl > 2)   { pr_CmdConf(); }
107     if (DebugLvl > 1)   { pr_CmdOpt(), pr_OpModeFlag(); pr_UserEnv(); }
108 #endif
109
110     /* set signal handler */
111     if (signal(SIGINT, SIG_IGN) != SIG_IGN)     signal(SIGINT, sigExit);
112     signal(SIGTERM, sigExit);
113     signal(SIGHUP, sigExit);
114     signal(SIGQUIT, sigExit);
115
116         /* create $HOME/.xims if needed */
117     if (OpMode == MODE_START
118         || (OpMode == MODE_MODE && Opt.SelectMode != SEL_MODE_QUERY)) {
119         if ((ret = create_xims_dir()) != NoError) {
120             OpErrCode = ret;
121             OpState = State_Init_Err;
122             ximsMain();         /* abort with error msg */
123         }
124     }
125
126     OpState = State_Init_Done;
127
128     switch (OpMode) {
129         case MODE_LISTNAME:
130         case MODE_LIST:         ret = ximsShowImsList(); break;
131         case MODE_CURRENT:      ret = ximsShowCurrentIms(); break;
132         case MODE_MODE:         ret = ximsSetMode(); break;
133         case MODE_REMCONF:      ret = ximsRemoteConf(); break;
134
135         case MODE_START:
136 #ifndef DEBUG2
137 # if defined(CSRG_BASED)
138                                 setsid();
139 # else
140                                 setpgrp();
141 # endif
142 #endif
143                                 ximsMain();     /* never returns */
144     }
145
146     Exit(ret);
147 }
148
149
150 void    sigExit(int sig)
151 {
152     DPR(("sigExit:  %s (%d)\n", sig_name(sig), sig));
153     signal(sig, SIG_IGN);
154     exitSignalNumber = sig;
155     Exit(ErrSignaled);
156 }
157
158 void    Exit(int err_code)
159 {
160     int         exit_code = IsNoError(err_code) ? 0 : 1;
161
162     DPR(("Exit(%s[%d]): exit(%d)\n",
163                                 error_name(err_code), err_code, exit_code));
164
165     if (Verbose > 0 && err_code != LastErrMsg) {
166         if (exit_code != 0 && !ErrMsgDisabled(err_code)) {
167             UseMsgWindow = False;               /* disable msg window */
168             put_xims_errmsg(err_code, 0, 0, 0);
169         }
170     }
171
172     if (OpFlag & FLAG_NOTIFY)
173         NotifyErrCode(exit_code == 0 ? NoError : err_code);
174
175     /*
176      * if the reason we're exiting is because of a syntax
177      * error, set the exit code to 2.
178      */
179     if (ErrSyntax == err_code)
180         exit_code = 2;
181
182     exit(exit_code);
183 }
184
185 int     NotifyErrCode(int err_code)
186 {
187     char        buf[BUFSIZ], *bp, val[20];
188     static bool notify_done = False;
189
190     if (/* !(OpFlag & FLAG_NOTIFY) || */ notify_done)
191         return False;
192     notify_done = True;
193
194     buf[0] = 0; bp = buf;
195     bp = strcpyx(bp, STR_ERRORCODE);
196     *bp++ = '=';
197     sprintf(val, "%ld", (long)err_code);
198     bp = strcpyx(bp, val);
199     *bp++ = '\n'; *bp = 0;
200
201     if (ErrFilePathNeeded(err_code)) {
202         bp = strcpyx(bp, STR_ERRORPATH);
203         *bp++ = '=';
204         if (err_code == ErrImsAborted)
205             bp = strcpyx(bp, Opt.LogPath);
206         else
207             bp = strcpyx(bp, errFilePath);
208         *bp++ = '\n'; *bp = 0;
209     }
210
211     if (OpMode == MODE_REMCONF) {
212         send_dtims_msg(WIN_ST_REMOTE_CONF, err_code);
213
214     } else if (OpMode == MODE_START && (OpFlag & FLAG_REMOTERUN)) {
215         send_dtims_msg(WIN_ST_REMOTE_RUN, err_code);
216
217     } else {
218         fflush(stdout); fflush(stderr);
219         (void) fwrite((void *)buf, (size_t)(bp - buf), (size_t)1, stdout);
220         fflush(stdout);
221     }
222
223     return True;
224 }
225
226
227 static int      IsNoError(ximsError error)
228 {
229     switch (error) {
230         case NoError: case ErrIsNone: case ErrNotRun:
231         case ErrImsWaiting: case ErrImsWaitDone:
232         case ErrImsConnecting: case ErrImsConnectDone:
233         case ErrNoImsEntry: case ErrNoLocaleConf:
234         case ErrNoSelectionFile: case ErrNoSelection: case ErrSaveSelection:
235         case ErrDisabled:
236                 return True;
237     }
238     return False;
239 }
240
241 static int      EnvNeeded(ximsError error)
242 {
243     switch (error) {
244         case NoError: case ErrIsNone: case ErrNotRun:
245         case ErrImsWaiting: case ErrImsWaitDone:
246         case ErrImsRunning: case ErrImsTimeout:
247         /* case ErrImsExecution: case ErrImsAborted: */
248         case ErrOpenResource:   /* case ErrSignaled: */
249                 return True;
250     }
251     return False;
252 }
253
254 static int      ErrMsgDisabled(ximsError error)
255 {
256     switch (error) {
257         case NoError: case ErrIsNone: case ErrNotRun:
258         case ErrImsWaiting: case ErrImsWaitDone:
259         case ErrImsConnecting: case ErrImsConnectDone:
260                 return True;
261         case ErrSignaled:
262                 return (Verbose <= 2);
263         case ErrInvState: case ErrInternal:
264                 return (Verbose <= 3);
265     }
266     return False;
267 }
268
269 int     ErrFilePathNeeded(ximsError error)
270 {
271     switch (error) {
272         case ErrFileOpen: case ErrFileCreate: case ErrDirCreate:
273         case ErrMissEntry: case ErrNoExecutable: case ErrImsAborted:
274         case ErrOpenResource:
275                 return True;
276     }
277     return False;
278 }
279
280 int     InWaitingState(void)
281 {
282     switch (OpState) {
283         case State_Init_Err:
284         case State_Finish_Defered:
285         case State_Mode_Done:
286             return True;
287     }
288     return False;
289 }
290
291 void    ximsMain(void)
292 {
293     static int  call_cnt = 0;
294
295     call_cnt++;
296
297     DPR(("\nximsMain(call_cnt=%d): OpState=%s  OpErrCode=%s[%d]\n",
298                 call_cnt, StateName(), error_name(OpErrCode), OpErrCode));
299
300 #ifdef  DEBUG
301     pr_brk("ximsMain");
302 #endif
303
304     if (OpFlag & FLAG_REMOTERUN) {
305         int ret;
306         if ((ret = prepare_remote(WIN_ST_REMOTE_RUN)) != NoError) {
307             Exit(ret);
308         }
309     }
310
311     switch (OpState) {
312         case State_Init_Done:           if (Verbose > 1)
313                                             put_xims_log("Started.", 0, 0, 0);
314                                         ximsSelect();
315
316         case State_Select_Done:
317         case State_Select_Canceled:     ximsStart();
318
319         case State_Start_Done:          ximsWait();
320
321         case State_Init_Err:
322         case State_Select_Err:
323         case State_Start_Err:
324         case State_Wait_Err:
325                         if (!WaitingDialogReply && !IsNoError(OpErrCode)) {
326                             LastErrMsg = OpErrCode;
327                             put_xims_errmsg(OpErrCode, 0, 0, 0);
328                         }
329
330         case State_Wait_Done:
331                                         ximsFinish();
332
333         case State_Finish:
334                         if (WaitingDialogReply) {
335                             DPR(("ximsMain(): enter xevent_loop()\n"));
336                             xevent_loop();      /* never returns */
337                             WaitingDialogReply = False; /* if failed */
338                         }
339
340         case State_Finish_Defered:
341                         if (OpState == State_Finish_Defered) {
342                             WaitingDialogReply = False;
343                             ximsFinish();
344                         }
345
346         case State_Finish_Done:         break;
347         case State_Finish_Err:          break;
348
349         case State_Mode_Done:
350         case State_Mode_Canceled:       break;
351
352         default:
353                                         OpErrCode = ErrInvState; break;
354     }
355
356     Exit(OpErrCode);
357 }
358
359
360 void    ximsFinish(void)
361 {
362     OpStateVal  oldOpState = OpState;
363
364     DPR(("ximsFinish(): OpState=%s  OpErrCode=%s[%d]\n",
365                         StateName(), error_name(OpErrCode), OpErrCode));
366
367     OpState = State_Finish;
368
369     if (oldOpState != State_Finish_Defered) {
370
371         if (!(OpFlag & FLAG_NORESOURCE) && isXsession())
372             restore_resources();
373
374         if (WaitingDialogReply) {
375             DPR2(("ximsFinish(): OpState => State_Finish_Defered\n"));;
376             OpState = State_Finish_Defered;
377             return;
378         }
379     }
380
381     if (OpMode == MODE_START && (OpFlag & FLAG_ENV)) {
382         if (userSel.name && EnvNeeded(OpErrCode)) {
383             OutEnv      outEnv;
384
385             CLR(&outEnv, OutEnv);
386             if (make_new_environ(&outEnv, &userSel) == NoError) {
387                 put_new_environ(&outEnv);
388                 clear_OutEnv(&outEnv);
389             }
390         } else {
391             DPR(("ximsFinish(): Not put env (pri->status=%s[%d])\n",
392                     error_name(userSel.renv->status), userSel.renv->status));
393         }
394     }
395
396     /* if (IsNoError(OpErrCode))        OpErrCode = NoError; */
397     OpState = State_Finish_Done;
398     return;
399 }
400
401
402 static int      ximsShowImsList(void)
403 {
404     int         ret;
405     int         i;
406     int         host_type = HOST_LOCAL;
407     char        *hostname;
408     ImsList     *list = (ImsList *) 0;
409
410     DPR(("ximsShowImsList()\n"));
411
412     hostname = Opt.HostName;
413     if (hostname) {
414         host_type = check_hostname(hostname);
415         userSel.hostname = NEWSTR(hostname);    /* for error msg */
416     }
417
418     switch (host_type) {
419         case HOST_UNKNOWN:
420             ret = ErrUnknownHost;
421             break;
422
423         case HOST_REMOTE:
424             ret = get_remote_conf(&list, hostname, NULL, NULL);
425             break;
426
427         case HOST_LOCAL:
428             ret = get_ims_list(&list, NULL, True);
429             break;
430     }
431
432     if (ret != NoError) {
433         DPR2(("ximsShowImsList: ret=%s[%d]\n", error_name(ret), ret));
434         /* return ret; */
435     } else if (Verbose < 1) {
436         for (i = 0; i < list->num_ent; i++)
437             puts(list->elist[i]->name);
438     } else {
439         int     err, len;
440
441         for (i = 0; i < list->num_ent; i++) {
442             /* If invoked from dtstyle with -listname put the "#" if this is 
443                the default one. */
444             if (Opt.Listname == 1)
445                 if (i == list->default_idx)
446                     putchar('#');
447             err = list->elist[i]->status;
448             if (err)    putchar('(');
449             fputs(list->elist[i]->name, stdout);
450             if (err)    putchar(')');
451             /* If invoked from dtstyle with -listname put the label */
452             if (Opt.Listname == 1) {
453                 putchar(' ');
454                 fputs(list->elist[i]->label, stdout);
455             }
456
457             if (Verbose > 1) {
458                 char    *msg = "cannot execute";
459                 switch (err) {
460                     case NoError:
461                         msg = "ok"; break;
462                     case ErrNoExecutable:
463                         msg = "no executable file"; break;
464                     case ErrNoImsConf:
465                         msg = "no configuration file"; break;
466                     case ErrMissEntry:
467                         msg = "invalid configuration file"; break;
468                 }
469                 len = strlen(list->elist[i]->name) + (err ? 2 : 0);
470                 for ( ; len < 16; len++)        putchar(' ');
471                 putchar(' '); putchar('['); fputs(msg, stdout); putchar(']');
472             }
473             putchar('\n');
474         }
475     }
476     fflush(stdout);
477
478     if (list) {
479         clear_ImsList(list); FREE(list);
480     }
481
482     return NoError;
483 }
484
485 static int      ximsShowCurrentIms(void)
486 {
487     int         ret = NoError;
488     FileSel     *fsel;
489
490     DPR(("ximsShowCurrentIms()\n"));
491
492     if (read_user_selection(&fsel, NULL) != NoError) {
493         DPR2(("No selection file.\n"));
494         return ErrNoSelectionFile;
495     }
496
497     if (fsel->name) {
498         if (fsel->hostname)
499             printf("%s\t[on %s]\n", fsel->name, fsel->hostname);
500         else
501             puts(fsel->name);
502         fflush(stdout);
503     } else {
504         DPR2(("No IMS selected.\n"));
505         ret = ErrNoSelection;
506     }
507
508     clear_FileSel(fsel); FREE(fsel);
509
510     return ret;
511 }
512
513
514 static int      prepare_remote(int win_st)
515 {
516     int         ret;
517     char        **av = NULL;
518     int         ac = 0;
519     int         cur_st;
520
521     DPR(("prepare_remote()\n"));
522
523 #ifndef DEBUG
524     Verbose = DebugLvl = 0;     /* disable error messages */
525 #endif
526     UseMsgWindow = False;
527
528     if ((ret = init_window_env()) != NoError)
529         return ret;
530
531     if (winEnv.atom_owner == None)
532         return ErrRemoteData;
533
534     cur_st = get_window_status();
535     if (cur_st != win_st) {
536         DPR(("prepare_remote(): invalid status '%d', should be '%d'\n",
537                                                 cur_st, win_st));
538         return ErrRemoteData;
539     }
540
541     ret = get_window_data(&ac, &av);    /* additional options */
542     if (ret != NoError) {
543         DPR(("prepare_remote(): get_window_data (%s[%d])\n",
544                             error_name(ret), ret));
545     }
546
547     if (ret == NoError) {
548         ret = parse_options(ac, av);
549         if (ret != NoError) {
550             DPR(("secondary parse_options(): failed (%s[%d])\n",
551                                 error_name(ret), ret));
552         }
553     }
554
555     return NoError;
556 }
557
558 static int      ximsRemoteConf(void)
559 {
560     int         ret;
561     char        *locale;
562
563     DPR(("ximsRemoteConf()\n"));
564
565     if ((ret = prepare_remote(WIN_ST_REMOTE_CONF)) != NoError)
566         return ret;
567
568     locale = userEnv.real_locale ? userEnv.real_locale : userEnv.locale;
569
570     ret = put_remote_conf(locale, Opt.ImsName);
571
572     return ret;
573 }
574
575
576 static int      ximsSetMode(void)
577 {
578     int         ret = NoError;
579     int         cur_mode = SEL_MODE_NONE;
580     ImsList     imsList;
581
582     DPR(("ximsSetMode(op=%d)\n", Opt.SelectMode));
583
584     OpState = State_Mode;
585
586     if ((ret = read_localeconf(&imsList, NULL)) != NoError) {
587         DPR(("ximsSetMode(%s) locale '%s' isn't supported\n", userEnv.locale));
588         /* return ErrNoLocaleConf; */
589     }
590
591     cur_mode = get_select_mode();
592     if (cur_mode != SEL_MODE_AUTO && cur_mode != SEL_MODE_NOAUTO)
593         cur_mode = imsList.def_selmode;
594
595     switch (Opt.SelectMode) {
596         case SEL_MODE_NONE:
597         case SEL_MODE_QUERY:    show_select_mode(cur_mode);
598                                 break;
599         case SEL_MODE_WIN:      start_mode_window(cur_mode);
600                                         /* never returned */
601                                 break;
602 #ifdef  SelectMode_ONCE
603         case SEL_MODE_ONCE:
604 #endif  /* SelectMode_ONCE */
605         case SEL_MODE_AUTO:
606         case SEL_MODE_NOAUTO:   ret = set_select_mode(cur_mode, Opt.SelectMode);
607                                 break;
608     }
609
610     OpErrCode = ret;
611     OpState = State_Mode_Done;
612     return ret;
613 }
614
615 static void     show_select_mode(int mode)
616 {
617     char        *valp;
618
619     printf("%s: \t", (catgets(catd,NL_SETN,20, "SelectMode")));
620
621     switch (mode) {
622         default:
623 #ifdef  DEBUG
624         case SEL_MODE_NONE:     valp = "<NOT DEFINED>"; /* break; */
625 #endif
626         case SEL_MODE_NOAUTO:
627             valp = (catgets(catd,NL_SETN,21, "ask_at_login"));
628             break;
629         case SEL_MODE_AUTO:
630             valp = (catgets(catd,NL_SETN,22, "resume_current_input_method"));
631             break;
632 #ifdef  SelectMode_ONCE
633         case SEL_MODE_ONCE:
634             valp = "auto-selection if once selected";
635             break;
636 #endif  /* SelectMode_ONCE */
637     }
638     puts(valp); fflush(stdout);
639
640     return;
641 }
642
643
644 static int      set_locale_env(char *locale)
645 {
646     char        *env_name, *env_value, *bp, *vp, buf[BUFSIZ], buf2[BUFSIZ];
647     static char *last_lang_env[2] = { NULL, NULL };
648
649     buf[0] = buf2[0] = 0;
650     env_name = "LANG";
651     env_value = getenv(env_name);
652     if (env_value)
653         snprintf(buf, sizeof(buf), "%s", env_value);
654     if (locale && *locale) {
655         if (!*buf || strcmp(locale, buf)) {
656             bp = strcpyx(buf, env_name); *bp++ = '=';
657             strcpyx(bp, locale);
658             putenv(bp = NEWSTR(buf));
659             FREE(last_lang_env[0]);
660             last_lang_env[0] = bp;
661         }
662     } else if (*buf)
663         locale = buf;
664     else
665         return ErrNoLocale;
666
667     env_name = "LC_ALL";
668     env_value = getenv(env_name);
669     if (env_value)
670         snprintf(buf2, sizeof(buf2), "%s", env_value);
671     if (!*buf2 || strcmp(locale, buf2)) {
672         bp = strcpyx(buf2, env_name); *bp++ = '=';
673         strcpyx(bp, locale);
674         putenv(bp = NEWSTR(buf2));
675         FREE(last_lang_env[1]);
676         last_lang_env[1] = bp;
677     }
678
679     setlocale(LC_ALL, locale);
680
681     /* set XFILESEARCHPATH */
682     vp = getenv(ENV_XFILESEARCHPATH);
683     bp = strcpyx(buf, ENV_XFILESEARCHPATH);
684     bp = strcpyx(bp, "=");
685     if (vp) {
686         bp = strcpyx(bp, vp);
687         bp = strcpyx(bp, ":");
688     }
689     bp = strcpyx(bp, ENV_XFILESEARCHPATH_STRING);
690     if(*buf) {
691         putenv(XtNewString(buf));
692     }
693
694     /* set NLSPATH */
695     vp = getenv(ENV_NLSPATH);
696     bp = strcpyx(buf, ENV_NLSPATH);
697     bp = strcpyx(bp, "=");
698     if (vp) {
699         bp = strcpyx(bp, vp);
700         bp = strcpyx(bp, ":");
701     }
702     bp = strcpyx(bp, ENV_NLSPATH_STRING);
703     /* BUG should this be putenv(bp) ? */
704     if(*buf) {
705         putenv(XtNewString(buf));
706     }
707
708 #ifdef  NLS
709     if (catd != (nl_catd) -1)   (void) catclose(catd);
710     catd = (nl_catd) -1;        (void) catclose(catd);
711
712     if (Verbose > 0) {
713         catd = catopen(DTIMS_PROGNAME, 0);
714     }
715 #endif  /* NLS */
716
717     return NoError;
718 }
719
720 static void     init_command(char *progname)
721 {
722         /* globals */
723     ProgramName = progname;
724     if (progname = strrchr(progname, '/'))
725         ProgramName = progname + 1;
726 #ifdef  unused
727     if (strstr(ProgramName, "mode"))            ProgramType = MODE_MODE;
728     else if (strstr(ProgramName, "list"))       ProgramType = MODE_LIST;
729     else if (strstr(ProgramName, "current"))    ProgramType = MODE_CURRENT;
730     else if (strstr(ProgramName, "conf"))       ProgramType = MODE_REMCONF;
731     else
732 #endif
733         ProgramType = MODE_START;
734
735     OpState = State_None;
736     OpMode = ProgramType;
737     OpFlag = FLAG_DEFAULT;
738     OpErrCode = NoError;
739     LogFp = stderr;
740     Wargc = 0;
741     Wargv = NULL;
742     WaitingDialogReply = False;
743     WaitingActionDone = False;
744     UseMsgWindow = True;
745     IsRemote = False;
746     LastErrMsg = NoError;
747     Verbose = 1;
748     DebugLvl = 0;
749
750     ximsErrArgs[0] = ximsErrArgs[1] = ximsErrArgs[2] = (void *) 0;
751     errFilePath[0] = 0;
752     errFuncName = NULL;
753
754     CLR(&Conf, CmdConf);
755     CLR(&Opt, CmdOpt);
756     CLR(&winEnv, WinEnv);
757     CLR(&userEnv, UserEnv);
758     CLR(&userSel, UserSelection);
759     localList = (ImsList *) 0;
760
761     return;
762 }
763
764
765 static bool     optname_match(char *name, char *str, int minlen)
766 {
767     int         nlen, slen;
768
769     if (strcmp(name, str) == 0)         return True;
770     nlen = strlen(name);
771     slen = strlen(str);
772     if (slen >= nlen || slen < minlen)  return False;
773     if (strncmp(name, str, slen) == 0)  return True;
774
775     return False;
776 }
777
778 static int      parse_options(int argc, char **argv)
779 {
780     char        *opt;
781     int         i, n;
782     int         wac = 1;
783     char        *wav[80];
784     int         orgMode;
785     static bool first_time = True;
786
787 #define SET_FLAG(f)     OpFlag |= (f)
788 #define CLR_FLAG(f)     OpFlag &= ~(f)
789 #define CHK_FLAG(f)     (OpFlag & (f))
790
791     if (first_time) {
792         argc--; argv++;
793
794             /* preset */
795         Opt.Listname = 0;
796         orgMode = OpMode;
797         if (orgMode == MODE_START)      SET_FLAG(FLAG_WINDOW);
798         Opt.SelectMode = SEL_MODE_NONE;
799     }
800
801     for (i = 0; i < argc; i++) {
802         opt = argv[i];
803         if (*opt++ != '-')      goto _inv_opt;
804
805             /* option for MODE */
806         if (optname_match("mode", opt, 2)) {
807             if (orgMode != MODE_START && orgMode != MODE_MODE)
808                 goto _inv_opt;
809             OpMode = MODE_MODE;
810 #if     0       /* not implemented yet */
811         } else if (optname_match("style", opt, 3)) {
812             if (orgMode != MODE_START && orgMode != MODE_MODE)
813                 goto _inv_opt;
814             OpMode = MODE_STYLE;
815 #endif
816         } else if (optname_match("listname", opt, 5)) {
817             if (orgMode != MODE_START && orgMode != MODE_LISTNAME)
818                 goto _inv_opt;
819             OpMode = MODE_LISTNAME;
820             Opt.Listname = 1;
821         } else if (optname_match("list", opt, 2)) {
822             if (orgMode != MODE_START && orgMode != MODE_LIST)
823                 goto _inv_opt;
824             OpMode = MODE_LIST;
825         } else if (optname_match("current", opt, 2)) {
826             if (orgMode != MODE_START && orgMode != MODE_CURRENT)
827                 goto _inv_opt;
828             OpMode = MODE_CURRENT;
829         } else if (optname_match("remoteconf", opt, 7)) {
830             if (orgMode != MODE_START && orgMode != MODE_REMCONF)
831                 goto _inv_opt;
832             OpMode = MODE_REMCONF;
833             SET_FLAG(FLAG_NOTIFY);
834
835             /* option for FLAG */
836         } else if (optname_match("nosave", opt, 4)) {
837             SET_FLAG(FLAG_NOSAVE);
838         } else if (optname_match("nostart", opt, 4)) {
839             SET_FLAG(FLAG_NOSTART);
840         } else if (optname_match("noenv", opt, 4)) {
841             CLR_FLAG(FLAG_ENV);
842         } else if (optname_match("envonly", opt, 4)) {
843             SET_FLAG(FLAG_NOSTART|FLAG_ENV);
844         } else if (optname_match("env", opt, 2)) {
845             SET_FLAG(FLAG_ENV);
846         } else if (optname_match("nowait", opt, 4)) {
847             SET_FLAG(FLAG_NOWAIT);
848         } else if (optname_match("notimeout", opt, 5)) {
849             SET_FLAG(FLAG_NOTIMEOUT);
850         } else if (optname_match("noresource", opt, 5)) {
851             SET_FLAG(FLAG_NORESOURCE);
852         } else if (optname_match("noremote", opt, 5)) {
853             SET_FLAG(FLAG_NOREMOTE);
854         } else if (optname_match("notify", opt, 5)) {
855             SET_FLAG(FLAG_NOTIFY);
856         } else if (optname_match("connect", opt, 4)) {
857             SET_FLAG(FLAG_CONNECT);
858         } else if (optname_match("dt", opt, 2)) {
859             SET_FLAG(FLAG_DT);
860 # ifdef old_hpux
861             CLR_FLAG(FLAG_VUE);
862         } else if (optname_match("vue", opt, 2)) {
863             SET_FLAG(FLAG_VUE);
864             CLR_FLAG(FLAG_DT);
865 # endif /* old_hpux */
866         } else if (optname_match("window", opt, 2)) {
867             SET_FLAG(FLAG_WINDOW);
868         } else if (optname_match("nowindow", opt, 4)) {
869             CLR_FLAG(FLAG_WINDOW);
870         } else if (optname_match("remoterun", opt, 7)) {
871             SET_FLAG(FLAG_REMOTERUN);
872             SET_FLAG(FLAG_NOTIFY);
873
874         } else if (optname_match("auto", opt, 2)) {
875             Opt.SelectMode = SEL_MODE_AUTO;
876         } else if (optname_match("noauto", opt, 3)) {
877             Opt.SelectMode = SEL_MODE_NOAUTO;
878 #ifdef  SelectMode_ONCE
879         } else if (optname_match("once", opt, 3)) {
880             Opt.SelectMode = SEL_MODE_ONCE;
881 #endif  /* SelectMode_ONCE */
882
883             /* help, verbose & debug options */
884         } else if (optname_match("help", opt, 1)) {
885             if (first_time)
886                 do_usage = True;
887         } else if (optname_match("quiet", opt, 1)) {
888             Verbose = DebugLvl = 0;
889         } else if (optname_match("verbose", opt, 1)) {
890             Verbose++;
891         } else if (optname_match("debug", opt, 2)) {
892             Verbose++; DebugLvl++;
893
894         } else if (i >= argc - 1 || !*(argv[i+1])) {
895             goto _inv_opt;      /* the rest options need an argument */
896
897             /* options with an argument */
898         } else if (optname_match("imsoption", opt, 4)) {
899             i++;
900             Opt.ImsOption = argv[i];
901         } else if (optname_match("ims", opt, 2)) {
902             i++;
903             Opt.ImsName = argv[i];
904         } else if (optname_match("display", opt, 2)) {
905             i++;
906             Opt.DisplayName = argv[i];
907             wav[wac++] = argv[i - 1]; wav[wac++] = argv[i];     /* ??? */
908         } else if (optname_match("locale", opt, 2)) {
909             i++;
910             Opt.LocaleName = argv[i];
911         } else if (optname_match("CDE_locale", opt, 2)) {
912             i++;
913             Opt.LocaleName = find_system_locale_name(argv[i]);
914         } else if (optname_match("hostname", opt, 2)) {
915             i++;
916             Opt.HostName = argv[i];
917         } else if (optname_match("config", opt, 2)) {
918             i++;
919             Opt.ConfPath = argv[i];
920         } else if (optname_match("file", opt, 2)) {
921             i++;
922             Opt.UserPath = argv[i];
923         } else if (optname_match("log", opt, 2)) {
924             i++;
925             Opt.LogPath = argv[i];
926         } else if (optname_match("resource", opt, 3)) {
927             i++;
928             Opt.ResourceFile = argv[i];
929         } else if (optname_match("shell", opt, 2)) {
930             i++;
931             Opt.ShellName = argv[i];
932         } else if (optname_match("timeout", opt, 3)) {
933             i++;
934             if (str_to_int(argv[i], &n) && n >= 0)
935                 Opt.Timeout = n;
936         } else if (optname_match("interval", opt, 3)) {
937             i++;
938             if (str_to_int(argv[i], &n) && n >= 0)
939                 Opt.Interval = n;
940
941             /* Xt options */
942         } else if (optname_match("font", opt, 2)
943                 || optname_match("fn", opt, 2)
944                 || optname_match("fg", opt, 2)
945                 || optname_match("bg", opt, 2)
946                 || optname_match("bd", opt, 2)
947                 || optname_match("foreground", opt, 4)
948                 || optname_match("backgroundg", opt, 4)
949                 || optname_match("bordercolor", opt, 4)
950                 || optname_match("geometry", opt, 2)
951                 || optname_match("title", opt, 2)
952                 || optname_match("xnlLanguage", opt, 3)
953                 /* || optname_match("iconic", opt, 4) */
954                 || optname_match("xrm", opt, 2)) {
955             i++;
956             wav[wac++] = argv[i - 1]; wav[wac++] = argv[i];
957
958         } else
959             goto _inv_opt;
960     }
961     first_time = False;
962
963     if (do_usage)       return NoError;
964
965     switch (OpMode) {           /* adjust OpFlag */
966 #if     0       /* noy implemented yet */
967         case MODE_STYLE:
968             SET_FLAG(FLAG_DT | FLAG_WINDOW);
969             CLR_FLAG(FLAG_VUE);
970             break;
971 #endif
972
973         case MODE_START:
974             if (Opt.ImsName) {
975                 SET_FLAG(FLAG_NOSAVE);
976                 /* CLR_FLAG(USE_WINDOW_MASK); */
977                 Opt.SelectMode = SEL_MODE_GIVEN;
978             }
979             if (Opt.LogPath) {  /* open log file */
980                 if (set_errorlog(Opt.LogPath) != NoError)
981                     Opt.LogPath = NULL;
982             }
983             if (CHK_FLAG(FLAG_REMOTERUN)) {
984                 SET_FLAG(FLAG_NOTIFY);
985                 SET_FLAG(FLAG_NOSAVE);
986                 CLR_FLAG(USE_WINDOW_MASK);
987             }
988             break;
989
990         case MODE_MODE:
991             if (CHK_FLAG(FLAG_WINDOW)) {
992                 Opt.SelectMode = SEL_MODE_WIN;
993             } else if (Opt.SelectMode == SEL_MODE_NONE) {
994                 Opt.SelectMode = SEL_MODE_QUERY;
995                 CLR_FLAG(USE_WINDOW_MASK);
996             }
997             break;
998
999         case MODE_LISTNAME:
1000             SET_FLAG(FLAG_WINDOW);
1001             break;
1002
1003         default:
1004             CLR_FLAG(USE_WINDOW_MASK);
1005             break;
1006     }
1007
1008     if (CHK_FLAG(USE_WINDOW_MASK)) {
1009             /* create argc & argv for window */
1010         Wargv = ALLOC(wac + 1 + 4, char *);     /* spare for '-xnlLanguage' */
1011         memcpy(Wargv, wav, sizeof(char *) * wac);
1012         Wargv[0] = ProgramName;
1013         Wargv[wac] = NULL;
1014         Wargc = wac;
1015     } else {
1016         UseMsgWindow = False;           /* disable msg window */
1017     }
1018
1019 #undef  CLR_FLAG
1020 #undef  SET_FLAG
1021 #undef  CHK_FLAG
1022
1023     return NoError;
1024
1025 _inv_opt:
1026     DPR(("%s: invalid option '%s'\n", ProgramName,  argv[i]));
1027     setErrArg1(argv[i]);
1028
1029     return ErrSyntax;
1030 }
1031
1032
1033         /* ********  usage  ******** */
1034
1035 #ifdef  DEBUG
1036 typedef struct {
1037     char        *name;
1038     char        *desc;
1039 } OptDesc;
1040
1041 #if     0
1042 static OptDesc  opts_start[] = {
1043     { "-env",   "print modified environment variables" },
1044     { "-shell <name>",  "override $SHELL" },
1045     { "-ims <name>",    "specifies input method name" },
1046     { "-imsopt <string>",       "specifies command options for input method server" },
1047     { "-host <name>",   "specifies host where input method server should be run" },
1048     { "-mode",  "change input method selection mode" },
1049     { "-list",  "show registered input method" },
1050     { "-help",  "show this message" },
1051     { NULL, NULL }
1052 };
1053
1054 static OptDesc  opts_mode[] = {
1055     { "-auto",          "enable auto-selection mode" },
1056     { "-noauto",        "disable auto-selection mode" },
1057     { NULL, NULL }
1058 };
1059 #endif
1060
1061 static OptDesc  opts_internal[] = {
1062     { "-display <dpy>", "override $DISPLAY" },
1063     { "-current",       "show selected input method" },
1064     { "-listname",      "show registered input method for dtstyle" },
1065     { "-remoteconf",    "print IMS configuration data for remote execution" },
1066     { "-remoterun",     "start IMS as remote execution" },
1067     { "-nosave",        "not save the selection" },
1068     { "-select",        "force select" },
1069     { "-noenv",         "disable printing environment variables" },
1070     { "-envonly",       "-noenv & -nostart" },
1071     { "-nostart",       "not start IMS" },
1072     { "-noresouce",     "not load session resource files" },
1073     { "-nowait",        "immediately exits after IMS invocation" },
1074     { "-notimeout",     "do not timeout" },
1075     { "-noremote",      "disable remote execution" },
1076     { "-notify",        "print error code to stderr" },
1077 # ifdef old_hpux
1078     { "-vue",           "in VUE environment" },
1079     { "-connect",       "enable try_connect" },
1080 # endif /* old_hpux */
1081 #ifdef  SelectMode_ONCE
1082     { "-once",          "auto-selection once selected" },
1083 #endif  /* SelectMode_ONCE */
1084     { "-dt"     ,       "in CDE environment" },
1085     { "-window",        "use window environment" },
1086     { "-nowindow",      "do not use window environment" },
1087     { "-timeout  <num>",           "specifies timeout period (sec.)" },
1088     { "-interval <num>",           "specifies check interval (msec.)" },
1089     { "-locale  <locale>",         "override $LANG" },
1090     { "-CDE_locale  <CDE_locale>", "CDE generic locale name" },
1091     { "-resource  <file>",         "specifies resource file" },
1092     { "-config <file>", "specifies configuration file" },
1093     { "-file <file>",   "specifies user selection file" },
1094     { "-log <file>",    "specifies log file" },
1095     { "-fn <fontlist>", "specifies font" },
1096     { "-quiet",         "print no messages" },
1097     { "-verbose",       "print verbose messages" },
1098     { "-debug",         "print debug messages" },
1099     { "<Xt options>",   "standard X toolkit options" },
1100     { NULL, NULL }
1101 };
1102 #endif  /* DEBUG */
1103
1104 static void     usage(int force)
1105 {
1106     char        *fmt = "\t%-20s%s\n";
1107
1108     if (!force && Verbose <= 0) return;
1109
1110     fprintf(LogFp, (catgets(catd,NL_SETN,1, "usage:  %s  [options ..]")),
1111                                                             ProgramName);
1112     putc('\n', LogFp);
1113
1114     if (OpMode != MODE_MODE) {
1115         fprintf(LogFp, fmt,
1116             "-env", (catgets(catd,NL_SETN,2, "print modified environment variables")));
1117         fprintf(LogFp, fmt,
1118             "-shell <name>", (catgets(catd,NL_SETN,3, "override $SHELL")));
1119         fprintf(LogFp, fmt,
1120             "-ims <name>", (catgets(catd,NL_SETN,4, "specifies input method name")));
1121         fprintf(LogFp, fmt,
1122             "-imsopt <string>", (catgets(catd,NL_SETN,5, "specifies command options for input method server")));
1123         fprintf(LogFp, fmt,
1124             "-host <name>", (catgets(catd,NL_SETN,6, "specifies host where input method server should be run")));
1125         fprintf(LogFp, fmt,
1126             "-mode", (catgets(catd,NL_SETN,7, "change input method selection mode")));
1127         fprintf(LogFp, fmt,
1128             "-list", (catgets(catd,NL_SETN,8, "print registered input method")));
1129         fprintf(LogFp, fmt,
1130             "-help", (catgets(catd,NL_SETN,9, "show this message")));
1131     } else {
1132         fprintf(LogFp, fmt,
1133             "-auto", (catgets(catd,NL_SETN,23, "force 'resume_current_input_method' mode")));
1134         fprintf(LogFp, fmt,
1135             "-noauto", (catgets(catd,NL_SETN,24, "force 'ask_at_login' mode")));
1136     }
1137
1138 #ifdef  DEBUG
1139     if (Verbose > 1) {
1140         OptDesc *opts;
1141         fprintf(LogFp, "\n    <internal options>\n");
1142         for (opts = opts_internal; opts->name; opts++)
1143             fprintf(LogFp, fmt, opts->name, opts->desc);
1144     }
1145 #endif
1146
1147 }
1148
1149
1150         /* ********  error messages  ******** */
1151
1152 char    *xims_errmsg(int err_num, void *arg1, void *arg2, void *arg3)
1153 {
1154     char        *fmt = NULL, *bp;
1155     int         len;
1156     static char msgbuf[BUFSIZ];
1157
1158     switch (err_num) {
1159         case NoError:
1160                 break;
1161         case ErrSyntax:         /* arg1: option string */
1162                 fmt = (catgets(catd,NL_SETN,31, "invalid option '%s'"));
1163                 break;
1164         case ErrNoHome:
1165                 fmt = (catgets(catd,NL_SETN,32, "environment variable 'HOME' not defined"));
1166                 break;
1167         case ErrNoLocale:
1168                 fmt = (catgets(catd,NL_SETN,33, "environment variable 'LANG' not defined"));
1169                 break;
1170         case ErrNoCDELocale:
1171                 fmt = (catgets(catd,NL_SETN,34, "this locale is not supported by the desktop."));
1172                 break;
1173         case ErrNoDisplay:
1174                 fmt = (catgets(catd,NL_SETN,35, "environment variable 'DISPLAY' not defined"));
1175                 break;
1176
1177         case ErrFileOpen:       /* arg1: file name */
1178                 fmt = (catgets(catd,NL_SETN,36, "cannot open file\n  [%s]"));
1179                 setErrArg1(errFilePath);
1180                 break;
1181         case ErrFileCreate:     /* arg1: file name */
1182                 fmt = (catgets(catd,NL_SETN,37, "cannot create file\n  [%s]"));
1183                 setErrArg1(errFilePath);
1184                 break;
1185         case ErrDirCreate:      /* arg1: dir name */
1186                 fmt = (catgets(catd,NL_SETN,38, "cannot create directory\n  [%s]"));
1187                 setErrArg1(errFilePath);
1188                 break;
1189         case ErrMissEntry:      /* arg1: entry name, arg2: file name */
1190                 fmt = (catgets(catd,NL_SETN,39, "missing '%s' entry in configuration file\n  [%s]"));
1191                 setErrArg2(errFilePath);
1192                 break;
1193
1194         case ErrAnotherProg:
1195                 fmt = (catgets(catd,NL_SETN,40, "another '%s' is already running"));
1196                 setErrArg1(ProgramName);
1197                 break;
1198         case ErrNoSelectionFile:        /* arg1: locale name */
1199                 fmt = (catgets(catd,NL_SETN,41, "no selection file for '%s'"));
1200                 setErrArg1(userEnv.locale);
1201                 break;
1202         case ErrSaveSelection:  /* arg1: file name */
1203                 fmt = (catgets(catd,NL_SETN,42, "cannot create selection file\n  [%s]"));
1204                 setErrArg1(errFilePath);
1205                 break;
1206         case ErrNoSelection:    /* arg1: locale name */
1207                 fmt = (catgets(catd,NL_SETN,43, "no ims selected for '%s'"));
1208                 setErrArg1(userEnv.locale);
1209                 break;
1210         case ErrNoLocaleConf:   /* arg1: file name */
1211                 fmt = (catgets(catd,NL_SETN,44, "no locale configuration file for '%s'"));
1212                 setErrArg1(userEnv.locale);
1213                 break;
1214         case ErrNoImsEntry:     /* arg1: locale name */
1215                 fmt = (catgets(catd,NL_SETN,45, "no ims configured for '%s'"));
1216                 setErrArg1(userEnv.locale);
1217                 break;
1218         case ErrNoImsConf:      /* arg1: ims name */
1219                 fmt = (catgets(catd,NL_SETN,46, "no ims configuration file for '%s'"));
1220                 setErrArg1(userSel.name);
1221                 break;
1222         case ErrNotRegistered:  /* arg1: ims name */
1223                 fmt = (catgets(catd,NL_SETN,47, "ims '%s' not registered"));
1224                 setErrArg1(userSel.name);
1225                 break;
1226         case ErrNoExecutable:   /* arg1: ims name, arg2: file name */
1227                 fmt = (catgets(catd,NL_SETN,48, "no executable file for '%s'\n  [%s]"));
1228                 setErrArg1(userSel.name);
1229                 setErrArg2(userSel.ent->ims->cmd_path);
1230                 break;
1231
1232         case ErrImsRunning:     /* arg1: ims name */
1233                 fmt = (catgets(catd,NL_SETN,49, "ims '%s' is already running"));
1234                 setErrArg1(userSel.name);
1235                 break;
1236         case ErrImsExecution:   /* arg1: ims name */
1237                 fmt = (catgets(catd,NL_SETN,50, "cannot execute ims '%s'"));
1238                 setErrArg1(userSel.name);
1239                 break;
1240         case ErrImsAborted:     /* arg1: ims name, arg2: log file */
1241                 fmt = (catgets(catd,NL_SETN,51, "ims '%s' aborted.  See log file.\n  [%s]"));
1242                 setErrArg1(userSel.name);
1243                 if (userSel.host_type == HOST_REMOTE)
1244                     setErrArg2(errFilePath);
1245                 else
1246                     setErrArg2(Opt.LogPath);
1247                 break;
1248         case ErrImsTimeout:     /* arg1: file name */
1249                 fmt = (catgets(catd,NL_SETN,52, "ims '%s' is not available yet"));
1250                 setErrArg1(userSel.name);
1251                 break;
1252
1253         case ErrUnknownHost:    /* arg1: host name */
1254                 fmt = (catgets(catd,NL_SETN,53, "unknown host '%s'"));
1255                 setErrArg1(userSel.hostname);
1256                 break;
1257         case ErrRemoteAction:   /* arg1: action name */
1258                 fmt = (catgets(catd,NL_SETN,54, "action '%s' failed"));
1259                 setErrArg1(errFuncName);
1260                 break;
1261         case ErrRemoteData:     /* arg1: host name */
1262                 fmt = (catgets(catd,NL_SETN,55, "remote execution failed on '%s'"));
1263                 setErrArg1(userSel.hostname);
1264                 break;
1265         case ErrNoImsstart:     /* arg1: host name */
1266                 fmt = (catgets(catd,NL_SETN,56, "remote functionality is not available on '%s'"));
1267                 setErrArg1(userSel.hostname);
1268                 break;
1269         case ErrRemoteNoIms:    /* arg1: host name */
1270                 fmt = (catgets(catd,NL_SETN,57, "no ims registered on '%s'"));
1271                 setErrArg1(userSel.hostname);
1272                 break;
1273         case ErrRemoteMissIms:  /* arg1: ims name, arg2: host name */
1274                 fmt = (catgets(catd,NL_SETN,58, "ims '%1$s' not registered on '%2$s'"));
1275                 setErrArg1(userSel.name);
1276                 setErrArg2(userSel.hostname);
1277                 break;
1278
1279         case ErrOpenDpy:        /* arg1: display name */
1280                 fmt = (catgets(catd,NL_SETN,59, "cannot open display '%s'"));
1281                 setErrArg1(userEnv.displayname);
1282                 break;
1283
1284 #ifdef  DEBUG
1285         case ErrSignaled:       /* arg1: signal number */
1286                 fmt = "terminated by signal (signal=%d)";
1287                 setErrArg1(exitSignalNumber);
1288                 break;
1289         case ErrDisabled:       /* arg1: program name, arg2: env name */
1290                 fmt = "ximsstart is disabled ('%s' is set)";
1291                 setErrArg1(ENV_NO_DTIMSSTART);
1292                 break;
1293         case ErrRemoteIms:      /* arg1: ims name, arg2: host name */
1294                 fmt = "cannot execute ims '%s' on '%s'";
1295                 setErrArg1(userSel.name);
1296                 setErrArg2(userSel.hostname);
1297                 break;
1298         case ErrOpenResource:   /* arg1: file name */
1299                 fmt = "cannot open resource file\n  [%s]";
1300                 setErrArg1(Opt.ResourceFile);
1301                 break;
1302         case ErrMemory:         /* arg1: function name */
1303                 fmt = "cannot allocate memory in %s()";
1304                 setErrArg1(errFuncName);
1305                 break;
1306
1307         case ErrIsNone:         /* arg1: ims name */
1308                 fmt = "the selected ims is '%s'";
1309                 setErrArg1(userSel.name);
1310                 break;
1311         case ErrNotRun:         /* arg1: ims name */
1312                 fmt = "the selected ims '%s' need not to run";
1313                 setErrArg1(userSel.name);
1314                 break;
1315         case ErrImsWaiting:     /* arg1: ims name */
1316                 fmt = "internal error [ImsWaiting] (ims='%s')";
1317                 setErrArg1(userSel.name);
1318                 break;
1319         case ErrImsWaitDone:    /* arg1: ims name */
1320                 fmt = "internal error [ImsWaitDone] (ims='%s')";
1321                 setErrArg1(userSel.name);
1322                 break;
1323         case ErrImsConnecting:  /* arg1: ims name */
1324                 fmt = "internal error [ImsConnecting] (ims='%s')";
1325                 setErrArg1(userSel.name);
1326                 break;
1327         case ErrImsConnectDone: /* arg1: ims name */
1328                 fmt = "internal error [ImsConnectDone] (ims='%s')";
1329                 setErrArg1(userSel.name);
1330                 break;
1331         case ErrInvState:       /* arg1: OpStateVal */
1332                 fmt = "internal error [invalid state: '%d']";
1333                 setErrArg1(OpState);
1334                 break;
1335         case ErrInternal:       /* arg1: function name */
1336                 fmt = "internal error in %s()";
1337                 setErrArg1(errFuncName);
1338                 break;
1339 #endif  /* DEBUG */
1340     }
1341
1342     if (!fmt)   return NULL;
1343
1344     bp = strcpyx(msgbuf, ProgramName); *bp++ = ':'; *bp++ = ' ';
1345     if (!arg1)  arg1 = ximsErrArgs[0];
1346     if (!arg2)  arg2 = ximsErrArgs[1];
1347     if (!arg3)  arg3 = ximsErrArgs[2];
1348     sprintf(bp, fmt, arg1, arg2, arg3);
1349     len = strlen(bp);
1350     bp[len++] = '\n'; bp[len] = '\0';
1351
1352     return msgbuf;
1353 }
1354