Merge branch 'master' of https://git.code.sf.net/p/cdesktopenv/code
[oweals/cde.git] / cde / programs / dtterm / sunDtTermServer.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 /* $TOG: sunDtTermServer.c /main/6 1999/09/17 13:29:51 mgreess $ */
24 /*                                                                      *
25  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
26  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
27  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
28  * (c) Copyright 1993, 1994 Novell, Inc.                                *
29  */
30
31 #include "TermHeader.h"
32 #include "TermPrimDebug.h"
33 #include "TermView.h"
34 #include "TermPrimMessageCatI.h"
35 #include "TermPrimSetPty.h"
36 #ifdef  LOG_USAGE
37 #include "DtTermLogit.h"
38 #endif  /* LOG_USAGE */
39 #include <signal.h>
40 #include <errno.h>
41 #include <Dt/Service.h>
42 #include <Dt/UserMsg.h>
43 #include <Dt/DtP.h>
44 #include <Tt/tttk.h>
45 #include <X11/IntrinsicP.h>
46 #include <X11/CoreP.h>
47 #include <Xm/XmAll.h>
48
49 #define GETXMSTRING(s, m, d)    XmStringCreateLocalized(GETMESSAGE(s,m,d))
50
51 #define VENDOR                "CDE"
52 #define VERSION               "1.0"
53
54 static char * procId;
55 static Tt_pattern * DtTermToolTalkPattern = NULL;
56 static Boolean sendStopped = False;
57 XtInputId ProcessToolTalkInputId = 0;
58 static int ttFd;
59 char DTTERM_CLASS_NAME[] = "Dtterm";
60 char *displayString = NULL;
61 Widget refWidget;
62
63 #ifdef  TIMEOUT
64 #define STICKAROUND     15              /* 15 minutes... */
65 static XtIntervalId waitId = (XtIntervalId) 0;
66 #endif  /* TIMEOUT */
67
68 extern void
69 sunSetupIA(Widget w);
70
71 void
72 DieFromToolTalkError(Widget, char*, Tt_status);
73
74 Tt_message 
75 SessionCallback( Tt_message msg, void * client_data, Tt_message contract);
76
77 Tt_callback_action
78 HandleTtRequest(Tt_message msg, Tt_pattern pat);
79
80 static void
81 dttermNewHandler(Tt_message msg);
82
83 #ifdef  TIMEOUT
84 static void TimeOut(XtPointer clientData, XtIntervalId *id);
85 #endif  /* TIMEOUT */
86
87 Boolean
88 FinalizeToolTalkSession( )
89 {
90     Tt_status   ttRc;
91     int         i;
92
93     if (DtTermToolTalkPattern && tt_ptr_error(DtTermToolTalkPattern) == TT_OK) {
94         ttRc = ttdt_session_quit(NULL, DtTermToolTalkPattern, 1);
95         if (ProcessToolTalkInputId)
96             XtRemoveInput(ProcessToolTalkInputId);
97         return(True);
98     }
99     ttRc = ttdt_close(NULL, NULL, sendStopped);
100     return(True);
101 }
102
103 Tt_message
104 SessionCallback( Tt_message msg, void * client_data, Tt_message contract)
105 {
106     char        *opString = tt_message_op(msg);
107     Tttk_op     op = tttk_string_op(opString);
108
109     tt_free(opString);
110
111     switch (op) {
112         int i;
113
114         default:
115             break;
116         case TTDT_QUIT:
117             if (contract == 0) {
118                 tt_message_reply(msg);
119                 FinalizeToolTalkSession( );
120                 exit(0);
121             }
122           /* Should we send some type of tt failure message? */
123             return 0;
124     }
125     return msg;
126 }
127
128 int
129 InitializeToolTalkSession(Widget topLevel, Boolean sendStarted)
130 {
131     Tt_status   ttstat;
132     char        *errfmt;
133
134     sendStopped = sendStarted;
135     procId = ttdt_open(&ttFd,
136                        DTTERM_CLASS_NAME,
137                        VENDOR,
138                        VERSION,
139                        sendStarted);
140
141     ttstat = tt_ptr_error(procId);
142     errfmt =
143       GETMESSAGE(10, 2, "Could not connect to ToolTalk:\n%s\nExiting ...");
144     DieFromToolTalkError( topLevel, errfmt, ttstat );
145
146     ttstat = tt_ptype_declare("DT_Terminal");
147     DieFromToolTalkError( topLevel, "tt_ptype_declare", ttstat );
148
149     ttstat = tt_ptype_opnum_callback_add("DT_Terminal", 0, HandleTtRequest);
150     DieFromToolTalkError( topLevel, "tt_ptype_opnum_callback_add", ttstat );
151
152     ttstat = tt_ptype_declare("SDT_Terminal");
153     DieFromToolTalkError( topLevel, "tt_ptype_declare", ttstat );
154
155     ttstat = tt_ptype_opnum_callback_add("SDT_Terminal", 0, HandleTtRequest);
156     DieFromToolTalkError( topLevel, "tt_ptype_opnum_callback_add", ttstat );
157
158     /*
159      * If we were started by a message, the following call to
160      * tttk_Xt_input_handler will process it.  Otherwise,
161      * tttk_Xt_input_handler will just return.
162      */
163     tttk_Xt_input_handler(NULL, 0, 0);
164
165     return(TT_OK);
166 }
167
168 int
169 FinishToolTalkInit(Widget topLevel)
170 {
171     ProcessToolTalkInputId =
172             XtAppAddInput(XtWidgetToApplicationContext(topLevel),
173                           ttFd, (XtPointer)XtInputReadMask,
174                           tttk_Xt_input_handler, procId);
175     DtTermToolTalkPattern = ttdt_session_join(tt_default_session( ),
176                                               SessionCallback,
177                                               topLevel,
178                                               NULL,
179                                               1);
180     if (tt_is_err(tt_ptr_error(DtTermToolTalkPattern))) {
181         ttdt_close(NULL, NULL, sendStopped);
182         return(0);
183     }
184     refWidget = topLevel;
185     if (!displayString) {
186         /* This dtterm -sdtserver must have been started up from either a
187          * session startup or the command line.  */
188         displayString = DisplayString(XtDisplay(refWidget));
189     }
190
191
192 }
193
194 Tt_callback_action
195 HandleTtRequest(Tt_message msg, Tt_pattern pat)
196 {
197     char        *op;
198     Tt_status   status;
199
200     op = tt_message_op( msg );
201     status = tt_ptr_error( op );
202     if (tt_is_err(status) || (op == 0)) {
203         /* Let tttk_Xt_input_handler() Do The Right Thing */
204         return TT_CALLBACK_CONTINUE;
205     }
206     if ((!strcmp(op, "SDtTerminal_New")) || (!strcmp(op, "DtTerminal_New")))  {
207         if ((getuid() == tt_message_uid(msg)) &&
208             (getgid() == tt_message_gid(msg))) {
209             dttermNewHandler( msg );
210         } else {
211             tt_message_reject(msg);
212             tt_message_destroy(msg);
213             return TT_CALLBACK_PROCESSED;
214         }
215     } else {
216         tt_free(op);
217         return TT_CALLBACK_CONTINUE;
218     }
219
220     tt_free(op);
221     return TT_CALLBACK_PROCESSED;
222 }
223
224 /*ARGSUSED*/
225 static void
226 dttermNewHandler(
227     Tt_message msg)
228 {
229     Widget                shellWidget;
230     int                   pid = -1;
231     Arg                   arglist[20];
232     int                   argcnt = 0;
233     char                  *msgFile;
234     char                  numArgs;
235     int                   i, j, k;
236     char                  *displayEnv, *newDisplayString;
237
238     msgFile = tt_message_file(msg);
239     if (tt_is_err(tt_ptr_error(msgFile))) msgFile = 0;
240     numArgs = tt_message_args_count(msg);
241     if (tt_is_err( tt_int_error(numArgs))) numArgs = 0;
242     for (i = 0; i < numArgs; i++) {
243         char *vtype, *val;
244
245         vtype = tt_message_arg_type(msg, i);
246         if ((vtype == 0) || (tt_is_err(tt_ptr_error(vtype)))) {
247             continue;
248         }
249         val = tt_message_arg_val(msg, i);
250         if(strcmp(vtype, "-display") == 0) {
251             newDisplayString = XtNewString(val);
252         }
253         tt_free( val );
254         tt_free( vtype );
255     }
256
257     if (!displayString) {
258         /* This tt message is part of an action dtterm -server startup.  */
259         displayString = newDisplayString;
260         displayEnv = (char *)malloc(strlen("DISPLAY=") +
261                                     strlen(displayString) + 2);
262         displayEnv[0]=NULL;
263         strcat(displayEnv, "DISPLAY=");
264         strcat(displayEnv, displayString);
265         putenv(displayEnv);
266         tt_free(msgFile);
267         tt_message_reply(msg);
268         tttk_message_destroy(msg);
269         return;
270     } else {
271         if (strcmp(displayString, newDisplayString)) {
272             tt_free(msgFile);
273             tt_message_reject(msg);
274             XtFree(newDisplayString);
275             return;
276         }
277         XtFree(newDisplayString);
278     }
279     
280     argcnt = 0;
281     (void) XtSetArg(arglist[argcnt], XmNallowShellResize, True);
282             argcnt++;
283     shellWidget = XtAppCreateShell((char *) 0, "Dtterm",
284             applicationShellWidgetClass, XtDisplay((Widget) refWidget),
285             arglist, argcnt);
286
287     /* parse off messageFields and build the dttermview arglist... */
288     argcnt = 0;
289
290     /* create the dtterm... */
291     (void) CreateInstance(shellWidget, "dtTermView", arglist, argcnt, True);
292
293     (void) XtRealizeWidget(shellWidget);
294 #ifdef sun
295     sunSetupIA(shellWidget);
296 #endif
297
298 #ifdef  TIMEOUT
299             /* since we now have active instances, we can remove our
300              * wait timeout...
301              */
302             if (waitId) {
303                 (void) XtRemoveTimeOut(waitId);
304                 waitId = (XtIntervalId) 0;
305             }
306 #endif  /* TIMEOUT */
307             
308     tt_free(msgFile);
309     tt_message_reply(msg);
310     tttk_message_destroy(msg);
311 }
312
313
314
315 Boolean
316 ServerStartSession(Widget topLevel, int argc, char **argv, Boolean loginShell, 
317                    char **commandToExec)
318 {
319     return(InitializeToolTalkSession(topLevel, True));
320 }
321
322 #ifdef  TIMEOUT
323 static void
324 TimeOut(
325     XtPointer             clientData,
326     XtIntervalId         *id
327 )
328 {
329     /* if we have no instances active, go away... */
330     if (InstanceCount <= 0) {
331         (void) exit(0);
332     }
333
334     /* otherwise, clear the waitId... */
335     if (*id == waitId) {
336         waitId = (XtIntervalId) 0;
337     }
338 }
339 #endif  /* TIMEOUT */
340
341
342 static void
343 ExitCB (Widget dialog, XtPointer client_data, XtPointer call_data)
344 {
345     exit((int) client_data);
346 }
347
348 void
349 DieFromToolTalkError(Widget parent, char *errfmt, Tt_status status)
350 {
351     Arg          args[10];
352     Widget       dialog, dialogShell;
353     char        *errmsg, *statmsg, *title;
354     XmString     xms_errmsg, xms_ok, xms_title;
355     int          n;
356
357     if (! tt_is_err(status)) return;
358     statmsg = tt_status_message(status);
359     errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
360     sprintf(errmsg, errfmt, statmsg);
361
362     xms_ok = GETXMSTRING(10, 3, "OK");
363     xms_errmsg = XmStringCreateLocalized(errmsg);
364     xms_title = GETXMSTRING(10, 1, "Terminal - Error");
365
366     n = 0;
367     XtSetArg(args[n], XmNautoUnmanage, False); n++;
368     XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
369     XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
370     XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
371     XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
372
373     dialog = XmCreateErrorDialog(parent, "IconEditorError", args, n);
374     XtAddCallback(dialog, XmNokCallback, ExitCB, (XtPointer) status);
375     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
376     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
377
378     /*
379      * Disable the frame menu from dialog since we don't want the user
380      * to be able to close dialogs with the frame menu
381      */
382     dialogShell = XtParent(dialog);
383     n = 0;
384     XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
385     XtSetValues(dialogShell, args, n);
386     XtManageChild(dialog);
387     XtRealizeWidget(dialogShell);
388
389     _DtSimpleError("Dtterm", DtFatalError, NULL, errmsg);
390
391     XtFree(errmsg);
392     XmStringFree(xms_ok);
393     XmStringFree(xms_errmsg);
394     XmStringFree(xms_title);
395
396     while (TRUE)
397       XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll);
398 }