fsDialog.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  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. /* $XConsortium: fsDialog.c /main/6 1996/10/08 11:58:08 mustafa $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. *
  27. * FILE: fsDialog.c
  28. *
  29. * COMPONENT_NAME: Desktop File Manager (dtfile)
  30. *
  31. * Description: Containes routines to handle contents of dtfile.config
  32. *
  33. * FUNCTIONS: configFileName
  34. * configFileOK
  35. * fsDialogAvailable
  36. * getFSType
  37. * readConfigFile
  38. * readDialogData
  39. * readFSID
  40. * readLine
  41. * stricmp
  42. * strip
  43. *
  44. * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
  45. * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
  46. * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
  47. * (c) Copyright 1993, 1994, 1995 Novell, Inc.
  48. *
  49. ****************************************************************************
  50. ************************************<+>*************************************/
  51. /*---------------------------------------------------------------------------------
  52. *
  53. * fsDialogAvailable (String path, dtFSData *fsDialogData)
  54. *
  55. * For the file specified by path, determine if there is a properties
  56. * dialog specific to the file system that the file is on.
  57. * For example, if the file is in AFS there might be a dialog to edit
  58. * the Access Control List. fsDialogData is filled if there is a dialog.
  59. * path must not include host:
  60. *
  61. * If any errors are encountered, FALSE is returned and no other action is taken
  62. * or message displayed.
  63. *
  64. *--------------------------------------------------------------------------------*/
  65. #include <string.h>
  66. #include <stdlib.h>
  67. #include <stdio.h>
  68. #include <ctype.h>
  69. #include <errno.h>
  70. #include <sys/stat.h>
  71. #include <Dt/UserMsg.h> /* for DtSimpleError */
  72. #include <Xm/Xm.h>
  73. #include "Encaps.h"
  74. #include "ModAttr.h"
  75. #include "FileMgr.h"
  76. #include "Desktop.h"
  77. #include "Main.h"
  78. /*-----------------------------------------------------
  79. * Configuration file search order is:
  80. *
  81. * $DTFSCONFIG (meant to be used for debugging)
  82. * $HOME/CONFIGFILENAME
  83. * SYSCONFIGFILEDIR/CONFIGFILENAME
  84. * DEFCONFIGFILEDIR/$LANG/CONFIGFILENAME
  85. * DEFCONFIGFILEDIR/C/CONFIGFILENAME
  86. *
  87. * The function configFileName() determines the correct
  88. * name. It will apply $LANG where appropriate.
  89. *
  90. *-----------------------------------------------------*/
  91. #define SYSCONFIGFILEDIR CDE_CONFIGURATION_TOP "/config"
  92. #define DEFCONFIGFILEDIR CDE_INSTALLATION_TOP "/config"
  93. #define CONFIGFILENAME "dtfile.config"
  94. #define DEFCONFIGFILENAME CDE_INSTALLATION_TOP "/config/C/dtfile.config"
  95. /*--------------------------------------------------------
  96. Platform-specific includes required for getFSType()
  97. *--------------------------------------------------------*/
  98. #ifdef __aix
  99. #endif
  100. #if defined(sun)
  101. #include <sys/types.h>
  102. #include <sys/statvfs.h>
  103. #endif
  104. #ifdef __hpux
  105. #include <sys/vfs.h>
  106. #endif
  107. /*----------------------
  108. * global variables
  109. *----------------------*/
  110. #define EMSGMAX 1024
  111. char g_errorMessage[EMSGMAX];
  112. /*--------------------
  113. Local functions
  114. *--------------------*/
  115. static void getFSType (const String path,
  116. String fsType,
  117. String platform);
  118. static void readConfigFile (const String fsType,
  119. const String platform,
  120. dtFSData * fsDialogData,
  121. Boolean * dialogAvailable);
  122. static String configFileName (void);
  123. static void readFSID (FILE * fptr,
  124. const String fsType,
  125. const String platform,
  126. String fsID);
  127. static void readDialogData (FILE * fptr,
  128. const String fsID,
  129. Boolean * dialogAvailable,
  130. dtFSData * fsDialogData);
  131. static int readLine (FILE * fptr, String line);
  132. static int stricmp (const String s1, const String s2);
  133. static String strip (String s);
  134. static Boolean configFileOK(void);
  135. /*----------------------
  136. * fsDialogAvailable
  137. *----------------------*/
  138. Boolean
  139. fsDialogAvailable (const String path, dtFSData *fsDialogData)
  140. {
  141. char fsType[MAXLINELENGTH], platform[MAXLINELENGTH];
  142. Boolean dialogAvailable;
  143. DPRINTF(("fsDialogAvailble: checking path \"%s\"\n",path));
  144. if ( ! configFileOK())
  145. return FALSE;
  146. getFSType(path, fsType, platform);
  147. DPRINTF((" fsType=\"%s\"\n platform=\"%s\"\n",fsType,platform));
  148. if (strlen(fsType) == 0)
  149. return FALSE;
  150. else
  151. {
  152. readConfigFile(fsType, platform, fsDialogData, &dialogAvailable);
  153. if (dialogAvailable)
  154. {
  155. strcpy (fsDialogData->path,path);
  156. }
  157. return dialogAvailable;
  158. }
  159. }
  160. /*--------------------------------------------------------------------------------
  161. *
  162. * configFileOK
  163. *
  164. * is the configuration file accessible?
  165. *
  166. *------------------------------------------------------------------------------*/
  167. static Boolean
  168. configFileOK(void)
  169. {
  170. struct stat buf;
  171. int err;
  172. String fname;
  173. String msg1, msg2;
  174. fname = configFileName();
  175. err = stat(fname, &buf);
  176. DPRINTF((" config file \"%s\" stat ret=%i\n",fname,err));
  177. if (err == 0)
  178. return TRUE;
  179. else
  180. {
  181. msg1 = GETMESSAGE(21, 22, "Cannot open file manager configuration file: ");
  182. msg2 = strerror(errno);
  183. sprintf(g_errorMessage,"%s%s\n %s\n",msg1,fname,msg2);
  184. _DtSimpleError (application_name, DtError, NULL, g_errorMessage, NULL);
  185. return FALSE;
  186. }
  187. } /* end configFileOK */
  188. /*--------------------------------------------------------------------------------
  189. *
  190. * getFSType
  191. *
  192. * Do the platform-specific work required to determine what type of file system
  193. * the file defined by path is on. Return strings defining the file system type
  194. * and the platform. Any errors result in a fsType set to the null string.
  195. *
  196. * Both fsType and platform are allocated by the caller
  197. *
  198. * The strings used in platform and fsType must match those used in
  199. * the configuration file.
  200. *
  201. *--------------------------------------------------------------------------------*/
  202. static void getFSType(const String path,
  203. String fsType,
  204. String platform)
  205. {
  206. #ifdef __aix
  207. #define GETFSTYPE
  208. struct stat buf;
  209. strncpy(platform,"aix",MAXLINELENGTH);
  210. if (lstat(path, &buf) == 0)
  211. sprintf(fsType,"%i",buf.st_vfstype);
  212. else
  213. strncpy(fsType,"",MAXLINELENGTH);
  214. #endif /* __aix */
  215. #ifdef sun
  216. #define GETFSTYPE
  217. struct statvfs buf;
  218. strncpy(platform,"sunos",MAXLINELENGTH);
  219. if (statvfs(path, &buf) == 0)
  220. strncpy(fsType,buf.f_basetype,MAXLINELENGTH);
  221. else
  222. strncpy(fsType,"",MAXLINELENGTH);
  223. #endif /* sun */
  224. #ifdef __hpux
  225. #define GETFSTYPE
  226. struct statfs buf;
  227. strncpy(platform,"hpux",MAXLINELENGTH);
  228. if (statfs(path, &buf) == 0)
  229. sprintf(fsType,"%li",buf.f_fsid[1]);
  230. else
  231. strncpy(fsType,"",MAXLINELENGTH);
  232. #endif /* __hpux */
  233. #ifndef GETFSTYPE
  234. strncpy(platform,"unknown",MAXLINELENGTH);
  235. strncpy(fsType, "",MAXLINELENGTH);
  236. #endif /* unknown platform */
  237. return;
  238. } /* end getFSType */
  239. /*--------------------------------------------------------------------------------
  240. *
  241. * readConfigFile
  242. *
  243. * Given the platform and type of file system, read the configuration file to
  244. * determine if there is a file-system specific dialog. If there is, fill
  245. * fsDialogData. If there is no file or if the file has no entry for
  246. * platform:fsType, dialogAvailable is set to FALSE.
  247. *
  248. * The configuration file consists of two parts. The first is a list of entries
  249. * (ending with "end") of the form
  250. *
  251. * platform:file-system-type=file-system-id
  252. *
  253. * where platform is one of the strings from getFSType(), file-system-type is
  254. * a (platform-dependent) string identifying the type of file system, and
  255. * file-system-id is a string used in the configuration file to identify the
  256. * file system. The second part of the file consists of lists of attributes
  257. * (in the form name = value, one per line) for each of the file system id's.
  258. * Blank lines and lines beginning with * are ignored as is case. A example
  259. * is given below.
  260. *
  261. * -------------------------------------------------
  262. * * sample dtfs configuration file
  263. *
  264. * aix:4=afs
  265. * hpux:8=afs
  266. * sunos:nfs=nfs
  267. * end
  268. *
  269. * afs: buttonlabel = Change AFS ACL ...
  270. * fsDialog = modAttrAFS
  271. * warning = File system access may be further restriced by AFS ACLs
  272. *
  273. * nfs: buttonLabel = Change NFS attributes ...
  274. * fsDialog = <configuration-location>/bin/modNFSAttr
  275. * -------------------------------------------------
  276. *
  277. *--------------------------------------------------------------------------------*/
  278. static void
  279. readConfigFile(const String fsType,
  280. const String platform,
  281. dtFSData * fsDialogData,
  282. Boolean * dialogAvailable)
  283. {
  284. char fsID[MAXLINELENGTH];
  285. FILE * fptr;
  286. String fname, msg1, msg2;
  287. *dialogAvailable = FALSE;
  288. fname = configFileName();
  289. fptr = fopen(fname,"r");
  290. if (fptr == NULL)
  291. {
  292. msg1 = GETMESSAGE(21, 22, "Cannot open file manager configuration file: ");
  293. msg2 = strerror(errno);
  294. sprintf(g_errorMessage,"%s%s\n %s\n",msg1,fname,msg2);
  295. _DtSimpleError (application_name, DtError, NULL, g_errorMessage, NULL);
  296. return;
  297. }
  298. readFSID(fptr, fsType, platform, fsID);
  299. DPRINTF((" fsID=\"%s\"\n",fsID));
  300. readDialogData(fptr, fsID, dialogAvailable, fsDialogData);
  301. /* make sure that a dialog program has been specified or execl will do unfortunate things */
  302. if (strlen(fsDialogData->fsDialogProgram) == 0)
  303. {
  304. *dialogAvailable = FALSE;
  305. if (strlen(fsDialogData->buttonLabel) != 0)
  306. {
  307. msg1 = XtNewString(GETMESSAGE(21, 29, "No value was provided for the fsDialog field in dtfile's configuration file"));
  308. _DtSimpleError (application_name, DtError, NULL, msg1, NULL);
  309. XtFree(msg1);
  310. }
  311. }
  312. fclose(fptr);
  313. return;
  314. } /* end readConfigFile */
  315. /*--------------------------------------------------------------------------------
  316. *
  317. * configFileName
  318. *
  319. * return the name of the configuration file which defines file-system
  320. * specific dialogs ... a hierarchy of names is searched until a file
  321. * is found ... no checking is done to see if it can be read
  322. *
  323. *------------------------------------------------------------------------------*/
  324. static String
  325. configFileName(void)
  326. {
  327. int i, err;
  328. struct stat buf;
  329. String s;
  330. static char fn[MAX_PATH]=""; /* remember name once its been determined */
  331. if (strlen(fn) != 0) return fn; /* has filename been determined already? */
  332. for (i=0; i < 4; i++)
  333. {
  334. switch (i)
  335. {
  336. case 0: /* file name $DTFSCONFIG */
  337. if ( (s=getenv("DTFSCONFIG")) != NULL) /* a convenience for debugging */
  338. strncpy(fn,s,MAX_PATH);
  339. else /* DTFSCONFIG not defined */
  340. continue;
  341. break;
  342. case 1: /* $HOME/dtfile.config */
  343. if ( (s=getenv("HOME")) != NULL)
  344. {
  345. strncpy(fn,s,MAX_PATH);
  346. strcat (fn,"/");
  347. strncat(fn,CONFIGFILENAME,MAX_PATH-strlen(fn)-1);
  348. }
  349. else /* $HOME not defined */
  350. continue;
  351. break;
  352. case 2: /* SYSCONFIGFILEDIR, e.g. /etc/dt/config/dtfile.config */
  353. strncpy(fn,SYSCONFIGFILEDIR,MAX_PATH);
  354. strcat (fn,"/");
  355. strncat(fn,CONFIGFILENAME,MAX_PATH-strlen(fn)-1);
  356. break;
  357. case 3: /* DEFCONFIGFILEDIR, e.g. /usr/dt/config/C/dtfile.config */
  358. strncpy(fn,DEFCONFIGFILEDIR,MAX_PATH);
  359. strcat (fn,"/");
  360. if ( (s=getenv("LANG")) != NULL)
  361. {
  362. strncat(fn,s,MAX_PATH-strlen(fn)-1);
  363. strcat (fn,"/");
  364. }
  365. else
  366. {
  367. strncat(fn,"C",MAX_PATH-strlen(fn)-1);
  368. strcat (fn,"/");
  369. }
  370. strncat(fn,CONFIGFILENAME,MAX_PATH-strlen(fn)-1);
  371. break;
  372. } /* end switch */
  373. err = stat(fn, &buf);
  374. DPRINTF((" config file \"%s\" stat ret=%i\n",fn,err));
  375. if (err == 0) /* file is found */
  376. return fn;
  377. } /* end loop over possible config files */
  378. /* didn't find any of the files (this should never, ever happen) */
  379. /* return the name of the factory default (case 3 above) which should always be there */
  380. strncpy(fn,DEFCONFIGFILENAME,MAX_PATH);
  381. return fn;
  382. } /* end configFileName */
  383. /*--------------------------------------------------------------------------------
  384. *
  385. * readFSID
  386. *
  387. * get the file-system identifier from the configuration file
  388. *
  389. * fptr refers to an open configuration file
  390. * fsType and platform identify the platfrom (aix, hpux, sunos, etc)
  391. * and file-system type (afs, nfs, dfs, etc.)
  392. * fsID is filled by matching platform:fsType with with information in the
  393. * file and reading the id; the string comparisons are case insensitive
  394. * if there is more than one match, the last fsID found will be returned;
  395. * if no match is found, fsID is returned as ""
  396. * upon conclusion, the file is positioned past the "end" record
  397. *
  398. *------------------------------------------------------------------------------*/
  399. static void
  400. readFSID ( FILE * fptr,
  401. const String fsType,
  402. const String platform,
  403. String fsID)
  404. {
  405. char line[MAXLINELENGTH];
  406. String pform, type, id;
  407. int lineLength;
  408. String lineIn, lineOut;
  409. fsID[0] = '\0';
  410. while ( (lineLength=readLine(fptr,line)) != EOF &&
  411. stricmp(line,"end") != 0 )
  412. {
  413. /* readLine has changed all white space to blanks ... now remove
  414. the blanks as they are not significant here */
  415. for (lineIn = lineOut = line; *lineIn != '\0'; lineIn++)
  416. if (*lineIn != ' ')
  417. {
  418. *lineOut = *lineIn;
  419. lineOut++;
  420. }
  421. *lineOut = '\0';
  422. pform = strtok(line,":");
  423. type = strtok(NULL,"=");
  424. id = strtok(NULL," ");
  425. if (stricmp(pform,platform)==0 && stricmp(type,fsType)==0)
  426. strncpy(fsID,id,MAXLINELENGTH);
  427. }
  428. return;
  429. } /* end readFSID */
  430. /*--------------------------------------------------------------------------------
  431. *
  432. * readDialogData
  433. *
  434. * fill dtFSData with information from the configuration file; set
  435. * dialogAvailable
  436. *
  437. * fsID is a file-system identifier defined, in the configuration file,
  438. * by a platform:file-system-type pair. The configuration file is
  439. * searched from its current position until a definition section
  440. * for fsID is found. The string comparison is case insensitive; if more
  441. * than one match is found, the last in the file is used. The fields in
  442. * dtFSData are initialized (e.g. string fields are set to "") if no
  443. * matches are found or if no match is found for a particular field.
  444. * Upon conclusion, the file is positioned at EOF.
  445. *
  446. *------------------------------------------------------------------------------*/
  447. static void
  448. readDialogData( FILE * fptr,
  449. const String fsID,
  450. Boolean * dialogAvailable,
  451. dtFSData * fsDialogData)
  452. {
  453. int lineLength;
  454. String s, id, token1, token2;
  455. String msg1;
  456. char line[MAXLINELENGTH];
  457. *dialogAvailable = FALSE;
  458. /* initialize fields in fsDialogData */
  459. strcpy(fsDialogData->buttonLabel,"");
  460. strcpy(fsDialogData->fsDialogProgram,"");
  461. strcpy(fsDialogData->warningMessage,"");
  462. fsDialogData->dismissStdPermissionDialog = FALSE;
  463. if (strlen(fsID) == 0)
  464. return;
  465. /* loop over lines in the file; note that readLine is called
  466. from within the loop except for the first pass */
  467. for (lineLength=readLine(fptr,line); lineLength != EOF; )
  468. {
  469. id = strtok(line,":");
  470. if (stricmp(id,fsID) == 0)
  471. {
  472. /* a section matching the input fsID has been found */
  473. *dialogAvailable = TRUE;
  474. token1 = strtok(NULL," =");
  475. s = strchr(token1,'\0') + 1; /* first character after token1 */
  476. token2 = &s[strspn(s," =")]; /* first non-blank, non-= after token1 */
  477. /* loop to get data for fields in fsDialogData */
  478. while(strchr(token1,':') == NULL && lineLength != EOF)
  479. {
  480. if (stricmp(token1,"buttonlabel") == 0)
  481. strncpy(fsDialogData->buttonLabel,token2,MAXLINELENGTH);
  482. else if (stricmp(token1,"warning") == 0)
  483. {
  484. strncpy(fsDialogData->warningMessage,token2,MAXLINELENGTH);
  485. }
  486. else if (stricmp(token1,"fsdialog") == 0)
  487. strncpy(fsDialogData->fsDialogProgram,token2,MAXLINELENGTH);
  488. else if (stricmp(token1,"dismiss") == 0)
  489. fsDialogData->dismissStdPermissionDialog = (stricmp(token2,"yes") == 0);
  490. else
  491. {
  492. msg1 = GETMESSAGE(21, 24, "Unknown field label in file manager configuration file: ");
  493. sprintf(g_errorMessage,"%s\"%s\"\n",msg1,token1);
  494. _DtSimpleError (application_name, DtWarning, NULL, g_errorMessage, NULL);
  495. }
  496. lineLength = readLine(fptr,line);
  497. if (lineLength != EOF)
  498. {
  499. token1 = strtok(line," =");
  500. s = strchr(token1,'\0') + 1;
  501. token2 = &s[strspn(s," =")];
  502. }
  503. } /* end while */
  504. } /* end if */
  505. else
  506. {
  507. /* the current line does not match fsID ... get next line */
  508. lineLength = readLine(fptr,line);
  509. }
  510. } /* end for */
  511. if ( ! *dialogAvailable )
  512. {
  513. msg1 = GETMESSAGE(21, 25, "No information found in file manager configuration file for file-system identifier");
  514. sprintf(g_errorMessage,"%s \"%s\"\n",msg1,fsID);
  515. _DtSimpleError (application_name, DtError, NULL, g_errorMessage, NULL);
  516. }
  517. } /* end readDialogData */
  518. /*--------------------------------------------------------------------------------
  519. *
  520. * readLine
  521. *
  522. * read a line from the stream pointed to by fptr and return it in line
  523. * line is allocated by the caller
  524. *
  525. * blank lines and lines starting with * are skipped
  526. * leading and trailing white space is removed
  527. * imbedded white space characters are changed to blanks
  528. * imbedded "\n" is changed to space, newline
  529. * the length of the line or EOF (on end-of-file or error) is returned
  530. *
  531. *------------------------------------------------------------------------------*/
  532. static int
  533. readLine(FILE * fptr, String line)
  534. {
  535. const char commentChar = '#';
  536. char myLine[MAXLINELENGTH];
  537. String s, t;
  538. int i, len;
  539. while (TRUE)
  540. {
  541. if ( fgets(myLine,MAXLINELENGTH,fptr) == NULL)
  542. return EOF;
  543. else
  544. {
  545. s = strip(myLine); /* remove leading & trailing whitespace */
  546. if ((len=strlen(s)) != 0 && s[0] != commentChar)
  547. {
  548. /* change imbedded white space characters to spaces */
  549. for (i=0; i<len; i++)
  550. if (isspace(s[i]))
  551. s[i] = ' ';
  552. /* change any imbedded "\n" to space followed by newline */
  553. while ( (t=strstr(s,"\\n")) != NULL )
  554. {
  555. *t = ' '; /* space */
  556. *(t+1) = '\n'; /* new line */
  557. }
  558. strncpy(line,s,MAXLINELENGTH);
  559. return len;
  560. }
  561. }
  562. }
  563. } /* end readLine */
  564. /*--------------------------------------------------------------------------------
  565. *
  566. * stricmp
  567. *
  568. * compare strings ignoring case, return value as in strcmp
  569. *
  570. *------------------------------------------------------------------------------*/
  571. static int
  572. stricmp(const String s1, const String s2)
  573. {
  574. int i;
  575. for (i=0; tolower(s1[i]) == tolower(s2[i]); i++)
  576. if (s1[i] == '\0')
  577. return 0;
  578. return (tolower(s1[i]) > tolower(s2[i])) ? +1 : -1;
  579. } /* end stricmp */
  580. /*--------------------------------------------------------------------------------
  581. *
  582. * strip
  583. *
  584. * remove trailing white space by inserting \0
  585. * return a pointer to the first non-white space character
  586. *------------------------------------------------------------------------------*/
  587. static String
  588. strip(String s)
  589. {
  590. int i;
  591. for (i=(strlen(s)-1); isspace(s[i]) && i>=0; i--)
  592. ;
  593. s[i+1] = '\0';
  594. for (i=0; isspace(s[i]); i++)
  595. ;
  596. return &s[i];
  597. } /* end strip */
  598. /*----------------
  599. * for testing
  600. *----------------*/
  601. /*
  602. main(int argc, char **argv)
  603. {
  604. char pwd[100];
  605. int err = 0;
  606. Boolean test;
  607. dtFSData data;
  608. if(argc > 1)
  609. {
  610. strcpy(pwd, argv[1]);
  611. }
  612. else
  613. {
  614. getcwd(pwd,sizeof(pwd));
  615. }
  616. printf("testing file \"%s\"\n",pwd);
  617. test = fsDialogAvailable(pwd, &data);
  618. if (test)
  619. {
  620. printf("dialog is available\n");
  621. printf(" buttonLabel=\"%s\"\n",data.buttonLabel);
  622. printf(" fsDialogProgram=\"%s\"\n",data.fsDialogProgram);
  623. }
  624. else
  625. {
  626. printf("dialog not available\n");
  627. }
  628. }
  629. */