dtcreate: Resolve coverity issues
[oweals/cde.git] / cde / programs / dtcreate / fileio.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29
30 #include <Dt/Icon.h>
31
32 #include <stdlib.h>
33 #include "dtcreate.h"
34 #include "cmnrtns.h"
35 #include "fileio.h"
36 #include "parser.h"
37 #include "ErrorDialog.h"
38
39 #define COMMENT_CHAR      '#'
40 #define MAX_KEY           10000
41 #define MAX_KEY_SIZE      5
42 #define MAX_HEADER_LINES  13
43
44 /*****************************************************************************/
45 /*                                                                           */
46 /*  CalculateMagicCookie                                                     */
47 /*                                                                           */
48 /*   description: Calculates a integer (the "key" value) which reflects the  */
49 /*                contents of the given file from the current file-offset    */
50 /*                to the end of file.                                        */
51 /*                Comment lines (those starting with '!' or '#') are ignored */
52 /*                in calculating the key value.                              */
53 /*                                                                           */
54 /*    input: pointer to FILE                                                 */
55 /*    output: integer - magic cookie                                         */
56 /*                                                                           */
57 /*****************************************************************************/
58 int CalculateMagicCookie(FILE *fp)
59 {
60
61 #define PRIME1  2999
62 #define PRIME2  353
63 #define PRIME3  113
64
65   long  save_offset, file_id;
66   int   c, prev_c, char_sum, nline, nword, nchar, inword;
67
68   /**************************************************************************/
69   /* Since we will be traversing the file, we save the file-offset          */
70   /* so that we can restore it before returning                             */
71   /**************************************************************************/
72   save_offset = ftell( fp );
73
74   inword = FALSE;
75   char_sum = nline = nword = nchar = 0;
76   prev_c = '0';   /* This is arbitrary, but '0' not '\0' IS intended */
77
78   while ( (c = fgetc( fp )) != EOF ) {
79     if ( c == COMMENT_CHAR ) {
80        while ( (c = fgetc( fp )) != EOF && c != '\n' )
81                ; /* skip characters to end of line */
82     } else {
83        char_sum += (c * (prev_c%10));
84        prev_c = c;
85        ++nchar;
86
87        if (c == '\n') {
88           ++nline;
89        }
90        if ( c == ' ' || c == '\n' || c == '\t' ) {
91           inword = FALSE;
92        } else if ( inword == FALSE ) {
93           inword = TRUE;
94           ++nword;
95        }
96     }
97   }
98
99   file_id = PRIME1 * nline + PRIME2 * nword + PRIME3 * nchar + char_sum;
100
101 #ifdef DEBUG
102   printf( "nline = %d nword = %d nchar = %d char_sum = %d\n",
103           nline, nword, nchar, char_sum );
104   printf( "file_id = %ld\n", file_id );
105 #endif
106
107   /**************************************************************************/
108   /* We restore the file-offset to its previous value                       */
109   /**************************************************************************/
110   (void) fseek( fp, save_offset, 0 );
111   return ( file_id % MAX_KEY );
112 }
113
114 /****************************************************************************/
115 /*                                                                          */
116 /*  SetCookie   - find the location in the file to write the magic cookie   */
117 /*                and update the file with the magic cookie.                */
118 /*                                                                          */
119 /*  input   - file pointer                                                  */
120 /*  output  - none                                                          */
121 /*                                                                          */
122 /****************************************************************************/
123 void SetCookie(FILE *fp)
124 {
125   int     iCookie;
126   long    lSave_offset;
127   char    buffer[256];
128   char    *keystr;
129   char    *retbuf;
130   fpos_t  filepos;
131   char    *mc_pos;
132   char    *mc_clrpos;
133   int     i;
134   int     size;
135
136   /**************************************************************************/
137   /* Save file pointer initial setting                                      */
138   /**************************************************************************/
139   lSave_offset = ftell (fp);
140
141   /**************************************************************************/
142   /* Set file pointer to beginning of file                                  */
143   /**************************************************************************/
144   fseek(fp, 0, SEEK_SET);
145
146   /**************************************************************************/
147   /* Calculate magic cookie                                                 */
148   /**************************************************************************/
149   iCookie = CalculateMagicCookie(fp);
150 #ifdef DEBUG
151   printf("Magic Cookie: %d\n", iCookie);
152 #endif
153
154   /**************************************************************************/
155   /* Find location in header and store cookie                               */
156   /**************************************************************************/
157   keystr = (char *)NULL;
158   retbuf = buffer;
159   i = 0;
160   while ( !keystr && retbuf && (i < MAX_HEADER_LINES) ) {
161     fgetpos(fp, &filepos);
162     retbuf = fgets(buffer, 80, fp);
163     keystr = strstr (buffer, "$KEY:");
164     i++;
165   }
166
167   if (!keystr) {
168 #ifdef DEBUG
169      printf("No '$KEY' keyword in file. Magic Cookie not written to file.\n");
170 #endif
171      return;
172   }
173   mc_pos = strchr(keystr, ':');
174   if (mc_pos) {
175      mc_pos += 2;
176      sprintf(mc_pos, "%i", iCookie);
177      size = strlen(mc_pos);
178      if (size < MAX_KEY_SIZE) {
179         mc_clrpos = mc_pos + size;
180         for (i=size; i < MAX_KEY_SIZE; i++) {
181             *mc_clrpos = ' ';
182             mc_clrpos++;
183         }
184      }
185   }
186   fsetpos (fp, &filepos);
187   fputs (buffer, fp);
188
189   /**************************************************************************/
190   /* Set file pointer back to initial setting                               */
191   /**************************************************************************/
192   fseek (fp, lSave_offset, SEEK_SET);
193   return;
194 }
195
196 /****************************************************************************/
197 /*                                                                          */
198 /*  CheckCookie  - check if the magic cookie exists in the file and is the  */
199 /*                 correct value.                                           */
200 /*                                                                          */
201 /*  input    - file pointer                                                 */
202 /*  output   - boolean indicating if correct value or not, TRUE = good      */
203 /*                                                                          */
204 /****************************************************************************/
205 Boolean CheckCookie(FILE *fp)
206 {
207   int     iNewCookie, iOldCookie;
208   long    lSave_offset;
209   char    buffer[256];
210   char    *msgPtr, *errPtr;
211   char    *keystr;
212   char    *retbuf;
213   fpos_t  filepos;
214   char    *mc_pos;
215   int     i;
216   Boolean bGoodCookie = TRUE;
217
218   /**************************************************************************/
219   /* Save file pointer initial setting                                      */
220   /**************************************************************************/
221   lSave_offset = ftell (fp);
222
223   /**************************************************************************/
224   /* Set file pointer to beginning of file                                  */
225   /**************************************************************************/
226   fseek (fp, 0, SEEK_SET);
227
228   /**************************************************************************/
229   /* Calculate magic cookie                                                 */
230   /**************************************************************************/
231   iNewCookie = CalculateMagicCookie(fp);
232 #ifdef DEBUG
233   printf("New Magic Cookie: %d\n", iNewCookie);
234 #endif
235
236   /**************************************************************************/
237   /* Find location in header of old cookie and retrieve it.                 */
238   /**************************************************************************/
239   keystr = (char *)NULL;
240   retbuf = buffer;
241   i = 0;
242   while ( !keystr && retbuf && (i < MAX_HEADER_LINES) ) {
243     fgetpos(fp, &filepos);
244     retbuf = fgets(buffer, 80, fp);
245     keystr = strstr (buffer, "$KEY:");
246     i++;
247   }
248
249   if (!keystr) {
250 #ifdef DEBUG
251      printf("No '$KEY' keyword in file header. File is invalid.\n");
252 #endif
253      msgPtr = GETMESSAGE(5, 67,
254          "Create Action can only edit files that were created\n\
255 and edited by Create Action.");
256      errPtr = XtNewString(msgPtr);
257      display_error_message(CreateActionAppShell, errPtr);
258      XtFree(errPtr);
259      bGoodCookie = FALSE;
260      fseek (fp, lSave_offset, SEEK_SET);
261      return(bGoodCookie);
262   }
263
264   mc_pos = strchr(keystr, ':');
265   mc_pos += 2;
266
267   sscanf(mc_pos, "%i", &iOldCookie);
268 #ifdef DEBUG
269   printf("Old Magic Cookie: %d\n", iOldCookie);
270 #endif
271
272
273   /**************************************************************************/
274   /* Check if cookies are the same.                                         */
275   /**************************************************************************/
276 #ifdef DEBUG
277   if (iOldCookie == iNewCookie) {
278      printf("Cookies are good = %i\n", iNewCookie);
279   }
280 #endif
281
282   if (iOldCookie != iNewCookie) {
283
284 #ifdef DEBUG
285      printf("Cookies are bad; n=%i, o=%i\n", iNewCookie, iOldCookie);
286 #endif
287
288      msgPtr = GETMESSAGE(5, 66,
289          "Could not load the file because it has been altered by some\n\
290 other means other than Create Action.  This could have been caused\n\
291 by modifying the file with a text editor or some other tool.");
292      errPtr = XtNewString(msgPtr);
293      display_error_message(CreateActionAppShell, errPtr);
294      XtFree(errPtr);
295      bGoodCookie = FALSE;
296   }
297
298   /**************************************************************************/
299   /* Set file pointer back to initial setting                               */
300   /**************************************************************************/
301   fseek (fp, lSave_offset, SEEK_SET);
302   return(bGoodCookie);
303 }
304
305 /*****************************************************************************/
306 /*                                                                           */
307 /*  MakeExecString                                                           */
308 /*                                                                           */
309 /*    return codes:                                                          */
310 /*                                                                           */
311 /*      ptr  good                                                            */
312 /*      0    bad                                                             */
313 /*                                                                           */
314 /*****************************************************************************/
315 char * MakeExecString(char *pszCmd, char *pszPrompt)
316
317 {
318   char    *pszExecString;
319   char    *pArgSrc = (char *)NULL;
320   char    *pArgDst = (char *)NULL;
321   char    *pTmp;
322   char    pszArgStr[10];
323   int     size = 0;
324   int     cArgs = 0;
325   int     val;
326   Boolean bDidPrompt = FALSE;
327 #define   ARGSIZE  7    /* sizeof "%Arg_n%" */
328
329   pArgSrc = pszCmd;
330   while (pArgSrc = strchr(pArgSrc, '$')) {
331 #ifdef DEBUG
332     printf("%d  pArgSrc = %s\n", cArgs, pArgSrc);
333 #endif
334     pArgSrc++;
335     val = *pArgSrc;
336     switch (val) {
337       case '1': case '2': case '3': case '4': case '5':
338       case '6': case '7': case '8': case '9': case '*':
339                 cArgs++;
340                 break;
341     }
342   }
343
344 #ifdef DEBUG
345   printf("Args found = %d\n", cArgs);
346 #endif
347
348   size = 1;
349   size += cArgs * ARGSIZE;
350   size += strlen(pszCmd);
351   if (pszPrompt) {
352      size += strlen(pszPrompt) + 2;
353   }
354   pszExecString = (char *)XtMalloc(size);
355
356   strcpy(pszExecString, pszCmd);
357   pArgSrc = pszCmd;
358   pTmp = pszExecString;
359   while (pArgSrc = strchr(pArgSrc, '$')) {
360     pArgDst = strchr(pTmp, '$');
361     pTmp = pArgDst;
362     *pArgDst = '\0';
363     pTmp++;
364     val = *pTmp;
365     switch (val) {
366       case '1': case '2': case '3': case '4': case '5':
367       case '6': case '7': case '8': case '9': case '*':
368                 pArgSrc+=2;
369                 if (*pTmp == '*') {
370                    strcat(pszExecString, "%Args");
371                 } else {
372                    sprintf(pszArgStr, "%%Arg_%c", *pTmp);
373                    strcat(pszExecString, pszArgStr);
374                 }
375                 if ((pszPrompt) && (!bDidPrompt)) {
376                    strcat(pszExecString, "\"");
377                    strcat(pszExecString, pszPrompt);
378                    strcat(pszExecString, "\"");
379                    bDidPrompt = TRUE;
380                 }
381                 strcat(pszExecString, "%");
382                 break;
383     }
384     if (*pArgSrc) {
385        strcat(pszExecString, pArgSrc);
386        pArgSrc++;
387     }
388   }
389 #ifdef DEBUG
390   printf("EXEC_STRING = '%s'\n", pszExecString);
391 #endif
392   return(pszExecString);
393 }
394
395 /*****************************************************************************/
396 /*                                                                           */
397 /*  WriteDefinitionFile                                                      */
398 /*                                                                           */
399 /*    return codes:                                                          */
400 /*                                                                           */
401 /*      0    successful                                                      */
402 /*      1    could not open file                                             */
403 /*                                                                           */
404 /*****************************************************************************/
405 ushort WriteDefinitionFile(char *pszFile, ActionData *pAD)
406
407 {
408   FILE            *fp = (FILE *)NULL;
409   int             i;
410   FiletypeData    *pFtD;
411   char            buffer[MAXBUFSIZE];
412   char            *ptr;
413   char            *msgPtr, *fmtPtr, *errPtr;
414
415   /***************************************************************************/
416   /* Open action and filetypes definition file for writing.                  */
417   /***************************************************************************/
418   if ((fp = fopen(pszFile, "w+")) == NULL) {
419 #ifdef DEBUG
420     printf("Can not open file.\n"); /* debug */
421 #endif
422     msgPtr = GETMESSAGE(5, 55, "Could not create the following file:");
423     fmtPtr = "%s\n   %s";
424     errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
425                        strlen(pszFile) + 1) * sizeof(char));
426     sprintf(errPtr, fmtPtr, msgPtr, pszFile);
427     display_error_message(CreateActionAppShell, errPtr);
428     XtFree(errPtr);
429     return(1);
430   }
431 #ifdef DEBUG
432   printf("database file = %s\n", pszFile); /* debug */
433 #endif
434
435   /***************************************************************************/
436   /* Write comment area of action and filetype definition file, including    */
437   /* revision number and magic cookie.                                       */
438   /***************************************************************************/
439   fprintf(fp, "######################################################################\n");
440   fprintf(fp, "#\n");
441   fprintf(fp, "#    Common Desktop Environment (CDE)\n");
442   fprintf(fp, "#\n");
443   fprintf(fp, "#    Action and DataType Definition File\n");
444   fprintf(fp, "#\n");
445   fprintf(fp, "#      Generated by the CreateAction tool\n");
446   fprintf(fp, "#\n");
447   fprintf(fp, "#      $Revision: 1.0\n");
448   fprintf(fp, "#\n");
449   fprintf(fp, "#      $KEY: nnnnn \n");
450   fprintf(fp, "#\n");
451   fprintf(fp, "######################################################################\n");
452   fprintf(fp, "#\n");
453   fprintf(fp, "#    WARNING:\n");
454   fprintf(fp, "#\n");
455   fprintf(fp, "#    This file was generated by the CDE CreateAction tool.\n");
456   fprintf(fp, "#    If this file is modified by some other tool, such as vi,\n");
457   fprintf(fp, "#    the CreateAction tool will no longer be able to load and\n");
458   fprintf(fp, "#    update this file.  For this reason, changes to this file\n");
459   fprintf(fp, "#    should be handled through CreateAction whenever possible.\n");
460   fprintf(fp, "#\n");
461   fprintf(fp, "######################################################################\n");
462   fprintf(fp, "\n");
463
464   /***************************************************************************/
465   /* Write the main Action definition.                                       */
466   /***************************************************************************/
467   ptr = GetCoreName(pszFile);
468   fprintf(fp, "ACTION %s\n", ptr);
469   free(ptr);
470   fprintf(fp, "{\n");
471   fprintf(fp, "     LABEL         %s\n", pAD->pszName);
472   fprintf(fp, "     TYPE          COMMAND\n");
473   ptr = MakeExecString(AD.pszCmd, AD.pszPrompt);
474   if (ptr) {
475      fprintf(fp, "     EXEC_STRING   %s\n", ptr);
476      XtFree(ptr);
477   }
478   if (pAD->pszIcon) {
479 #ifdef OLDICON
480     fprintf(fp, "     LARGE_ICON    %s.m\n", pAD->pszIcon);
481     fprintf(fp, "     SMALL_ICON    %s.t\n", pAD->pszIcon);
482 #else
483     if (ActionHasIcon()) {
484        fprintf(fp, "     ICON          %s\n", pAD->pszName);
485     } else {
486        fprintf(fp, "     ICON          %s\n", pAD->pszIcon);
487     }
488 #endif
489   }
490 #ifdef DEBUG
491   printf("CA flags = %X\n", pAD->fsFlags);
492 #endif
493   if (pAD->fsFlags & CA_WT_TERM) fprintf(fp, "     WINDOW_TYPE   TERMINAL\n");
494   else if (pAD->fsFlags & CA_WT_PERMTERM) fprintf(fp, "     WINDOW_TYPE   PERM_TERMINAL\n");
495   else if (pAD->fsFlags & CA_WT_SHELLTERM) fprintf(fp, "     WINDOW_TYPE   SHELL_TERMINAL\n");
496   else fprintf(fp, "     WINDOW_TYPE   NO_STDIO\n");
497
498   if ((pAD->papFiletypes) && (pAD->fsFlags & CA_DF_ONLYFTFILES)) {
499     fprintf(fp, "     ARG_TYPE      %s", (pAD->papFiletypes[0])->pszName);
500     for (i=1; i < pAD->cFiletypes; i++) {
501       pFtD = pAD->papFiletypes[i];
502       fprintf(fp, ",%s", pFtD->pszName);
503     }
504     fprintf(fp, "\n");
505   }
506
507   if (pAD->pszHelp) {
508     fprintf(fp, "     DESCRIPTION   %s\n", pAD->pszHelp);
509   }
510   fprintf(fp, "}\n");
511   fprintf(fp, "\n");
512
513   /***************************************************************************/
514   /* Write the filetype definitions.                                         */
515   /***************************************************************************/
516   if (pAD->papFiletypes) {
517     for (i=0; i < pAD->cFiletypes; i++) {
518       pFtD = pAD->papFiletypes[i];
519       /***********************************************************************/
520       /* Write the data attributes declaration.                              */
521       /***********************************************************************/
522       fprintf(fp, "DATA_ATTRIBUTES %s\n", pFtD->pszName);
523       fprintf(fp, "{\n");
524       fprintf(fp, "     ACTIONS       Open");
525       if (pFtD->pszPrintCmd) {
526         fprintf(fp, ",Print");
527       }
528       fprintf(fp, "\n");
529       if (pFtD->pszIcon) {
530 #ifdef OLDICON
531         fprintf(fp, "     LARGE_ICON    %s.m\n", pFtD->pszIcon);
532         fprintf(fp, "     SMALL_ICON    %s.t\n", pFtD->pszIcon);
533 #else
534         if (FiletypeHasIcon(pFtD)) {
535            fprintf(fp, "     ICON          %s\n", pFtD->pszName);
536         } else {
537            fprintf(fp, "     ICON          %s\n", pFtD->pszIcon);
538         }
539 #endif
540       }
541       if (pFtD->pszHelp) {
542         fprintf(fp, "     DESCRIPTION   %s\n", pFtD->pszHelp);
543       }
544       fprintf(fp, "}\n");
545       fprintf(fp, "\n");
546       /***********************************************************************/
547       /* Write the data criteria   declaration.                              */
548       /***********************************************************************/
549       fprintf(fp, "DATA_CRITERIA %sA\n", pFtD->pszName);
550       fprintf(fp, "{\n");
551       fprintf(fp, "     DATA_ATTRIBUTES_NAME %s\n", pFtD->pszName);
552       if (pFtD->pszPermissions) {
553         fprintf(fp, "     MODE          %s\n", pFtD->pszPermissions);
554       }
555       if (pFtD->pszPattern) {
556         fprintf(fp, "     PATH_PATTERN  %s\n", pFtD->pszPattern);
557       }
558       if (pFtD->pszContents) {
559          if (pFtD->fsFlags & CA_FT_CNTSTRING)
560             strcpy(buffer, "string");
561          else if (pFtD->fsFlags & CA_FT_CNTBYTE)
562             strcpy(buffer, "byte");
563          else if (pFtD->fsFlags & CA_FT_CNTSHORT)
564             strcpy(buffer, "short");
565          else if (pFtD->fsFlags & CA_FT_CNTLONG)
566             strcpy(buffer, "long");
567          fprintf(fp, "     CONTENT       %d %s %s\n", pFtD->sStart, buffer, pFtD->pszContents);
568       }
569       fprintf(fp, "}\n");
570       fprintf(fp, "\n");
571       /***********************************************************************/
572       /* Write the Open MAP action.                                          */
573       /***********************************************************************/
574       fprintf(fp, "ACTION Open\n");
575       fprintf(fp, "{\n");
576       fprintf(fp, "     ARG_TYPE      %s\n", pFtD->pszName);
577       fprintf(fp, "     TYPE          MAP\n");
578       fprintf(fp, "     MAP_ACTION    %s\n", pAD->pszName);
579       fprintf(fp, "     LABEL         %s\n", GETMESSAGE(7, 30, "Open"));
580       fprintf(fp, "}\n");
581       fprintf(fp, "\n");
582       /***********************************************************************/
583       /* Write the Print filetype action and MAP action.                     */
584       /***********************************************************************/
585       if (pFtD->pszPrintCmd) {
586         /*********************************************************************/
587         /* First write the print filetype action.                            */
588         /*********************************************************************/
589         fprintf(fp, "ACTION %s_PRINT\n", pFtD->pszName);
590         fprintf(fp, "{\n");
591         fprintf(fp, "     TYPE          COMMAND\n");
592         ptr = MakeExecString(pFtD->pszPrintCmd, NULL);
593         if (ptr) {
594            fprintf(fp, "     EXEC_STRING   %s\n", ptr);
595          /*fprintf(fp, "     EXEC_STRING   %s\n", pFtD->pszPrintCmd);*/
596            XtFree(ptr);
597         }
598         fprintf(fp, "     WINDOW_TYPE   NO_STDIO\n");
599         fprintf(fp, "}\n");
600         fprintf(fp, "\n");
601         /*********************************************************************/
602         /* Now writhe the Print MAP action.                                  */
603         /*********************************************************************/
604         fprintf(fp, "ACTION Print\n");
605         fprintf(fp, "{\n");
606         fprintf(fp, "     ARG_TYPE      %s\n", pFtD->pszName);
607         fprintf(fp, "     TYPE          MAP\n");
608         fprintf(fp, "     MAP_ACTION    %s_PRINT\n", pFtD->pszName);
609         fprintf(fp, "     LABEL         %s\n", GETMESSAGE(7, 31, "Print"));
610         fprintf(fp, "}\n");
611         fprintf(fp, "\n");
612       }
613     }
614   }
615   SetCookie(fp);
616   if (fp) fclose(fp);
617   if(pszFile) {
618     chmod(pszFile, 0644);
619   }
620   return(0);
621 }
622
623 /*****************************************************************************/
624 /*                                                                           */
625 /*  WriteActionFile                                                          */
626 /*                                                                           */
627 /*    return codes:                                                          */
628 /*                                                                           */
629 /*      0    successful                                                      */
630 /*      1    could not open file                                             */
631 /*                                                                           */
632 /*****************************************************************************/
633 ushort WriteActionFile(ActionData *pAD)
634
635 {
636   FILE            *fp = (FILE *)NULL;
637   char            *pszFile;
638   char            *newName;
639   char            *pszEnvVar;
640   char            *msgPtr, *fmtPtr, *errPtr;
641
642   /***************************************************************************/
643   /* Open action file for writing.                                           */
644   /***************************************************************************/
645   newName = ReplaceSpaces(AD.pszName);
646   pszEnvVar = getenv("HOME");
647   pszFile = NULL;
648   if ( pszEnvVar && strlen(pszEnvVar) ) {
649      pszFile = XtMalloc(strlen(pszEnvVar) + strlen(newName) + 10);
650      if (pszFile) sprintf(pszFile, "%s/%s", pszEnvVar, newName);
651   } else {
652      pszFile = XtMalloc(strlen(newName) + 10);
653      if (pszFile) sprintf(pszFile, "/tmp/%s", newName);
654   }
655   free(newName);
656
657   /***************************************************************************/
658   /* Open action file for writing.                                           */
659   /***************************************************************************/
660   if (pszFile == NULL || (fp = fopen(pszFile, "w")) == NULL) {
661 #ifdef DEBUG
662     printf("Can not open file.\n"); /* debug */
663 #endif
664     msgPtr = GETMESSAGE(5, 55, "Could not create the following file:");
665     fmtPtr = "%s\n   %s";
666     errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
667                        strlen(pszFile) + 1) * sizeof(char));
668     sprintf(errPtr, fmtPtr, msgPtr, pszFile);
669     display_error_message(CreateActionAppShell, errPtr);
670     XtFree(errPtr);
671     XtFree(pszFile);
672     return(1);
673   }
674 #ifdef DEBUG
675   printf("action file = %s\n", pszFile); /* debug */
676 #endif
677   /***************************************************************************/
678   /* Write action file contents.                                             */
679   /***************************************************************************/
680   fprintf(fp, "################################################\n");
681   fprintf(fp, "#\n");
682   fprintf(fp, "#  action\n");
683   fprintf(fp, "#\n");
684   fprintf(fp, "#  Common Desktop Environment (CDE)\n");
685   fprintf(fp, "#\n");
686   fprintf(fp, "#  $TOG: fileio.c /main/9 1998/10/26 17:18:19 mgreess $\n");
687   fprintf(fp, "#\n");
688   fprintf(fp, "################################################\n");
689   fprintf(fp, "\n");
690   fprintf(fp, "# This file represents a CDE Dt action.  The contents of the file do\n");
691   fprintf(fp, "# not matter; however, the file must have executable permission and the\n");
692   fprintf(fp, "# name of the file must match an entry in the action database (*.dt files).\n");
693   fprintf(fp, "#\n");
694   fprintf(fp, "# For more information on Dt actions, see the CDE Dt manuals.\n");
695   fprintf(fp, "\n");
696   fprintf(fp, "echo \"Common Desktop Environment Dt action\"\n");
697   fprintf(fp, "\n");
698
699   fclose(fp);
700   chmod(pszFile, 0755);
701   return(0);
702 }
703
704 /******************************************************************************/
705 /* check_file_exists - check if the file exists that is passed in, if not     */
706 /*                     display error dialog.                                  */
707 /*                                                                            */
708 /* INPUT:   filename      - name of file to check if it exists or not.        */
709 /*                                                                            */
710 /* OUTPUT:  TRUE          - file exists                                       */
711 /*          FALSE         - file does not exist                               */
712 /*                                                                            */
713 /******************************************************************************/
714 Boolean check_file_exists (char *pszFileName)
715 {
716   FILE *exists;
717
718   /***************************************/
719   /* see if file exists                  */
720   /***************************************/
721   exists = fopen (pszFileName, "r");
722
723   /***************************************/
724   /* if exists, return good return code  */
725   /***************************************/
726   if (exists) {
727     fclose (exists);
728     return(TRUE);
729   } else {
730 #ifdef DEBUG
731     printf("File '%s' does not exist!\n", pszFileName);
732 #endif
733     return(FALSE);
734   }
735 }
736
737 /*****************************************************************************/
738 /*                                                                           */
739 /*  OpenDefinitionFile                                                       */
740 /*                                                                           */
741 /*    return codes:                                                          */
742 /*                                                                           */
743 /*      0    successful                                                      */
744 /*      1    error                                                           */
745 /*                                                                           */
746 /*****************************************************************************/
747 int OpenDefinitionFile(char *pszFile, ActionData *pAD)
748
749 {
750   FILE       *fp = (FILE *)NULL;
751   int        rc = 1;
752   char       *msgPtr, *fmtPtr, *errPtr;
753
754   /***************************************************************************/
755   /* Open action and filetypes definition file for reading.                  */
756   /***************************************************************************/
757   if ((fp = fopen(pszFile, "r+")) == NULL) {
758 #ifdef DEBUG
759     printf("Can not open file.\n"); /* debug */
760 #endif
761     msgPtr = GETMESSAGE(5, 60, "Could not open the following file:");
762     fmtPtr = "%s\n   %s";
763     errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
764                        strlen(pszFile) + 1) * sizeof(char));
765     sprintf(errPtr, fmtPtr, msgPtr, pszFile);
766     display_error_message(CreateActionAppShell, errPtr);
767     XtFree(errPtr);
768     return(1);
769   }
770 #ifdef DEBUG
771   printf("Opened database file = %s\n", pszFile); /* debug */
772 #endif
773
774   /***************************************************************************/
775   /* If magic cookie is good, then parse the file.                           */
776   /***************************************************************************/
777   if (CheckCookie(fp)) {
778 #ifdef DEBUG
779      printf("Cookie good, call parse code\n");
780 #endif
781      rc = GetActionData(fp, pAD);
782
783      /************************************************************************/
784      /* If error, display error message.                                     */
785      /************************************************************************/
786      if (rc) {
787         msgPtr = GETMESSAGE(5, 90, "Could not parse the following file:");
788         fmtPtr = "%s\n   %s";
789         errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
790                            strlen(pszFile) + 1) * sizeof(char));
791         sprintf(errPtr, fmtPtr, msgPtr, pszFile);
792         display_error_message(CreateActionAppShell, errPtr);
793         XtFree(errPtr);
794         fclose(fp);
795         return(1);
796      }
797   }
798   fclose(fp);
799   return(rc);
800 }
801
802 /******************************************************************************/
803 /* CheckDirtyIcon - check if icon has a DirtyBit set                          */
804 /*                                                                            */
805 /* INPUT:   Icon Widget   - widget id of icon gadget to check                 */
806 /*                                                                            */
807 /* OUTPUT:  TRUE          - dirty bit is set                                  */
808 /*          FALSE         - dirty bit is not set                              */
809 /*                                                                            */
810 /******************************************************************************/
811 Boolean CheckDirtyIcon (Widget wid)
812 {
813   IconData  *pIconData;
814
815   pIconData = GetIconDataFromWid(wid);
816   if (pIconData) {
817      if ( (pIconData->pmDirtyBit) || (pIconData->bmDirtyBit) ) {
818         return(True);
819      }
820   }
821   return(False);
822 }
823
824 /*****************************************************************************/
825 /*                                                                           */
826 /*  CreateIconName                                                           */
827 /*                                                                           */
828 /*    return codes:                                                          */
829 /*                                                                           */
830 /*      0    successful                                                      */
831 /*      1    could not open file                                             */
832 /*                                                                           */
833 /*****************************************************************************/
834 char * CreateIconName(char *pszDirName, char *pszBaseName, enum icon_size_range enumSize, char *pszType, Boolean bIsMask)
835 {
836   char  *pszName;
837   char  pszSize[MAX_EXT_SIZE];
838
839   switch (enumSize) {
840     case Large_Icon :
841                strcpy(pszSize, LARGE_EXT);
842                break;
843     case Medium_Icon :
844                strcpy(pszSize, MEDIUM_EXT);
845                break;
846     case Small_Icon :
847                strcpy(pszSize, SMALL_EXT);
848                break;
849     case Tiny_Icon :
850                strcpy(pszSize, TINY_EXT);
851                break;
852     case None_Selected :
853                pszSize[0] = 0;
854   }
855   if (bIsMask) {
856      strcat(pszSize, "_m");
857   }
858   if (pszDirName) {
859      pszName = XtMalloc(strlen(pszDirName) + strlen(pszBaseName) + strlen(pszSize) + strlen(pszType) + 1);
860      if (pszName) {
861         sprintf(pszName, "%s%s%s%s", pszDirName, pszBaseName, pszSize, pszType);
862      }
863   } else {
864      pszName = XtMalloc(strlen(pszBaseName) + strlen(pszSize) + strlen(pszType) + 1);
865      if (pszName) {
866         sprintf(pszName, "%s%s%s", pszBaseName, pszSize, pszType);
867      }
868   }
869   return(pszName);
870 }
871
872 /*****************************************************************************/
873 /*                                                                           */
874 /*  CopyFile                                                                 */
875 /*                                                                           */
876 /*    return codes:                                                          */
877 /*                                                                           */
878 /*      0    successful                                                      */
879 /*      1    could not open file                                             */
880 /*                                                                           */
881 /*****************************************************************************/
882 ushort CopyFile(char *pszSource, char *pszDest)
883
884 {
885   int            fdSource;
886   int            fdDest;
887   int            len;
888   int            rlen;
889   ushort         usRc = 0;
890   char           *buffer;
891   char           *msgPtr, *fmtPtr, *errPtr;
892
893   fdSource = open(pszSource, O_RDONLY);
894   if (fdSource == -1) {
895      msgPtr = GETMESSAGE(5, 60, "Could not open the following file:");
896      fmtPtr = "%s\n   %s";
897      errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
898                         strlen(pszSource) + 1) * sizeof(char));
899      sprintf(errPtr, fmtPtr, msgPtr, pszSource);
900      display_error_message(CreateActionAppShell, errPtr);
901      XtFree(errPtr);
902      usRc = 1;
903   } else {
904      /************************************************************/
905      /* Find out how big a buffer is needed                      */
906      /************************************************************/
907      len = lseek(fdSource, 0, SEEK_END);
908      (void) lseek(fdSource, 0, SEEK_SET);
909      buffer = XtMalloc((Cardinal) (len + 1));
910      if ((rlen = read(fdSource, buffer, len)) != len) {
911         /*********************************************************/
912         /* Didn't read whole file!                               */
913         /*********************************************************/
914      } else {
915         fdDest = creat(pszDest, 0644);
916         /*fdDest = open(pszDest, O_WRONLY);*/
917         if (fdDest == -1) {
918            msgPtr = GETMESSAGE(5, 55, "Could not create the following file:");
919            fmtPtr = "%s\n   %s";
920            errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
921                               strlen(pszDest) + 1) * sizeof(char));
922            sprintf(errPtr, fmtPtr, msgPtr, pszDest);
923            display_error_message(CreateActionAppShell, errPtr);
924            XtFree(errPtr);
925            usRc = 1;
926         } else {
927            if ((rlen = write(fdDest, buffer, len)) != len) {
928               /***************************************************/
929               /* Didn't write the whole file!                    */
930               /***************************************************/
931            }
932
933            close(fdDest);
934         }
935      }
936
937      XtFree(buffer);
938      close(fdSource);
939   }
940   return(usRc);
941 }
942
943 /*****************************************************************************/
944 /*                                                                           */
945 /*  CreateDirName                                                            */
946 /*                                                                           */
947 /*    return codes:                                                          */
948 /*                                                                           */
949 /*      NULL        error has occurred                                       */
950 /*      not NULL    name of directory to store icons                         */
951 /*                                                                           */
952 /*****************************************************************************/
953 char * CreateDirName(void)
954 {
955   char  *pszNewName = (char *)NULL;
956   char  *pszDirName = (char *)NULL;
957   char  *pszEnvVar;
958   char  *msgPtr, *errPtr;
959
960   pszEnvVar = getenv("HOME");
961   if ( pszEnvVar && strlen(pszEnvVar) ) {
962      pszDirName = XtMalloc(strlen(pszEnvVar) + strlen("/.dt/icons/") + 1);
963      sprintf(pszDirName, "%s/.dt/icons/", pszEnvVar);
964   } else {
965      msgPtr = GETMESSAGE(5, 170, "The HOME environment variable is not set.\n\
966 The HOME environment variable must be set in order\n\
967 for this action to be saved.");
968      errPtr = XtNewString(msgPtr);
969      display_error_message(CreateActionAppShell, errPtr);
970      XtFree(errPtr);
971   }
972   return(pszDirName);
973 }
974
975 /*****************************************************************************/
976 /*                                                                           */
977 /*  CopyFilesFromWid                                                         */
978 /*                                                                           */
979 /*    return codes:                                                          */
980 /*                                                                           */
981 /*      0    successful                                                      */
982 /*      1    could not open file                                             */
983 /*                                                                           */
984 /*****************************************************************************/
985 ushort CopyFilesFromWid(ActionData *pAD, Widget wid)
986
987 {
988   IconData      *pIconData;
989   char          *pszDirName = (char *)NULL;
990   Boolean       bHaveError = FALSE;
991   char          *pszIconName = (char *)NULL;
992   char          *pszNewName = (char *)NULL;
993   char          *pszMaskName = (char *)NULL;
994
995   pszDirName = CreateDirName();
996   if (!pszDirName) bHaveError = True;
997
998   pIconData = GetIconDataFromWid(wid);
999   pszNewName = ReplaceSpaces(pAD->pszName);
1000
1001   if ((!bHaveError) && (pIconData)) {
1002      pszIconName = CreateIconName(pszDirName, pszNewName, pIconData->size, PIXMAP_EXT, FALSE);
1003      if ((!pszIconName) || (CopyFile(pIconData->pmFileName, pszIconName))) {
1004         bHaveError = True;
1005      }
1006      if (pszIconName) XtFree(pszIconName);
1007   }
1008
1009   if ((!bHaveError) && (pIconData)) {
1010      pszIconName = CreateIconName(pszDirName, pszNewName, pIconData->size, BITMAP_EXT, FALSE);
1011      if ((!pszIconName) || (CopyFile(pIconData->bmFileName, pszIconName))) {
1012         bHaveError = True;
1013      }
1014      if (pszIconName) XtFree(pszIconName);
1015
1016      /**********************************************/
1017      /* Now see if it has a mask file.             */
1018      /**********************************************/
1019      if (!bHaveError) {
1020         pszMaskName = CreateMaskName(pIconData->bmFileName);
1021         if ((pszMaskName) && (check_file_exists(pszMaskName))) {
1022 #ifdef DEBUG
1023            printf("Mask file exists = %s\n", pszMaskName); /* debug */
1024 #endif
1025            pszIconName = CreateIconName(pszDirName, pszNewName, pIconData->size, BITMAP_EXT, TRUE);
1026            if ((!pszIconName) || (CopyFile(pszMaskName, pszIconName))) {
1027               bHaveError = True;
1028            }
1029            if (pszIconName) XtFree(pszIconName);
1030            XtFree(pszMaskName);
1031         }
1032      }
1033   }
1034
1035   if (pszNewName) XtFree(pszNewName);
1036   if (pszDirName) XtFree(pszDirName);
1037
1038   if (bHaveError) {
1039      return(1);
1040   } else {
1041      return(0);
1042   }
1043 }
1044 /******************************************************************************/
1045 /* ActionHasIcon - check if any of the main action's icons have dirty bit set */
1046 /*                                                                            */
1047 /* INPUT:   none                                                              */
1048 /*                                                                            */
1049 /* OUTPUT:  TRUE          - action has icon                                   */
1050 /*          FALSE         - no icon for this action                           */
1051 /*                                                                            */
1052 /******************************************************************************/
1053 Boolean ActionHasIcon (void)
1054 {
1055   if ( CheckDirtyIcon(CA_LRG_IconGadget) ||
1056        CheckDirtyIcon(CA_MED_IconGadget) ||
1057        CheckDirtyIcon(CA_TINY_IconGadget) ) {
1058      return(True);
1059   } else {
1060      return(False);
1061   }
1062
1063 }
1064
1065 /******************************************************************************/
1066 /* FiletypeHasIcon - check if the filetype has modified icons.                */
1067 /*                                                                            */
1068 /* INPUT:   Filetype data structure pointer                                   */
1069 /*                                                                            */
1070 /* OUTPUT:  TRUE          - action has icon                                   */
1071 /*          FALSE         - no icon for this action                           */
1072 /*                                                                            */
1073 /******************************************************************************/
1074 Boolean FiletypeHasIcon (FiletypeData *pFtD)
1075 {
1076   if ( (pFtD->pszMedPmIcon) ||
1077        (pFtD->pszMedBmIcon) ||
1078        (pFtD->pszTinyPmIcon) ||
1079        (pFtD->pszTinyBmIcon) ) {
1080      return(True);
1081   } else {
1082      return(False);
1083   }
1084
1085 }
1086
1087 /*****************************************************************************/
1088 /*                                                                           */
1089 /*  CopyIconFiles                                                            */
1090 /*                                                                           */
1091 /*    return codes:                                                          */
1092 /*                                                                           */
1093 /*      0    successful                                                      */
1094 /*      1    could not open file                                             */
1095 /*                                                                           */
1096 /*****************************************************************************/
1097 ushort CopyIconFiles(ActionData *pAD)
1098
1099 {
1100   Boolean       bHaveError = FALSE;
1101   FiletypeData  *pFtD;
1102   int           i;
1103   char          *pszDirName = (char *)NULL;
1104   char          *pszNewIconName;
1105   char          *pszNewIconMask;
1106   char          *pszOldIconName;
1107   char          *ptr;
1108   char          buffer[MAXFILENAME];
1109
1110 #define  CIF_ERROR    1
1111 #define  CIF_SUCCESS  0
1112
1113   if (ActionHasIcon()) {
1114      if ( !bHaveError && (CopyFilesFromWid(pAD, CA_LRG_IconGadget) != 0) ) {
1115         bHaveError = TRUE;
1116      }
1117      if ( !bHaveError && (CopyFilesFromWid(pAD, CA_MED_IconGadget) != 0) ) {
1118         bHaveError = TRUE;
1119      }
1120      if ( !bHaveError && (CopyFilesFromWid(pAD, CA_TINY_IconGadget) != 0) ) {
1121         bHaveError = TRUE;
1122      }
1123   }
1124
1125   if (!bHaveError && (pAD->papFiletypes)) {
1126      pszDirName = CreateDirName();
1127      for (i=0; i < pAD->cFiletypes; i++) {
1128        pFtD = pAD->papFiletypes[i];
1129        if (FiletypeHasIcon(pFtD)) {
1130           FIND_ICONGADGET_ICON(pFtD->pszIcon, pszOldIconName, DtMEDIUM);
1131           if (pszOldIconName) {
1132              ptr = strstr(pszOldIconName, MEDIUM_EXT);
1133              if (ptr) *ptr = '\0';
1134           }
1135
1136           /*****************************************************************/
1137           /* Medium Pixmap                                                 */
1138           /*****************************************************************/
1139           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Medium_Icon, PIXMAP_EXT, FALSE);
1140           if (pszNewIconName) {
1141              if (pFtD->pszMedPmIcon) {
1142                 CopyFile(pFtD->pszMedPmIcon, pszNewIconName);
1143              } else {
1144                 ptr = CreateIconName((char *)NULL, pszOldIconName, Medium_Icon, PIXMAP_EXT, FALSE);
1145                 if (ptr) {
1146                    CopyFile(ptr, pszNewIconName);
1147                    XtFree(ptr);
1148                 }
1149              }
1150              if (pszNewIconName) XtFree(pszNewIconName);
1151           }
1152
1153           /*****************************************************************/
1154           /* Medium Bitmap                                                 */
1155           /*****************************************************************/
1156           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Medium_Icon, BITMAP_EXT, FALSE);
1157           pszNewIconMask = CreateIconName(pszDirName, pFtD->pszName, Medium_Icon, BITMAP_EXT, TRUE);
1158           if (pszNewIconName) {
1159              if (pFtD->pszMedBmIcon) {
1160                 CopyFile(pFtD->pszMedBmIcon, pszNewIconName);
1161                 /****************************/
1162                 /* Now do the mask file.    */
1163                 /****************************/
1164                 sprintf(buffer, "%s_m", pFtD->pszMedBmIcon);
1165                 if (pszNewIconMask && check_file_exists(buffer)) {
1166                    CopyFile(buffer, pszNewIconMask);
1167                 }
1168              } else {
1169                 ptr = CreateIconName((char *)NULL, pszOldIconName, Medium_Icon, BITMAP_EXT, FALSE);
1170                 if (ptr) {
1171                    CopyFile(ptr, pszNewIconName);
1172                    XtFree(ptr);
1173                 }
1174                 /****************************/
1175                 /* Now do the mask file.    */
1176                 /****************************/
1177                 ptr = CreateIconName((char *)NULL, pszOldIconName, Medium_Icon, BITMAP_EXT, TRUE);
1178                 if (ptr && check_file_exists(ptr) && pszNewIconMask) {
1179                    CopyFile(ptr, pszNewIconMask);
1180                    XtFree(ptr);
1181                 }
1182              }
1183              if (pszNewIconName) XtFree(pszNewIconName);
1184              if (pszNewIconMask) XtFree(pszNewIconMask);
1185           }
1186
1187           /*****************************************************************/
1188           /* Tiny Pixmap                                                   */
1189           /*****************************************************************/
1190           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Tiny_Icon, PIXMAP_EXT, FALSE);
1191           if (pszNewIconName) {
1192              if (pFtD->pszTinyPmIcon) {
1193                 CopyFile(pFtD->pszTinyPmIcon, pszNewIconName);
1194              } else {
1195                 ptr = CreateIconName((char *)NULL, pszOldIconName, Tiny_Icon, PIXMAP_EXT, FALSE);
1196                 if (ptr) {
1197                    CopyFile(ptr, pszNewIconName);
1198                    XtFree(ptr);
1199                 }
1200              }
1201              if (pszNewIconName) XtFree(pszNewIconName);
1202           }
1203
1204           /*****************************************************************/
1205           /* Tiny Bitmap                                                   */
1206           /*****************************************************************/
1207           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Tiny_Icon, BITMAP_EXT, FALSE);
1208           pszNewIconMask = CreateIconName(pszDirName, pFtD->pszName, Tiny_Icon, BITMAP_EXT, TRUE);
1209           if (pszNewIconName) {
1210              if (pFtD->pszTinyBmIcon) {
1211                 CopyFile(pFtD->pszTinyBmIcon, pszNewIconName);
1212                 /****************************/
1213                 /* Now do the mask file.    */
1214                 /****************************/
1215                 sprintf(buffer, "%s_m", pFtD->pszTinyBmIcon);
1216                 if (pszNewIconMask && check_file_exists(buffer)) {
1217                    CopyFile(buffer, pszNewIconMask);
1218                 }
1219              } else {
1220                 ptr = CreateIconName((char *)NULL, pszOldIconName, Tiny_Icon, BITMAP_EXT, FALSE);
1221                 if (ptr) {
1222                    CopyFile(ptr, pszNewIconName);
1223                    XtFree(ptr);
1224                 }
1225                 /****************************/
1226                 /* Now do the mask file.    */
1227                 /****************************/
1228                 ptr = CreateIconName((char *)NULL, pszOldIconName, Tiny_Icon, BITMAP_EXT, TRUE);
1229                 if (ptr && check_file_exists(ptr) && pszNewIconMask) {
1230                    CopyFile(ptr, pszNewIconMask);
1231                    XtFree(ptr);
1232                 }
1233              }
1234              if (pszNewIconName) XtFree(pszNewIconName);
1235              if (pszNewIconMask) XtFree(pszNewIconMask);
1236           }
1237        }
1238      }
1239   }
1240
1241   return(CIF_SUCCESS);
1242 }