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