Link with C++ linker
[oweals/cde.git] / cde / programs / dtimsstart / util.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: util.c /main/6 1996/07/12 15:44:21 pascale $ */
24
25 #include <DtHelp/LocaleXlate.h>  /* for locale equivalence between platforms */
26 #include "xims.h"
27 #include <sys/stat.h>
28
29
30         /* ********  locale name manupilation  ******** */
31
32 int find_CDE_locale_name()
33 {
34     UserEnv   *uenv = &userEnv;
35    _DtXlateDb db = NULL;
36    int        ret = NoError;
37    char       plat[_DtPLATFORM_MAX_LEN];
38    int        execver;
39    int        compver;
40    static bool first = True;
41    
42    if (first) {
43
44        uenv->CDE_locale = NULL;
45
46        ret = _DtLcxOpenAllDbs(&db);
47
48        if (ret == NoError)
49            ret = _DtXlateGetXlateEnv(db, plat, &execver, &compver);
50
51        if (ret == NoError)
52            ret = _DtLcxXlateOpToStd(db, plat, compver, DtLCX_OPER_SETLOCALE,
53                                     uenv->locale, &uenv->CDE_locale,
54                                     NULL, NULL, NULL);
55        if (ret == NoError)
56            ret = _DtLcxCloseDb(&db);
57
58        first = False;
59    }
60    return ret;
61 }
62
63 char *find_system_locale_name(CDE_locale)
64     char *CDE_locale;
65 {
66    _DtXlateDb db = NULL;
67    int        ret = NoError;
68    char       plat[_DtPLATFORM_MAX_LEN];
69    int        execver;
70    int        compver;
71    char       *locale = NULL;
72
73    ret = _DtLcxOpenAllDbs(&db);
74
75    if (ret == NoError)
76        ret = _DtXlateGetXlateEnv(db, plat, &execver, &compver);
77
78    if (ret == NoError)
79        ret = _DtLcxXlateStdToOp(db, plat, compver, DtLCX_OPER_SETLOCALE,
80                                     CDE_locale, NULL, NULL, NULL,
81                                     &locale);
82    if (ret == NoError)
83        ret = _DtLcxCloseDb(&db);
84
85    if (ret == NoError)
86        return (locale);
87    else
88        return (NULL);
89 }
90
91
92
93         /* ********  string manupilation  ******** */
94
95 char    *strcpyx(dest, src)
96     register char       *dest, *src;
97 {
98     while (*dest++ = *src++) ;
99     return(--dest);
100 }
101
102 #ifdef  unused
103 char    *strcpy2(dest, src1, src2)
104     register char       *dest, *src1, *src2;
105 {
106     while (*dest++ = *src1++) ;
107     --dest;
108     while (*dest++ = *src2++) ;
109     return(--dest);
110 }
111
112 char    *newstradded(src1, src2, src3)
113     register char       *src1, *src2, *src3;
114 {
115     register char       *p;
116     char        *dest;
117
118     dest = p = ALLOC(strlen(src1) + strlen(src2) + strlen(src3) + 1, char);
119     if (src1)   { while (*p++ = *src1++) ; p--; }
120     if (src2)   { while (*p++ = *src2++) ; p--; }
121     if (src3)   { while (*p++ = *src3++) ; }
122     return(dest);
123 }
124 #endif  /* unused */
125
126
127 int     str_to_int(ptr, val)
128     char *ptr;
129     int *val;
130 {
131     int base;
132     char *pp;
133
134     /* if (!ptr || !*ptr || !val)       return(False); */
135     *val = 0;
136     base = ptr[0] == '0' ? (((ptr[1] & 0xdf) == 'X') ? 16 : 8) : 10;
137     *val = strtol(ptr, &pp, base);
138     if (!pp || *pp)     return(False);
139     return(True);
140 }
141
142 bool    str_to_bool(ptr, def_val)
143     char        *ptr;
144     bool        def_val;
145 {
146     if (!ptr || !*ptr)  return def_val;
147     skip_white(ptr);
148
149     switch (*ptr) {             /* true/false , 0/1 , yes/no , on/off */
150         case '1':
151         case 'T': case 't':
152         case 'Y': case 'y':
153                 def_val = True; break;
154
155         case '0':
156         case 'F': case 'f':
157         case 'N': case 'n':
158                 def_val = False; break;
159
160         case 'O': case 'o':
161                 if (ptr[1] == 'N' || ptr[1] == 'n')
162                     def_val = True;
163                 else if (ptr[1] == 'F' || ptr[1] == 'f')
164                     def_val = False;
165                 break;
166     }
167     return def_val;
168 }
169
170 char    *trim_line(ptr)
171     char        *ptr;
172 {
173     register char       *lastp;
174
175     skip_white(ptr);
176     for (lastp = ptr + strlen(ptr) - 1;
177         lastp >= ptr && (is_white(*lastp) || *lastp == '\n'); lastp--) ;
178     *(lastp + 1) = 0;
179     return ptr;         /* return lastp > ptr ? ptr : NULL; */
180 }
181
182 char    **parse_strlist(ptr, sep_ch)
183     register char       *ptr;
184     char        sep_ch;
185 {
186     char        *pbuf[100], **new, **bp;
187     char        *sep, *p;
188     int         n;
189     char        *save_ptr;
190
191     if (!ptr || !*ptr)  return (char **)0;
192     ptr = save_ptr = NEWSTR(ptr);
193
194     if (!sep_ch)        sep_ch = ',';
195     bp = pbuf; pbuf[0] = NULL;
196     new = (char **) 0;
197     while (ptr) {
198         if (sep = strchr(ptr, sep_ch))  *sep++ = 0;
199         p = trim_line(ptr);
200         if (*p) {
201             *bp++ = NEWSTR(p);
202             if (bp - pbuf >= 100)       sep = NULL;     /* over-flow */
203         }
204         ptr = sep;
205     }
206     n = bp - pbuf;
207     if (n > 0) {
208         new = ALLOC(n + 1, char *);
209         memcpy((void *) new, (void *)pbuf, n * sizeof(char *));
210         new[n] = NULL;
211     }
212     FREE(save_ptr);
213
214     return new;
215 }
216
217 #ifdef  unused
218 int     pack_strlist(ptr, listp, sep_ch)
219     char        *ptr, **listp;
220     char        sep_ch;
221 {
222     register char       *bp = ptr, **lp = listp;
223
224     /* if (!ptr)        return 0; */
225     if (!lp || !*lp) {
226         *ptr = 0;
227         return 0;
228     }
229     if (!sep_ch)        sep_ch = ',';
230
231     for (bp; *lp; lp++) {
232         bp = strcpyx(bp, *lp);
233         *bp++ = sep_ch;
234     }
235
236     DPR2(("pack_strlist(): ptr='%s'\n", ptr));
237
238     return bp - ptr;
239 }
240 #endif  /* unused */
241
242 void    free_strlist(pp)
243     char        **pp;
244 {
245     register char       **ptr = pp;
246
247     if (!ptr)   return;
248     for ( ; *ptr; ptr++)        FREE(*ptr);
249     FREE(pp);
250 }
251
252
253         /* ********  display string  ******** */
254
255 bool    parse_dpy_str(display_str, host, dnum, snum, dnet)
256     char        *display_str, **host;
257     int         *dnum, *snum, *dnet;
258 {
259     char        buf[BUFSIZ], hostbuf[BUFSIZ], *p, *hp, *pdnum, *psnum;
260     int         isdnet = 0;
261
262     strcpy(buf, display_str);
263
264         /* extract host name */
265     if (!(p = strchr(buf, ':')))        return False;
266     *p++ = 0;
267     if (*p == ':') {    /* DECnet ? */
268         *p++ = 0;
269         isdnet = 1;
270     }
271     pdnum = p;
272     hp = buf;
273     if (!*hp || strcmp(hp, "unix") == 0 || strcmp(hp, "local") == 0) {
274         gethostname(hostbuf, BUFSIZ);
275         hp = hostbuf;
276     }
277     if (p = strchr(hp, '.'))    *p = 0;
278
279         /* extract display number */
280     for (p = pdnum; *p && isdigit(*p); p++) ;
281     if (p == pdnum || (*p && *p != '.'))
282         return False;
283
284     psnum = NULL;
285     if (*p) {   /* extract screen number */
286         *p++ = 0;       /* must be '.' */
287         for (psnum = p; *p && isdigit(*p); p++) ;
288         if (p == psnum || *p)   psnum = NULL;
289         *p++ = 0;
290     }
291
292     if (dnum)   *dnum = atoi(pdnum);
293     if (snum)   *snum = psnum ? atoi(psnum) : 0;
294     if (dnet)   *dnet = isdnet ? 1 : 0;
295     if (host)   *host = NEWSTR(hp);
296
297     DPR3(("parse_dpy_str(%s):\thost=%s dnum=%d snum=%d dnet=%d\n",
298                                 display_str, *host, *dnum, *snum, *dnet));
299
300     return True;
301 }
302
303 char    *std_dpy_str(display_str, snum)
304     char        *display_str;
305     int         *snum;
306 {
307     char        buf[BUFSIZ], *bp, val[20];
308     char        *host = NULL;
309     int         dnum = 0, dnet = 0;
310
311     if (snum)   *snum = 0;
312     if (parse_dpy_str(display_str, &host, &dnum, snum, &dnet) == False)
313         return NULL;
314
315     /* sprintf(buf, "%s:%s%d", host, dnet ? ":" : NULL, dnum); */
316     bp = buf; buf[0] = 0;
317     bp = strcpyx(bp, host); *bp++ = ':';
318     if (dnet)   *bp++ = ':';
319     sprintf(val, "%ld", (long) dnum);
320     bp = strcpyx(bp, val);
321
322     DPR3(("std_dpy_str(): \"%s\" --> \"%s\"  snum=%d\n",
323                                         display_str, buf, *snum));
324
325     FREE(host);
326     return NEWSTR(buf);
327 }
328
329
330         /* ********  file & dir manipulation  ******** */
331
332 int     make_user_dir(path)
333     char        *path;
334 {
335     if (!is_directory(path, False)) {
336         if (access(path, F_OK) == 0)
337             return False;
338         if (mkdir(path, 0777) != 0)
339             return False;
340         DPR(("make_user_dir(%s): created\n", path));
341     }
342     return True;
343 }
344
345 char    *dirname(path)
346     char        *path;
347 {
348     static char dname[MAXPATHLEN];
349     register char       *p = path;
350     int         dlen;
351
352     /* if (!p || !p[0])         return NULL; */
353
354     for (p = path + strlen(path) - 1; p > path && *p == '/'; p--) ;
355     dlen = p - path + 1;
356     memcpy(dname, path, dlen);
357     dname[dlen] = 0;
358
359     if (p = strrchr(dname, '/')) {
360         if (p == dname)
361             dname[1] = 0;
362         else {
363             *p = 0;
364             for ( ; p > dname && *p == '/'; p--) *p = 0;
365         }
366     } else
367         strcpy(dname, ".");
368
369     return dname;
370
371 }
372
373 int     is_directory(path, must_writable)
374     char        *path;
375     int         must_writable;
376 {
377     struct stat stb;
378     int         mode = R_OK|X_OK;
379
380     if (must_writable)  mode |= W_OK;
381     return stat(path, &stb) == 0 && S_ISDIR(stb.st_mode)
382                 && access(path, mode) == 0;
383 }
384
385 #ifdef  unused
386 int     is_regularfile(path)
387     char        *path;
388 {
389     struct stat stb;
390     return stat(path, &stb) == 0 && S_ISREG(stb.st_mode);
391 }
392
393 int     is_emptyfile(path)
394     char        *path;
395 {
396     struct stat stb;
397     return stat(path, &stb) == 0 && S_ISREG(stb.st_mode) && stb.st_size == 0;
398 }
399 #endif  /* unused */
400
401
402 int     is_executable(path)
403     char        *path;
404 {
405     struct stat stb;
406     return stat(path, &stb) == 0 && S_ISREG(stb.st_mode)
407                 && access(path, R_OK|X_OK) == 0;
408 }
409
410 #ifdef  unused
411 int     is_writable(path)
412     char        *path;
413 {
414     if (access(path, R_OK|W_OK) == 0)
415         return True;
416     else if (errno == ENOENT)           /* check directory permission */
417         return is_directory(dirname(path), True);
418     else
419         return False;
420 }
421 #endif  /* unused */
422
423 int     is_readable(path, allow_empty)
424     char        *path;
425     int         allow_empty;
426 {
427     struct stat stb;
428     return stat(path, &stb) == 0 && S_ISREG(stb.st_mode)
429         && access(path, R_OK) == 0 && (allow_empty || stb.st_size > 0);
430 }
431
432
433         /* ********  file reading  ******** */
434
435 static int      tag_line_num = 0;
436 static char     *tag_linebuf = NULL;
437 static char     *tag_file = NULL;
438
439 int     start_tag_line(fname)
440     char        *fname;
441 {
442     if (fname) {
443         if (!tag_linebuf)
444             tag_linebuf = ALLOC(BUFSIZ, char);
445         tag_linebuf[0] = 0;
446         tag_file = fname;
447     } else {
448         if (tag_linebuf)        FREE(tag_linebuf);
449         tag_linebuf = tag_file = 0;
450     }
451     tag_line_num = 0;
452     return True;
453 }
454
455 int     read_tag_line(fp, tagp, valp)
456     FILE        *fp;
457     char        **tagp, **valp;
458 {
459     char        *lp, *lp2;
460
461     while (fgets(lp = tag_linebuf, BUFSIZ, fp)) {
462         tag_line_num++;
463         skip_white(lp);         /* lp = trim_line(lp); */
464         if (!*lp || *lp == '\n' || is_comment_char(*lp))
465             continue;
466         if (!(lp2 = strchr(lp, TAG_END_CHAR))) {
467             DPR3(("\t[line=%d] no tag on '%s'\n", tag_line_num, tag_file));
468             continue;
469         }
470         *lp2++ = 0;
471         lp2 = trim_line(lp2);
472
473         *tagp = lp;
474         *valp = *lp2 ? lp2 : 0;
475         return tag_line_num;
476     }
477     *tagp = *valp = 0;
478
479     return (ferror(fp)) ? -1 : 0;
480 }
481
482
483         /* ********  put messages  ******** */
484
485 void    put_xims_msg(msg_type, err_num, arg1, arg2, arg3)
486     int         msg_type, err_num;
487     void        *arg1, *arg2, *arg3;
488 {
489     int         ret = -2;
490     char        *msg;
491
492     msg = xims_errmsg(err_num, arg1, arg2, arg3);
493
494 #if     0
495     {   static char     buf[80];
496         sprintf(buf, "ERROR: %s (%d)\n", error_name(err_num), err_num);
497         msg = buf;
498     }
499 #endif
500
501     if (!msg || !*msg)  return;
502
503     if (UseMsgWindow && useWINDOW()) {
504         ret = put_msg_win(msg_type, msg);
505     }
506
507     if (ret < 0) {
508         fputs(msg, LogFp);
509     }
510
511     LastErrMsg = err_num;
512
513     return;
514 }
515
516 void    put_xims_errmsg(err_num, arg1, arg2, arg3)
517     int         err_num;
518     void        *arg1, *arg2, *arg3;
519 {
520     if (Verbose > 0)
521         put_xims_msg(MSGTYP_FATAL, err_num, arg1, arg2, arg3);
522 }
523
524 void    put_xims_warnmsg(err_num, arg1, arg2, arg3)
525     int         err_num;
526     void        *arg1, *arg2, *arg3;
527 {
528     if (Verbose > 0)
529         put_xims_msg(MSGTYP_WARN, err_num, arg1, arg2, arg3);
530 }
531
532
533 #ifdef  DEBUG
534     /* for DPR*() macro */
535 void    print_msg(fmt, arg1, arg2, arg3, arg4, arg5)
536     char        *fmt;
537     void        *arg1, *arg2, *arg3, *arg4, *arg5;
538 {
539     fprintf(LogFp, fmt, arg1, arg2, arg3, arg4, arg5);
540 }
541 #endif
542
543
544 int     put_xims_log(fmt, arg1, arg2, arg3)
545     char        *fmt;
546     void        *arg1, *arg2, *arg3;
547 {
548     FILE        *fp;
549     char        *logpath = Opt.LogPath;
550
551     /* if (Verbose < 1) return False; */
552
553     if (fp = fopen(logpath, "a")) {
554         char    time_str[80];
555         time_t  tm = time((time_t *)0);
556
557         if (strftime(time_str, 80, /* "%x %X" */ "%D %T", localtime(&tm)) == 0)
558             time_str[0] = 0;
559         fprintf(fp, "[%s] %s: ", time_str, ProgramName);
560         fprintf(fp, fmt, arg1, arg2, arg3);
561         putc('\n', fp);
562         fclose(fp);
563         return True;
564     }
565     DPR(("put_xims_log(); failed on '%s'\n", logpath));
566     return False;
567 }
568
569
570         /* ********  clear structure  ******** */
571
572 void    clear_ImsConf(ims)
573     ImsConf     *ims;
574 {
575     FREE(ims->servername);
576     FREE(ims->servername2);
577     FREE(ims->classname);
578     FREE(ims->property);
579     FREE(ims->cmd_path);
580     FREE(ims->cmd_param);
581     FREE(ims->env_set);
582     FREE(ims->env_unset);
583     FREE(ims->env_pass);
584
585     CLR(ims, ImsConf);
586 }
587
588 void    clear_ImsEnt(ent)
589     ImsEnt      *ent;
590 {
591     FREE(ent->name);
592     FREE(ent->fname);
593     FREE(ent->label);
594     if (ent->ims) {
595         clear_ImsConf(ent->ims);
596         FREE(ent->ims);
597     }
598     CLR(ent, ImsEnt);
599 }
600
601 void    clear_ImsList(list)
602     ImsList     *list;
603 {
604     int         i;
605
606     for (i = 0; i < list->num_ent; i++) {
607         clear_ImsEnt(list->elist[i]);
608         FREE(list->elist[i]);
609     }
610     FREE(list->elist);
611
612     CLR(list, ImsList);
613     list->default_idx = -1;
614     list->def_selmode = SEL_MODE_NOAUTO;
615 }
616
617
618 void    clear_FileSel(fsel)
619     FileSel     *fsel;
620 {
621     FREE(fsel->name);
622     FREE(fsel->hostname);
623     FREE(fsel->real_fname);
624     FREE(fsel->com_opt);
625     if (fsel->opts) {
626         ImsOpt  **op;
627         for (op = fsel->opts; *op; op++) {
628             FREE((*op)->ims_name);
629             FREE((*op)->opt_str);
630             FREE(*op);
631         }
632         FREE(fsel->opts);
633     }
634
635     CLR(fsel, FileSel);
636
637     fsel->select_mode = SEL_MODE_NONE;
638     fsel->iconic = -1;
639     fsel->dpy_specific = False;
640 }
641
642 void    clear_UserSelection(sel)
643     UserSelection       *sel;
644 {
645     FREE(sel->name);
646     FREE(sel->hostname);
647     if (sel->fsel) {
648         clear_FileSel(sel->fsel);
649         FREE(sel->fsel);
650     }
651     if (sel->renv) {
652         clear_RunEnv(sel->renv);
653         FREE(sel->renv);
654     }
655             /* FREE(sel->list); don't free */
656             /* FREE(sel->ent);  don't free */
657
658     CLR(sel, UserSelection);
659
660     sel->host_type = HOST_LOCAL;
661     sel->flag = F_SELECT_NONE;
662     sel->status = NoError;
663     sel->ims_idx = -1;
664     sel->iconic = -1;
665 }
666
667
668 void    clear_RunEnv(renv)
669     RunEnv      *renv;
670 {
671     FREE(renv->im_mod);
672     FREE(renv->atom_name);
673     FREE(renv->cmdbuf);
674
675     CLR(renv, RunEnv);
676     renv->status = NoError;;
677 }
678
679
680 void    clear_OutEnv(oenv)
681     OutEnv      *oenv;
682 {
683     EnvEnt      *ep;
684
685     if (!oenv)  return;
686     if (oenv->set)
687         for (ep = oenv->set; ep->name; ep++) {
688             FREE(ep->name); FREE(ep->value);
689         }
690     if (oenv->unset)
691         for (ep = oenv->unset; ep->name; ep++) {
692             FREE(ep->name); FREE(ep->value);
693         }
694 }
695
696
697 #ifdef  unused
698 void    clear_UserEnv()
699 {
700     UserEnv     *uenv = &userEnv;
701
702     FREE(uenv->hostname);
703     FREE(uenv->username);
704     FREE(uenv->homedir);
705     FREE(uenv->locale);
706     FREE(uenv->real_locale);
707     FREE(uenv->displayname);
708     FREE(uenv->displaydir);
709     FREE(uenv->xmodifiers);
710     FREE_LIST(uenv->locale_aliases);
711
712     CLR(&userEnv, UserEnv);
713     return;
714 }
715
716 void    clear_CmdConf()
717 {
718     if (cmdconf_initialized) {
719         CmdConf *conf = &Conf;
720         LocaleAlias     **ap;
721         int     i;
722
723         FREE(conf->imsConfDir);
724         FREE(conf->imsAppDir);
725         FREE(conf->imsLogDir);
726         FREE(conf->imsLogDile);
727         FREE(conf->imsDir);
728         FREE(conf->userImsDir);
729         FREE(conf->userTmpDir);
730         FREE(conf->userAltDir);
731
732         for (i = 0; i < NUM_PROTOCOLS; i++) {
733             FREE(conf->xmod[i]);
734             FREE(conf->atom[i]);
735         }
736         for (i = 0; i < NUM_ACTIONS; i++) {
737             FREE(conf->action[i]);
738         }
739         if (conf->remote) {
740             FREE(conf->remote->passEnv);
741             FREE(conf->remote);
742         }
743         if (conf->dt) {
744             FREE(conf->dt->confDir);
745             FREE(conf->dt->userDir);
746             FREE(conf->dt->resPath);
747             FREE(conf->dt);
748         }
749 # ifdef old_hpux
750         if (conf->vue) {
751             FREE(conf->vue->confDir);
752             FREE(conf->vue->userDir);
753             FREE(conf->vue->uselite);
754             FREE(conf->vue->resPath);
755             FREE(conf->vue->litePath);
756             FREE(conf->vue);
757         }       
758         if (conf->alias) {
759             for (ap = conf->alias; *ap; ap++) {
760                 FREE((*ap)->name);
761                 FREE((*ap)->aliases);
762             }
763             FREE(conf->alias);
764         }
765         if (conf->xhp) {
766             for (i = 0; i < XHP_LANG_NUM; i++)
767                 FREE(conf->xhp[i].locales);
768             FREE(conf->xhp);
769         }
770 # endif /* old_hpux */
771     }
772     CLR(&Conf, CmdConf);
773     cmdconf_initialized = False;
774     return;
775 }
776
777 void    clear_WinEnv()
778 {
779     CLR(&winEnv, WinEnv);
780 }
781
782 void    clear_CmdOpt()
783 {
784     CLR(&Opt, CmdOpt);
785 }
786
787 void    clear_All()
788 {
789     UserSelection       *sel = &userSel;
790
791     if (sel->list && sel->list != localList) {
792         clear_ImsList(sel->list);
793         FREE(sel->list);
794     }
795     if (localList) {
796         clear_ImsList(localList);
797         FREE(localList);
798     }
799
800     clear_UserSelection(sel);
801         /* clear_FileSel(sel->fsel); */
802         /* clear_RunEnv(sel->renv); */
803
804     clear_WinEnv();
805     clear_UserEnv();
806     clear_CmdConf();
807     clear_CmdOpt();
808 }
809
810 #endif  /* unused */
811
812
813 #ifdef  DEBUG
814
815         /* ********  print structure (for DEBUG)  ******** */
816
817 void    pr_FileSel(fsel)
818     FileSel     *fsel;
819 {
820     fprintf(LogFp, "FileSel:\tdpy_specific=%d  real_fname=%s  select_mode=%d\n",
821         fsel->dpy_specific, fsel->real_fname, fsel->select_mode);
822     fprintf(LogFp, "\tname=%s  host=%s  iconic=%d  com_opt='%s'  opts=%#x\n",
823         fsel->name, fsel->hostname, fsel->iconic, fsel->com_opt, fsel->opts);
824
825     if (fsel->opts) {
826         ImsOpt  **op;
827         for (op = fsel->opts; *op; op++)
828             fprintf(LogFp, "\t  opts[%d] <%s>\t'%s'\n",
829                         op - fsel->opts, (*op)->ims_name, (*op)->opt_str);
830     }
831 }
832
833 void    pr_UserSelection(sel)
834     UserSelection       *sel;
835 {
836     fprintf(LogFp, "userSelection:\tstatus=%s  flag=%#x  ims_idx=%d\n",
837                         error_name(sel->status), sel->flag, sel->ims_idx);
838     fprintf(LogFp, "\tname=%s  host=%s  host_type=%d  iconic=%d\n",
839                         sel->name, sel->hostname, sel->host_type, sel->iconic);
840     fprintf(LogFp, "\tfsel=%#x  list=%#x  ent=%#x  renv=%#x\n",
841                         sel->fsel, sel->list, sel->ent, sel->renv);
842     if (sel->fsel)      pr_FileSel(sel->fsel);
843     if (sel->renv)      pr_RunEnv(sel->renv);
844 }
845
846 void    pr_ImsConf(conf, ims_name)
847     ImsConf     *conf;
848     char        *ims_name;
849 {
850     char        **p;
851
852     fprintf(LogFp, "ImsConf:\tname=%s  protocols=%s%s%s%s\n", ims_name,
853                 (conf->protocols & ProtoBit(Proto_XIM)) ? "XIM,"  : NULL,
854                 (conf->protocols & ProtoBit(Proto_Ximp)) ? "Ximp,"  : NULL,
855                 (conf->protocols & ProtoBit(Proto_Xsi)) ? "Xsi,"  : NULL,
856 # ifdef old_hpux
857                 (conf->protocols & ProtoBit(Proto_Xhp)) ? "Xhp," : NULL,
858 # else
859                 NULL,
860 # endif /* old_hpux */
861                 (conf->protocols & ProtoBit(Proto_None)) ? "None,"  : NULL);
862     fprintf(LogFp, "\tproperty=%s  servername=%s (%s) class=%s\n",
863                 conf->property, conf->servername,
864                 conf->servername2, conf->classname);
865     fprintf(LogFp, "\tpath=%s  param='%s'\n",
866                 conf->cmd_path, conf->cmd_param);
867     fprintf(LogFp, "\ttimeout=%d  interval=%d  flags=%s%s%s\n",
868                 conf->timeout, conf->interval,
869                 (conf->flags & F_NO_SERVER) ? "no_server,"  : NULL,
870                 (conf->flags & F_NO_REMOTE) ? "no_remote,"  : NULL,
871                 (conf->flags & F_NO_OPTION) ? "no_option," : NULL,
872                 (conf->flags & F_TRY_CONNECT) ? "try_connect," : NULL);
873     fprintf(LogFp, "\tenv_set: '%s'\n", conf->env_set);
874     fprintf(LogFp, "\tenv_unset: '%s'\n", conf->env_unset);
875     fprintf(LogFp, "\tenv_pass: '%s'\n", conf->env_pass);
876     fputc('\n', LogFp);
877 }
878
879 void    pr_ImsEnt(ent, idx)
880     ImsEnt      *ent;
881     int         idx;
882 {
883     fprintf(LogFp, "ImsEnt[%d]:\tname=%s  fname=%s  label=%s  ims=%#x\n",
884                 idx, ent->name, ent->fname, ent->label, ent->ims);
885 }
886
887 void    pr_ImsList(list)
888     ImsList     *list;
889 {
890     int         i;
891     ImsEnt      *ent;
892
893     fprintf(LogFp, "ImsList:\tstatus=%d  num_ent=%d  def_idx=%d  def_sel=%d\n",
894         list->status, list->num_ent, list->default_idx, list->def_selmode);
895     for (i = 0; i < list->num_ent; i++) {
896         ent = list->elist[i];
897         pr_ImsEnt(ent, i);
898         if (ent->ims)   pr_ImsConf(ent->ims, ent->name);
899     }
900 }
901
902 void    pr_WinEnv(wenv)
903     WinEnv      *wenv;
904 {
905     fprintf(LogFp, "WinEnv:\tstatus=%d  Dpy=%#x  topW=%#x  appC=%#x\n",
906                 wenv->status, wenv->Dpy, wenv->TopW, wenv->appC);
907     fprintf(LogFp, "\tatom_owner=%#x  atom: main=%d status=%d data=%d\n",
908                 wenv->atom_owner, wenv->atom_main, wenv->atom_status, wenv->atom_data);
909 }
910
911 void    pr_RunEnv(renv)
912     RunEnv      *renv;
913 {
914     fprintf(LogFp, "RunEnv:\tstatus=%s  is_remote=%d  proto=%d\n",
915                 error_name(renv->status), renv->is_remote, proto_name(renv->proto));
916     fprintf(LogFp, "\tim_mod='%s'  atom_name='%s'  prop_atom=%d\n",
917                 renv->im_mod, renv->atom_name, renv->prop_atom);
918     fprintf(LogFp, "\tpid=%d  wait_status=%#x  cmdbuf='%s'\n",
919                 renv->pid, renv->wait_status, renv->cmdbuf);
920 }
921
922
923 void    pr_UserEnv()
924 {
925     UserEnv     *uenv = &userEnv;
926
927     fprintf(LogFp, "UserEnv:\n");
928     fprintf(LogFp, "\thostname=\"%s\"\n", uenv->hostname);
929     fprintf(LogFp, "\tusername=\"%s\"\n", uenv->username);
930     fprintf(LogFp, "\tlocale=\"%s\"  real_locale=\"%s\"\n",
931                                         uenv->locale, uenv->real_locale);
932     fprintf(LogFp, "\thomedir=\"%s\"\n", uenv->homedir);
933     fprintf(LogFp, "\tdisplayname=\"%s\"\n", uenv->displayname);
934     fprintf(LogFp, "\tdisplaydir=\"%s\"\n", uenv->displaydir);
935     fprintf(LogFp, "\tscreen_num=%d\n", uenv->screen_num);
936 }
937
938 void    pr_OutEnv(oenv)
939     OutEnv      *oenv;
940 {
941     EnvEnt      *ep;
942
943     fprintf(LogFp, "OutEnv:\n");
944     fprintf(LogFp, "  set:  \t");
945     if (oenv->set)
946         for (ep = oenv->set; ep->name; ep++)
947             fprintf(LogFp, "%s='%s' ", ep->name, ep->value);
948     putc('\n', LogFp);
949
950     fprintf(LogFp, "  unset:\t");
951     if (oenv->unset)
952         for (ep = oenv->unset; ep->name; ep++)
953             fprintf(LogFp, "%s='%s' ", ep->name, ep->value);
954     putc('\n', LogFp);
955 }
956
957
958 void    pr_CmdConf()
959 {
960     int         i;
961     CmdConf     *conf = &Conf;
962 # ifdef old_hpux
963     LocaleAlias **ap;
964 # endif /* old_hpux */
965     register char       **p;
966
967     fprintf(LogFp, "CmdConf:\n");
968     fprintf(LogFp, "\timsConfDir=%s\n", conf->imsConfDir);
969     fprintf(LogFp, "\timsAppDir=%s\n", conf->imsAppDir);
970     fprintf(LogFp, "\timsLogDir=%s\n", conf->imsLogDir);
971     fprintf(LogFp, "\timsLogFile=%s\n", conf->imsLogFile);
972     fprintf(LogFp, "\timsDir=%s\n", conf->imsDir);
973     fprintf(LogFp, "\tuserImsDir=%s\n", conf->userImsDir);
974     fprintf(LogFp, "\tuserTmpDir=%s\n", conf->userTmpDir);
975     fprintf(LogFp, "\tuserAltDir=%s\n", conf->userAltDir);
976
977 # ifdef old_hpux
978     fprintf(LogFp, "\tImXmod:\tXIM=%s  Ximp=%s  Xsi=%s  Xhp=%s  None=%s\n",
979                 conf->xmod[Proto_XIM], conf->xmod[Proto_Ximp],
980                 conf->xmod[Proto_Xsi], conf->xmod[Proto_Xhp], conf->atom[Proto_None]);
981     fprintf(LogFp, "\tImAtom:\tXIM=%s  Ximp=%s  Xsi=%s  Xhp=%s  None=%s\n",
982                 conf->atom[Proto_XIM], conf->atom[Proto_Ximp],
983                 conf->atom[Proto_Xsi], conf->atom[Proto_Xhp], conf->atom[Proto_None]);
984 # else
985     fprintf(LogFp, "\tImXmod:\tXIM=%s  Ximp=%s  Xsi=%s  None=%s\n",
986                 conf->xmod[Proto_XIM], conf->xmod[Proto_Ximp],
987                 conf->xmod[Proto_Xsi], conf->atom[Proto_None]);
988     fprintf(LogFp, "\tImAtom:\tXIM=%s  Ximp=%s  Xsi=%s  None=%s\n",
989                 conf->atom[Proto_XIM], conf->atom[Proto_Ximp],
990                 conf->atom[Proto_Xsi], conf->atom[Proto_None]);
991 # endif /* old_hpux */
992
993     fprintf(LogFp, "\tAction[%d]:\t{ ", NUM_ACTIONS);
994         for (i = 0; i < NUM_ACTIONS; i++)
995             fprintf(LogFp, "\"%s\", ", conf->action[i]);
996         fprintf(LogFp, "}\n");
997
998     fprintf(LogFp, "\tRemote:\tDisabled=%s  useRemsh=%s  timeout=%d\n",
999                 conf->remote->disabled ? "True" : "False",
1000                 conf->remote->useRemsh ? "True" : "False",
1001                 conf->remote->timeout);
1002     fprintf(LogFp, "\t  Env:\t%s\n", conf->remote->passEnv);
1003
1004     if (conf->dt) {
1005         fprintf(LogFp, "\tDtEnv:\tConfDir=%s  UserDir=%s\n",
1006                     conf->dt->confDir, conf->dt->userDir);
1007         fprintf(LogFp, "\t  resPath=\"%s\"\n", conf->dt->resPath);
1008     } else
1009         fprintf(LogFp, "\tDtEnv:\t<None>\n");
1010
1011 # ifdef old_hpux
1012     if (conf->vue) {
1013         fprintf(LogFp, "\tVueEnv:\tConfDir=%s  UserDir=%s\n",
1014                                 conf->vue->confDir, conf->vue->userDir);
1015         fprintf(LogFp, "\t  uselite=%s\n", conf->vue->uselite);
1016         fprintf(LogFp, "\t  resPath=\"%s\"\n", conf->vue->resPath);
1017         fprintf(LogFp, "\t  litePath=\"%s\"\n", conf->vue->litePath);
1018     } else
1019         fprintf(LogFp, "\tVueEnv:\t<None>\n");
1020
1021     fprintf(LogFp, "\tlocaleAlias:\t%s\n", conf->alias ? NULL : "None");
1022     if (conf->alias) {
1023         for (ap = conf->alias; *ap; ap++)
1024             fprintf(LogFp, "\t  [%s]\t%s\n", (*ap)->name, (*ap)->aliases);
1025     }
1026
1027     fprintf(LogFp, "\txhp:\t%s\n", conf->xhp ? NULL : "None");
1028     if (conf->xhp) {
1029         for (i = 0; i < XHP_LANG_NUM; i++)
1030             fprintf(LogFp, "\t  [%c]\t%s\n",
1031                                 conf->xhp[i].type, conf->xhp[i].locales);
1032     }
1033 # endif /* old_hpux */
1034 }
1035
1036 void    pr_CmdOpt()
1037 {
1038     fprintf(LogFp, "CmdOpt:\tDisplayName=%s  LocaleName=%s  ShellName=%s\n",
1039                         Opt.DisplayName, Opt.LocaleName, Opt.ShellName);
1040     fprintf(LogFp, "\tConfPath=%s  UserPath=%s\n",
1041                         Opt.ConfPath, Opt.UserPath);
1042     fprintf(LogFp, "\tLogPath=%s  ResourceFile=%s\n",
1043                         Opt.LogPath, Opt.ResourceFile);
1044     fprintf(LogFp, "\tImsName=%s  HostName=%s  ImsOption=%s\n",
1045                         Opt.ImsName, Opt.HostName, Opt.ImsOption);
1046     fprintf(LogFp, "\tSelectMode=%d  Timeout=%d  Interval=%d\n",
1047                         Opt.SelectMode, Opt.Timeout, Opt.Interval);
1048 }
1049
1050 void    pr_OpModeFlag()
1051 {
1052     char        *name = "<unknown>";
1053
1054     switch (OpMode) {
1055         case MODE_START:        name = "START"; break;
1056         case MODE_MODE:         name = "MODE"; break;
1057         case MODE_STYLE:        name = "STYLE"; break;
1058         case MODE_LIST:         name = "LIST"; break;
1059         case MODE_CURRENT:      name = "CURRENT"; break;
1060         case MODE_REMCONF:      name = "REMCONF"; break;
1061     }
1062     fprintf(LogFp, "OpMode=%s[%d]  OpFlag=[%#x] ", name, OpMode, OpFlag);
1063
1064     if (OpFlag) {
1065         if (OpFlag & FLAG_ENV)          fputs("Env, ", LogFp);
1066         if (OpFlag & FLAG_NOSAVE)       fputs("NoSave, ", LogFp);
1067         if (OpFlag & FLAG_NOSTART)      fputs("NoStart, ", LogFp);
1068         if (OpFlag & FLAG_NOWAIT)       fputs("NoWait, ", LogFp);
1069         if (OpFlag & FLAG_NOTIMEOUT)    fputs("NoTimeout, ", LogFp);
1070         if (OpFlag & FLAG_NORESOURCE)   fputs("NoResource, ", LogFp);
1071         if (OpFlag & FLAG_NOREMOTE)     fputs("NoRemote, ", LogFp);
1072         if (OpFlag & FLAG_NOTIFY)       fputs("Notify, ", LogFp);
1073         if (OpFlag & FLAG_CONNECT)      fputs("Connect, ", LogFp);
1074         if (OpFlag & FLAG_REMOTERUN)    fputs("RemoteRun, ", LogFp);
1075         if (OpFlag & FLAG_WINDOW)       fputs("Window, ", LogFp);
1076         if (OpFlag & FLAG_DT)           fputs("Dt, ", LogFp);
1077 # ifdef old_hpux
1078         if (OpFlag & FLAG_VUE)          fputs("Vue, ", LogFp);
1079 # endif /* old_hpux */
1080     }
1081     putc('\n', LogFp);
1082 }
1083
1084 static char     *StateNameTbl[] = {
1085     "None",
1086     "Init",
1087     "Init_Err",
1088     "Init_Done",
1089     "Select",
1090     "Select_Err",
1091     "Select_Canceled",
1092     "Select_Done",
1093     "Start",
1094     "Start_Err",
1095     "Start_Done",
1096     "Wait",
1097     "Wait_Err",
1098     "Wait_Done",
1099     "Finish",
1100     "Finish_Err",
1101     "Finish_Defered",
1102     "Finish_Done",
1103     "Mode",
1104     "Mode_Canceled",
1105     "Mode_Done"
1106 };
1107 #define NumStates       (sizeof(StateNameTbl) / sizeof(char *))
1108
1109 char    *StateName()
1110 {
1111     return (OpState >= 0 && OpState < NumStates) ?
1112                                 StateNameTbl[OpState] : "<unknown>";
1113 }
1114
1115
1116         /* ********  error name  ******** */
1117
1118 char    *error_name(error)
1119     ximsError   error;
1120 {
1121     char        *name = "<unknown>";
1122
1123 # ifdef __STDC__
1124 #define ERR_CASE(err)   case err :      name = #err; break
1125 # else
1126 #define ERR_CASE(err)   case err :      name = "err"; break
1127 # endif /* __STDC__ */
1128
1129     switch (error) {
1130         ERR_CASE(NoError);
1131         ERR_CASE(ErrSyntax);
1132         ERR_CASE(ErrNoHome);
1133         ERR_CASE(ErrNoLocale);
1134         ERR_CASE(ErrNoCDELocale);
1135         ERR_CASE(ErrNoDisplay);
1136         ERR_CASE(ErrDisabled);
1137         ERR_CASE(ErrSignaled);
1138
1139             /* file */
1140         ERR_CASE(ErrFileOpen);
1141         ERR_CASE(ErrFileCreate);
1142         ERR_CASE(ErrDirCreate);
1143         ERR_CASE(ErrMissEntry);
1144
1145             /* Selection */
1146         ERR_CASE(ErrAnotherProg);
1147         ERR_CASE(ErrNoSelectionFile);
1148         ERR_CASE(ErrSaveSelection);
1149         ERR_CASE(ErrNoSelection);
1150         ERR_CASE(ErrNoLocaleConf);
1151         ERR_CASE(ErrNoImsEntry);
1152         ERR_CASE(ErrNoImsConf);
1153         ERR_CASE(ErrNotRegistered);
1154         ERR_CASE(ErrNoExecutable);
1155
1156             /* Start */
1157         ERR_CASE(ErrImsRunning);
1158         ERR_CASE(ErrImsExecution);
1159         ERR_CASE(ErrImsAborted);
1160         ERR_CASE(ErrImsTimeout);
1161         ERR_CASE(ErrUnknownHost);
1162         ERR_CASE(ErrRemoteAction);
1163         ERR_CASE(ErrRemoteData);
1164         ERR_CASE(ErrRemoteNoIms);
1165         ERR_CASE(ErrRemoteMissIms);
1166         ERR_CASE(ErrNoImsstart);
1167         ERR_CASE(ErrRemoteIms);
1168
1169             /* X */
1170         ERR_CASE(ErrOpenDpy);
1171
1172             /* misc */
1173         ERR_CASE(ErrMemory);
1174
1175             /*internal */
1176         ERR_CASE(ErrIsNone);
1177         ERR_CASE(ErrNotRun);
1178         ERR_CASE(ErrImsWaiting);
1179         ERR_CASE(ErrImsWaitDone);
1180         ERR_CASE(ErrImsConnecting);
1181         ERR_CASE(ErrImsConnectDone);
1182         ERR_CASE(ErrInvState);
1183         ERR_CASE(ErrInternal);
1184     }
1185 #undef  ERR_CASE
1186
1187     return name;
1188 }
1189
1190
1191 static char *_proto_names[NUM_PROTOCOLS] =
1192 # ifdef old_hpux
1193                         { "None", "XIM", "Ximp", "Xsi", "Xhp" };
1194 # else
1195                         { "None", "XIM", "Ximp", "Xsi" };
1196 # endif /* old_hpux */
1197
1198 char    *proto_name(proto_idx)
1199     int         proto_idx;
1200 {
1201     if (proto_idx >= 0 && proto_idx < NUM_PROTOCOLS)
1202         return _proto_names[proto_idx];
1203     else
1204         return NULL;
1205 }
1206
1207 static char     *SigNames[] = {         /* 1 ~ 32 */
1208     "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT,ABRT", "EMT", "FPE",
1209     "KILL", "BUS", "SEGV", "SYS", "PIPE", "ALRM", "TERM", "USR1",
1210     "USR2", "CHLD", "PWR", "VTALRM", "PROF", "POLL,IO", "WINCH", "STOP",
1211     "TSTP", "CONT", "TTIN", "TTOU", "URG", "LOST", "(reserved)", "DIL",
1212 };
1213
1214 #define MaxSigNum       (sizeof(SigNames) / sizeof(char *))
1215
1216 char    *sig_name(sig)
1217     int         sig;
1218 {
1219     return (sig > 0 && sig <= MaxSigNum) ? SigNames[sig - 1] : "<unknown>";
1220 }
1221
1222
1223 void    pr_brk(msg)
1224     char        *msg;
1225 {
1226     static char *last_brk = 0;
1227     char        *new_brk = (char *) sbrk(0);
1228     long        inc = (long) (new_brk - last_brk);
1229
1230     inc += inc > 0 ? 1023 : -1023;
1231     DPR(("%s: BREAK=%p (Inc=%+d KB)\n", msg, new_brk, inc/1024));
1232
1233     last_brk = new_brk;
1234 }
1235
1236 #endif  /* DEBUG */
1237