dtfile/SharedProcs.c: coverity CID 89068; use after free
[oweals/cde.git] / cde / programs / dtfile / SharedProcs.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 /* $XConsortium: SharedProcs.c /main/7 1996/10/03 14:01:42 drk $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  *
27  *   FILE:           SharedProcs.c
28  *
29  *   COMPONENT_NAME: Desktop File Manager (dtfile)
30  *
31  *   Description:    Contains the set of functions which are of general
32  *                   use to all DT clients.
33  *
34  *   FUNCTIONS: BuildBufferFileName
35  *              RenameCollisions
36  *              RenameEntry
37  *              RetrieveAndUseNameTemplateInfo
38  *              SetBufferFileNames
39  *              _DtAddOneSubdialog
40  *              _DtBuildActionArgsWithDroppedBuffers
41  *              _DtBuildActionArgsWithDroppedFiles
42  *              _DtBuildActionArgsWithSelectedFiles
43  *              _DtBuildActionArgsWithDTSelectedFiles
44  *              _DtBuildFMTitle
45  *              _DtBuildPath
46  *              _DtChangeTildeToHome
47  *              _DtCheckAndFreePixmapData
48  *              _DtCheckForDataTypeProperty
49  *              _DtCompileActionVector
50  *              _DtCopyDroppedFileInfo
51  *              _DtDestroySubdialog
52  *              _DtDestroySubdialogArray
53  *              _DtDuplicateDialogNameList
54  *              _DtFollowLink
55  *              _DtFreeActionArgs
56  *              _DtFreeDroppedBufferInfo
57  *              _DtFreeDroppedFileInfo
58  *              _DtGenericDestroy
59  *              _DtGenericMapWindow
60  *              _DtGenericUpdateWindowPosition
61  *              _DtGetSelectedFilePath
62  *              _DtHideOneSubdialog
63  *              _DtIsBufferExecutable
64  *              _DtLoadSubdialogArray
65  *              _DtMappedCB
66  *              _DtPName
67  *              _DtPathFromInput
68  *              _DtResolveAppManPath
69  *              _DtRetrieveDefaultAction
70  *              _DtRetrievePixmapData
71  *              _DtSaveSubdialogArray
72  *              _DtSetDroppedBufferInfo
73  *              _DtSetDroppedFileInfo
74  *              _DtSpacesInFileNames
75  *              _DtStringsAreEquivalent
76  *
77  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
78  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
79  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
80  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
81  *
82  ****************************************************************************
83  ************************************<+>*************************************/
84
85 #include <sys/types.h>
86 #include <sys/stat.h>
87 #include <errno.h>
88 #include <fcntl.h>
89 #include <limits.h>
90 #include <stdio.h>
91 #include <time.h>
92 #include <pwd.h>
93 #include <ctype.h>
94
95 #include <Xm/Xm.h>
96 #include <Xm/XmP.h>
97 #include <Xm/VendorSEP.h>
98 #include <Xm/MessageB.h>
99 #include <Xm/RowColumn.h>
100 #include <Xm/MwmUtil.h>
101 #include <Xm/Protocols.h>
102 #include <X11/ShellP.h>
103 #include <X11/Shell.h>
104 #include <X11/Xatom.h>
105 /* Copied from Xm/BaseClassI.h */
106 extern XmWidgetExtData _XmGetWidgetExtData( 
107                         Widget widget,
108 #if NeedWidePrototypes
109                         unsigned int extType) ;
110 #else
111                         unsigned char extType) ;
112 #endif /* NeedWidePrototypes */
113
114 #include <Dt/DtP.h>
115 #include <Dt/Connect.h>
116 #include <Dt/DtNlUtils.h>
117 #include <Dt/Dts.h>
118 #include <Dt/Icon.h>
119 #include <Dt/IconP.h>
120 #include <Dt/IconFile.h>
121 #include <Dt/Action.h>
122 #include <Dt/Dnd.h>
123 #include <Dt/Utility.h>
124 #include <Dt/SharedProcs.h>
125
126 #include <Tt/tttk.h>
127
128 #include "Encaps.h"
129 #include "FileMgr.h"
130 #include "Desktop.h"
131 #include "Common.h"
132 #include "Main.h"
133 #include "SharedProcs.h"
134
135 extern char *pathcollapse();
136
137
138 /* Defines */
139 #define RW_ALL S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
140
141
142 /* Global controlling whether auto-positioning is enabled */
143 Boolean disableDialogAutoPlacement = False;
144
145
146 /********    Static Function Declarations    ********/
147
148 static void SetBufferFileNames (
149                         char **file_set,
150                         DtDndBuffer *buffers,
151                         int num_of_buffers) ;
152 static char * BuildBufferFileName (
153                         char *file_name,
154                         int postfix_index,
155                         void *buffer,
156                         int buffer_size) ;
157 static char * RetrieveAndUseNameTemplateInfo(
158                         void *buffer,
159                         int buffer_size,
160                         char *template_input) ;
161 static void RenameEntry(
162                         char **name,
163                         unsigned int addIndex) ;
164 static void RenameCollisions(
165                         char **list,
166                         int count) ;
167
168 /********    End Static Function Declarations    ********/
169
170
171 /************************************************************************
172  *
173  *  _DtPName
174  *      Returns the parent directory of its argument.
175  *      Does this by looking for the last "/" in the name, and
176  *      NULL'ing it out.
177  *
178  ************************************************************************/
179
180 char *
181 _DtPName(
182         register char *name )
183
184 {
185    register char * q;
186    static char pnam[MAXPATHLEN];
187    static char dot[] = ".";
188
189    strcpy(pnam, name);
190    q = strrchr(pnam, '/');
191
192    if (q == NULL)
193       q = pnam;
194    else if ((q == pnam) &&
195 #ifdef NLS16
196             (mblen(q, MB_CUR_MAX) == 1) &&
197 #endif
198             (*q == '/'))
199    {
200       q++;
201    }
202
203    *q = '\0';
204
205    return(pnam[0] ? pnam : dot);
206 }
207
208
209 /*
210  * Given a filename, follow it to the end of its link.  Returns NULL if
211  * a recursive symbolic link is found.
212  *
213  * Note, the path returned is a static buffer, and should not be freed by
214  * the calling function.
215  */
216
217 char *
218 _DtFollowLink (
219    char * path)
220 {
221    char link_path[MAXPATHLEN];
222    static char file[MAXPATHLEN];
223    int link_len;
224    char * end;
225    int history_count;
226    int history_size;
227    char ** history;
228    int i;
229
230    /* Used to check for symbolic link loops */
231    history_count = 0;
232    history_size = 100;
233    history = (char **)XtMalloc(sizeof(char *) * history_size);
234
235    strcpy(file, path);
236
237    while ((link_len = readlink(file, link_path, MAXPATHLEN)) > 0)
238    {
239       link_path[link_len] = '\0';
240
241       /* Force the link to be an absolute path, if necessary */
242       if (link_path[0] != '/')
243       {
244          /* Relative paths are relative to the current directory */
245          end = strrchr(file, '/') + 1;
246          *end = '\0';
247          strcat(file, link_path);
248       }
249       else
250          strcpy(file, link_path);
251
252       /* Check for a recursive loop; abort if found */
253       for (i = 0; i < history_count; i++)
254       {
255          if (strcmp(file, history[i]) == 0)
256          {
257             for (i = 0; i < history_count; i++)
258                XtFree(history[i]);
259             XtFree((char *)history);
260             history = NULL;
261             return(NULL);
262          }
263       }
264
265       /* Add to the history list */
266       if (history_count >= history_size)
267       {
268          history_size += 100;
269          history = (char **)XtRealloc((char *)history,
270                                       sizeof(char *) * history_size);
271       }
272       history[history_count++] = XtNewString(file);
273    }
274
275    /* Free up the history list */
276    for (i = 0; i < history_count; i++)
277       XtFree(history[i]);
278    XtFree((char *)history);
279    history = NULL;
280
281    return(file);
282 }
283
284
285 /************************************************************************
286  *
287  *  _DtStringsAreEquivalent
288  *      Compare two strings and return true if equal.
289  *      The comparison is on lower cased strings.  It is the callers
290  *      responsibility to ensure that test_str is already lower cased.
291  *
292  ************************************************************************/
293
294 Boolean
295 _DtStringsAreEquivalent(
296         register char *in_str,
297         register char *test_str )
298 {
299 #ifdef NLS16
300    wchar_t c1;
301    wchar_t c2;
302    int c1size, c2size;
303 #endif
304    register int i;
305    register int j;
306
307 #ifdef NLS16
308    if (is_multibyte)
309    {
310       for (;;)
311       {
312          /* Convert each character from multibyte to wide format */
313          c1size = mbtowc(&c1, in_str, MB_CUR_MAX);
314          c2size = mbtowc(&c2, test_str, MB_CUR_MAX);
315
316          /* No match, if the two characters have different byte counts */
317          if (c1size != c2size)
318             return(False);
319
320          /* Do case conversion only for single byte characters */
321          if (c1size == 1)
322          {
323             if (isupper((int) c1))
324                c1 = tolower((int) c1);
325          }
326
327          /* See if the two wide characters match */
328          if (c1 != c2)
329             return(False);
330
331          /* Are we at the end of the string? */
332          if (c1 == '\0')
333             return(True);
334
335          /* Keep comparing */
336          in_str += c1size;
337          test_str += c2size;
338       }
339    }
340    else
341 #endif
342    {
343       for (;;)
344       {
345          i = *in_str;
346          j = *test_str;
347
348          if (isupper (i)) i = tolower (i);
349          if (i != j) return (False);
350          if (i == 0) return (True);
351
352          in_str++;
353          test_str++;
354       }
355    }
356 }
357
358
359
360 void
361 _DtDuplicateDialogNameList (
362         char ** nameList,
363         char ** newNameList,
364         int newNameListSize,
365         int * nameCount )
366
367 {
368    int i;
369
370    /*  Get a copy of the name list to be used to build new name lists.  */
371    *nameCount = 0;
372    while (nameList[*nameCount] != NULL)
373    {
374       newNameList[*nameCount] = nameList[*nameCount];
375       (*nameCount)++;
376    }
377
378    /* NULL out any remaining array entries */
379    for (i = (*nameCount); i < newNameListSize; i++)
380       newNameList[i] = NULL;
381 }
382
383
384 void
385 _DtLoadSubdialogArray (
386         char ** nameList,
387         int    nameCount,
388         DialogData *** dialogArray,
389         int    dialogCount,
390         int    dialogId,
391         XrmDatabase dataBase,
392         int    firstId )
393
394 {
395    int i;
396    char number[10];
397
398    /* Load sub-dialogs */
399    nameList[nameCount] = number;
400    nameList[nameCount + 1] = NULL;
401
402    /* Get text annotation dialogs */
403    *dialogArray = (DialogData **) XtMalloc(sizeof(DialogData *) * dialogCount);
404
405    for (i = 0; i < dialogCount; i++)
406    {
407       sprintf(number, "%d", firstId);
408       (*dialogArray)[i] = _DtGetResourceDialogData(dialogId, dataBase, nameList);
409       firstId++;
410    }
411 }
412
413
414
415 void
416 _DtSaveSubdialogArray (
417         char ** nameList,
418         int    nameCount,
419         DialogData ** dialogArray,
420         int    dialogCount,
421         int    fd,
422         int    firstId )
423
424 {
425    int i;
426    char number[10];
427
428    nameList[nameCount] = number;
429    nameList[nameCount + 1] = NULL;
430
431    for (i = 0; i < dialogCount; i++)
432    {
433       sprintf(number, "%d", firstId);
434       _DtWriteDialogData(dialogArray[i], fd, nameList);
435       firstId++;
436    }
437 }
438
439
440 void
441 _DtDestroySubdialogArray (
442         DialogData ** dialogArray,
443         int    dialogCount )
444
445 {
446    int i;
447
448    for (i = 0; i < dialogCount; i++)
449    {
450       if (_DtIsDialogShowing(dialogArray[i]))
451          _DtHideDialog(dialogArray[i], False);
452
453       _DtFreeDialogData(dialogArray[i]);
454    }
455    XtFree((char *)dialogArray);
456 }
457
458
459 void
460 _DtDestroySubdialog (
461         DialogData * dialogData )
462
463 {
464    if (dialogData)
465    {
466       if (_DtIsDialogShowing(dialogData))
467          _DtHideDialog(dialogData, False);
468       _DtFreeDialogData(dialogData);
469    }
470 }
471
472
473 void
474 _DtHideOneSubdialog (
475         DialogData * dialogData,
476         DialogData *** dialogArray,
477         int         * dialogCountPtr )
478
479 {
480    int i, j;
481
482    for (i = 0; i < *dialogCountPtr; i++)
483    {
484       if (dialogData == (*dialogArray)[i])
485       {
486          for (j = i; j < (*dialogCountPtr) - 1; j++)
487             (*dialogArray)[j] = (*dialogArray)[j + 1];
488          break;
489       }
490    }
491
492    /*  Free or decrease the size of the dialog data list  */
493    (*dialogCountPtr)--;
494    if (*dialogCountPtr == 0)
495    {
496       XtFree((char *)*dialogArray);
497       *dialogArray = NULL;
498    }
499    else
500    {
501       *dialogArray = (DialogData **)
502          XtRealloc((char *)*dialogArray,
503                    sizeof(DialogData *) * (*dialogCountPtr));
504    }
505 }
506
507
508 void
509 _DtAddOneSubdialog (
510         DialogData * dialogData,
511         DialogData *** dialogArray,
512         int         * dialogCountPtr )
513
514 {
515    int count;
516
517    count = *dialogCountPtr;
518    (*dialogCountPtr)++;
519    (*dialogArray) = (DialogData **) XtRealloc((char *)(*dialogArray),
520                                   sizeof(DialogData *) * (*dialogCountPtr));
521    (*dialogArray)[count] = dialogData;
522 }
523
524
525 /*
526  * This function acts as a frontend to the encapsulator's map callback
527  * function.  If we are in the middle of a restore session, then we don't
528  * want the map callback to alter the placement of the dialog, so we will
529  * not call the encapsulator's function.
530  */
531
532 void
533 _DtMappedCB(
534          Widget w,
535          XtPointer client_data,
536          XtPointer call_data )
537 {
538    if (!disableDialogAutoPlacement)
539       _DtmapCB(w,client_data,call_data);
540
541    XtRemoveCallback(w, XmNpopupCallback, (XtCallbackProc)_DtMappedCB, client_data);
542 }
543
544
545 /*
546  * This is the generic function for registering the map callback.
547  */
548
549 void
550 _DtGenericMapWindow (
551      Widget parent,
552      XtPointer recordPtr)
553 {
554    GenericRecord * genericRecord = (GenericRecord *) recordPtr;
555
556    XtAddCallback (genericRecord->shell, XmNpopupCallback,
557                   (XtCallbackProc)_DtMappedCB, (XtPointer) parent);
558 }
559
560
561 /*
562  * This is the generic function for destroying a dialog widget hierarchy.
563  */
564
565 void
566 _DtGenericDestroy(
567         XtPointer recordPtr )
568
569 {
570    GenericRecord * genericRecord = (GenericRecord *) recordPtr;
571
572    XtDestroyWidget(genericRecord->shell);
573    XtFree((char *) genericRecord);
574 }
575
576
577 /*
578  * This is the generic function for updating the shell's x and y, to
579  * take the window manager border into consideration.
580  */
581
582 void
583 _DtGenericUpdateWindowPosition(
584         DialogData * dataPtr )
585
586 {
587    DialogInstanceData * genericData = (DialogInstanceData *) dataPtr->data;
588    GenericRecord * genericRecord;
589
590    /* Do nothing, if the dialog is not displayed */
591    if (genericData->displayed == True)
592    {
593       XmVendorShellExtObject vendorExt;
594       XmWidgetExtData        extData;
595       Window                 junkWindow;
596       int                    t_x, t_y;
597       Arg                    args[5];
598
599       genericRecord = (GenericRecord *)_DtGetDialogInstance(dataPtr);
600
601       XtSetArg(args[0], XmNwidth, &genericData->width);
602       XtSetArg(args[1], XmNheight, &genericData->height);
603       XtGetValues(genericRecord->shell, args, 2);
604
605       XTranslateCoordinates(XtDisplay(genericRecord->shell),
606                        XtWindow(genericRecord->shell),
607                        RootWindowOfScreen(XtScreen(genericRecord->shell)),
608                        0, 0, &t_x, &t_y,
609                        &junkWindow);
610       genericData->x = (Position) t_x;
611       genericData->y = (Position) t_y;
612
613       /* Modify x & y to take into account window mgr frames */
614       extData=_XmGetWidgetExtData(genericRecord->shell, XmSHELL_EXTENSION);
615       vendorExt = (XmVendorShellExtObject)extData->widget;
616       genericData->x -= vendorExt->vendor.xOffset;
617       genericData->y -= vendorExt->vendor.yOffset;
618    }
619 }
620
621
622 /*
623  * This is a function for building a path from directory and filename
624  * parameters.
625  */
626
627 void
628 _DtBuildPath(
629         char         *path,
630         char         *directory,
631         char         *fileName)
632
633 {
634   if (directory)
635   {
636     if (fileName)
637       sprintf(path, "%s/%s", directory, fileName);
638     else
639       sprintf(path, "%s", directory);
640   }
641   else
642   {
643     if (fileName)
644       sprintf(path, "%s", fileName);
645     else
646       sprintf(path, "%s", "");
647   }
648 }
649
650
651 /*
652  * This is a function for retrieving the pixmap data for a data type.
653  */
654
655 PixmapData *
656 _DtRetrievePixmapData(
657         char         *dataType,
658         char         *fileName,
659         char         *directory,
660         Widget        shell,
661         int           size)
662
663 {
664   PixmapData *pixmapData;
665   char path[MAXPATHLEN];
666   char *iconName;
667
668   pixmapData = (PixmapData *) XtMalloc(sizeof(PixmapData));
669   if (!pixmapData)
670     return NULL;
671
672   path[0] = 0x0;
673   _DtBuildPath(path, directory, fileName);
674
675   pixmapData->size = size;
676
677   /* retrieve host name */
678   pixmapData->hostPrefix = DtDtsDataTypeToAttributeValue(dataType,
679                                                          DtDTS_DA_DATA_HOST,
680                                                          NULL);
681
682   /*
683      retrieve instance icon name if one exists; otherwise, retrieve class
684      icon name
685   */
686   if (path[0] != 0x0)
687   {
688     pixmapData->instanceIconName = DtDtsDataTypeToAttributeValue(dataType,
689                                             DtDTS_DA_INSTANCE_ICON,
690                                             path);
691   }
692   else
693     pixmapData->instanceIconName = NULL;
694
695   if (pixmapData->instanceIconName == NULL)
696   {
697     pixmapData->iconName = DtDtsDataTypeToAttributeValue( dataType, 
698                                                           DtDTS_DA_ICON, NULL);
699     if( pixmapData->iconName == NULL )
700     {
701       if( strcmp( dataType, LT_DIRECTORY ) == 0 )
702         pixmapData->iconName = XtNewString( "DtdirB" );
703       else
704         pixmapData->iconName = XtNewString( "Dtdeflt" );
705     }
706   }
707   else
708   {
709     pixmapData->iconName = NULL;
710   }
711
712   /* retrieve icon file name */
713   if (pixmapData->size == LARGE)
714      pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
715                                                pixmapData->instanceIconName,
716                                                pixmapData->iconName,
717                                                pixmapData->hostPrefix,
718                                                DtMEDIUM);
719   else
720      pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
721                                                pixmapData->instanceIconName,
722                                                pixmapData->iconName,
723                                                pixmapData->hostPrefix,
724                                                DtTINY);
725
726   /* return pixmap data */
727   return(pixmapData);
728 }
729
730
731 /*
732  * This is a function for checking the size, etc of an icon pixmap and
733  * freeing the pixmap data for an icon.
734  */
735
736 void
737 _DtCheckAndFreePixmapData(
738         char         *dataType,
739         Widget        shell,
740         DtIconGadget  iconGadget,
741         PixmapData   *pixmapData)
742
743 {
744   Arg   args[1];
745
746   if (!pixmapData)
747     return;
748
749   /*
750      if there was an instance icon name; verify that the pixmap parameters
751      do not exceed system limits; if system limits are exceeded, retrieve
752      class icon name and set icon gadget image resource to this value
753   */
754   if (pixmapData->instanceIconName)
755   {
756
757     if(! pixmapData->iconFileName && iconGadget->icon.pixmap == 0)
758     { /* Try to get pixmap name
759       */
760       char * tmp, * ptr;
761
762       tmp = XtNewString( pixmapData->instanceIconName );
763       if( ptr = strrchr( tmp,'/' ) )
764         *(ptr) = 0;
765       XmeFlushIconFileCache( tmp );
766
767       if (pixmapData->iconFileName != NULL)
768          XtFree(pixmapData->iconFileName);
769       if (pixmapData->size == LARGE)
770         pixmapData->iconFileName = _DtGetIconFileName( XtScreen(shell),
771                                               pixmapData->instanceIconName,
772                                               NULL,
773                                               pixmapData->hostPrefix,
774                                               DtMEDIUM );
775       else
776         pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
777                                               pixmapData->instanceIconName,
778                                               NULL,
779                                               pixmapData->hostPrefix,
780                                               DtTINY);
781
782
783
784       XtSetArg(args[0], XmNimageName, pixmapData->iconFileName);
785       XtSetValues((Widget) iconGadget, args, 1);
786
787       XtFree( tmp );
788     }
789
790
791
792     DtDtsFreeAttributeValue(pixmapData->instanceIconName);
793     pixmapData->instanceIconName = NULL;
794
795     if (iconGadget->icon.pixmap == 0                     ||
796         iconGadget->icon.pixmap_width == 0               ||
797         iconGadget->icon.pixmap_height == 0              ||
798         (Dimension)iconGadget->icon.pixmap_width > (Dimension)instanceWidth    ||
799         (Dimension)iconGadget->icon.pixmap_height > (Dimension)instanceHeight)
800     {
801
802       pixmapData->iconName = DtDtsDataTypeToAttributeValue(
803                                              dataType, 
804                                              DtDTS_DA_ICON, NULL);
805
806       /* retrieve icon file name */
807       if (pixmapData->iconFileName != NULL)
808       {
809          XtFree(pixmapData->iconFileName);
810          pixmapData->iconFileName = NULL;
811       }
812
813       if (pixmapData->size == LARGE)
814             pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
815                                              pixmapData->instanceIconName,
816                                              pixmapData->iconName,
817                                              pixmapData->hostPrefix,
818                                              DtMEDIUM);
819       else
820             pixmapData->iconFileName = _DtGetIconFileName(XtScreen(shell),
821                                              pixmapData->instanceIconName,
822                                              pixmapData->iconName,
823                                              pixmapData->hostPrefix,
824                                              DtTINY);
825
826
827
828       XtSetArg(args[0], XmNimageName, pixmapData->iconFileName);
829       XtSetValues((Widget) iconGadget, args, 1);
830
831       DtDtsFreeAttributeValue(pixmapData->iconName);
832       pixmapData->iconName = NULL;
833     }
834   }
835   else
836   {
837      DtDtsFreeAttributeValue(pixmapData->iconName);
838      pixmapData->iconName = NULL;
839   }
840
841   DtDtsFreeAttributeValue(pixmapData->hostPrefix);
842   if (pixmapData->iconFileName)
843      XtFree(pixmapData->iconFileName);
844
845   XtFree((char *) pixmapData);
846 }
847
848
849 /*
850  * This is a function for checking for a datatype property.
851  */
852
853 Boolean
854 _DtCheckForDataTypeProperty(
855         char *dataType,
856         char *property)
857
858 {
859    char *properties;
860    char *prop;
861    char *props;
862    Boolean found = False;
863
864
865    properties = DtDtsDataTypeToAttributeValue(dataType,
866                                               DtDTS_DA_PROPERTIES,
867                                               NULL);
868
869    if (properties)
870    {
871      props = properties;
872      prop = props;
873      while (props = DtStrchr(props, ','))
874      {
875        *props = '\0';
876        if (strcmp(prop, property) == 0)
877        {
878          found = True;
879          break;
880        }
881        *props = ','; 
882        props++;
883        prop = props;
884      }
885
886      if (!props)
887      {
888        if (strcmp(prop, property) == 0)
889          found = True;
890      }
891
892      DtDtsFreeAttributeValue(properties);
893    }
894
895    return found;
896 }
897
898
899 /*
900  * This is a function for compiling a vectorized action list for a data type.
901  */
902
903 char **
904 _DtCompileActionVector(
905         char *dataType)
906
907 {
908    char *actions;
909    char **vector = NULL;
910
911    actions = DtDtsDataTypeToAttributeValue(dataType,
912                                            DtDTS_DA_ACTION_LIST,
913                                            NULL);
914    if (actions)
915      vector = (char **) _DtVectorizeInPlace(actions, ',');
916
917    return(vector);
918 }
919
920
921 /*
922  * This is a generic function for retrieving the default action for a data
923  * type.
924  */
925
926 char *
927 _DtRetrieveDefaultAction(
928         char *dataType)
929
930 {
931    char *actions;
932    char *acts;
933    char *default_action = NULL;
934
935    actions = DtDtsDataTypeToAttributeValue(dataType,
936                                            DtDTS_DA_ACTION_LIST,
937                                            NULL);
938    if (actions)
939    {
940      if (acts = DtStrchr(actions, ','))
941        *acts = '\0';
942      default_action = XtNewString(actions);
943
944      DtDtsFreeAttributeValue(actions);
945    }
946
947    return(default_action);
948 }
949
950
951 /*
952  * This is a function for building a title for a File Manager view.
953  */
954
955 char *
956 _DtBuildFMTitle(
957         FileMgrData *file_mgr_data )
958
959 {
960    char *title, *ptr, *fileLabel, *fileName;
961
962    if (fileLabel = DtDtsFileToAttributeValue(file_mgr_data->current_directory,
963                                              DtDTS_DA_LABEL))
964       ptr = fileLabel;
965    else if (fileName = strrchr(file_mgr_data->current_directory, '/'))
966       ptr = fileName + 1;
967    else
968       ptr = "";
969
970    if (file_mgr_data->title)
971    {
972       if (file_mgr_data->toolbox &&
973           strcmp(file_mgr_data->current_directory,
974                  file_mgr_data->restricted_directory) != 0)
975       {
976          title = (char *)XtMalloc(strlen(file_mgr_data->title) +
977                                   strlen(ptr) +
978                                   4); /* Need for blank dash blank NULL */
979          sprintf(title, "%s - %s", file_mgr_data->title, ptr);
980       }
981       else
982       {
983          title = XtNewString(file_mgr_data->title);
984       }
985    }
986    else
987    {
988       if (strcmp(file_mgr_data->current_directory, "/") == 0 && !fileLabel)
989       {
990          title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) +
991                                   strlen(file_mgr_data->host) +
992                                   strlen(root_title) +
993                                   5); /* Need for blank dash blank colon NULL */
994          sprintf( title, "%s - %s:%s", (GETMESSAGE(12, 7, "File Manager")),
995                                        file_mgr_data->host,
996                                        root_title );
997       }
998       else
999       {
1000          title = (char *)XtMalloc(strlen((GETMESSAGE(12, 7, "File Manager"))) +
1001                                   strlen(ptr) +
1002                                   4); /* Need for blank dash blank NULL */
1003          sprintf( title, "%s - %s", (GETMESSAGE(12, 7, "File Manager")), ptr);
1004       }
1005    }
1006
1007    DtDtsFreeAttributeValue(fileLabel);
1008    return(title);
1009 }
1010
1011
1012 /*
1013  * This is a function for building a path from the directory name
1014  * and file name pieces of a FileViewData structure.
1015  */
1016
1017 char *
1018 _DtGetSelectedFilePath(
1019         FileViewData *selected_file )
1020
1021 {
1022    char *directory;
1023    char *file;
1024    char *path;
1025
1026    directory = ((DirectorySet *)selected_file->directory_set)->name;
1027    file = selected_file->file_data->file_name;
1028
1029    if (strcmp(directory, "/") == 0)
1030    {
1031       path = XtMalloc(strlen(directory) + strlen(file) + 1);
1032       sprintf(path, "%s%s", directory, file);
1033    }
1034    else
1035    {
1036       path = XtMalloc(strlen(directory) + strlen(file) + 2);
1037       sprintf(path, "%s/%s", directory, file);
1038    }
1039
1040    return(path);
1041 }
1042
1043
1044 /*
1045  * This is a generic function for building action parameters from an array of
1046  * file view data structures.
1047  */
1048
1049 void
1050 _DtBuildActionArgsWithSelectedFiles(
1051         FileViewData **selection_list,
1052         int selected_count,
1053         DtActionArg **action_args,
1054         int *arg_count )
1055
1056 {
1057    *arg_count = 0;
1058
1059    *action_args = (DtActionArg *)
1060                      XtCalloc(1, sizeof(DtActionArg) * selected_count);
1061
1062    if (*action_args)
1063    {
1064       int i;
1065
1066       for(i = 0; i < selected_count; i++)
1067       {
1068          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1069          ((*action_args)[(*arg_count)++]).u.file.name =
1070                          _DtGetSelectedFilePath(selection_list[i]);
1071       }
1072    }
1073 }
1074
1075
1076 void
1077 _DtBuildActionArgsWithDTSelectedFiles(
1078         DesktopRec **selection_list,
1079         int selected_count,
1080         DtActionArg **action_args,
1081         int *arg_count )
1082
1083 {
1084    *arg_count = 0;
1085
1086    *action_args = (DtActionArg *)
1087                      XtCalloc(1, sizeof(DtActionArg) * selected_count);
1088
1089    if (*action_args)
1090    {
1091       int i;
1092
1093       for(i = 0; i < selected_count; i++)
1094       {
1095          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1096          ((*action_args)[(*arg_count)++]).u.file.name =
1097                   _DtGetSelectedFilePath(selection_list[i]->file_view_data);
1098       }
1099    }
1100 }
1101
1102
1103 /*
1104  * This is a generic function for building action parameters from drag and drop
1105  * file information.
1106  */
1107
1108 void
1109 _DtBuildActionArgsWithDroppedFiles(
1110         FileViewData *dropped_on_obj,
1111         DtDndDropCallbackStruct *drop_parameters,
1112         DtActionArg **action_args,
1113         int *arg_count )
1114
1115 {
1116    *arg_count = 0;
1117
1118    if (dropped_on_obj)
1119       *action_args = (DtActionArg *) XtCalloc
1120         (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1));
1121    else
1122       *action_args = (DtActionArg *) XtCalloc
1123         (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems);
1124
1125    if (*action_args)
1126    {
1127       int i;
1128
1129       if (dropped_on_obj)
1130       {
1131          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1132          ((*action_args)[(*arg_count)++]).u.file.name =
1133                          _DtGetSelectedFilePath(dropped_on_obj);
1134       }
1135
1136       for(i = 0; i < drop_parameters->dropData->numItems; i++)
1137       {
1138          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1139          ((*action_args)[(*arg_count)++]).u.file.name =
1140                          XtNewString(drop_parameters->dropData->data.files[i]);
1141       }
1142    }
1143 }
1144
1145
1146 /*
1147  * This is a generic function for building action parameters from drag and drop
1148  * buffer information.
1149  */
1150
1151
1152 void
1153 _DtBuildActionArgsWithDroppedBuffers(
1154         FileViewData *dropped_on_obj,
1155         DtDndDropCallbackStruct *drop_parameters,
1156         DtActionArg **action_args,
1157         int *arg_count )
1158
1159 {
1160    *arg_count = 0;
1161
1162    if (dropped_on_obj)
1163       *action_args = (DtActionArg *) XtCalloc
1164         (1, sizeof(DtActionArg) * (drop_parameters->dropData->numItems + 1));
1165    else
1166       *action_args = (DtActionArg *) XtCalloc
1167         (1, sizeof(DtActionArg) * drop_parameters->dropData->numItems);
1168
1169    if (*action_args)
1170    {
1171       int i;
1172       DtActionBuffer buffer_arg = {NULL, 0, NULL, NULL, False};
1173
1174       if (dropped_on_obj)
1175       {
1176          ((*action_args)[(*arg_count)]).argClass = DtACTION_FILE;
1177          ((*action_args)[(*arg_count)++]).u.file.name =
1178                          _DtGetSelectedFilePath(dropped_on_obj);
1179       }
1180
1181       for(i = 0; i < drop_parameters->dropData->numItems; i++)
1182       {
1183          buffer_arg.bp = drop_parameters->dropData->data.buffers[i].bp;
1184          buffer_arg.size = drop_parameters->dropData->data.buffers[i].size;
1185          buffer_arg.name = drop_parameters->dropData->data.buffers[i].name;
1186
1187          ((*action_args)[(*arg_count)]).argClass = DtACTION_BUFFER;
1188          ((*action_args)[(*arg_count)++]).u.buffer = buffer_arg;
1189       }
1190    }
1191 }
1192
1193
1194 /*
1195  * This is a generic function for freeing action parameters.
1196  */
1197
1198 void
1199 _DtFreeActionArgs(
1200         DtActionArg *action_args,
1201         int arg_count )
1202
1203 {
1204    int i;
1205
1206    for (i = 0; i < arg_count; i++)
1207    {
1208       if (action_args[i].argClass == DtACTION_FILE)
1209       {
1210          XtFree(action_args[i].u.file.name);
1211          action_args[i].u.file.name = NULL;
1212       }
1213    }
1214    
1215    XtFree((char *) action_args);
1216 }
1217
1218
1219 /************************************************************************
1220  * The following functions deal with Buffer Manipulation and Naming
1221  ************************************************************************/
1222
1223 /*
1224  * This is a generic function for extracting buffer information from
1225  * drop input.
1226  */
1227
1228 void
1229 _DtSetDroppedBufferInfo(char **file_set,
1230               BufferInfo *buffer_set,
1231               char **host_set,
1232               DtDndDropCallbackStruct *drop_parameters)
1233
1234 {
1235
1236  int num_of_buffers = drop_parameters->dropData->numItems;
1237  int i;
1238  DtDndBuffer *buffers = drop_parameters->dropData->data.buffers;
1239
1240
1241  DPRINTF (("Executing..._DtSetDroppedBufferInfo\n"));
1242
1243  /* Initialize file_set and ensure of unique file names for unamed buffers*/
1244  SetBufferFileNames(file_set, buffers, num_of_buffers);
1245
1246  for (i= 0; i < num_of_buffers; i++)
1247   {
1248
1249      (buffer_set[i]).buf_ptr = buffers[i].bp;
1250      (buffer_set[i]).size    = buffers[i].size;
1251
1252      host_set[i] = XtNewString(home_host_name);
1253
1254      DPRINTF(("_DtSetDroppedBufferInfo:\n host_set[%d]=%s,\
1255               buffer_set[%d].buf_ptr=%p, buffer_set[%d].size=%d\n",
1256               i, host_set[i], i, buffer_set[i].buf_ptr, i, buffer_set[i].size));
1257   }
1258 }
1259
1260
1261 /*
1262  * This is a function for creating file names for a set of buffers.
1263  */
1264
1265 static void
1266 SetBufferFileNames (char **file_set,
1267                     DtDndBuffer *buffers,
1268                     int num_of_buffers)
1269 {
1270  int null_filenames_count = 0;
1271  int i;
1272  int first_nullfile_index = 0;
1273  Boolean NULL_FILENAMES=FALSE;
1274
1275  DPRINTF (("Executing...SetBufferFileNames\n"));
1276
1277  for (i = 0; i < num_of_buffers; i++)
1278  {
1279      if (buffers[i].name == NULL)
1280      {
1281        /* generate buffer name using Untitled as a base name */
1282        file_set[i]=BuildBufferFileName(DEFAULT_BUFFER_FILENAME,
1283                                        -1,
1284                                        buffers[i].bp,
1285                                        buffers[i].size);
1286      }
1287      else
1288      {
1289         /* file name is supplied by the drag initiator */
1290        file_set[i] = XtNewString(buffers[i].name);
1291      }
1292
1293      DPRINTF(("file_set[%d]=%s\n", i, file_set[i]));
1294
1295  } /* end for loop */
1296
1297
1298  /* Rename any collisions to unique names  */
1299  RenameCollisions(file_set, num_of_buffers);
1300
1301  return;
1302 }
1303
1304
1305 /*
1306  * This is a generic function for generating a name for an untitled buffer.
1307  * A default name (Untitled) is used in conjunction with the name template
1308  * information from the types database.
1309  */
1310
1311 static char *
1312 BuildBufferFileName (char   *file_name,
1313                      int     postfix_index,
1314                      void   *buffer,
1315                      int     buffer_size)
1316 {
1317   const char delim = '_';
1318   char *new_file_name;
1319
1320
1321   DPRINTF (("Executing....BuildBufferFileName\n"));
1322
1323   /* Malloc memory and contruct the new file name */
1324   new_file_name = (char *) XtMalloc (strlen(file_name) + 1 +
1325                                      MAX_POSTFIX_LENGTH  + 1);
1326
1327   DPRINTF (("BuildBufferFileName: Old file name is %s\n", file_name));
1328
1329   /* determine whether to append post fix name */
1330   if (postfix_index == -1)
1331      strcpy(new_file_name, file_name);
1332   else
1333      sprintf(new_file_name,"%s%c%d", file_name, delim, postfix_index);
1334
1335   /* Retrieve the name template if it exists and use it in the filename */
1336   new_file_name = RetrieveAndUseNameTemplateInfo(buffer,
1337                                                  buffer_size,
1338                                                  new_file_name);
1339
1340   DPRINTF(("BuildBufferFileName: Returning new_file_name=%s\n", new_file_name));
1341
1342   /* return new file name */
1343   return (new_file_name);
1344 }
1345
1346
1347
1348 /*
1349  * This is a function for building a buffer name using predfined input
1350  * and name template information from the types database.
1351  * WARNING: template_input will be freed. It must point to a char *.
1352  */
1353
1354 static char *
1355 RetrieveAndUseNameTemplateInfo(
1356         void *buffer,
1357         int buffer_size,
1358         char *template_input)
1359
1360 {
1361    char *name_template;
1362    char *buffer_name = NULL;
1363
1364    name_template = DtDtsBufferToAttributeValue(buffer,
1365                                                buffer_size,
1366                                                DtDTS_DA_NAME_TEMPLATE,
1367                                                NULL);
1368    if (name_template)
1369       buffer_name = (char *) XtMalloc(strlen(name_template) +
1370                                       strlen(template_input) +
1371                                        1);
1372    if (buffer_name)
1373    {
1374       sprintf(buffer_name, name_template, template_input);
1375       DtDtsFreeAttributeValue(name_template);
1376       XtFree(template_input);
1377       return(buffer_name);
1378    }
1379    else
1380    {
1381       return(template_input);
1382    }
1383 }
1384
1385
1386 /*
1387  * This is a function for resolving collisions in a list of buffer names.
1388  */
1389
1390 static void
1391 RenameCollisions( char ** list, int count )
1392 {
1393   register int i, j, k, l;
1394   char flg = 0, flg2 = 0;
1395
1396   for( i = 0; i < count; ++i )
1397   {
1398     unsigned int addIndex = 1;
1399
1400     if( *(list[i]) == 0x0 )
1401     {
1402       k = i;
1403       flg = 1;
1404     }
1405
1406     for( j = i+1; j < count; ++j )
1407     {
1408       if( strcmp( list[i], list[j] ) == 0 )
1409       {
1410         RenameEntry( &(list[j]), ++addIndex );
1411         l = i;
1412         flg2 = 1;
1413       }
1414     }
1415     if( flg2 )
1416     {
1417       flg2 = 0;
1418       RenameEntry( &(list[l]), 1 );
1419     }
1420   }
1421   if( flg )
1422   {
1423     free( list[k] );
1424     list[k] = (char *)malloc( strlen( DEFAULT_BUFFER_FILENAME ) + 1 );
1425     sprintf( list[k], "%s", DEFAULT_BUFFER_FILENAME );
1426   }
1427 }
1428
1429
1430 /*
1431  * This is a function for adding an index to a buffer name which has
1432  * collided.
1433  */
1434
1435 static void
1436 RenameEntry( char ** name, unsigned int addIndex )
1437 {
1438
1439 #define MAX_INT_SIZE 15
1440
1441 char * tmpPtr, * newName;
1442
1443   if( *name == 0x0 )
1444     return;
1445   else if( **name == 0x0 )
1446   {
1447     newName = (char *)XtCalloc(1,strlen(DEFAULT_BUFFER_FILENAME)+ MAX_INT_SIZE);
1448     sprintf( newName, "%s_%d", DEFAULT_BUFFER_FILENAME, addIndex );
1449   }
1450   else
1451   {
1452     tmpPtr = strrchr( *name, '.' );
1453
1454     newName = (char *)XtCalloc( 1, strlen( *name ) + MAX_INT_SIZE );
1455
1456     if( tmpPtr == NULL )
1457       sprintf( newName, "%s_%d", *name, addIndex );
1458     else if( tmpPtr == *name )
1459       sprintf( newName, "%d%s", addIndex, *name );
1460     else
1461     {
1462       *tmpPtr = 0x0;
1463       sprintf( newName, "%s_%d.%s", *name, addIndex, ++tmpPtr);
1464     }
1465   }
1466   free( *name );
1467   *name = newName;
1468 }
1469
1470
1471 /*
1472  * This is a generic function for freeing buffer information extracted from
1473  * drop input.
1474  */
1475
1476 void
1477 _DtFreeDroppedBufferInfo(char **file_set,
1478               BufferInfo *buffer_set,
1479               char **host_set,
1480               int num_of_buffers)
1481 {
1482   int i;
1483
1484   DPRINTF (("Executing..._DtFreeDroppedBufferInfo\n"));
1485
1486   /* Check for Null pointers */
1487   if (file_set && buffer_set && host_set )
1488   {
1489      for (i=0; i< num_of_buffers; i++ )
1490      {
1491        XtFree(file_set[i]);
1492        XtFree(host_set[i]);
1493      }
1494
1495      XtFree((char *)file_set);
1496      XtFree((char *)host_set);
1497      XtFree((char *)buffer_set);
1498   }
1499 }
1500
1501
1502 /*
1503  * This is a generic function for determining if a buffer is executable.
1504  */
1505
1506 Boolean
1507 _DtIsBufferExecutable(
1508         void *buffer,
1509         int buffer_size)
1510
1511 {
1512    char *exe_attribute;
1513    Boolean is_exe = False;
1514
1515    exe_attribute = DtDtsBufferToAttributeValue(buffer,
1516                                                buffer_size,
1517                                                "IS_EXECUTABLE",
1518                                                NULL);
1519    if (exe_attribute)
1520    {
1521       if (DtDtsIsTrue(exe_attribute))
1522          is_exe = True;
1523
1524       DtDtsFreeAttributeValue(exe_attribute);
1525    }
1526
1527    return(is_exe);
1528 }
1529
1530
1531 /*
1532  * This is a generic function for extracting file information from drop input.
1533  */
1534
1535 void
1536 _DtSetDroppedFileInfo(
1537         DtDndDropCallbackStruct *drop_parameters,
1538         char ***file_set,
1539         char ***host_set)
1540 {
1541    int numFiles, i;
1542
1543    numFiles = drop_parameters->dropData->numItems;
1544
1545    *file_set = (char **)XtMalloc(sizeof(char *) * numFiles);
1546    *host_set = (char **)XtMalloc(sizeof(char *) * numFiles);
1547    for(i = 0; i < numFiles; i++)
1548    {
1549       (*file_set)[i] = XtNewString(drop_parameters->dropData->data.files[i]);
1550       (*host_set)[i] = home_host_name;
1551
1552       DPRINTF(("ProcessMoveCopyLink:\n host_set[%d]=%s, file_set[%d]=%s\n",
1553                i, (*host_set)[i], i, (*file_set)[i]));
1554    }
1555 }
1556
1557
1558 /*
1559  * This is a generic function for copying file info extracted from drop input.
1560  */
1561
1562 void
1563 _DtCopyDroppedFileInfo(
1564         int num_files,
1565         char **orig_file_set,
1566         char **orig_host_set,
1567         char ***new_file_set,
1568         char ***new_host_set)
1569 {
1570    int i;
1571
1572    *new_file_set = (char **)XtMalloc(sizeof(char *) * num_files);
1573    *new_host_set = (char **)XtMalloc(sizeof(char *) * num_files);
1574    for(i = 0; i < num_files; i++)
1575    {
1576       (*new_file_set)[i] = XtNewString(orig_file_set[i]);
1577       (*new_host_set)[i] = XtNewString(orig_host_set[i]);
1578    }
1579 }
1580
1581
1582 /*
1583  * This is a generic function for freeing file info extracted from drop input.
1584  */
1585
1586 void
1587 _DtFreeDroppedFileInfo(
1588         int num_files,
1589         char **file_set,
1590         char **host_set)
1591 {
1592    int i;
1593
1594    for(i = 0; i < num_files; i++)
1595       XtFree(file_set[i]);
1596
1597    XtFree((char *)file_set);
1598    XtFree((char *)host_set);
1599 }
1600
1601
1602 /*
1603  * This is a generic function for resolving a cannonical path from user input.
1604  */
1605
1606 void
1607 _DtPathFromInput(
1608         char *input_string,
1609         char *current_dir,
1610         char **host,
1611         char **rel_path)
1612
1613 {
1614    char *path;
1615    char *tmp_path = NULL;
1616    char *true_path = NULL;
1617    Tt_status tt_status;
1618    int dir_len;
1619
1620    /* find host */
1621    *host = XtNewString(home_host_name);
1622
1623    /* find relative path */
1624    tmp_path = path = XtNewString(input_string);
1625
1626    /* Strip any spaces from name -- input is overwritten */
1627    path = (char *) _DtStripSpaces(path);
1628
1629    /* Resolve, if there're any, environment variables */
1630    {
1631       FILE *pfp;
1632       char command[MAXPATHLEN];
1633
1634       sprintf(command,"echo %s",path);
1635
1636       if((pfp=popen(command,"r")) != NULL)
1637       {
1638           int read_ok = 1;
1639
1640           if (NULL == (fgets(command,MAXPATHLEN,pfp))) 
1641           {
1642               /*
1643                * Try a few more reads and if the read still fails, 
1644                * just use the path as is.
1645                */
1646               int i;
1647               for (i=0; i < 5; i++) 
1648               {
1649                   sleep (1);
1650                   if (NULL != (fgets(command,MAXPATHLEN,pfp))) 
1651                       break;
1652              }
1653              if (i >= 5)
1654                  read_ok = 0;
1655          }
1656
1657          if (read_ok) 
1658          {
1659              command[strlen(command)-1] = '\0';
1660              XtFree(path);
1661              path = XtNewString(command);
1662              pclose(pfp);
1663          }
1664       }
1665    }
1666
1667    /* Resolve '~' -- new memory is allocated, old memory is freed */
1668    if (*path == '~')
1669       path = _DtChangeTildeToHome(path);
1670
1671    /* If current dir provided, check for relative path */
1672    if (path && current_dir)
1673    {
1674       if (*path != '/')
1675       {
1676          /* file is relative path i.e.      xyz/abc */
1677          if (strcmp(current_dir, "/") == 0)
1678          {
1679             tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 1);
1680             sprintf(tmp_path, "%s%s", current_dir, path);
1681          }
1682          else
1683          {
1684             tmp_path = (char *)XtMalloc(strlen(current_dir) + strlen(path) + 2);
1685             sprintf(tmp_path, "%s/%s", current_dir, path);
1686          }
1687
1688          XtFree(path);
1689          path = tmp_path;
1690          tmp_path = NULL;
1691       }
1692    }
1693    else if (!path)
1694    {
1695      *rel_path = NULL;
1696      XtFree(tmp_path);
1697      return;
1698    }
1699
1700    /* Resolve '.' or '..' -- input is overwritten, output may be NULL! */
1701    /* Save pointer to path to free if output is NULL.                  */
1702    tmp_path = path;
1703    path = (char *) DtEliminateDots(path);
1704
1705    if (path)
1706    {
1707       /* Resolve to local pathname */
1708       true_path = ResolveLocalPathName(*host,
1709                                        path,
1710                                        NULL,
1711                                        home_host_name,
1712                                        &tt_status);
1713       XtFree(path);
1714
1715       /* Strip off trailing '/' */
1716       dir_len = strlen(true_path);
1717       if (dir_len > 1 && *(true_path + dir_len - 1) == '/')
1718          *(true_path + dir_len - 1) = '\0';
1719    }
1720    else
1721    {
1722       true_path = NULL;
1723       XtFree(tmp_path);
1724    }
1725
1726    *rel_path = true_path;
1727 }
1728
1729
1730 /*
1731  * This function takes a path name, and resolves any leading '~' to refer
1732  * to one of the following:
1733  *
1734  *   1) if ~ or ~/path, then it resolves to the user's home directory on
1735  *      their home host.
1736  *
1737  *   2) if ~user or ~user/path, then it resolves to the specified user's
1738  *      home directory on the home host.
1739  *
1740  * This function never resolves to any host but the home host, since we
1741  * have no way of determining a user's home directory on any system other
1742  * than the home system.
1743  */
1744
1745 char *
1746 _DtChangeTildeToHome (
1747         char *input_string)
1748 {
1749    char *path;
1750    char *full_path;
1751    struct passwd * pwInfo;
1752
1753    if ((input_string[1] != '\0') && (input_string[1] != '/'))
1754    {
1755       char *path;
1756
1757       /* ~user or ~user/path format */
1758
1759       /* is there a path? */
1760       path = DtStrchr(input_string, '/');
1761
1762       /* find user */
1763       if (path)
1764          *path = '\0';
1765       if ((pwInfo = getpwnam(input_string + 1)) == NULL)
1766       {
1767          /* user doesn't exist */
1768          if (path)
1769             *path = '/';
1770          return NULL;
1771       }
1772
1773       if (path)
1774       {
1775          /* ~user/path format */
1776
1777          *path = '/';
1778
1779          if (strcmp(pwInfo->pw_dir, "/") == 0)
1780          {
1781             /* We don't want to end up with double '/' in the path */
1782             full_path = (char *) XtMalloc(strlen(path) + 1);
1783             strcpy(full_path, path);
1784          }
1785          else
1786          {
1787             full_path = (char *) XtMalloc(strlen(pwInfo->pw_dir) +
1788                                           strlen(path) + 1);
1789             sprintf(full_path, "%s%s", pwInfo->pw_dir, path);
1790          }
1791       }
1792       else
1793       {
1794          /* ~user format */
1795
1796          full_path = XtMalloc(strlen(pwInfo->pw_dir) + 1);
1797          strcpy(full_path, pwInfo->pw_dir);
1798       }
1799    }
1800    else if (input_string[1])
1801    {
1802       /* ~/path format */
1803
1804       /* NOTE: users_home_dir has trailing '/' */
1805       full_path = XtMalloc(strlen(users_home_dir) + strlen(input_string+2) + 1);
1806       sprintf(full_path, "%s%s", users_home_dir, (input_string + 2));
1807    }
1808    else
1809    {
1810       /* ~ format */
1811
1812       full_path = XtMalloc(strlen(users_home_dir) + 1);
1813       strcpy(full_path, users_home_dir);
1814    }
1815
1816    XtFree(input_string);
1817    return(full_path);
1818 }
1819
1820
1821 /*
1822  * This function checks for spaces in filenames.
1823  */
1824 #ifdef _CHECK_FOR_SPACES
1825
1826 Boolean
1827 _DtSpacesInFileNames(
1828          char **fileNames, 
1829          int  fileCount )
1830 {
1831   int i;
1832
1833   for (i = 0; i < fileCount; i++)
1834   {
1835      fileNames[i] = (char *) _DtStripSpaces(fileNames[i]);
1836
1837      if (DtStrchr (fileNames[i], ' ') != NULL ||
1838          DtStrchr (fileNames[i], '\t') != NULL)
1839         return(TRUE);
1840   }
1841
1842   return(FALSE);
1843 }
1844
1845 #endif
1846
1847 /*
1848  * This resolves the path for an appmanager object to its true path.
1849  */
1850
1851 char *
1852 _DtResolveAppManPath(
1853          char *path,
1854          char *restricted_dir )
1855 {
1856    if (strlen(path) > strlen(restricted_dir))
1857    {
1858       char *linkDir, *ptr, *tmpPath;
1859
1860       linkDir = path + strlen(restricted_dir) + 1;
1861       ptr = DtStrchr(linkDir, '/');
1862       if (ptr)
1863       {
1864          *ptr = '\0';
1865          linkDir = _DtFollowLink(path);
1866          *ptr = '/';
1867          tmpPath = XtMalloc(strlen(linkDir) + strlen(ptr) + 1);
1868          sprintf(tmpPath, "%s%s", linkDir, ptr);
1869          XtFree(path);
1870          path = tmpPath;
1871       }
1872       else
1873       {
1874          linkDir = _DtFollowLink(path);
1875          XtFree(path);
1876          path = XtNewString(linkDir);
1877       }
1878    }
1879
1880    return(path);
1881 }