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