Files
cdesktop/cde/programs/dtinfo/clients/dtinfo_start/dtinfo_start.c
2018-04-28 12:30:20 -06:00

649 lines
16 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: dtinfo_start.c /main/9 1999/09/20 13:26:59 mgreess $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*
* This file contains the main program for: dtinfo_start
*/
#include <stdio.h>
#include <stdlib.h>
#include <X11/Intrinsic.h>
#include <Xm/XmP.h>
#include <Xm/XmAll.h>
#include <Dt/EnvControlP.h>
#include <Dt/Action.h>
#include <Dt/DtGetMessageP.h>
#include <Dt/MsgLog.h>
#include <Dt/Dt.h>
#include <Tt/tt_c.h>
#include "dtinfo_start.h"
#include "dtinfo_start.opnums"
/*
* Operation names, number of arguments and default action names
*/
static const char * LOAD_INFO_LIB_STRING = "DtInfo_LoadInfoLib";
static const int LOAD_INFO_LIB_ARGS = 3;
static const char * LOAD_INFO_LIB_ACTION = "DtInfoStart";
static const char * SHOW_INFO_AT_LOC_STRING = "DtInfo_ShowInfoAtLoc";
static const int SHOW_INFO_AT_LOC_ARGS = 4;
static const char * SHOW_INFO_LIB_SECTION_ACTION = "DtInfoStartAtLoc";
/*
* Static global vars
*/
static Widget top_level;
static XtAppContext app_context;
static const int time_out = 1000; /* milliseconds */
static const int SET_NUM = 1; /* message cat set number */
static const char * name = "DtInfo"; /* ptype name and Xt name */
/*
* Forward declarations for static functions
*/
static int InvokeAction (
char * prog_name,
int op_num,
const char * action_name,
char * exec_host,
char * info_lib,
char * topic);
static void ActionDoneCallback (
DtActionInvocationID id,
XtPointer client_data,
DtActionArg * args,
int num_args,
DtActionStatus status);
static void Exit (
XtPointer client_data,
XtIntervalId id);
static Tt_status ConnectToMessageServer (
char * prog_name);
static void ReceiveMessage (
XtPointer client_data,
int * fd,
XtInputId * id);
static void LogToolTalkError (
DtMsgLogType msg_type,
char * prog_name,
char * function_name,
Tt_status error_num);
static void DieFromToolTalkError (
Widget parent,
char * errfmt,
Tt_status status);
int
main (
int argc,
char ** argv)
{
Display * display;
Arg args[10];
int i = 0;
Tt_status status;
XtSetLanguageProc (NULL, NULL, NULL);
_DtEnvControl (DT_ENV_SET);
XtToolkitInitialize ();
app_context = XtCreateApplicationContext ();
if (!(display = XtOpenDisplay (app_context, NULL, NULL, name,
NULL, 0, &argc, argv))) {
DtMsgLogMessage (argv[0], DtMsgLogError,
(char *) GETMESSAGE (SET_NUM, 7, "XtOpenDisplay() failed. Perhaps the DISPLAY environment\nvariable is not set or is invalid."));
exit (1);
}
/*
* Create a minimalist application shell - needed by
* DtActionInvoke.
*/
XtSetArg (args[i], XtNallowShellResize, True); i++;
XtSetArg (args[i], XtNmappedWhenManaged, False); i++;
XtSetArg (args[i], XtNheight, 1); i++;
XtSetArg (args[i], XtNwidth, 1); i++;
top_level = XtAppCreateShell (argv[0],
name,
topLevelShellWidgetClass,
display,
args,
i);
XtRealizeWidget (top_level);
/*
* Initialize the desktop
*/
if (DtAppInitialize (app_context, display, top_level,
argv[0], (char *)name) == False) {
DtMsgLogMessage (argv[0], DtMsgLogError,
(char *) GETMESSAGE (SET_NUM, 8, "DtAppInitialize() failed. Perhaps the desktop environment\nis not properly installed."));
exit (1);
}
/*
* Connect to the message server
*/
status = ConnectToMessageServer (argv[0]);
if (TT_OK != status) {
char *errfmt;
/*
* An error Message has already been logged.
*/
errfmt = GETMESSAGE (2, 2,
"Could not connect to ToolTalk:\n%s\nExiting ...");
DieFromToolTalkError (top_level, errfmt, status);
}
/*
* Load the datatypes and actions
*/
DtDbLoad();
XtAppMainLoop (app_context);
return (0);
}
static int
InvokeAction (
char * prog_name,
int op_num,
const char * action_name,
char * exec_host,
char * info_lib,
char * topic)
{
DtActionArg * args;
int num_args = 1;
DtActionInvocationID action_id;
if (op_num == SHOW_INFO_AT_LOC)
num_args = 2;
args = (DtActionArg *) XtCalloc (num_args, sizeof (DtActionArg));
if (!args) {
DtMsgLogMessage (prog_name, DtMsgLogError,
(char *) GETMESSAGE (SET_NUM, 6,
"Cannot invoke an action because malloc(1) failed."));
return (0);
}
args[0].argClass = DtACTION_FILE;
args[0].u.file.name = info_lib;
if (op_num == SHOW_INFO_AT_LOC) {
args[1].argClass = DtACTION_BUFFER;
args[1].u.buffer.name = topic;
args[1].u.buffer.size = strlen (topic) + 1;
args[1].u.buffer.writable = False;
}
action_id = DtActionInvoke (top_level,
(char *) action_name,
args,
num_args,
NULL,
exec_host,
NULL,
True,
(DtActionCallbackProc) ActionDoneCallback,
prog_name);
#if defined(DEBUG)
DtMsgLogMessage (prog_name, DtMsgLogError, "Invoked %s\n", action_name);
#endif
/*
* The following test, comment and code are from:
* $TOP/dtaction/Main.c
*
* "Set up a timer if we didn't get a valid procId --
* since there will be no invocation update in that case."
*/
if (!action_id) {
XtAppAddTimeOut (app_context,
10,
(XtTimerCallbackProc) Exit,
NULL);
}
return (1);
}
/* ARGSUSED */
static void
ActionDoneCallback (
DtActionInvocationID id,
XtPointer client_data,
DtActionArg * args,
int num_args,
DtActionStatus status)
{
#if defined(DEBUG)
char *status_name;
switch (status) {
case DtACTION_DONE:
status_name = "DtACTION_DONE";
break;
case DtACTION_OK:
status_name = "DtACTION_DONE";
break;
case DtACTION_INVOKED:
status_name = "DtACTION_DONE";
break;
case DtACTION_FAILED:
status_name = "DtACTION_DONE";
break;
case DtACTION_CANCELED:
status_name = "DtACTION_DONE";
break;
case DtACTION_INVALID_ID:
status_name = "DtACTION_DONE";
break;
case DtACTION_STATUS_UPDATE:
status_name = "DtACTION_DONE";
break;
default:
status_name = "UNKNOWN";
break;
}
#endif
switch (status) {
case DtACTION_DONE:
case DtACTION_OK:
#if defined(DEBUG)
DtMsgLogMessage ("dtinfo_start", DtMsgLogError,
"Action returned %s\n", status_name);
#endif
XtAppAddTimeOut(app_context, 10 * time_out,
(XtTimerCallbackProc) Exit,
NULL);
case DtACTION_INVOKED:
case DtACTION_FAILED:
case DtACTION_CANCELED:
case DtACTION_INVALID_ID:
case DtACTION_STATUS_UPDATE:
default:
#if defined(DEBUG)
DtMsgLogMessage ("dtinfo_start", DtMsgLogError,
"Action returned %s\n", status_name);
#endif
XtAppAddTimeOut(app_context, 10 * time_out,
(XtTimerCallbackProc) Exit,
NULL);
}
}
static Tt_status
ConnectToMessageServer (
char * prog_name)
{
int mark;
char * procid;
int ttfd;
Tt_status status;
mark = tt_mark();
procid = tt_open();
status = tt_pointer_error (procid);
if (status != TT_OK) {
LogToolTalkError (DtMsgLogError, prog_name,
"tt_open", status);
tt_release (mark);
return (status);
}
status = tt_ptype_declare (name);
if (status != TT_OK) {
LogToolTalkError (DtMsgLogError, prog_name,
"tt_ptype_declare", status);
tt_release (mark);
return (status);
}
ttfd = tt_fd ();
if ((tt_int_error (ttfd)) != TT_OK) {
LogToolTalkError (DtMsgLogError, prog_name,
"tt_fd", status);
tt_release (mark);
return (status);
}
XtAppAddInput (app_context, ttfd, (XtPointer) XtInputReadMask,
ReceiveMessage, (char *) prog_name);
status = tt_session_join (tt_default_session());
if ((tt_int_error (ttfd)) != TT_OK) {
LogToolTalkError (DtMsgLogError, prog_name,
"tt_session_join", status);
tt_release (mark);
return (status);
}
tt_release(mark);
return (TT_OK);
}
/* ARGSUSED */
static void
ReceiveMessage (
XtPointer client_data,
int * fd,
XtInputId * id)
{
static int last_op_num = 0;
int op_num;
int opstatus;
int num_args;
Tt_message message;
const char * action_name;
char * exec_host;
char * locale;
char * topic = NULL;
char * prog_name = (char *) client_data;
static char lang[200];
const char * op_name;
char * info_lib = NULL;
message = tt_message_receive();
/* from tt_message_receive(3), and after examining other TT clients */
if (message == 0) return;
if (tt_pointer_error (message) != TT_OK) {
LogToolTalkError (DtMsgLogError, prog_name,
"tt_message_receive",
tt_pointer_error (message));
exit (1);
}
op_num = tt_message_opnum (message);
switch (op_num) {
case LOAD_INFO_LIB:
op_name = LOAD_INFO_LIB_STRING;
break;
case SHOW_INFO_AT_LOC:
op_name = SHOW_INFO_AT_LOC_STRING;
break;
default: {
/*
* Don't know how I got this message
*/
DtMsgLogMessage (prog_name, DtMsgLogError,
(char *) GETMESSAGE (SET_NUM, 11, "The message operation '%d' is not supported."),
op_num);
tt_message_reject (message);
tt_message_destroy(message);
exit (1);
}
}
/*
* Check the number of arguments
*/
num_args = tt_message_args_count (message);
if ((op_num == LOAD_INFO_LIB && num_args != LOAD_INFO_LIB_ARGS) ||
(op_num == SHOW_INFO_AT_LOC && num_args != SHOW_INFO_AT_LOC_ARGS)) {
DtMsgLogMessage (prog_name, DtMsgLogError,
(char *) GETMESSAGE (SET_NUM, 12, "Message '%s' does not have the required\nnumber of arguments '%d'."),
op_name,
(op_num == LOAD_INFO_LIB) ?
LOAD_INFO_LIB_ARGS : SHOW_INFO_AT_LOC_ARGS);
tt_message_reject (message);
tt_message_destroy(message);
exit (1);
}
/*
* Check for an info lib
*/
info_lib = tt_message_file (message);
if ((tt_ptr_error (info_lib) != TT_OK) || info_lib == NULL) {
/*
* Use DTINFOLIBDEFAULT if it is defined
*/
if ((info_lib = getenv ("DTINFOLIBDEFAULT")) == NULL) {
DtMsgLogMessage (prog_name, DtMsgLogError,
(char *) GETMESSAGE (SET_NUM, 10, "An InfoLib was not provided in the '%s' message\nand the environment variable DTINFOLIBDEFAULT was not defined."),
op_name);
exit (1);
}
}
if ((action_name = tt_message_arg_val (message, 0)) == NULL) {
action_name = (op_num == LOAD_INFO_LIB) ?
LOAD_INFO_LIB_ACTION : SHOW_INFO_LIB_SECTION_ACTION;
DtMsgLogMessage (prog_name, DtMsgLogWarning,
(char *) GETMESSAGE (SET_NUM, 13, "Message '%s' specified a NULL action name.\nAction '%s' will be invoked."),
op_name,
action_name);
}
if ((exec_host = tt_message_arg_val (message, 1)) == NULL) {
DtMsgLogMessage (prog_name, DtMsgLogWarning,
(char *) GETMESSAGE (SET_NUM, 14, "Message '%s' specified a NULL execution host."),
op_name);
}
if ((locale = tt_message_arg_val (message, 2)) == NULL) {
DtMsgLogMessage (prog_name, DtMsgLogWarning,
(char *) GETMESSAGE (SET_NUM, 15, "Message '%s' specified a NULL locale."),
op_name);
}
else {
/*
* Put locale into the environment so that DtActionInvoke
* will propagate it to the dtinfo process.
*/
(void) snprintf (lang, sizeof(lang), "LANG=%s", locale);
(void) putenv (lang);
}
if (op_num == SHOW_INFO_AT_LOC) {
if ((topic = tt_message_arg_val (message, 3)) == NULL) {
DtMsgLogMessage (prog_name, DtMsgLogError,
(char *) GETMESSAGE (SET_NUM, 16, "Message '%s' specified a NULL topic."),
op_name);
exit (1);
}
}
if (op_num == last_op_num)
{
#if defined(DEBUG)
DtMsgLogMessage("dtinfo_start", DtMsgLogError,
"Received a duplicate tooltalk message: %s",
(op_num == LOAD_INFO_LIB) ?
"LOAD_INFO_LIB" : "SHOW_INFO_AT_LOC" );
#endif
}
else
{
#if defined(DEBUG)
DtMsgLogMessage(
"dtinfo_start", DtMsgLogError,
"Received a tooltalk message: %s\nInvoking action %s",
(op_num==LOAD_INFO_LIB) ? "LOAD_INFO_LIB" : "SHOW_INFO_AT_LOC",
action_name);
#endif
last_op_num = op_num;
opstatus = InvokeAction (prog_name,
op_num,
action_name,
exec_host,
info_lib,
topic);
if (!opstatus) {
tt_message_fail (message);
exit (1);
}
}
tt_message_reply (message);
tt_message_destroy(message);
}
static void
LogToolTalkError (
DtMsgLogType msg_type,
char * prog_name,
char * function_name,
Tt_status error_num)
{
char *message;
message = tt_status_message(error_num);
DtMsgLogMessage (prog_name, msg_type, "%s: %s", function_name, message);
}
#define GETXMSTRING(s, m, d) XmStringCreateLocalized(GETMESSAGE(s,m,d))
static void
ExitCB (Widget dialog, XtPointer client_data, XtPointer call_data)
{
exit((size_t) client_data);
}
static void
DieFromToolTalkError(Widget parent, char *errfmt, Tt_status status)
{
Arg args[10];
Widget dialog, dialogShell;
char *errmsg, *statmsg;
XmString xms_errmsg, xms_ok, xms_title;
int n, errmsglen;
if (! tt_is_err(status)) return;
statmsg = tt_status_message(status);
errmsglen = strlen(errfmt) + strlen(statmsg) + 2;
errmsg = XtMalloc(errmsglen);
snprintf(errmsg, errmsglen, errfmt, statmsg);
xms_ok = GETXMSTRING(2, 3, "OK");
xms_errmsg = XmStringCreateLocalized(errmsg);
xms_title = GETXMSTRING(2, 1, "Dtinfo: Error");
n = 0;
XtSetArg(args[n], XmNautoUnmanage, False); n++;
XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
dialog = XmCreateErrorDialog(parent, "DtinfoStartError", args, n);
XtAddCallback(dialog, XmNokCallback, ExitCB, (XtPointer) status);
XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
/*
* Disable the frame menu from dialog since we don't want the user
* to be able to close dialogs with the frame menu
*/
dialogShell = XtParent(dialog);
n = 0;
XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
XtSetValues(dialogShell, args, n);
XtManageChild(dialog);
XtRealizeWidget(dialogShell);
XtFree(errmsg);
XmStringFree(xms_ok);
XmStringFree(xms_errmsg);
XmStringFree(xms_title);
while (TRUE)
XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll);
}
/* ARGSUSED */
static void
Exit (
XtPointer client_data,
XtIntervalId id)
{
/*
* The following code to determine if DtActionInvoke
* resulted in the posting a dialog is from:
* $TOP/dtaction/Main.c
*/
if (top_level->core.num_popups == 0)
exit(0);
XtAppAddTimeOut (app_context,
time_out,
(XtTimerCallbackProc) Exit,
NULL);
}