2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: ActionDb.c /main/8 1998/07/30 12:09:13 mgreess $ */
24 /*************************************<+>*************************************
25 *****************************************************************************
31 ** Description: Source file for the action database loading functions.
35 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
36 ** (c) Copyright 1993, 1994 International Business Machines Corp.
37 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
38 ** (c) Copyright 1993, 1994 Novell, Inc.
39 ****************************************************************************
40 ************************************<+>*************************************/
43 #include <sys/types.h>
46 #include <X11/Intrinsic.h>
52 #include <Dt/Message.h>
53 #include <Dt/DbReader.h>
54 #include <Dt/Connect.h>
55 #include <Dt/DtNlUtils.h>
56 #include <Dt/UserMsg.h>
57 #include <Dt/CommandM.h>
59 #include <Dt/ActionUtilP.h>
60 #include <Dt/ActionP.h>
61 #include <Dt/ActionDbP.h>
63 #include <Dt/Utility.h>
67 #include "myassertP.h"
68 #include "DtSvcLock.h"
70 /******** Global Function Declarations ********/
72 extern Boolean _DtEmptyString(
75 /******** End Private Function Declarations ********/
78 /******** Static Function Declarations ********/
80 static void InitializeLocalizedStrings ( void ) ;
82 /******** End Static Function Declarations ********/
85 * Pointers to the localized strings.
88 static char *noFields;
89 static char *unrecogField;
90 static char *unrecogType;
92 static char *noExecString;
93 static char *unrecogMsgType;
94 static char *dupFields;
95 static char *invldField;
96 static char *missingField;
97 static char *missingName;
98 static char *unrecogMsgType2;
101 /*****************************************************************************
102 *****************************************************************************
104 * Public API Functions
106 *****************************************************************************
107 *****************************************************************************/
111 /******************************************************************************
112 ******************************************************************************
114 * Private API Functions
116 ******************************************************************************
117 ******************************************************************************/
119 /******************************************************************************
123 ******************************************************************************/
126 * See if two strings are exactly the same.
134 if ((strcmp(string1, string2) == 0) && (strlen(string1) == strlen(string2)))
142 * Return TRUE if the string pointer is NULL, or if the string is empty.
143 * Empty is also defined to be nothing but spaces.
150 if ((str == NULL)||(strlen(str) == 0)||(strlen(str) == DtStrspn(str, " ")))
162 #ifdef _DT_ALLOW_DT_MSGS
164 * The "DT_ARGn_VALUE" and "TT_ARGn_VALUE" field names are represented by
165 * macros (_DtACTION_DTN_VALUE, _DtACTION_TTN_VALUE) which define identical
166 * strings "_VALUE". (The field names minus the "[DT]_ARGn" prefix.)
168 * To allow an unambiguous table lookup by field name we add the
169 * _DtPFX prefix macro to the "DT_ARGn" field name.
172 #endif /* _DT_ALLOW_DT_MSGS */
175 * List all the action record fields we care about
176 * along with the bitmask that represents the field.
178 static _DtActNameAndBit _DtActNamesAndBits[] = {
179 _DtACTION_LABEL, _ActDb_LABEL_SET,
180 _DtACTION_TYPE, _ActDb_TYPE_SET,
181 _DtACTION_ARG_CLASS, _ActDb_ARG_CLASS_SET,
182 _DtACTION_ARG_MODE, _ActDb_ARG_MODE_SET,
183 _DtACTION_ARG_TYPE, _ActDb_ARG_TYPE_SET,
184 _DtACTION_ARG_COUNT, _ActDb_ARG_COUNT_SET,
185 _DtACTION_DESCRIPTION, _ActDb_DESCRIPTION_SET,
186 _DtACTION_ICON, _ActDb_ICON_SET,
187 /*******************************************************************
188 Meaningless for actions -- ignore these for now
189 _DtACTION_INSTANCE_ICON, _ActDb_INSTANCE_ICON_SET,
190 *******************************************************************/
191 _DtACTION_MAP_ACTION, _ActDb_MAP_ACTION_SET,
192 _DtACTION_EXEC_STRING, _ActDb_EXEC_STRING_SET,
193 _DtACTION_EXEC_HOST, _ActDb_EXEC_HOST_SET,
194 _DtACTION_CWD, _ActDb_CWD_SET,
195 _DtACTION_WINDOW_TYPE, _ActDb_WINDOW_TYPE_SET,
196 _DtACTION_TERM_OPTS, _ActDb_TERM_OPTS_SET,
197 _DtACTION_TT_CLASS, _ActDb_TT_CLASS_SET,
198 _DtACTION_TT_SCOPE, _ActDb_TT_SCOPE_SET,
199 _DtACTION_TT_OPERATION, _ActDb_TT_OPERATION_SET,
200 _DtACTION_TT_FILE, _ActDb_TT_FILE_SET,
201 _DtACTION_TTN_MODE, _ActDb_TT_ARGN_MODE_SET,
202 _DtACTION_TTN_VTYPE, _ActDb_TT_ARGN_VTYP_SET,
203 _DtACTION_TTN_REP_TYPE, _ActDb_TT_ARGN_RTYP_SET,
204 _DtACTION_TTN_VALUE, _ActDb_TT_ARGN_VAL_SET,
206 #ifdef _DT_ALLOW_DT_MSGS
207 _DtACTION_DT_REQUEST_NAME, _ActDb_DT_REQ_NAME_SET,
208 _DtACTION_DT_SVC, _ActDb_DT_SVC_SET,
209 _DtACTION_DT_NOTIFY_NAME, _ActDb_DT_NTFY_NAME_SET,
210 _DtACTION_DT_NGROUP, _ActDb_DT_NGROUP_SET,
211 _DtPFX _DtACTION_DTN_VALUE, _ActDb_DT_ARGN_VAL_SET,
212 #endif /* _DT_ALLOW_DT_MSGS */
216 #define NUM_FIELD_NAMES sizeof(_DtActNamesAndBits)/sizeof(_DtActNameAndBit) - 1
218 /******************************************************************************
220 * _DtActFieldBitLookup
221 * Lookup the mask value associated with the given field name in the array
222 * of names and field bits. If the field name is not recognized return the
223 * default value associated with the NULL field name (i.e. 0 ).
225 ******************************************************************************/
229 _DtActFieldBitLookup(char *name)
233 #ifdef _DT_ALLOW_DT_MSGS
234 char dtnamebuf[sizeof(_DtPFX) + sizeof(_DtACTION_DTN_VALUE)] = _DtPFX;
235 #endif /* _DT_ALLOW_DT_MSGS */
240 * Check for [DT]T_ARGn_ fields
241 * The following code assumes that a unique suffix identifying each
242 * field results from stripping off the leading "[DT]_ARGn" string.
243 * This assumption is not valid for DT_ARGn_VALUE and TT_ARGn_VALUE.
244 * so we resort to further skulduggery.
246 if ( !strncmp("TT_ARG",np,sizeof("TT_ARG")-1) )
248 np = np + sizeof("TT_ARG"); /* first char beyond prefix */
249 while( *np && (mblen(np,MB_CUR_MAX) == 1) && DtIsdigit(np) )
250 np=DtNextChar(np); /* skip past digits */
252 #ifdef _DT_ALLOW_DT_MSGS
253 else if ( !strncmp("DT_ARG",np,sizeof("DT_ARG")-1) )
255 np = np + sizeof("DT_ARG"); /* first char beyond prefix */
256 while( *np && (mblen(np,MB_CUR_MAX) == 1) && DtIsdigit(np) )
257 np=DtNextChar(np); /* skip past digits */
260 * Add the prefix to disambiguate the field name for
263 np=strcat(dtnamebuf,np);
267 #endif /* _DT_ALLOW_DT_MSGS */
272 for ( j = 0; j < NUM_FIELD_NAMES; j++ )
273 if ( !strcmp(_DtActNamesAndBits[j].name,np) )
274 break; /* found matching field name */
276 return _DtActNamesAndBits[j].bit;
279 /******************************************************************************
281 * _DtActFieldNameLookup
282 * Lookup the name string associated with the given mask bit in the array
283 * of names and field bits. If the mask bit is not recognized return the
284 * default value associated with the NULL field name (i.e. 0 ).
286 ******************************************************************************/
289 _DtActFieldNameLookup(long bitmask)
296 for ( j = 0; j < NUM_FIELD_NAMES; j++ )
297 if ( _DtActNamesAndBits[j].bit == bitmask )
298 break; /* found matching field name */
300 return _DtActNamesAndBits[j].name;
304 /******************************************************************************
306 * _DtActDupFieldNameCheck
307 * return True if "name" duplicates an existing fieldName.
309 ******************************************************************************/
311 _DtActDupFieldNameCheck(DtDtsDbField **fields,int numFields,XrmQuark name)
315 for ( i = 0; i < numFields; i++ )
317 if (fields[i]->fieldName == name)
325 /******************************************************************************
327 * _DtActValidateFieldValue
328 * Given a bitmask and action database field value apply some heuristics
329 * to determine the validity of the value. Return a newly allocated
330 * "sanitized" value for valid fields, NULL otherwise.
332 ******************************************************************************/
334 _DtActValidateFieldValue( long bit, char *value, char *actName, char *filename)
339 char bigBuf[_DtAct_MAX_BUF_SIZE];
342 if (!(value && *value))
345 * Empty field value -- ignore
350 /* work on a new copy of the value */
351 val = strdup( value );
354 * Strip trailing blanks from all fields except EXEC_STRING and
355 * DESCRIPTION. The database reader should guarantee that leading
356 * blanks have been stripped from the value field.
358 if ( !(bit & ( _ActDb_EXEC_STRING_SET | _ActDb_DESCRIPTION_SET )))
359 _DtRemoveTrailingBlanksInPlace(&val);
363 case _ActDb_TYPE_SET:
364 if ( strcmp(_DtACTION_MAP,val)
365 && strcmp(_DtACTION_COMMAND,val)
366 && strcmp(_DtACTION_TT_MSG,val)
367 #ifdef _DT_ALLOW_DT_MSGS
368 && strcmp(_DtACTION_DT_REQUEST,val)
369 && strcmp(_DtACTION_DT_NOTIFY,val)
370 #endif /* _DT_ALLOW_DT_MSGS */
374 * Invalid field value -- issue error msg.
376 buf = malloc(_DtAct_MAX_BUF_SIZE);
377 (void) sprintf(buf, unrecogMsgType, actName, filename,
378 val, _DtACTION_TYPE);
379 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
380 if ( val ) free(val);
385 case _ActDb_EXEC_HOST_SET:
387 * Do NOT add to an existing EXEC_HOST definition.
390 case _ActDb_ARG_CLASS_SET:
392 /* Check the list of classes */
395 while ( (p = DtStrchr(start,_DtACT_LIST_SEPARATOR_CHAR)) )
398 * temporarily truncate string for testing
401 if ( strcmp(_DtACT_ANY,start) &&
402 strcmp(_DtACTION_FILE,start) &&
403 strcmp(_DtACTION_BUFFER,start) )
406 * Invalid field value -- issue error msg.
408 buf = malloc(_DtAct_MAX_BUF_SIZE);
409 (void) sprintf(buf, unrecogMsgType, actName, filename,
410 start, _DtACTION_ARG_CLASS);
411 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
412 if ( val ) free(val);
416 *p = _DtACT_LIST_SEPARATOR_CHAR;
419 if ( strcmp(_DtACT_ANY,start) &&
420 strcmp(_DtACTION_FILE,start) &&
421 strcmp(_DtACTION_BUFFER,start) )
424 * Invalid field value -- issue error msg.
426 buf = malloc(_DtAct_MAX_BUF_SIZE);
427 (void) sprintf(buf, unrecogMsgType, actName, filename,
428 start, _DtACTION_ARG_CLASS);
429 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
430 if ( val ) free(val);
435 case _ActDb_ARG_MODE_SET:
436 /* Check for the valid values of ARG_MODE */
437 if ( strcmp(val,_DtACT_ANY)
438 && strcmp(val, _DtACT_ARG_MODE_WRITE)
439 && strcmp(val, _DtACT_ARG_MODE_NOWRITE) )
441 /* Invalid Value for ARG_MODE */
442 buf = malloc(_DtAct_MAX_BUF_SIZE);
443 (void) sprintf(buf, unrecogMsgType, actName, filename,
444 val, _DtACTION_ARG_MODE);
445 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
446 if ( val ) free(val);
447 buf = malloc(_DtAct_MAX_BUF_SIZE);
450 break; /* valid value */
451 case _ActDb_ARG_TYPE_SET:
452 /* We cannot yet check arg types the database is not complete */
454 case _ActDb_ARG_COUNT_SET:
455 if ( !strcmp(val,_DtACT_ANY) )
457 for (p=val; *p; p=DtNextChar(p))
459 if ( p == val && ((*p == _DtACT_LT_CHAR)
460 || (*p == _DtACT_GT_CHAR)))
462 /* skip past "> or <" modifiers */
465 if ( !(mblen(p,MB_CUR_MAX) == 1 && DtIsdigit(p)) )
468 * Report Error -- invalid field
470 buf = malloc(_DtAct_MAX_BUF_SIZE);
471 (void) sprintf(buf, unrecogMsgType, actName,
473 _DtACTION_ARG_COUNT);
474 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
475 if ( val ) free(val);
481 case _ActDb_WINDOW_TYPE_SET:
482 if ( strcmp(_DtACTION_TERMINAL,val) &&
483 strcmp(_DtACTION_PERM_TERMINAL,val) &&
484 strcmp(_DtACTION_NO_STDIO,val) )
487 * Invalid field value -- issue error msg.
489 buf = malloc(_DtAct_MAX_BUF_SIZE);
490 (void) sprintf(buf, unrecogMsgType, actName, filename,
491 val, _DtACTION_WINDOW_TYPE);
492 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
500 * This field must be in [host:]/path format
502 * WE REQUIRE A FULL PATH NAME TO BE SPECIFIED FOR THE
503 * DIRECTORY OTHERWISE WE CANNOT DISTINGUISH BETWEEN A
504 * RELATIVE FILE ENDING IN ':' AND A HOSTNAME FOLLOWED
508 && !( (mblen(val,MB_CUR_MAX) == 1)
509 && DtIsspace(DtNextChar(val))) )
510 break; /* Accept as good with no hostname */
512 for ( p = val; *p ; p=DtNextChar(p) )
516 * Accept as a valid hostname as long as
517 * there is a string of non-white
518 * and non-slash characters before the first
519 * colon and the first colon is immediately
520 * followed by a slash.
523 && ( *(DtNextChar(p)) == '/' ) && ( p != val) )
524 break; /* Accept this as good with hostname */
528 || ( (mblen(p,MB_CUR_MAX) == 1) && DtIsspace(p)))
530 /* looks like an error */
531 buf = malloc(_DtAct_MAX_BUF_SIZE);
532 (void) sprintf(buf, unrecogMsgType, actName,
533 filename, val, _DtACTION_CWD);
534 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
535 if ( val ) free(val);
537 /*********************
538 reject the entire record containing this field
539 *********************/
545 /* looks like an error */
546 buf = malloc(_DtAct_MAX_BUF_SIZE);
547 (void) sprintf(buf, unrecogMsgType, actName,
548 filename, val, _DtACTION_CWD);
549 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
552 /*********************
553 reject the entire record containing this field
554 *********************/
558 case _ActDb_TT_CLASS_SET:
559 if ( strcmp(_DtACTION_TT_NOTICE,val) &&
560 strcmp(_DtACTION_TT_REQUEST,val) )
563 * Invalid field value -- issue error msg.
565 buf = malloc(_DtAct_MAX_BUF_SIZE);
566 (void) sprintf(buf, unrecogMsgType, actName, filename,
567 val, _DtACTION_TT_CLASS);
568 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
569 if ( val ) free(val);
574 case _ActDb_TT_SCOPE_SET:
575 if ( strcmp(_DtACTION_TT_SESSION,val) &&
576 strcmp(_DtACTION_TT_FILE,val) &&
577 strcmp(_DtACTION_TT_BOTH,val) &&
578 strcmp(_DtACTION_TT_FILE_IN_SESSION,val) )
581 * Invalid field value -- issue error msg.
583 buf = malloc(_DtAct_MAX_BUF_SIZE);
584 (void) sprintf(buf, unrecogMsgType, actName, filename,
585 val, _DtACTION_TT_SCOPE);
586 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
587 if ( val ) free(val);
592 case _ActDb_TT_FILE_SET:
594 * Must be a real file (host:/syntax?)
595 * -- convert to network file syntax?
596 * or %ARG_n% keyword.
597 * NOTE: only one file may be specified
600 case _ActDb_TT_ARGN_MODE_SET:
602 * MODE is required for tooltalk actions
603 * it must be one of TT_IN, TT_OUT or TT_INOUT
605 if ( strcmp(_DtACTION_TT_MODE_IN,val ) &&
606 strcmp(_DtACTION_TT_MODE_OUT,val) &&
607 strcmp(_DtACTION_TT_MODE_INOUT,val) )
610 * Invalid field value -- issue error msg.
612 buf = malloc(_DtAct_MAX_BUF_SIZE);
613 (void) sprintf(buf, unrecogMsgType2, actName, filename,
614 val, _DtACTION_TTN_ARG,
615 "n", _DtACTION_TTN_MODE);
616 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
617 if ( val ) free(val);
622 case _ActDb_TT_ARGN_VTYP_SET:
624 * VTYPE -- semantic type name (i.e. title) applied to tooltalk
625 * message value (TT_ARGn_VALUE). The value of this field is
626 * either an arbitrary string, or an action argument reference
630 case _ActDb_TT_ARGN_RTYP_SET:
632 * REP_TYPE -- representation type of the corresponding tooltalk value.
633 * Valid values are: UNDEFINED, INTEGER, BUFFER, and STRING.
635 if ( strcmp(_DtACTION_TT_RTYP_UND,val ) &&
636 strcmp(_DtACTION_TT_RTYP_INT,val) &&
637 strcmp(_DtACTION_TT_RTYP_BUF,val) &&
638 strcmp(_DtACTION_TT_RTYP_STR,val) )
641 * Invalid field value -- issue error msg.
643 buf = malloc(_DtAct_MAX_BUF_SIZE);
644 (void) sprintf(buf, unrecogMsgType2, actName, filename,
645 val, _DtACTION_TTN_ARG,
646 "n", _DtACTION_TTN_REP_TYPE);
647 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
648 if ( val ) free(val);
653 case _ActDb_TT_ARGN_VAL_SET:
655 * The value for the Nth tooltalk argument. This field may be
656 * an arbitrary string.
659 #ifdef _DT_ALLOW_DT_MSGS
660 case _ActDb_DT_REQ_NAME_SET:
662 case _ActDb_DT_NTFY_NAME_SET:
664 #endif /* _DT_ALLOW_DT_MSGS */
682 sizeof(_DtACTION_TTN_ARG) + /* ARGn prefix */
683 3 + /* space for 3 decimal digits */
684 sizeof(_DtACTION_TTN_REP_TYPE)]; /* space for longest suffix */
687 myassert(actionType); /* actionType should never be NULL */
690 * Check action type information for accuracy/completeness.
692 if ( !strcmp(actionType,_DtACTION_COMMAND) )
695 * Check that all recognized fields are suitable for
696 * COMMAND type actions.
700 #ifdef _DT_ALLOW_DT_MSGS
701 | _ActDb_DT_REQUEST_BITS
702 | _ActDb_DT_NOTIFY_BITS
703 #endif /* _DT_ALLOW_DT_MSGS */
707 * Fields unsuitable for COMMAND type actions were
708 * found. -- reject this record.
710 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
711 (void) sprintf (buf, invldField,
712 XrmQuarkToString(actp->recordName),
713 fileName, _DtACTION_COMMAND );
718 * Check that all required fields are present or that
719 * the appropriate default has been set.
721 if ( !(mask & _ActDb_EXEC_STRING_SET) )
723 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
724 (void) sprintf (buf, noExecString,
725 XrmQuarkToString(actp->recordName),
726 fileName, _DtACTION_EXEC_STRING);
730 else if ( !strcmp(actionType,_DtACTION_MAP) )
733 * Check that all recognized fields are suitable for
738 #ifdef _DT_ALLOW_DT_MSGS
739 | _ActDb_DT_REQUEST_BITS
740 | _ActDb_DT_NOTIFY_BITS
741 #endif /* _DT_ALLOW_DT_MSGS */
745 * Fields unsuitable for MAP type actions were
746 * found. -- reject this record.
748 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
749 (void) sprintf (buf, invldField,
750 XrmQuarkToString(actp->recordName),
751 fileName, _DtACTION_MAP );
755 * Check for required fields
757 if ( !(mask & _ActDb_MAP_ACTION_SET) )
759 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
760 (void) sprintf (buf, missingField,
761 XrmQuarkToString(actp->recordName),
762 fileName, _DtACTION_MAP_ACTION, _DtACTION_MAP);
767 else if ( !strcmp(actionType,_DtACTION_TT_MSG) )
770 * Check that all recognized fields are suitable for
771 * TT_MSG type actions.
775 #ifdef _DT_ALLOW_DT_MSGS
776 | _ActDb_DT_NOTIFY_BITS
777 | _ActDb_DT_REQUEST_BITS
778 #endif /* _DT_ALLOW_DT_MSGS */
782 * Fields unsuitable for TT_MSG type actions were
783 * found. -- reject this record.
785 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
786 (void) sprintf (buf, invldField,
787 XrmQuarkToString(actp->recordName),
788 fileName, _DtACTION_TT_MSG );
793 * Insure that all the required fields are present.
795 if ( !(mask & _ActDb_TT_CLASS_SET) )
797 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
798 (void) sprintf (buf, missingField,
799 XrmQuarkToString(actp->recordName),
800 fileName, _DtACTION_TT_CLASS, _DtACTION_TT_MSG);
803 if ( !(mask & _ActDb_TT_SCOPE_SET) )
805 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
806 (void) sprintf (buf, missingField,
807 XrmQuarkToString(actp->recordName),
808 fileName, _DtACTION_TT_SCOPE, _DtACTION_TT_MSG);
811 if ( !(mask & _ActDb_TT_OPERATION_SET) )
813 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
814 (void) sprintf (buf, missingField,
815 XrmQuarkToString(actp->recordName),
816 fileName, _DtACTION_TT_OPERATION,
822 * Check if tooltalk arg info is supplied by this action
824 if ( (mask & _ActDb_TT_ARGN_BITS) )
827 * Check for consistency of the fields
828 * describing tooltalk arguments.
830 if ( !( mask & _ActDb_TT_ARGN_MODE_SET) )
832 char argModeString[ 1
833 + sizeof(_DtACTION_TTN_ARG)
834 + sizeof(_DtACTION_TTN_MODE)];
836 * Missing required arg mode
838 sprintf(argModeString,"%s%s%s",
842 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
843 (void) sprintf (buf, missingField,
844 XrmQuarkToString(actp->recordName),
852 * For each tt arg mode specifier see that the other
853 * required info has been supplied.
854 * -- If a mode specifier is missing for a TT argument;
855 * that argument and all subsequent TT args will
857 * MOVE THIS UP TO DATABASE LOAD TIME
859 for ( i = 0; True; i++ )
861 sprintf(argnFieldName,"%s%d%s",
862 _DtACTION_TTN_ARG, i, _DtACTION_TTN_MODE);
863 if ( !(s = _DtDtsDbGetFieldByName(actp,
865 break; /* no argn mode specified */
867 * See that the other required tt argn
868 * fields exist for n == i.
871 if ( strcmp(s, _DtACTION_TT_MODE_OUT ) )
875 * VTYPE is required for mode
878 sprintf(argnFieldName,"%s%d%s",
879 _DtACTION_TTN_ARG, i,
880 _DtACTION_TTN_VTYPE);
881 if (!(s= _DtDtsDbGetFieldByName(actp,
885 * Missing required field
887 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
890 XrmQuarkToString(actp->recordName),
897 /* RWV -- more checks to add */
903 #ifdef _DT_ALLOW_DT_MSGS
904 else if ( !strcmp(actionType,_DtACTION_DT_REQUEST))
907 * Check that all recognized fields are suitable for
908 * DT_REQUEST type actions.
910 if ( mask & ( _ActDb_CMD_BITS
911 | _ActDb_DT_NOTIFY_BITS
916 * Fields unsuitable for DT_REQUEST type actions were
917 * found. -- reject this record.
919 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
920 (void) sprintf (buf, invldField,
921 XrmQuarkToString(actp->recordName),
922 fileName, _DtACTION_DT_REQUEST );
927 else if ( !strcmp(actionType,_DtACTION_DT_NOTIFY))
930 * Check that all recognized fields are suitable for
931 * Dt_NOTIFY type actions.
933 if ( mask & ( _ActDb_DT_REQUEST_BITS
939 * Fields unsuitable for DT_NOTIFY type actions were
940 * found. -- reject this record.
942 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
943 (void) sprintf (buf, invldField,
944 XrmQuarkToString(actp->recordName),
945 fileName, _DtACTION_DT_NOTIFY );
950 #endif /* _DT_ALLOW_DT_MSGS */
955 * Unrecognized action type
956 * Throw out the whole record
958 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
959 (void) sprintf (buf, unrecogType, _DtACTION_TYPE,
960 actionType, fileName );
965 * The record checks out OK
970 /******************************************************************************
972 * _DtActionConverter - given a list of the fields for an action
973 * definition, put the definition into an internal array.
975 * Returns 'True' if the definition was rejected for any reason, otherwise,
976 * 'False' is returned.
978 * Note: Space that is allocated for database structures uses vanilla
979 * malloc/strdup/realloc/free functions because the database
980 * component (Dts) attempts to be independent of X and Xt.
981 * Space for local usage is allocated using XtMalloc/XtNewString/
982 * /XtRealloc/XtFree family of functions which are somewhat more robust
983 * than the vanilla allocators.
985 * (Replaces _DtParseActionDbEntry)
986 *****************************************************************************/
989 _DtActionConverter(DtDtsDbField * fields,
992 Boolean rejectionStatus)
994 static int firstTime = True;
995 DtDtsDbDatabase *act_db;
996 DtDtsDbRecord *act_rec;
999 unsigned int mask = 0;
1000 char bigBuf[_DtAct_MAX_BUF_SIZE];
1002 char *fileName = _DtDbPathIdToString(pathId);
1005 _DtSvcProcessLock();
1009 InitializeLocalizedStrings ();
1013 * The action database should have been initialized in
1016 act_db = _DtDtsDbGet(_DtACTION_NAME);
1019 /* Action records require that an action name be specified */
1020 if (fields[0].fieldValue == NULL)
1023 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
1024 sprintf (buf, missingName, _DtACTION_NAME, fileName);
1025 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
1027 if (buf) XtFree(buf);
1028 _DtSvcProcessUnlock();
1031 else if ( fields[1].fieldName == 0)
1033 /* The record contains no fields */
1034 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
1035 (void) sprintf (buf, noFields, fields[0].fieldValue, fileName);
1036 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
1038 if (buf) XtFree(buf);
1039 _DtSvcProcessUnlock();
1045 * The first field contains the record name.
1047 act_rec = _DtDtsDbAddRecord(act_db);
1048 act_rec->recordName = XrmStringToQuark(fields[0].fieldValue);
1051 * Get all the field data -- we may get an arbitrary number
1052 * of TT_ARGn_MODE, TT_ARGn_VTYPE, or DT_ARGn_VALUE fields.
1053 * We may also want to support user-defined fields at some
1054 * time in the future -- for now reject unrecognized fileds.
1056 for ( i=1; fields[i].fieldName; i++)
1058 unsigned long ThisBit = 0;
1059 char *fieldVal = NULL;
1061 /* find the corresponding field entry and bitmask */
1063 if ((ThisBit = _DtActFieldBitLookup(XrmQuarkToString(fields[i].fieldName))) != 0)
1065 switch ((int)(fieldVal=_DtActValidateFieldValue(ThisBit,
1066 fields[i].fieldValue, fields[0].fieldValue,
1071 * invalid minor field
1072 * -- reject field only
1078 * Invalid critical field
1079 * --reject entire record
1081 _DtDtsDbDeleteRecord(act_rec,act_db);
1083 _DtSvcProcessUnlock();
1088 * validated fieldVal returned
1093 if ( ThisBit == _ActDb_TYPE_SET )
1094 actionType = fieldVal;
1096 else /* Unrecognized Field */
1100 * Unrecognized Field:
1101 * issue a warning and ignore it for now.
1102 * --- Later we may decide to
1103 * store arbitrary fields for users.
1104 * As a control we may require that a user field
1105 * name begin with some well-known string
1108 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
1109 (void) sprintf (buf, unrecogField,
1110 fields[0].fieldValue,
1112 XrmQuarkToString(fields[i].fieldName),
1113 fields[i].fieldValue);
1117 /*************************************************
1118 * Unrecognized Field -- lets NOT reject the
1119 * entire record (for now) and just ignore the
1120 * unrecognized field. -- this allows old
1121 * syntax to exist in an action record without
1122 * causing outright rejection of the record.
1123 * We may decide to reject such records again
1124 * once things settle down, hence the UNREACHABLE
1125 * code which follows the continue statement.
1126 *************************************************/
1127 _DtSimpleError(DtProgName,DtWarning, NULL, "%s", buf);
1128 if (buf) XtFree(buf);
1132 if ( mask & ThisBit )
1135 * An exhaustive name check is required for the "*_ARGn_"
1136 * fields -- a simple bitmask check is sufficient for
1137 * other field names.
1139 if ( ((ThisBit & _ActDb_ARGN_BITS)
1140 && _DtActDupFieldNameCheck( act_rec->fieldList,
1141 act_rec->fieldCount,
1142 fields[i].fieldName))
1143 || !(ThisBit & _ActDb_ARGN_BITS) )
1146 * Attempt to redefine a field
1147 * reject this record.
1149 buf = XtMalloc(_DtAct_MAX_BUF_SIZE);
1150 (void) sprintf (buf,dupFields, fields[0].fieldValue,
1152 XrmQuarkToString(fields[i].fieldName));
1153 _DtSimpleError(DtProgName,DtError, NULL, "%s", buf);
1154 _DtDtsDbDeleteRecord(act_rec,act_db);
1156 if (buf) XtFree(buf);
1158 _DtSvcProcessUnlock();
1165 fld = _DtDtsDbAddField(act_rec);
1166 fld->fieldName = fields[i].fieldName;
1167 fld->fieldValue = fieldVal;
1172 * Fill in default action type if necessary
1174 if ( !(mask & _ActDb_TYPE_SET) )
1177 * No type specified for this action
1178 * -- revert to default type (i.e. COMMAND).
1180 mask |= _ActDb_TYPE_SET;
1181 actionType = _DtACT_TYPE_DFLT;
1186 * Now check the record for consistency
1189 if ( (buf = _DtActCheckRecord(act_rec,actionType,mask,fileName))
1193 * This is an invalid record
1195 _DtSimpleError(DtProgName,DtError,NULL,"%s",buf);
1196 _DtDtsDbDeleteRecord(act_rec,act_db);
1200 _DtSvcProcessUnlock();
1204 act_rec->seq = ++(act_db->ActionSequenceNumber);
1205 act_rec->pathId = pathId;
1208 _DtSvcProcessUnlock();
1214 _DtFreeActionDB( void )
1216 DtDtsDbDatabase *act_db = _DtDtsDbGet(_DtACTION_NAME);
1220 _DtDtsDbDeleteDb(act_db);
1225 /********************
1227 * InitializeLocalizedStrings - initializes the localized strings.
1229 * MODIFIED: The following variables are all initialized.
1232 * char *unrecogField;
1233 * char *unrecogType;
1235 * char *noExecString;
1236 * char *unrecogMsgType;
1239 * char *missingField;
1240 * char *missingName;
1241 * char *unrecogMsgType2;
1243 ********************/
1246 InitializeLocalizedStrings ( void )
1248 noFields = XtNewString (((char *) Dt11GETMESSAGE (6, 1, "The action definition \"%s\" in the file:\n \"%s\"\n does not have any fields.\n")));
1250 unrecogField = XtNewString (((char *) Dt11GETMESSAGE (6, 2, "The action definition \"%s\" in the file\n \"%s\"\n contains the following unrecognized field name and value:\n \"%s\":\"%s\"\n")));
1252 unrecogType = XtNewString (((char *) Dt11GETMESSAGE (6, 4, "The \"%s\" field in the action definition \"%s\"\n in the file \"%s\"\n has an unrecognized action type.\n")));
1254 noMapTo = XtNewString (((char *) Dt11GETMESSAGE (6, 5, "The action definition \"%s\" in the file\n \"%s\"\n is not mapped properly. The \"%s\" field\n should be: TYPE MAP action_mapped_to.\n")));
1256 noExecString = XtNewString (((char *) Dt11GETMESSAGE (6, 8, "The action definition \"%s\" in the file\n \"%s\"\n is a \"COMMAND\" action type but lacks the\n required field \"%s\".\n")));
1258 unrecogMsgType = XtNewString (((char *) Dt11GETMESSAGE (6, 11, "The action definition \"%s\" in the file\n \"%s\"\n has the illegal value \"%s\" in the \"%s\" field.\n")));
1260 dupFields = XtNewString (((char *) Dt11GETMESSAGE (6, 12, "The action definition \"%s\" in the file\n \"%s\"\n contains duplicate fields named:\n \"%s\".\n")));
1262 invldField = XtNewString (((char *) Dt11GETMESSAGE (6, 13, "The action definition \"%s\" in the file\n \"%s\"\n contains invalid fields for \"%s\" type actions.\n")));
1264 missingField = XtNewString (((char *) Dt11GETMESSAGE (6, 14, "The action definition \"%s\" in the file\n \"%s\"\n is missing the required field, \"%s\"\n for \"%s\" type actions.\n")));
1266 missingName = XtNewString (((char *) Dt11GETMESSAGE (4, 1, "A \"%s\" definition in the file:\n \"%s\"\n is missing a name. Add the name\n to the defintion.\n")));
1268 unrecogMsgType2 = XtNewString (((char *) Dt11GETMESSAGE (6, 16, "The action definition \"%s\" in the file\n \"%s\"\n has the illegal value \"%s\" in the \"%s%s%s\" field.\n")));