diff --git a/cde/lib/DtTerm/TermPrim/TermPrim.c b/cde/lib/DtTerm/TermPrim/TermPrim.c index 7254c2b94..9dc3320b4 100644 --- a/cde/lib/DtTerm/TermPrim/TermPrim.c +++ b/cde/lib/DtTerm/TermPrim/TermPrim.c @@ -748,6 +748,60 @@ _DtTermPrimGetFontSet (void) XmFontListFreeFontContext(fontContext); } +/* Motif's default render table is a single core XFontStruct, even in a + * multi-byte locale. The terminal buffer, however, holds wchar_t + * whenever MB_CUR_MAX > 1 (see TermPrimBuffer.c), and that buffer can + * only be drawn through the fontset renderer. Build a fontset out of + * the font we were handed so the buffer and the renderer stay in step; + * otherwise the wide buffer gets drawn a byte at a time and every + * character is followed by sizeof(wchar_t) - 1 garbage cells... + */ +static XFontSet +MakeFontSetFromFont(Widget w, XFontStruct *font) +{ + unsigned long ret; + char *fontName; + char *baseName; + char *c; + char **missingCharsetList; + int missingCharsetCount; + XFontSet fontSet; + + if (!font || !XGetFontProperty(font, XA_FONT, &ret)) { + return((XFontSet) 0); + } + + if (!(fontName = XGetAtomName(XtDisplay(w), ret))) { + return((XFontSet) 0); + } + + /* strip the charset registry and encoding off the XLFD and wildcard + * them, so XCreateFontSet() can pick a font for each charset the + * locale requires... + */ + baseName = XtMalloc(strlen(fontName) + 5); + (void) strcpy(baseName, fontName); + if ((c = strrchr(baseName, '-'))) { + *c = '\0'; + if ((c = strrchr(baseName, '-'))) { + (void) strcpy(c, "-*-*"); + } + } + + fontSet = XCreateFontSet(XtDisplay(w), baseName, + &missingCharsetList, &missingCharsetCount, (char **) 0); + if (missingCharsetCount > 0) { + (void) XFreeStringList(missingCharsetList); + } + + Debug('f', fprintf(stderr, ">>built fontset from \"%s\": %s\n", + baseName, fontSet ? "ok" : "FAILED")); + + (void) XtFree(baseName); + (void) XFree(fontName); + return(fontSet); +} + static TermFont CreateRenderFont ( @@ -764,6 +818,14 @@ CreateRenderFont /* get our fontset from the fontlist... */ (void) _DtTermPrimGetFontSet(w, fontList, &fontSet, &font); + /* if we are in a multi-byte locale the buffer holds wchar_t, so we + * need a fontset to draw it. Manufacture one if the fontlist only + * gave us a single core font... + */ + if (!fontSet && font && (MB_CUR_MAX > 1)) { + fontSet = MakeFontSetFromFont(w, font); + } + /* generate a TermFont from either the fontset or the font... */ if (fontSet) { termFont = _DtTermPrimRenderFontSetCreate(w, fontSet); diff --git a/cde/lib/DtTerm/TermPrim/TermPrimGetPty-pts.c b/cde/lib/DtTerm/TermPrim/TermPrimGetPty-pts.c index ed5b0af73..b12cf7714 100644 --- a/cde/lib/DtTerm/TermPrim/TermPrimGetPty-pts.c +++ b/cde/lib/DtTerm/TermPrim/TermPrimGetPty-pts.c @@ -33,6 +33,7 @@ #include "TermPrim.h" #include "TermPrimDebug.h" +#include "TermPrimUtil.h" #include "TermHeader.h" #include #include @@ -53,7 +54,19 @@ _DtTermPrimGetPty(char **ptySlave, char **ptyMaster) return(-1); } - if ((ptyFd = posix_openpt(O_RDWR)) >= 0) { + /* Our caller turns on suid root before calling us, but on this + * platform the pty slave is created owned by the *effective* uid of + * whoever opens the master, and grantpt() no longer chowns it. Left + * as root, the slave would be unopenable by the user once we drop + * privileges in the child, and the subprocess would die with + * "/dev/pts/N: Permission denied". We need no privilege at all to + * allocate a pty here, so drop it around the open... + */ + (void) _DtTermPrimToggleSuidRoot(False); + + ptyFd = posix_openpt(O_RDWR); + + if (ptyFd >= 0) { /* use grantpt to prevent other processes from grabbing the tty that * goes with the pty master we have opened. It is a mandatory step