ActionFind.c 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394
  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 libraries 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: ActionFind.c /main/11 1998/07/30 12:09:31 mgreess $ */
  24. /*************************************<+>*************************************
  25. *****************************************************************************
  26. **
  27. ** File: ActionFind.c
  28. **
  29. ** Project: DT
  30. **
  31. ** Description: Source file for the action database sorting and
  32. ** locating functions.
  33. **
  34. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  35. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  36. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  37. ** (c) Copyright 1993, 1994 Novell, Inc.
  38. **
  39. ****************************************************************************
  40. ************************************<+>*************************************/
  41. /*LINTLIBRARY*/
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #include <string.h>
  45. #include <X11/Intrinsic.h>
  46. #include <Xm/Xm.h>
  47. #include <Xm/XmP.h>
  48. #include <Tt/tttk.h>
  49. #include <Dt/DtP.h>
  50. #include <Dt/Message.h>
  51. #include <Dt/DbReader.h>
  52. #include <Dt/Connect.h>
  53. #include <Dt/DtNlUtils.h>
  54. #include <Dt/UserMsg.h>
  55. #include <Dt/CommandM.h>
  56. #include <Dt/ActionP.h>
  57. #include <Dt/ActionDb.h>
  58. #include <Dt/ActionUtilP.h>
  59. #include <Dt/ActionFind.h>
  60. #include "myassertP.h"
  61. #include <Dt/Utility.h>
  62. #include <Dt/DtsDb.h>
  63. #include <Dt/DtsMM.h>
  64. #include <Dt/Dts.h>
  65. #include "DtSvcLock.h"
  66. /******** Private Function Declarations ********/
  67. DtDtsMMRecord *
  68. _DtActionLocateRecord(
  69. DtShmBoson actQuark,
  70. unsigned long mask,
  71. DtShmBoson arg_type,
  72. int arg_count,
  73. DtDtsMMDatabase *act_db);
  74. /******** End Private Function Declarations ********/
  75. /******** Static Function Declarations ********/
  76. static int _DtActMMCompareObjClassMask(
  77. unsigned long objClassMask,
  78. char *actClass);
  79. static int _DtActMMCompareMode(
  80. unsigned long objMask,
  81. char *actMode);
  82. static int _DtActMMCompareType(
  83. DtShmBoson reqType,
  84. char *actType);
  85. static int _DtActMMCompareCount(
  86. int reqCount,
  87. char *actCount);
  88. static int _DtActionCompareRecordQuarks(
  89. DtDtsDbRecord ** record1,
  90. DtDtsDbRecord ** record2) ;
  91. static void _DtActionGetRecordWeight(
  92. DtDtsDbRecord ** record,
  93. long * primaryWeightPtr,
  94. long * secondaryWeightPtr );
  95. static void ParseMessage(
  96. register ActionPtr action,
  97. register char * str,
  98. register parsedMsg * msg) ;
  99. static Boolean ValidKeyword(
  100. char *start,
  101. char *end,
  102. char **prompt,
  103. int *keywordId,
  104. int *argNum,
  105. Boolean *isFile );
  106. static unsigned long _DtActMMParseArgTypesList(
  107. char *tlist,
  108. DtShmBoson **quarkAddr,
  109. int *countp);
  110. static unsigned long _DtActMMParseClassList(
  111. char *clist);
  112. static unsigned long _DtActMMParseArgCountString(
  113. char *countStr,
  114. int *countp);
  115. static unsigned long _DtActMMParseActionType(
  116. char *actionTypeStr);
  117. static void _DtActMMGetCmdInfo(
  118. DtDtsMMRecord *actRecp,
  119. ActionPtr actp);
  120. static void _DtActMMGetTtMsgInfo(
  121. DtDtsMMRecord *actRecp,
  122. ActionPtr actp);
  123. static int _DtActInputSeqCheck(
  124. DtDtsDbRecord *r1,
  125. DtDtsDbRecord *r2);
  126. static char * _DtActDbChooseLabel(
  127. DtDtsDbRecord *rec);
  128. static char * _DtActMMChooseLabel(
  129. DtDtsMMRecord *rec);
  130. static void _DtCheckForDuplicateRecord(
  131. DtDtsDbRecord *rec,
  132. DtDtsDbRecord *duprec);
  133. static char * _DtActGetDtsDbField(
  134. DtDtsDbRecord *recp,
  135. char * fieldName );
  136. static char *
  137. _DtActGetDtsMMField ( DtDtsMMRecord *actRecp, char *name );
  138. static void _DtSearchDuplicateRecord(
  139. DtDtsDbDatabase *db);
  140. #ifdef _DT_ALLOW_DT_MSGS
  141. static void _DtActDbGetDtNtfyInfo(
  142. DtDtsDbRecord *actRecp,
  143. ActionPtr actp);
  144. static void _DtActDbGetDtReqInfo(
  145. DtDtsDbRecord *actRecp,
  146. ActionPtr actp);
  147. #endif /* _DT_ALLOW_DT_MSGS */
  148. /******** End Static Function Declarations ********/
  149. #define SPECIFIC_ARG_CLASS 8
  150. #define SPECIFIC_ARG_TYPE 4
  151. #define SPECIFIC_ARG_MODE 2
  152. #define SPECIFIC_ARG_COUNT 1
  153. #define SECONDARY_SPECIFIC 4
  154. #define SECONDARY_LESS_THAN 3
  155. #define SECONDARY_GREATER_THAN 2
  156. #define SECONDARY_WILDCARD 1
  157. #define _MAX_MAP_ATTEMPTS 100
  158. /******************************************************************************
  159. * External data
  160. ******************************************************************************/
  161. extern XtAppContext _DtAppContext;
  162. /******************************************************************************
  163. ******************************************************************************
  164. *
  165. * Public API Functions
  166. *
  167. ******************************************************************************
  168. ******************************************************************************/
  169. /*****************************************************************************
  170. * DtActionDescription:
  171. *---------------------
  172. * This function returns the description associated with an action of the
  173. * given name, "actionName". If there are multiple actions with the desired
  174. * name, then the description of the "most generic" action of the given name
  175. * is returned.
  176. *
  177. * NOTE: A new copy of the description string is returned.
  178. * It is up to the calling function to free the space allocated
  179. * for the description string.
  180. *****************************************************************************/
  181. static char *_DtActionDbDescription(char *s);
  182. static char *_DtActionMMDescription(char *s);
  183. char *
  184. DtActionDescription (
  185. char *s
  186. )
  187. {
  188. char *actionDesc;
  189. _DtSvcAppLockDefault();
  190. actionDesc = (use_in_memory_db) ? _DtActionDbDescription(s) :
  191. _DtActionMMDescription(s);
  192. _DtSvcAppUnlockDefault();
  193. return actionDesc;
  194. }
  195. static char *
  196. _DtActionDbDescription ( char *s )
  197. {
  198. int n;
  199. XrmQuark tmpq;
  200. DtDtsDbRecord **act_rec;
  201. DtDtsDbRecord **last_rec_found = NULL;
  202. DtDtsDbDatabase *act_db;
  203. _DtSvcProcessLock();
  204. act_db = _DtDtsDbGet(_DtACTION_NAME);
  205. myassert(s);
  206. if ( !s ) {
  207. _DtSvcProcessUnlock();
  208. return NULL;
  209. }
  210. tmpq = XrmStringToQuark(s);
  211. n = act_db->recordCount;
  212. for ( act_rec = act_db->recordList;
  213. n && act_rec && *act_rec ;
  214. act_rec++, n--)
  215. {
  216. if ( (*act_rec)->recordName == (long) tmpq )
  217. last_rec_found = act_rec;
  218. /*
  219. * Since actions are in name "quark" order, there is
  220. * no sense searching past the desired quark value.
  221. */
  222. if ( (*act_rec)->recordName > (long) tmpq )
  223. break;
  224. }
  225. if ( last_rec_found ) {
  226. _DtSvcProcessUnlock();
  227. return XtNewString(_DtActGetDtsDbField(
  228. *last_rec_found,_DtACTION_DESCRIPTION));
  229. }
  230. _DtSvcProcessUnlock();
  231. return NULL;
  232. }
  233. static char *
  234. _DtActionMMDescription ( char *s )
  235. {
  236. int n;
  237. DtShmBoson tmpq;
  238. DtDtsMMRecord *act_rec;
  239. DtDtsMMRecord *act_rec_list;
  240. DtDtsMMRecord *last_rec_found = NULL;
  241. DtDtsMMDatabase *act_db;
  242. int *start;
  243. _DtSvcProcessLock();
  244. act_db = _DtDtsMMGet(_DtACTION_NAME);
  245. myassert(s);
  246. if ( !s ) {
  247. _DtSvcProcessUnlock();
  248. return NULL;
  249. }
  250. if((tmpq = _DtDtsMMStringToBoson(s)) == -1)
  251. {
  252. _DtSvcProcessUnlock();
  253. return(NULL);
  254. }
  255. act_rec_list = _DtDtsMMGetPtr(act_db->recordList);
  256. start = (int*)_DtDtsMMGetDbName(act_db,tmpq);
  257. for ( n = *start; n < act_db->recordCount; n++)
  258. {
  259. act_rec = &act_rec_list[n];
  260. if ( act_rec->recordName == tmpq )
  261. last_rec_found = act_rec;
  262. /*
  263. * Since actions are in name "boson" order, there is
  264. * no sense searching past the desired quark value.
  265. */
  266. if ( act_rec->recordName > tmpq )
  267. break;
  268. }
  269. if ( last_rec_found ) {
  270. _DtSvcProcessUnlock();
  271. return _DtActGetDtsMMField(last_rec_found,
  272. _DtACTION_DESCRIPTION);
  273. }
  274. _DtSvcProcessUnlock();
  275. return NULL;
  276. }
  277. /******************************************************************************
  278. * DtActionExists --
  279. * Given a string return True; if the string corresponds to an
  280. * action name; False otherwise.
  281. *
  282. ******************************************************************************/
  283. static Boolean _DtActionDbExists(char *s);
  284. static Boolean _DtActionMMExists(char *s);
  285. Boolean
  286. DtActionExists( char *s)
  287. {
  288. Boolean actionExists;
  289. _DtSvcAppLockDefault();
  290. actionExists = (use_in_memory_db) ? _DtActionDbExists(s) :
  291. _DtActionMMExists(s);
  292. _DtSvcAppUnlockDefault();
  293. return actionExists;
  294. }
  295. static Boolean
  296. _DtActionDbExists(char *s)
  297. {
  298. int n;
  299. XrmQuark tmpq;
  300. DtDtsDbRecord **act_rec;
  301. DtDtsDbDatabase *act_db;
  302. _DtSvcProcessLock();
  303. act_db = _DtDtsDbGet(_DtACTION_NAME);
  304. myassert(s);
  305. if (!s) {
  306. _DtSvcProcessUnlock();
  307. return False;
  308. }
  309. tmpq = XrmStringToQuark(s);
  310. n = act_db->recordCount;
  311. myassert (act_db);
  312. for ( act_rec = act_db->recordList;
  313. n && act_rec && *act_rec;
  314. act_rec++, n--)
  315. {
  316. if ( (*act_rec)->recordName == (long) tmpq ) {
  317. _DtSvcProcessUnlock();
  318. return True;
  319. }
  320. }
  321. _DtSvcProcessUnlock();
  322. return False;
  323. }
  324. static Boolean
  325. _DtActionMMExists(char *s)
  326. {
  327. DtShmBoson tmpq;
  328. DtDtsMMDatabase *act_db;
  329. _DtSvcProcessLock();
  330. act_db = _DtDtsMMGet(_DtACTION_NAME);
  331. myassert(s);
  332. if (!s) {
  333. _DtSvcProcessUnlock();
  334. return False;
  335. }
  336. tmpq = _DtDtsMMStringToBoson(s);
  337. myassert (act_db);
  338. if(tmpq != -1 && _DtDtsMMGetDbName(act_db,tmpq))
  339. {
  340. _DtSvcProcessUnlock();
  341. return True;
  342. }
  343. _DtSvcProcessUnlock();
  344. return False;
  345. }
  346. /******************************************************************************
  347. * DtActionLabel --
  348. * Given an action name string return the label string
  349. * (localizable name) for the action. return NULL if no action is found.
  350. *
  351. * Return the label associated with the "most generic" action of the
  352. * given name in the database. In this case, we do not track down
  353. * MAP actions since even a MAP action may have its own label.
  354. ******************************************************************************/
  355. static char *_DtActionDbLabel(char *s);
  356. static char *_DtActionMMLabel(char *s);
  357. char *
  358. DtActionLabel( char *s)
  359. {
  360. char *actionLabel;
  361. _DtSvcAppLockDefault();
  362. actionLabel = (use_in_memory_db) ? _DtActionDbLabel(s) :
  363. _DtActionMMLabel(s);
  364. _DtSvcAppUnlockDefault();
  365. return actionLabel;
  366. }
  367. static char *
  368. _DtActionDbLabel ( char *s )
  369. {
  370. int n;
  371. XrmQuark tmpq;
  372. char *label;
  373. DtDtsDbRecord **act_rec;
  374. DtDtsDbRecord **last_rec_found = NULL;
  375. DtDtsDbDatabase *act_db;
  376. _DtSvcProcessLock();
  377. act_db = _DtDtsDbGet(_DtACTION_NAME);
  378. myassert(s);
  379. if ( !s ) {
  380. _DtSvcProcessUnlock();
  381. return NULL;
  382. }
  383. tmpq = XrmStringToQuark(s);
  384. n = act_db->recordCount;
  385. for ( act_rec = act_db->recordList;
  386. n && act_rec && *act_rec;
  387. act_rec++, n--)
  388. {
  389. if ( (*act_rec)->recordName == (long) tmpq )
  390. last_rec_found = act_rec;
  391. /*
  392. * Since actions are in name "quark" order, there is
  393. * no sense searching past the desired quark value.
  394. */
  395. if ( (*act_rec)->recordName > (long) tmpq )
  396. break;
  397. }
  398. if ( last_rec_found )
  399. {
  400. /*
  401. * We have found the desired action
  402. * Obtain the associated label (if any).
  403. */
  404. _DtSvcProcessUnlock();
  405. return _DtActDbChooseLabel(*last_rec_found);
  406. }
  407. /*
  408. * We failed to find the desired action -- therefore return NULL.
  409. */
  410. _DtSvcProcessUnlock();
  411. return NULL;
  412. }
  413. static char *
  414. _DtActionMMLabel ( char *s )
  415. {
  416. int n;
  417. DtShmBoson tmpq;
  418. char *label;
  419. DtDtsMMRecord *act_rec;
  420. DtDtsMMRecord *act_rec_list;
  421. DtDtsMMRecord *last_rec_found = NULL;
  422. DtDtsMMDatabase *act_db;
  423. int *start;
  424. _DtSvcProcessLock();
  425. act_db = _DtDtsMMGet(_DtACTION_NAME);
  426. myassert(s);
  427. if ( !s ) {
  428. _DtSvcProcessUnlock();
  429. return NULL;
  430. }
  431. if((tmpq = _DtDtsMMStringToBoson(s)) == -1)
  432. {
  433. _DtSvcProcessUnlock();
  434. return(NULL);
  435. }
  436. act_rec_list = _DtDtsMMGetPtr(act_db->recordList);
  437. start = (int*)_DtDtsMMGetDbName(act_db,tmpq);
  438. if ( !start ) {
  439. _DtSvcProcessUnlock();
  440. return NULL;
  441. }
  442. for ( n = *start; n < act_db->recordCount; n++)
  443. {
  444. act_rec = &act_rec_list[n];
  445. if ( act_rec->recordName == tmpq )
  446. last_rec_found = act_rec;
  447. /*
  448. * Since actions are in name "boson" order, there is
  449. * no sense searching past the desired quark value.
  450. */
  451. if ( act_rec->recordName > tmpq )
  452. break;
  453. }
  454. if ( last_rec_found )
  455. {
  456. /*
  457. * We have found the desired action
  458. * Obtain the associated label (if any).
  459. */
  460. _DtSvcProcessUnlock();
  461. return _DtActMMChooseLabel(last_rec_found);
  462. }
  463. /*
  464. * We failed to find the desired action -- therefore return NULL.
  465. */
  466. _DtSvcProcessUnlock();
  467. return NULL;
  468. }
  469. /******************************************************************************
  470. * DtActionIcon --
  471. * Given an action name string return the icon name string
  472. * for the action. return NULL if no action is found.
  473. *
  474. * Return the icon associated with the "most generic" action of the
  475. * given name in the database. In this case, we do not track down
  476. * MAP actions since even a MAP action may have its own icon.
  477. ******************************************************************************/
  478. static char *_DtActionDbIcon(char *s);
  479. static char *_DtActionMMIcon(char *s);
  480. char *
  481. DtActionIcon( char *s)
  482. {
  483. char *actionIcon;
  484. _DtSvcAppLockDefault();
  485. actionIcon = (use_in_memory_db) ? _DtActionDbIcon(s) :
  486. _DtActionMMIcon(s);
  487. _DtSvcAppUnlockDefault();
  488. return actionIcon;
  489. }
  490. static char *
  491. _DtActionDbIcon ( char *s )
  492. {
  493. int n;
  494. XrmQuark tmpq;
  495. char *iconString;
  496. DtDtsDbRecord **act_rec;
  497. DtDtsDbRecord **last_rec_found = NULL;
  498. DtDtsDbDatabase *act_db;
  499. _DtSvcProcessLock();
  500. act_db = _DtDtsDbGet(_DtACTION_NAME);
  501. myassert(s);
  502. if ( !s ) {
  503. _DtSvcProcessUnlock();
  504. return NULL;
  505. }
  506. tmpq = XrmStringToQuark(s);
  507. n = act_db->recordCount;
  508. for ( act_rec = act_db->recordList;
  509. n && act_rec && *act_rec;
  510. act_rec++, n--)
  511. {
  512. if ( (*act_rec)->recordName == (long) tmpq )
  513. last_rec_found = act_rec;
  514. /*
  515. * Since actions are in name "quark" order, there is
  516. * no sense searching past the desired quark value.
  517. */
  518. if ( (*act_rec)->recordName > (long) tmpq )
  519. break;
  520. }
  521. if ( last_rec_found )
  522. {
  523. /*
  524. * We have found the desired action
  525. * Obtain the associated icon name (if any).
  526. */
  527. if ((iconString =
  528. _DtActGetDtsDbField(*last_rec_found,_DtACTION_ICON))
  529. != NULL ) {
  530. _DtSvcProcessUnlock();
  531. return XtNewString(iconString);
  532. }
  533. /*
  534. * If no icon name is specified for this action
  535. * return the default action icon name.
  536. */
  537. _DtSvcProcessUnlock();
  538. return _DtGetActionIconDefault();
  539. }
  540. /*
  541. * We failed to find the desired action -- therefore return NULL.
  542. */
  543. _DtSvcProcessUnlock();
  544. return NULL;
  545. }
  546. static char *
  547. _DtActionMMIcon ( char *s )
  548. {
  549. int n;
  550. DtShmBoson tmpq;
  551. char *iconString;
  552. DtDtsMMRecord *act_rec;
  553. DtDtsMMRecord *act_rec_list;
  554. DtDtsMMRecord *last_rec_found = NULL;
  555. DtDtsMMDatabase *act_db;
  556. int *start;
  557. _DtSvcProcessLock();
  558. act_db = _DtDtsMMGet(_DtACTION_NAME);
  559. myassert(s);
  560. if ( !s ) {
  561. _DtSvcProcessUnlock();
  562. return NULL;
  563. }
  564. if((tmpq = _DtDtsMMStringToBoson(s)) == -1)
  565. {
  566. _DtSvcProcessUnlock();
  567. return(NULL);
  568. }
  569. act_rec_list = _DtDtsMMGetPtr(act_db->recordList);
  570. start = (int*)_DtDtsMMGetDbName(act_db,tmpq);
  571. for ( n = *start; n < act_db->recordCount; n++)
  572. {
  573. act_rec = &act_rec_list[n];
  574. if ( act_rec->recordName == tmpq )
  575. last_rec_found = act_rec;
  576. /*
  577. * Since actions are in name "boson" order, there is
  578. * no sense searching past the desired quark value.
  579. */
  580. if ( act_rec->recordName > tmpq )
  581. break;
  582. }
  583. if ( last_rec_found )
  584. {
  585. /*
  586. * We have found the desired action
  587. * Obtain the associated icon name (if any).
  588. */
  589. if ((iconString =
  590. _DtActGetDtsMMField(last_rec_found,_DtACTION_ICON))
  591. != NULL ) {
  592. _DtSvcProcessUnlock();
  593. return iconString;
  594. }
  595. /*
  596. * If no icon name is specified for this action
  597. * return the default action icon name.
  598. */
  599. _DtSvcProcessUnlock();
  600. return _DtGetActionIconDefault();
  601. }
  602. /*
  603. * We failed to find the desired action -- therefore return NULL.
  604. */
  605. _DtSvcProcessUnlock();
  606. return NULL;
  607. }
  608. /******************************************************************************
  609. ******************************************************************************
  610. *
  611. * Private API Functions
  612. *
  613. ******************************************************************************
  614. ******************************************************************************/
  615. /******************************************************************************
  616. *
  617. * _DtActGetDtsDbField( recp, *name )
  618. *
  619. * This function is a wrapper around _DtDtsGetFieldByName() which provides
  620. * default values for certain fields if they are not present in the
  621. * action database record.
  622. *
  623. ******************************************************************************/
  624. static char *
  625. _DtActGetDtsDbField ( DtDtsDbRecord *actRecp, char *name )
  626. {
  627. char *val = _DtDtsDbGetFieldByName( actRecp, name );
  628. if ( val )
  629. return val;
  630. /*
  631. * Return defaults for certain necessary fields.
  632. */
  633. if ( !strcmp( name, _DtACTION_TYPE ) )
  634. return _DtACT_TYPE_DFLT;
  635. if ( !strcmp( name, _DtACTION_ARG_CLASS ) )
  636. return _DtACT_ARG_CLASS_DFLT;
  637. if ( !strcmp( name, _DtACTION_ARG_TYPE ) )
  638. return _DtACT_ARG_TYPE_DFLT;
  639. if ( !strcmp( name, _DtACTION_ARG_COUNT ) )
  640. return _DtACT_ARG_CNT_DFLT;
  641. if ( !strcmp( name, _DtACTION_ARG_MODE ) )
  642. return _DtACT_ARG_MODE_DFLT;
  643. return NULL;
  644. }
  645. static char *
  646. _DtActGetDtsMMField ( DtDtsMMRecord *actRecp, char *name )
  647. {
  648. char *val = (char *)_DtDtsMMGetFieldByName( actRecp, name );
  649. if ( val )
  650. return _DtDtsMMExpandValue(val);
  651. /*
  652. * Return defaults for certain necessary fields.
  653. */
  654. if ( !strcmp( name, _DtACTION_TYPE ) )
  655. return strdup(_DtACT_TYPE_DFLT);
  656. if ( !strcmp( name, _DtACTION_ARG_CLASS ) )
  657. return strdup(_DtACT_ARG_CLASS_DFLT);
  658. if ( !strcmp( name, _DtACTION_ARG_TYPE ) )
  659. return strdup(_DtACT_ARG_TYPE_DFLT);
  660. if ( !strcmp( name, _DtACTION_ARG_COUNT ) )
  661. return strdup(_DtACT_ARG_CNT_DFLT);
  662. if ( !strcmp( name, _DtACTION_ARG_MODE ) )
  663. return strdup(_DtACT_ARG_MODE_DFLT);
  664. return NULL;
  665. }
  666. /******************************************************************************
  667. *
  668. * _DtActDbChooseLabel
  669. * This function returns a label string for the given action record.
  670. * If the record does not contain a specified label then the action name
  671. * name itself is returned.
  672. *
  673. ******************************************************************************/
  674. static char *
  675. _DtActDbChooseLabel(DtDtsDbRecord *rec)
  676. {
  677. char *label;
  678. if ( !rec )
  679. return NULL;
  680. if ((label=
  681. _DtActGetDtsDbField(rec, _DtACTION_LABEL)) != NULL)
  682. return XtNewString(label);
  683. /*
  684. * If no label is specified for this action
  685. * return the action name itself.
  686. */
  687. return XtNewString(XrmQuarkToString(rec->recordName));
  688. }
  689. static char *
  690. _DtActMMChooseLabel(DtDtsMMRecord *rec)
  691. {
  692. char *label;
  693. if ( !rec )
  694. return NULL;
  695. label= _DtActGetDtsMMField(rec, _DtACTION_LABEL);
  696. if (NULL != label)
  697. {
  698. /*
  699. * Fix FMM Purify error.
  700. */
  701. char *rtn = XtNewString(label);
  702. free((void*) label);
  703. return rtn;
  704. }
  705. /*
  706. * If no label is specified for this action
  707. * return the action name itself.
  708. */
  709. return XtNewString((char *)_DtDtsMMBosonToString(rec->recordName));
  710. }
  711. /*
  712. * This function is invoked by DtDbLoad(), once the complete
  713. * action database has been loaded. It will first sort lexically each of
  714. * the fields within all of the records. It will then sort the records,
  715. * based upon the specificity of the action defined within the record.
  716. * Lastly, it will replace the record 'compare' function associated with
  717. * this database, so that it can be used to help locate a record, based
  718. * on certain criteria.
  719. */
  720. /* used for building only */
  721. void
  722. _DtSortActionDb( void )
  723. {
  724. DtDtsDbDatabase * actionDB;
  725. int i;
  726. _DtSvcProcessLock();
  727. actionDB = _DtDtsDbGet(_DtACTION_NAME);
  728. for (i = 0; i < actionDB->recordCount; i++)
  729. {
  730. /*
  731. * Use the internal default DtsDb fieldsort function
  732. * which sorts fields lexically by name; by passing a
  733. * NULL for the compare function address.
  734. */
  735. _DtDtsDbFieldSort(actionDB->recordList[i], NULL);
  736. }
  737. _DtDtsDbRecordSort(actionDB, _DtActionCompareRecordQuarks);
  738. /*
  739. * We will mark duplicate records for deletion by setting
  740. * the "pathId" field to zero.
  741. */
  742. _DtSearchDuplicateRecord(actionDB);
  743. /*
  744. * Search for and delete action records which have been marked
  745. * for deletion by setting PathId to zero. These should be
  746. * duplicate records which have been overidden.
  747. */
  748. for ( i=0; i < actionDB->recordCount; i++ )
  749. {
  750. if (actionDB->recordList[i]->pathId == 0)
  751. {
  752. _DtDtsDbDeleteRecord(actionDB->recordList[i],actionDB);
  753. /*
  754. * Record deletion has adjusted the recordCount field for the
  755. * database. We must now adjust our counter (i) because record
  756. * deletion shifts all subsequent records down to backfill holes
  757. * in the record array. This means we must check the record at "i"
  758. * again because it is now a new, unchecked record.
  759. */
  760. i--;
  761. /*
  762. * RWV: We should probably add the capacity to announce removal of
  763. * such duplicate records.
  764. */
  765. }
  766. }
  767. _DtSvcProcessUnlock();
  768. }
  769. /* used for building only */
  770. static void
  771. _DtSearchDuplicateRecord(DtDtsDbDatabase *db)
  772. {
  773. int i, j;
  774. DtDtsDbRecord *rec1, *rec2;
  775. i = 0;
  776. while(i < db->recordCount - 1) {
  777. rec1 = db->recordList[i];
  778. j = ++i;
  779. /* see if rec1 is already marked as a duplicate */
  780. if ( rec1->pathId == 0 )
  781. continue;
  782. while(j < db->recordCount) {
  783. rec2 = db->recordList[j];
  784. if(rec1->recordName == rec2->recordName) {
  785. if(rec2->pathId != 0)
  786. _DtCheckForDuplicateRecord(rec1, rec2);
  787. j++;
  788. }
  789. else
  790. j = db->recordCount;
  791. }
  792. }
  793. }
  794. /******************************************************************************
  795. *
  796. * _DtCheckForDuplicateRecord
  797. *
  798. * Compare the name, class, type, mode and arg_counts of the two input records.
  799. * These are the selection criteria fields for actions.
  800. * If they are identical then mark the potential duplicate (duprec) for
  801. * deletion by setting its "pathId" field to zero. If the records are not
  802. * really duplicates do nothing.
  803. ******************************************************************************/
  804. /* used for building only */
  805. static void
  806. _DtCheckForDuplicateRecord( DtDtsDbRecord *rec, DtDtsDbRecord *duprec)
  807. {
  808. char *field1, *field2;
  809. /*
  810. * Compare action record name quarks
  811. */
  812. myassert(rec->recordName == duprec->recordName);
  813. if (rec->recordName != duprec->recordName)
  814. return; /* action names differ */
  815. /*
  816. * Compare class fields
  817. */
  818. field1 = _DtActGetDtsDbField(rec,_DtACTION_ARG_CLASS);
  819. field2 = _DtActGetDtsDbField(duprec,_DtACTION_ARG_CLASS);
  820. if ( strcmp(field1,field2) )
  821. return; /* arg_class fields differ */
  822. /*
  823. * Compare type fields
  824. */
  825. field1 = _DtActGetDtsDbField(rec,_DtACTION_ARG_TYPE);
  826. field2 = _DtActGetDtsDbField(duprec,_DtACTION_ARG_TYPE);
  827. if ( strcmp(field1,field2) )
  828. return; /* arg_type fields differ */
  829. /*
  830. * Compare mode fields
  831. */
  832. field1 = _DtActGetDtsDbField(rec,_DtACTION_ARG_MODE);
  833. field2 = _DtActGetDtsDbField(duprec,_DtACTION_ARG_MODE);
  834. if ( strcmp(field1,field2) )
  835. return; /* arg_mode fields differ */
  836. /*
  837. * Compare arg_count fields
  838. */
  839. field1 = _DtActGetDtsDbField(rec,_DtACTION_ARG_COUNT);
  840. field2 = _DtActGetDtsDbField(duprec,_DtACTION_ARG_COUNT);
  841. if ( strcmp(field1,field2) )
  842. return; /* arg_count fields differ */
  843. /*
  844. * Mark the potential duplicate record for later deletion
  845. */
  846. duprec->pathId = 0;
  847. return;
  848. }
  849. /*
  850. * This function is used to sort the action database records; the
  851. * records are sorted first by name (i.e. quark value) and then, if the names
  852. * match, according to their specificity; the more specific
  853. * a definition is, the higher it is in the database. Records which have
  854. * the same specificity will maintain their relative ordering. Each record
  855. * is assigned a 'weight', which is based upon the specificity of a
  856. * prioritized set of fields within that record (i.e. the 'signiture'
  857. * fields). The weight is assigned according to the following table;
  858. * the higher the table value, the more specific the action record is.
  859. *
  860. * -------------------------------------------
  861. * ARG_CLASS | S | S | S | S | N | N | N | N |
  862. * -------------------------------------------
  863. * ARG_TYPE | S | S | W | W | S | S | W | W |
  864. * -------------------------------------------
  865. * ARG_COUNT | S | W | S | W | S | W | S | W |
  866. * -------------------------------------------
  867. * weight -> 7 6 5 4 3 2 1 0
  868. *
  869. * KEY: S = Value is very specific
  870. * N = Value is not specific (i.e. "*", ">n", "<n")
  871. *
  872. * For action records which have a non-specific ARG_COUNT setting, there
  873. * is a second weight calculated. Non-specific ARG_COUNT values are
  874. * weighted using the following guidelines:
  875. *
  876. * specific -> highest
  877. * "<n"
  878. * ">n"
  879. * "*" -> lowest
  880. */
  881. /* used for building only */
  882. static int
  883. _DtActionCompareRecordQuarks(
  884. DtDtsDbRecord ** record1,
  885. DtDtsDbRecord ** record2 )
  886. {
  887. long r1PrimaryWeight, r1SecondaryWeight;
  888. long r2PrimaryWeight, r2SecondaryWeight;
  889. if ( (*record1)->recordName < (*record2)->recordName )
  890. return -1;
  891. else if ( (*record1)->recordName > (*record2)->recordName )
  892. return 1;
  893. /*
  894. * For actions whose names (i.e. quarks) match, apply the weighting
  895. * algorithm described above.
  896. */
  897. _DtActionGetRecordWeight(record1, &r1PrimaryWeight, &r1SecondaryWeight);
  898. _DtActionGetRecordWeight(record2, &r2PrimaryWeight, &r2SecondaryWeight);
  899. if (r1PrimaryWeight > r2PrimaryWeight)
  900. return(-1);
  901. else if ( r1PrimaryWeight < r2PrimaryWeight)
  902. return(1);
  903. else
  904. {
  905. /* If primary weights are the same, check the secondary weight */
  906. if (r1SecondaryWeight > r2SecondaryWeight)
  907. return(-1);
  908. else if (r1SecondaryWeight < r2SecondaryWeight)
  909. return(1);
  910. else
  911. {
  912. /*
  913. * If everything matches we must preserve input order.
  914. * We cannot simply assume that record1 preceded record2 in
  915. * the input order since the quick sort itself may have done some
  916. * rearranging, we must compare sequence numbers to determine
  917. * which action was defined first.
  918. *
  919. */
  920. return ((*record1)->seq - (*record2)->seq);
  921. }
  922. }
  923. /*myassert (0);
  924. return 0;
  925. */
  926. }
  927. /*
  928. * This function determines the weight which is to be assigned to an
  929. * action database entry. The algorithm used was described earlier,
  930. * and will not be repeated here. A higher weight is assigned for
  931. * more specifically defined actions (i.e. the 'signiture' fields
  932. * have not been wildcarded.
  933. */
  934. static void
  935. _DtActionGetRecordWeight(
  936. DtDtsDbRecord ** record,
  937. long * primaryWeightPtr,
  938. long * secondaryWeightPtr )
  939. {
  940. char * argClass = _DtActGetDtsDbField(*record, _DtACTION_ARG_CLASS);
  941. char * argType = _DtActGetDtsDbField(*record, _DtACTION_ARG_TYPE);
  942. char * argMode = _DtActGetDtsDbField(*record, _DtACTION_ARG_MODE);
  943. char * argCount = _DtActGetDtsDbField(*record, _DtACTION_ARG_COUNT);
  944. char * p;
  945. (*primaryWeightPtr) = 0;
  946. (*secondaryWeightPtr) = 0;
  947. if (strcmp(argClass, _DtACT_ANY))
  948. (*primaryWeightPtr) += SPECIFIC_ARG_CLASS;
  949. if (strcmp(argType, _DtACT_ANY))
  950. (*primaryWeightPtr) += SPECIFIC_ARG_TYPE;
  951. if (strcmp(argMode, _DtACT_ARG_MODE_ANY))
  952. (*primaryWeightPtr) += SPECIFIC_ARG_MODE;
  953. strtol(argCount, &p, 10);
  954. if ((p == argCount) || (*p != '\0'))
  955. {
  956. /* The ARG_COUNT field is not a simple integer value */
  957. if (DtStrchr(argCount, '<'))
  958. (*secondaryWeightPtr) = SECONDARY_LESS_THAN;
  959. else if (DtStrchr(argCount, '>'))
  960. (*secondaryWeightPtr) = SECONDARY_GREATER_THAN;
  961. else
  962. (*secondaryWeightPtr) = SECONDARY_WILDCARD;
  963. }
  964. else
  965. {
  966. (*primaryWeightPtr) += SPECIFIC_ARG_COUNT;
  967. (*secondaryWeightPtr) = SECONDARY_SPECIFIC;
  968. }
  969. }
  970. static unsigned long
  971. _DtActMMParseArgTypesList(char *tlist, DtShmBoson **quarkAddr, int *countp)
  972. {
  973. static DtShmBoson quark_for_wild_char = 0;
  974. unsigned long mask = 0;
  975. int tcount;
  976. DtShmBoson *qp;
  977. char **typeVec, **tvp;
  978. char buf[_DtAct_MAX_BUF_SIZE];
  979. _DtSvcProcessLock();
  980. if ( !quark_for_wild_char )
  981. quark_for_wild_char = _DtDtsMMStringToBoson(_DtACT_ANY);
  982. _DtSvcProcessUnlock();
  983. strcpy(buf,tlist);
  984. tvp = typeVec = _DtVectorizeInPlace(buf,_DtACT_LIST_SEPARATOR_CHAR);
  985. /*
  986. * Determine the number of types in the list
  987. */
  988. for ( tcount = 0; *tvp; tvp++, tcount++ );
  989. *countp = tcount;
  990. myassert(tcount != 0);
  991. qp = *quarkAddr = (DtShmBoson *) XtCalloc(tcount + 1,sizeof(DtShmBoson));
  992. for ( tvp = typeVec; *tvp; tvp++ )
  993. {
  994. *qp = _DtDtsMMStringToBoson(*tvp);
  995. if ( *qp == quark_for_wild_char )
  996. SET_ARG_TYPE_WILD(mask);
  997. qp++;
  998. }
  999. /*
  1000. * use XtFree because it deal with free of a NULL string.
  1001. */
  1002. XtFree((char *)typeVec);
  1003. return mask;
  1004. }
  1005. /*
  1006. * Parse the string containing a coma-separated list of supported classes
  1007. * and convert it to an array of integers. Allocate space for the int
  1008. * array and fill it in with the internal representation number for each
  1009. * supported class. Return a mask (long) with the bits representating the
  1010. * supported classes set.
  1011. */
  1012. static unsigned long
  1013. _DtActMMParseClassList(char *clist)
  1014. {
  1015. char buf[_DtAct_MAX_BUF_SIZE];
  1016. char *bp;
  1017. char **classVec, **cvp;
  1018. unsigned long mask = 0;
  1019. if ( !DtStrchr(clist, _DtACT_LIST_SEPARATOR_CHAR ) )
  1020. {
  1021. /*
  1022. * Only a single class is specified
  1023. */
  1024. if ( !strcmp(clist,_DtACT_ANY) )
  1025. SET_ARG_CLASS_WILD(mask);
  1026. else if ( !strcmp(clist,_DtACTION_FILE) )
  1027. SET_ARG_CLASS_FILE(mask);
  1028. else if ( !strcmp(clist,_DtACTION_BUFFER) )
  1029. SET_ARG_CLASS_BUFFER(mask);
  1030. else if ( !strcmp(clist,_DtACTION_STRING) )
  1031. SET_ARG_CLASS_STRING(mask);
  1032. myassert(mask != 0 );
  1033. return mask;
  1034. }
  1035. /*
  1036. * A list of classes was specified in the action definition
  1037. * Make a local copy of the class string.
  1038. * Then vectorize it in place.
  1039. */
  1040. strcpy(buf,clist);
  1041. cvp = classVec = _DtVectorizeInPlace(buf,_DtACT_LIST_SEPARATOR_CHAR);
  1042. for ( bp = *cvp; bp; bp = *cvp )
  1043. {
  1044. if ( !strcmp(bp,_DtACT_ANY) )
  1045. {
  1046. /* If its wild -- don't bother with any more parsing */
  1047. XtFree((char *)classVec);
  1048. return SET_ARG_CLASS_WILD(mask);
  1049. }
  1050. if ( !strcmp(bp,_DtACTION_FILE) )
  1051. SET_ARG_CLASS_FILE(mask);
  1052. else if ( !strcmp(bp,_DtACTION_BUFFER) )
  1053. SET_ARG_CLASS_BUFFER(mask);
  1054. else if ( !strcmp(bp,_DtACTION_STRING) )
  1055. SET_ARG_CLASS_STRING(mask);
  1056. cvp++;
  1057. }
  1058. XtFree((char *)classVec);
  1059. myassert(mask != 0 );
  1060. return mask;
  1061. }
  1062. static unsigned long
  1063. _DtActMMParseArgCountString( char *countStr, int *countp)
  1064. {
  1065. unsigned long mask = 0;
  1066. if ( !strcmp(countStr,_DtACT_ANY) )
  1067. return SET_ARG_COUNT_WILD(mask);
  1068. if ( *countStr == _DtACT_GT_CHAR )
  1069. {
  1070. SET_ARG_COUNT_GT(mask);
  1071. *countp = atoi(countStr + 1);
  1072. } else if ( *countStr == _DtACT_LT_CHAR )
  1073. {
  1074. SET_ARG_COUNT_LT(mask);
  1075. *countp = atoi(countStr + 1);
  1076. } else
  1077. *countp = atoi(countStr);
  1078. return mask;
  1079. }
  1080. static unsigned long
  1081. _DtActMMParseActionType(char *actionTypeStr)
  1082. {
  1083. unsigned long mask = 0;
  1084. if ( !strcmp(actionTypeStr,_DtACTION_COMMAND) )
  1085. return SET_CMD_ACTION(mask);
  1086. if ( !strcmp(actionTypeStr,_DtACTION_TT_MSG) )
  1087. return SET_TT_MSG(mask);
  1088. #ifdef _DT_ALLOW_DT_MSGS
  1089. if ( !strcmp(actionTypeStr,_DtACTION_DT_REQUEST) )
  1090. return SET_DT_REQUEST_MSG(mask);
  1091. if ( !strcmp(actionTypeStr,_DtACTION_DT_NOTIFY) )
  1092. return SET_DT_NOTIFY_MSG(mask);
  1093. #endif /* _DT_ALLOW_DT_MSGS */
  1094. myassert(0); /* we should never get here */
  1095. if ( !strcmp(actionTypeStr,_DtACTION_MAP) )
  1096. return SET_MAP_ACTION(mask);
  1097. return mask;
  1098. }
  1099. static void
  1100. _DtActMMGetCmdInfo(DtDtsMMRecord *actRecp, ActionPtr actp)
  1101. {
  1102. char *s;
  1103. char *tmp = NULL;
  1104. int amtToAlloc;
  1105. static char *titleStr = "-title \"";
  1106. /* set the WINDOW_TYPE action mask bits */
  1107. s = _DtActGetDtsMMField(actRecp,_DtACTION_WINDOW_TYPE);
  1108. if ( !s )
  1109. {
  1110. /*
  1111. * WINDOW_TYPE not set -- default to PERM_TERM
  1112. */
  1113. SET_PERM_TERM(actp->mask);
  1114. } else if ( !strcmp(s,_DtACTION_TERMINAL) )
  1115. SET_TERMINAL(actp->mask);
  1116. else if ( !strcmp(s, _DtACTION_NO_STDIO) )
  1117. SET_NO_STDIO(actp->mask);
  1118. else if ( !strcmp(s, _DtACTION_PERM_TERMINAL) )
  1119. SET_PERM_TERM(actp->mask);
  1120. else
  1121. {
  1122. /* unrecognized terminal type was obtained */
  1123. myassert(0); /* this should never happen */
  1124. SET_PERM_TERM(actp->mask);
  1125. }
  1126. _DtDtsMMSafeFree(s);
  1127. /* Get the (optional) CWD info */
  1128. if ( (s = _DtActGetDtsMMField(actRecp,_DtACTION_CWD)) != NULL)
  1129. {
  1130. /*
  1131. * HOST:CWD syntax is no longer recognized here.
  1132. * actp->u.cmd.contextHost = _DtHostString(s);
  1133. * actp->u.cmd.contextDir = _DtPathname(s);
  1134. */
  1135. /* Keywords are not allowed in the CWD field */
  1136. actp->u.cmd.contextDir = XtNewString(s);
  1137. }
  1138. _DtDtsMMSafeFree(s);
  1139. /* Get the (required) Exec String */
  1140. if ( (s = _DtActGetDtsMMField(actRecp,_DtACTION_EXEC_STRING)) != NULL)
  1141. {
  1142. ParseMessage(actp,s,&(actp->u.cmd.execString));
  1143. } else
  1144. {
  1145. /*
  1146. * Should never get here -- actions without exec strings
  1147. * should have been rejected by the action converter.
  1148. */
  1149. myassert(0);
  1150. ParseMessage(actp,getenv("SHELL"),&(actp->u.cmd.execString));
  1151. }
  1152. _DtDtsMMSafeFree(s);
  1153. /* Get the (optional) Exec Host List */
  1154. if ( (s = _DtActGetDtsMMField(actRecp,_DtACTION_EXEC_HOST)) != NULL)
  1155. {
  1156. ParseMessage(actp,s,&(actp->u.cmd.execHosts));
  1157. /*
  1158. * The execHostCount field will be filled in later when
  1159. * the parsed message is interpreted and the execHostArray
  1160. * is filled in.
  1161. */
  1162. } else
  1163. {
  1164. /* set to default exec host */
  1165. tmp = _DtGetExecHostsDefault();
  1166. ParseMessage(actp,tmp,&(actp->u.cmd.execHosts));
  1167. if (tmp)
  1168. XtFree(tmp);
  1169. }
  1170. _DtDtsMMSafeFree(s);
  1171. /* Get the (optional) Term Opts */
  1172. s = _DtActGetDtsMMField(actRecp,_DtACTION_TERM_OPTS);
  1173. /*
  1174. * Prepend with internally generated title
  1175. * -- user supplied titles will appear
  1176. * afterwards and therefore take precedence (for most terminal
  1177. * emulators.) Allocate enough space for the required strings
  1178. * space separators, quotes and NULL terminator.
  1179. */
  1180. amtToAlloc = strlen(titleStr) + strlen(actp->label) + 2;
  1181. if (s)
  1182. amtToAlloc += strlen(s) + 1;
  1183. tmp = XtMalloc(amtToAlloc);
  1184. strcpy(tmp, titleStr);
  1185. strcat(tmp, actp->label);
  1186. strcat(tmp, "\"");
  1187. if (s)
  1188. {
  1189. strcat(tmp, " ");
  1190. strcat(tmp, s);
  1191. }
  1192. _DtDtsMMSafeFree(s);
  1193. ParseMessage(actp,tmp,&(actp->u.cmd.termOpts));
  1194. if (tmp)
  1195. XtFree(tmp);
  1196. }
  1197. static void
  1198. _DtActMMGetTtMsgInfo(DtDtsMMRecord *actRecp, ActionPtr actp)
  1199. {
  1200. char argNname[ sizeof(_DtACTION_TTN_ARG) /* space for prefix */
  1201. + 9 /* enough space for three decimal digits */
  1202. + sizeof(_DtACTION_TTN_REP_TYPE)]; /* space for longest suffix */
  1203. int i;
  1204. char *s;
  1205. char *tmp = NULL;
  1206. /* Get the (required) tt_class field */
  1207. s = _DtActGetDtsMMField(actRecp,_DtACTION_TT_CLASS);
  1208. if (!s)
  1209. {
  1210. myassert(0); /* should never get here */
  1211. actp->u.tt_msg.tt_class = TT_CLASS_UNDEFINED;
  1212. }
  1213. else if ( !strcmp(s,_DtACTION_TT_REQUEST ))
  1214. {
  1215. actp->u.tt_msg.tt_class = TT_REQUEST;
  1216. }
  1217. else if ( !strcmp(s,_DtACTION_TT_NOTICE) )
  1218. {
  1219. actp->u.tt_msg.tt_class = TT_NOTICE;
  1220. }
  1221. else /* unrecognized string */
  1222. {
  1223. /*
  1224. * We should never get here -- such records should have
  1225. * been weeded out by the Action converter.
  1226. */
  1227. myassert(0);
  1228. actp->u.tt_msg.tt_class = TT_CLASS_UNDEFINED;
  1229. }
  1230. _DtDtsMMSafeFree(s);
  1231. /* Get the (required) TT_SCOPE field */
  1232. s = _DtActGetDtsMMField(actRecp,_DtACTION_TT_SCOPE);
  1233. if (!s)
  1234. {
  1235. myassert(0); /* should never get here */
  1236. actp->u.tt_msg.tt_scope = TT_SCOPE_NONE;
  1237. }
  1238. else if ( !strcmp(s,_DtACTION_TT_SESSION) )
  1239. {
  1240. actp->u.tt_msg.tt_scope = TT_SESSION;
  1241. }
  1242. else if ( !strcmp(s,_DtACTION_TT_FILE) )
  1243. {
  1244. actp->u.tt_msg.tt_scope = TT_FILE;
  1245. }
  1246. else if ( !strcmp(s,_DtACTION_TT_BOTH) )
  1247. {
  1248. actp->u.tt_msg.tt_scope = TT_BOTH;
  1249. }
  1250. else if ( !strcmp(s,_DtACTION_TT_FILE_IN_SESSION) )
  1251. {
  1252. actp->u.tt_msg.tt_scope = TT_FILE_IN_SESSION;
  1253. }
  1254. else
  1255. {
  1256. /* unrecognized tt_scope */
  1257. myassert(0); /* should never happen */
  1258. actp->u.tt_msg.tt_scope = TT_SCOPE_NONE;
  1259. }
  1260. _DtDtsMMSafeFree(s);
  1261. /* Get the (required) TT_OPERATION field */
  1262. if ( (s = _DtActGetDtsMMField(actRecp,_DtACTION_TT_OPERATION)) )
  1263. ParseMessage(actp,s,&(actp->u.tt_msg.tt_op));
  1264. else
  1265. {
  1266. myassert(0); /* should never get here */
  1267. }
  1268. _DtDtsMMSafeFree(s);
  1269. /* Get the (optional) TT_FILE field */
  1270. if ( (s = _DtActGetDtsMMField(actRecp,_DtACTION_TT_FILE)) )
  1271. {
  1272. /*
  1273. * Special considerations:
  1274. * >> %Args% keyword is invalid.
  1275. * >> This value must reference a single file
  1276. * >> host:syntax needs to be parsed.
  1277. */
  1278. ParseMessage(actp,s,&(actp->u.tt_msg.tt_file));
  1279. }
  1280. _DtDtsMMSafeFree(s); s = (char *) 0;
  1281. /*
  1282. * Get message argument values
  1283. */
  1284. for ( i=0; True; i++ )
  1285. {
  1286. sprintf(argNname,"%s%d%s",
  1287. _DtACTION_TTN_ARG,i,_DtACTION_TTN_MODE);
  1288. if ( !(s = _DtActGetDtsMMField(actRecp,argNname)) )
  1289. break; /* no more args */
  1290. actp->u.tt_msg.tt_argn_mode =
  1291. (int *)XtRealloc(
  1292. (char *)actp->u.tt_msg.tt_argn_mode,
  1293. sizeof(int) * (i+1) );
  1294. if ( !strcmp(s,_DtACTION_TT_MODE_IN) )
  1295. actp->u.tt_msg.tt_argn_mode[i] = TT_IN;
  1296. else if ( !strcmp(s,_DtACTION_TT_MODE_OUT) )
  1297. actp->u.tt_msg.tt_argn_mode[i] = TT_OUT;
  1298. else if ( !strcmp(s,_DtACTION_TT_MODE_INOUT) )
  1299. actp->u.tt_msg.tt_argn_mode[i] = TT_INOUT;
  1300. else
  1301. {
  1302. myassert(0); /* should never reach here */
  1303. actp->u.tt_msg.tt_argn_mode[i] = TT_IN;
  1304. }
  1305. /* get tt_argn_vtype info */
  1306. sprintf(argNname,"%s%d%s",
  1307. _DtACTION_TTN_ARG,i,_DtACTION_TTN_VTYPE);
  1308. actp->u.tt_msg.tt_argn_vtype =
  1309. (parsedMsg *)XtRealloc(
  1310. (char *)actp->u.tt_msg.tt_argn_vtype,
  1311. sizeof(parsedMsg) * (i+1) );
  1312. _DtDtsMMSafeFree(s); s = (char *)0;
  1313. s = _DtActGetDtsMMField(actRecp,argNname);
  1314. ParseMessage(actp,s,actp->u.tt_msg.tt_argn_vtype + i);
  1315. /* get tt_argn_value info */
  1316. sprintf(argNname,"%s%d%s",
  1317. _DtACTION_TTN_ARG,i,_DtACTION_TTN_VALUE);
  1318. actp->u.tt_msg.tt_argn_value =
  1319. (parsedMsg *)XtRealloc(
  1320. (char *)actp->u.tt_msg.tt_argn_value,
  1321. sizeof(parsedMsg) * (i+1) );
  1322. _DtDtsMMSafeFree(s); s = (char *)0;
  1323. s = _DtActGetDtsMMField(actRecp,argNname);
  1324. ParseMessage(actp,s,actp->u.tt_msg.tt_argn_value + i);
  1325. /* get tt_argn_rep_type info */
  1326. sprintf(argNname,"%s%d%s",
  1327. _DtACTION_TTN_ARG,i,_DtACTION_TTN_REP_TYPE);
  1328. actp->u.tt_msg.tt_argn_rep_type =
  1329. (int *)XtRealloc(
  1330. (char *)actp->u.tt_msg.tt_argn_rep_type,
  1331. sizeof(int) * (i+1) );
  1332. _DtDtsMMSafeFree(s); s = (char *)0;
  1333. if ( !(s = _DtActGetDtsMMField(actRecp,argNname)) )
  1334. actp->u.tt_msg.tt_argn_rep_type[i] =
  1335. DtACT_TT_REP_UNDEFINED;
  1336. else if ( !(strcmp(s,_DtACTION_TT_RTYP_UND)) )
  1337. actp->u.tt_msg.tt_argn_rep_type[i] =
  1338. DtACT_TT_REP_UNDEFINED;
  1339. else if ( !(strcmp(s,_DtACTION_TT_RTYP_INT)) )
  1340. actp->u.tt_msg.tt_argn_rep_type[i] =
  1341. DtACT_TT_REP_INT;
  1342. else if ( !(strcmp(s,_DtACTION_TT_RTYP_STR)) )
  1343. actp->u.tt_msg.tt_argn_rep_type[i] =
  1344. DtACT_TT_REP_STRING;
  1345. else if ( !(strcmp(s,_DtACTION_TT_RTYP_BUF)) )
  1346. actp->u.tt_msg.tt_argn_rep_type[i] =
  1347. DtACT_TT_REP_BUFFER;
  1348. else
  1349. {
  1350. myassert(0); /* should never reach here */
  1351. actp->u.tt_msg.tt_argn_rep_type[i] =
  1352. DtACT_TT_REP_UNDEFINED;
  1353. }
  1354. _DtDtsMMSafeFree(s); s = (char *)0;
  1355. }
  1356. _DtDtsMMSafeFree(s); s = (char *)0;
  1357. /*
  1358. * Perhaps we can make do with a single count if the assumption that
  1359. * the counts for mode,vtype,reptype and value always match is valid.
  1360. */
  1361. actp->u.tt_msg.mode_count = actp->u.tt_msg.vtype_count =
  1362. actp->u.tt_msg.rep_type_count = actp->u.tt_msg.value_count = i;
  1363. }
  1364. #ifdef _DT_ALLOW_DT_MSGS
  1365. static void
  1366. _DtActDbGetDtNtfyInfo(
  1367. DtDtsDbRecord *actRecp,
  1368. ActionPtr actp)
  1369. {
  1370. int i;
  1371. char argNval[ sizeof(_DtACTION_DTN_ARG) /* space for prefix */
  1372. + 3 /* enough space for three decimal digits */
  1373. + sizeof(_DtACTION_DTN_VALUE)]; /* space for suffix */
  1374. char *s;
  1375. char *tmp = NULL;
  1376. /* Get the (required) dt_ngroup field */
  1377. if ( !(s = _DtActGetDtsDbField(actRecp,_DtACTION_DT_NGROUP)) )
  1378. {
  1379. myassert(0); /* should never get here */
  1380. }
  1381. ParseMessage(actp,s,&(actp->u.dt_notify.ngroup));
  1382. /* Get the (required) dt_notify_string field */
  1383. if ( !(s = _DtActGetDtsDbField(actRecp,_DtACTION_DT_NOTIFY_NAME)) )
  1384. {
  1385. myassert(0); /* should never get here */
  1386. }
  1387. ParseMessage(actp,s,&(actp->u.dt_notify.notify));
  1388. /*
  1389. * Get message argument values
  1390. */
  1391. for ( i=0; True; i++ )
  1392. {
  1393. sprintf(argNval,"%s%d%s",
  1394. _DtACTION_DTN_ARG,i,_DtACTION_DTN_VALUE);
  1395. if ( !(s = _DtActGetDtsDbField(actRecp,argNval)) )
  1396. break; /* no more args */
  1397. actp->u.dt_notify.argn_value =
  1398. (parsedMsg *)XtRealloc(
  1399. (char *)actp->u.dt_notify.argn_value,
  1400. sizeof(parsedMsg) * (i+1) );
  1401. ParseMessage(actp,s,actp->u.dt_notify.argn_value + i);
  1402. }
  1403. actp->u.dt_notify.value_count = i;
  1404. }
  1405. static void
  1406. _DtActDbGetDtReqInfo(
  1407. DtDtsDbRecord *actRecp,
  1408. ActionPtr actp)
  1409. {
  1410. int i;
  1411. char argNval[ sizeof(_DtACTION_DTN_ARG) /* space for prefix */
  1412. + 3 /* enough space for three decimal digits */
  1413. + sizeof(_DtACTION_DTN_VALUE)]; /* space for suffix */
  1414. char *s;
  1415. char *tmp = NULL;
  1416. /* Get the (required) dt_svc field */
  1417. if ( !(s = _DtActGetDtsDbField(actRecp,_DtACTION_DT_SVC)) )
  1418. {
  1419. myassert(0); /* should never get here */
  1420. }
  1421. ParseMessage(actp,s,&(actp->u.dt_req.service));
  1422. /* Get the (required) dt_request_name field */
  1423. if ( !(s = _DtActGetDtsDbField(actRecp,_DtACTION_DT_REQUEST_NAME)) )
  1424. {
  1425. myassert(0); /* should never get here */
  1426. }
  1427. ParseMessage(actp,s,&(actp->u.dt_req.request));
  1428. for ( i=0; True; i++ )
  1429. {
  1430. sprintf(argNval,"%s%d%s",
  1431. _DtACTION_DTN_ARG,i,_DtACTION_DTN_VALUE);
  1432. if ( !(s = _DtActGetDtsDbField(actRecp,argNval)) )
  1433. break; /* no more args */
  1434. actp->u.dt_req.argn_value =
  1435. (parsedMsg *) XtRealloc(
  1436. (char *)actp->u.dt_req.argn_value,
  1437. sizeof(parsedMsg) * (i+1) );
  1438. ParseMessage(actp,s,actp->u.dt_req.argn_value + i);
  1439. }
  1440. actp->u.dt_req.value_count = i;
  1441. }
  1442. #endif /* _DT_ALLOW_DT_MSGS */
  1443. static int
  1444. _DtActMMCompareObjClassMask( unsigned long objClassMask, char *actClass)
  1445. {
  1446. char buf[_DtAct_MAX_BUF_SIZE];
  1447. char *bp;
  1448. char **classVec, **cvp;
  1449. if ( ! DtStrchr(actClass, _DtACT_LIST_SEPARATOR_CHAR ) )
  1450. {
  1451. /*
  1452. * Only a single class is specified
  1453. */
  1454. if ( !strcmp(actClass,_DtACT_ANY) )
  1455. return True;
  1456. if ( !strcmp(actClass,_DtACTION_FILE) )
  1457. /*
  1458. * Is this object REALLY a file (not a tmp file
  1459. * generated for a buffer object.
  1460. */
  1461. if ( IS_FILE_OBJ(objClassMask)
  1462. && !(IS_BUFFER_OBJ(objClassMask)) )
  1463. return True;
  1464. if ( !strcmp(actClass,_DtACTION_BUFFER) )
  1465. if ( IS_BUFFER_OBJ(objClassMask) )
  1466. return True;
  1467. if ( !strcmp(actClass,_DtACTION_STRING) )
  1468. if ( IS_STRING_OBJ(objClassMask) )
  1469. return True;
  1470. /* no single class spec match found */
  1471. return False;
  1472. }
  1473. /*
  1474. * A list of classes was specified in the action.
  1475. * Make a local copy of the class string
  1476. * Then vectorize it in place.
  1477. */
  1478. strcpy(buf,actClass);
  1479. cvp = classVec = _DtVectorizeInPlace(buf,_DtACT_LIST_SEPARATOR_CHAR);
  1480. for ( bp = *cvp; bp; bp = *cvp )
  1481. {
  1482. if ( !strcmp(actClass,_DtACT_ANY) )
  1483. {
  1484. XtFree((char *)classVec);
  1485. return True;
  1486. }
  1487. if ( !strcmp(bp,_DtACTION_FILE) )
  1488. {
  1489. if ( IS_ARG_CLASS_FILE(objClassMask) )
  1490. {
  1491. XtFree((char *)classVec);
  1492. return True;
  1493. }
  1494. }
  1495. else if ( !strcmp(bp,_DtACTION_BUFFER) )
  1496. {
  1497. if (IS_ARG_CLASS_BUFFER(objClassMask))
  1498. {
  1499. XtFree((char *)classVec);
  1500. return True;
  1501. }
  1502. }
  1503. else if ( !strcmp(bp,_DtACTION_STRING) )
  1504. {
  1505. if (IS_ARG_CLASS_STRING(objClassMask))
  1506. {
  1507. XtFree((char *)classVec);
  1508. return True;
  1509. }
  1510. }
  1511. cvp++;
  1512. }
  1513. XtFree((char *)classVec);
  1514. return False;
  1515. }
  1516. static int
  1517. _DtActMMCompareMode( unsigned long objMask, char *actMode)
  1518. {
  1519. if ( !actMode
  1520. || !strcmp(actMode,_DtACT_ARG_MODE_ANY)
  1521. || !strcmp(actMode,DtDTS_DT_UNKNOWN))
  1522. return True; /* We don't care about the mode */
  1523. if ( !strcmp(actMode,_DtACT_ARG_MODE_WRITE) && IS_WRITE_OBJ(objMask) )
  1524. return True;
  1525. if ( !strcmp(actMode,_DtACT_ARG_MODE_NOWRITE)
  1526. && !(IS_WRITE_OBJ(objMask)) )
  1527. return True;
  1528. return False;
  1529. }
  1530. static int
  1531. _DtActMMCompareType( DtShmBoson reqType, char *actType)
  1532. {
  1533. char buf[_DtAct_MAX_BUF_SIZE];
  1534. char *reqTypeStr = (char *)_DtDtsMMBosonToString(reqType);
  1535. char **typeVec;
  1536. char **tvp;
  1537. char *tp;
  1538. if ( ! DtStrchr(actType, _DtACT_LIST_SEPARATOR_CHAR ) )
  1539. {
  1540. /*
  1541. * Only a single type is specified
  1542. */
  1543. if ( !strcmp(actType,_DtACT_ANY) )
  1544. return True;
  1545. if ( !strcmp(actType,reqTypeStr) )
  1546. return True;
  1547. /* no single type spec match found */
  1548. return False;
  1549. }
  1550. /*
  1551. * Make a local copy of the class string
  1552. * Then vectorize it in place.
  1553. */
  1554. strcpy(buf,actType);
  1555. tvp = typeVec = _DtVectorizeInPlace(buf,_DtACT_LIST_SEPARATOR_CHAR);
  1556. for ( tp = *tvp; tp; tp = *tvp )
  1557. {
  1558. if ( !strcmp(tp,reqTypeStr) )
  1559. {
  1560. XtFree((char *)typeVec);
  1561. return True;
  1562. }
  1563. tvp++;
  1564. }
  1565. return False;
  1566. }
  1567. static int
  1568. _DtActMMCompareCount( int reqCount, char *actCount)
  1569. {
  1570. if ( !strcmp(actCount,_DtACT_ANY) )
  1571. return True;
  1572. if ( *actCount == _DtACT_GT_CHAR )
  1573. {
  1574. if ( reqCount > atoi( actCount+1 ))
  1575. return True;
  1576. return False;
  1577. }
  1578. if ( *actCount == _DtACT_LT_CHAR )
  1579. {
  1580. if ( reqCount < atoi( actCount+1 ))
  1581. return True;
  1582. return False;
  1583. }
  1584. if ( reqCount == atoi(actCount) )
  1585. return True;
  1586. return False;
  1587. }
  1588. /*
  1589. * This function is used when a request is made to locate the first
  1590. * action record meeting the criteria specified with the requestCriteria.
  1591. * The only fields within the requestCriteria which are of interest are
  1592. * the 'signiture' fields (ARG_CLASS, ARG_TYPE and ARG_COUNT). Of
  1593. * course, the action name is also important.
  1594. * This assumes the action database has already been sorted.
  1595. * and that default ARG_CLASS, ARG_TYPE and ARG_COUNT values have been
  1596. * entered into the database as needed.
  1597. */
  1598. DtDtsMMRecord *
  1599. _DtActionLocateRecord(
  1600. DtShmBoson actQuark,
  1601. unsigned long obj_mask,
  1602. DtShmBoson arg_type,
  1603. int arg_count,
  1604. DtDtsMMDatabase *act_db)
  1605. {
  1606. int n;
  1607. DtDtsMMRecord *act_rec;
  1608. DtDtsMMRecord *act_rec_list;
  1609. DtDtsMMRecord *last_rec_found = NULL;
  1610. char *tmp = 0;
  1611. int *start;
  1612. myassert (act_db);
  1613. act_rec_list = _DtDtsMMGetPtr(act_db->recordList);
  1614. start = (int*)_DtDtsMMGetDbName(act_db,actQuark);
  1615. if(!start)
  1616. {
  1617. return(NULL);
  1618. }
  1619. for ( n = *start; n < act_db->recordCount; n++)
  1620. {
  1621. act_rec = &act_rec_list[n];
  1622. /*
  1623. * compare the name quark field to the action quark
  1624. */
  1625. if ( act_rec->recordName != actQuark )
  1626. break;
  1627. _DtDtsMMSafeFree(tmp);
  1628. if ( !_DtActMMCompareObjClassMask(obj_mask,
  1629. tmp =_DtActGetDtsMMField(act_rec,_DtACTION_ARG_CLASS)))
  1630. continue;
  1631. _DtDtsMMSafeFree(tmp);
  1632. if ( !_DtActMMCompareType(arg_type,
  1633. tmp =_DtActGetDtsMMField(act_rec,_DtACTION_ARG_TYPE)))
  1634. continue;
  1635. _DtDtsMMSafeFree(tmp);
  1636. if ( !_DtActMMCompareCount(arg_count,
  1637. tmp =_DtActGetDtsMMField(act_rec,_DtACTION_ARG_COUNT)))
  1638. continue;
  1639. _DtDtsMMSafeFree(tmp);
  1640. if ( !_DtActMMCompareMode(obj_mask,
  1641. tmp =_DtActGetDtsMMField(act_rec,_DtACTION_ARG_MODE)))
  1642. continue;
  1643. _DtDtsMMSafeFree(tmp);
  1644. /*
  1645. * We've found a match
  1646. */
  1647. return act_rec;
  1648. }
  1649. _DtDtsMMSafeFree(tmp);
  1650. /*
  1651. * No match found
  1652. */
  1653. return NULL;
  1654. }
  1655. /***************************************************************************/
  1656. /***************************************************************************/
  1657. /* Message Parsing Functions */
  1658. /***************************************************************************/
  1659. /***************************************************************************/
  1660. /*
  1661. * Given pointers to the beginning and end of a possible keyword, see if
  1662. * the string matches any of the known keywords. Return TRUE if a match
  1663. * is found. The format for a keyword is:
  1664. *
  1665. * <Optional Qualifier><Keyword><Optional Prompt>
  1666. *
  1667. * The string passed in already has the leading and trailing `%' removed.
  1668. */
  1669. static Boolean
  1670. ValidKeyword(
  1671. char *start,
  1672. char *end,
  1673. char **prompt,
  1674. int *keywordId,
  1675. int *argNum,
  1676. Boolean *isFile )
  1677. {
  1678. /*
  1679. * Fill in the length of the keywords at compile time by
  1680. * using the "sizeof" operator (and subtracting one for the NULL).
  1681. */
  1682. static int localHostLen = sizeof(_DtACT_LOCALHOST_STR) - 1;
  1683. static int databaseHostLen = sizeof(_DtACT_DATABASEHOST_STR) - 1;
  1684. static int displayHostLen = sizeof(_DtACT_DISPLAYHOST_STR) - 1;
  1685. static int sessionHostLen = sizeof(_DtACT_SESSIONHOST_STR) - 1;
  1686. static int argsLen = sizeof(_DtACT_ARGS_STR) - 1;
  1687. static int arg_Len = sizeof(_DtACT_ARG_UNDER_STR) - 1;
  1688. static int stringQualifierLen = sizeof(_DtACT_STRING_QUALIFIER) - 1;
  1689. static int fileQualifierLen = sizeof(_DtACT_FILE_QUALIFIER) - 1;
  1690. int len = end - start + 1;
  1691. char *stop;
  1692. char *lastCh;
  1693. int lastChLen;
  1694. char savedChar;
  1695. Boolean FoundQualifier=False;
  1696. *keywordId = NO_KEYWORD;
  1697. *argNum = NO_ARG;
  1698. /*
  1699. * Determine if an optional qualifier was specified. For now, the
  1700. * only qualifiers we know about are "(String)" and "(File)", which
  1701. * are only valid for the "Args" , "Arg_<n>" or "Prompt" keywords.
  1702. * Is no qualifier is specified we default to String.
  1703. */
  1704. if ((len >= stringQualifierLen) &&
  1705. (strncmp(_DtACT_STRING_QUALIFIER,start,(size_t)stringQualifierLen) == 0))
  1706. {
  1707. FoundQualifier=True;
  1708. *isFile = False;
  1709. start += stringQualifierLen;
  1710. } else if (( len >= fileQualifierLen) &&
  1711. (strncmp(_DtACT_FILE_QUALIFIER, start,(size_t)fileQualifierLen) == 0))
  1712. {
  1713. FoundQualifier=True;
  1714. *isFile = True;
  1715. start += fileQualifierLen;
  1716. } else
  1717. *isFile = False; /* default to string behavior (except for Arg*) */
  1718. /* Compare the first portion of the string to each known keyword */
  1719. if ((len >= localHostLen) &&
  1720. (strncmp(_DtACT_LOCALHOST_STR, start, (size_t)localHostLen) == 0))
  1721. {
  1722. *isFile = False;
  1723. /* Flag that a keyword was found */
  1724. *keywordId = LOCAL_HOST;
  1725. *argNum = NO_ARG;
  1726. start += localHostLen;
  1727. }
  1728. else if ((len >= databaseHostLen) &&
  1729. (strncmp(_DtACT_DATABASEHOST_STR,start,(size_t)databaseHostLen)==0))
  1730. {
  1731. *isFile = False;
  1732. /* Flag that a keyword was found */
  1733. *keywordId = DATABASE_HOST;
  1734. *argNum = NO_ARG;
  1735. start += databaseHostLen;
  1736. }
  1737. else if ((len >= displayHostLen) &&
  1738. (strncmp(_DtACT_DISPLAYHOST_STR,start,(size_t)displayHostLen)==0))
  1739. {
  1740. *isFile = False;
  1741. /* Flag that a keyword was found */
  1742. *keywordId = DISPLAY_HOST;
  1743. *argNum = NO_ARG;
  1744. start += displayHostLen;
  1745. }
  1746. else if ((len >= sessionHostLen) &&
  1747. (strncmp(_DtACT_SESSIONHOST_STR,start,(size_t)sessionHostLen)==0))
  1748. {
  1749. *isFile = False;
  1750. /* Flag that a keyword was found */
  1751. *keywordId = SESSION_HOST;
  1752. *argNum = NO_ARG;
  1753. start += sessionHostLen;
  1754. }
  1755. else if ((len >= argsLen) &&
  1756. (strncmp(_DtACT_ARGS_STR, start, (size_t)argsLen) == 0))
  1757. {
  1758. /* Flag that a keyword was found */
  1759. *keywordId = ARG;
  1760. *argNum = ALL_ARGS;
  1761. /*
  1762. * Args keyword should default to File unless
  1763. * a String qualifier was encountered.
  1764. */
  1765. if ( !FoundQualifier )
  1766. *isFile=True;
  1767. start += argsLen;
  1768. }
  1769. else if ((len >= arg_Len) &&
  1770. (strncmp(_DtACT_ARG_UNDER_STR, start, (size_t)arg_Len) == 0))
  1771. {
  1772. /* Flag that a keyword was found */
  1773. *keywordId = ARG;
  1774. /*
  1775. * Args keyword should default to File unless
  1776. * a String qualifier was encountered.
  1777. */
  1778. if ( !FoundQualifier )
  1779. *isFile=True;
  1780. /* Determine which argument is to be used */
  1781. start += arg_Len;
  1782. *argNum = strtol(start, &stop, 10);
  1783. if (*argNum > 0)
  1784. start = stop;
  1785. else
  1786. {
  1787. /* Keyword was invalidly formed */
  1788. return(False);
  1789. }
  1790. }
  1791. /*
  1792. * See if this is the end of the keyword, or whether a prompt is
  1793. * there also.
  1794. */
  1795. if (start > end)
  1796. {
  1797. if (*keywordId != NO_KEYWORD)
  1798. {
  1799. /* All done */
  1800. *prompt = NULL;
  1801. return(True);
  1802. }
  1803. else
  1804. {
  1805. /* We never found a keyword */
  1806. return(False);
  1807. }
  1808. }
  1809. /*
  1810. * We've may have extracted a keyword, and the string still contains
  1811. * more characters; let's see if an optional prompt was specified. If
  1812. * the next character is a '"', then the last character in the string
  1813. * must also be a '"'; otherwise, the keyword was invalid. If the next
  1814. * character is not a '"', then the keyword is invalid.
  1815. */
  1816. savedChar = *DtNextChar(end);
  1817. lastCh = DtPrevChar(start, end+1);
  1818. lastChLen = mblen(lastCh, MB_LEN_MAX);
  1819. if ((start != end) && (*start == '"') && (lastChLen == 1) &&(*lastCh == '"'))
  1820. {
  1821. /* Valid prompt found; skip the quotes */
  1822. start++;
  1823. *prompt = (char *)XtMalloc((Cardinal)(end - start + 1));
  1824. (void)strncpy(*prompt, start, (size_t)(end - start));
  1825. (*prompt)[end - start] = '\0';
  1826. return(True);
  1827. }
  1828. /* If we made it down here, then the keyword was invalid */
  1829. return(False);
  1830. }
  1831. ActionPtr
  1832. _DtActionFindDBEntry( ActionRequest *reqp,
  1833. DtShmBoson actQuark )
  1834. {
  1835. int numSearches = 0;
  1836. DtDtsMMRecord *actRecp;
  1837. char *mapto = NULL;
  1838. long mask = 0;
  1839. DtShmBoson type = 0;
  1840. int num = 0;
  1841. ActionPtr actp = NULL;
  1842. char *origLabel = NULL;
  1843. char *tmp = 0;
  1844. DtDtsMMDatabase *act_db;
  1845. _DtSvcProcessLock();
  1846. act_db = _DtDtsMMGet(_DtACTION_NAME);
  1847. if ( reqp && reqp->numObjects && reqp->objects )
  1848. {
  1849. mask = reqp->objects[0].mask;
  1850. type = reqp->objects[0].type;
  1851. num = reqp->numObjects;
  1852. } else /* Treat missing objects as writable */
  1853. SET_WRITE_OBJ(mask);
  1854. /*
  1855. * Get the action record structure from the action database
  1856. */
  1857. for (actRecp = _DtActionLocateRecord(actQuark,mask,type,num, act_db);
  1858. actRecp;
  1859. actRecp = _DtActionLocateRecord(_DtDtsMMStringToBoson(mapto),
  1860. mask,type,num, act_db), numSearches++)
  1861. {
  1862. /*
  1863. * Check to see if this is a map action
  1864. */
  1865. if(!(mapto=_DtActGetDtsMMField(actRecp,_DtACTION_MAP_ACTION)))
  1866. break;
  1867. /*
  1868. * Save the label/name of the original action for displays.
  1869. */
  1870. if ( !origLabel )
  1871. origLabel = _DtActMMChooseLabel(actRecp);
  1872. if ( numSearches++ > _MAX_MAP_ATTEMPTS )
  1873. {
  1874. if ( reqp )
  1875. SET_TOO_MANY_MAPS(reqp->mask);
  1876. _DtSvcProcessUnlock();
  1877. free(mapto);
  1878. return NULL;
  1879. }
  1880. }
  1881. /*
  1882. * Fill in Action structure
  1883. * -- do some parsing here.
  1884. */
  1885. if ( actRecp )
  1886. {
  1887. actp = (Action *)XtCalloc(1,sizeof(Action));
  1888. actp->action = actRecp->recordName; /* save action quark */
  1889. /* pathId is boson; file_name_id needs to be quark! */
  1890. actp->file_name_id =
  1891. XrmStringToQuark(_DtDtsMMBosonToString(actRecp->pathId));
  1892. if ( origLabel )
  1893. actp->label = origLabel;
  1894. else
  1895. actp->label = _DtActMMChooseLabel(actRecp);
  1896. actp->description = _DtActGetDtsMMField(actRecp,
  1897. _DtACTION_DESCRIPTION);
  1898. actp->mask |= _DtActMMParseClassList(
  1899. tmp =_DtActGetDtsMMField(actRecp,_DtACTION_ARG_CLASS));
  1900. _DtDtsMMSafeFree(tmp);
  1901. actp->mask |= _DtActMMParseArgTypesList(
  1902. tmp =_DtActGetDtsMMField(actRecp,_DtACTION_ARG_TYPE),
  1903. &actp->arg_types, &actp->type_count );
  1904. _DtDtsMMSafeFree(tmp);
  1905. actp->mask |= _DtActMMParseArgCountString(
  1906. tmp =_DtActGetDtsMMField(actRecp,_DtACTION_ARG_COUNT),
  1907. &actp->arg_count);
  1908. _DtDtsMMSafeFree(tmp);
  1909. actp->mask |= _DtActMMParseActionType(
  1910. tmp =_DtActGetDtsMMField(actRecp,_DtACTION_TYPE));
  1911. _DtDtsMMSafeFree(tmp);
  1912. switch ( actp->mask & _DtAct_ACTION_TYPE_BITS )
  1913. {
  1914. case _DtAct_CMD_BIT:
  1915. _DtActMMGetCmdInfo(actRecp,actp);
  1916. break;
  1917. case _DtAct_TT_MSG_BIT:
  1918. _DtActMMGetTtMsgInfo(actRecp,actp);
  1919. break;
  1920. #ifdef _DT_ALLOW_DT_MSGS
  1921. case _DtAct_DT_REQ_MSG_BIT:
  1922. _DtActMMGetDtReqInfo(actRecp,actp);
  1923. break;
  1924. case _DtAct_DT_NTFY_MSG_BIT:
  1925. _DtActMMGetDtNtfyInfo(actRecp,actp);
  1926. break;
  1927. #endif /* _DT_ALLOW_DT_MSGS */
  1928. case _DtAct_MAP_BIT:
  1929. myassert(0); /* should never get here */
  1930. _DtFreeActionStruct(actp);
  1931. _DtSvcProcessUnlock();
  1932. return NULL;
  1933. break;
  1934. default: /* unkown action type */
  1935. myassert(0); /* should never get here */
  1936. _DtFreeActionStruct(actp);
  1937. _DtSvcProcessUnlock();
  1938. return NULL;
  1939. break;
  1940. }
  1941. }
  1942. /*
  1943. * actRecp is NULL -- therefore we were unable to locate an action.
  1944. * It may be that the action we could not locate was a mapped action.
  1945. * To give the user as much information as possible about the
  1946. * problem, put the name of the mapped action (if any) into the
  1947. * request's action name field -- this information will later be
  1948. * displayed in an error dialog.
  1949. */
  1950. if ( mapto )
  1951. {
  1952. XtFree(reqp->actionName);
  1953. reqp->actionName = mapto;
  1954. }
  1955. _DtSvcProcessUnlock();
  1956. return actp;
  1957. }
  1958. /*
  1959. * Take a message string, and break it up into its components. A component
  1960. * is composed of preceding text, a keyword and an optional prompt. The
  1961. * parsing will make our job easier when it comes time to substitute in
  1962. * the supplied set of parameters.
  1963. *
  1964. * During the parse operation, `string' always points to the beginning
  1965. * of where the last segment ended, and the next segment starts. 'start'
  1966. * always points to where within `string' the search for a keyword should
  1967. * start.
  1968. */
  1969. static void
  1970. ParseMessage(
  1971. register ActionPtr action,
  1972. register char * str,
  1973. register parsedMsg * msg )
  1974. {
  1975. char *start;
  1976. register char *string;
  1977. char *keywordStart, *keywordEnd;
  1978. char *prompt;
  1979. int keyword, argNum;
  1980. Boolean isFile;
  1981. register MsgComponent *newBlock;
  1982. /* Initialize all fields */
  1983. msg->parsedMessage = NULL;
  1984. msg->numMsgParts = 0;
  1985. msg->compiledMessage = NULL;
  1986. /* Make sure there is a message to parse */
  1987. if ((start = string = str) == NULL)
  1988. return;
  1989. /*
  1990. * This would be a good place to allow popen invocations
  1991. * for load balancing, etc. (See expand_shell() in Dts.c)
  1992. */
  1993. /* Parse out each keyword */
  1994. while (1)
  1995. {
  1996. /* Look for the start and end of a keyword */
  1997. if ((keywordStart = DtStrchr(start, '%')))
  1998. keywordEnd = DtStrchr(keywordStart+1, '%');
  1999. else
  2000. keywordEnd = NULL;
  2001. /* See if a keyword was found */
  2002. if ((keywordStart == NULL) || (keywordEnd == NULL))
  2003. {
  2004. /*
  2005. * No more keywords left; bundle the remaining string into
  2006. * a parse block, and return.
  2007. */
  2008. if (strlen(string) > 0)
  2009. {
  2010. msg->numMsgParts++;
  2011. msg->parsedMessage = (MsgComponent *)
  2012. XtRealloc((char *)msg->parsedMessage,
  2013. (Cardinal)(sizeof(MsgComponent) * msg->numMsgParts));
  2014. newBlock = msg->parsedMessage + (msg->numMsgParts - 1);
  2015. newBlock->precedingText = XtNewString(string);
  2016. newBlock->prompt = NULL;
  2017. newBlock->keyword = NO_KEYWORD;
  2018. newBlock->argNum = NO_ARG;
  2019. newBlock->mask = 0;
  2020. }
  2021. /* Free up the old msg string; we no longer need it */
  2022. return;
  2023. }
  2024. else
  2025. {
  2026. /*
  2027. * We've encountered what looks to be a keyword; see if it is
  2028. * a valid one. If it's not valid, then continue looking;
  2029. * otherwise, save it, and continue the parsing processing.
  2030. */
  2031. if (ValidKeyword(keywordStart+1, keywordEnd-1, &prompt,
  2032. &keyword, &argNum, &isFile))
  2033. {
  2034. msg->numMsgParts++;
  2035. msg->parsedMessage = (MsgComponent *)
  2036. XtRealloc((char *)msg->parsedMessage,
  2037. (Cardinal)(sizeof(MsgComponent) * msg->numMsgParts));
  2038. newBlock = msg->parsedMessage + (msg->numMsgParts - 1);
  2039. if (keywordStart != string)
  2040. {
  2041. /* Extract what we need; convert to NULL terminated */
  2042. newBlock->precedingText = (char *)
  2043. XtMalloc((Cardinal)(keywordStart - string + 1));
  2044. (void)strncpy(newBlock->precedingText, string,
  2045. (size_t)(keywordStart-string));
  2046. newBlock->precedingText[keywordStart - string] = '\0';
  2047. }
  2048. else
  2049. newBlock->precedingText = NULL;
  2050. newBlock->prompt = prompt;
  2051. newBlock->keyword = keyword;
  2052. newBlock->argNum = argNum;
  2053. newBlock->mask = 0;
  2054. if (isFile)
  2055. SET_TREAT_AS_FILE(newBlock->mask);
  2056. if (keyword == ARG)
  2057. {
  2058. /* Are we a single parameter action? */
  2059. if (argNum == 1)
  2060. {
  2061. if (IS_ARG_NONE_FOUND(action->mask))
  2062. SET_ARG_SINGLE_ARG(action->mask);
  2063. }
  2064. else
  2065. SET_ARG_MULTI_ARG(action->mask);
  2066. }
  2067. /* Continue the search following this keyword */
  2068. string = start = keywordEnd + 1;
  2069. }
  2070. else
  2071. {
  2072. /* Invalid keyword; keep searching */
  2073. start = keywordEnd;
  2074. }
  2075. }
  2076. }
  2077. }