Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtwm / Session.c
1 /* $TOG: Session.c /main/5 1997/05/20 08:20:18 samborn $ */
2 /************************************************************************
3  *
4  *  File:        Session.c
5  *
6  *  Project:     CDE
7  *
8  *  Description: This file contains the session management code for the
9  *               CDE front panel.
10  *
11  * (c) Copyright 1993, 1994 Hewlett-Packard Company
12  * (c) Copyright 1993, 1994 International Business Machines Corp.
13  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
14  * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
15  *
16  ************************************************************************/
17
18 #include <Dt/WsmP.h>
19
20 #include <Dt/Control.h>
21 #include <Dt/ControlP.h>
22
23 #include "DataBaseLoad.h"
24
25
26 #include <pwd.h>
27 #include <fcntl.h>
28 #include <sys/stat.h>
29 #include <dirent.h>
30
31
32
33 extern void ToggleDefaultControl(ControlData *, SubpanelData *, ControlData *);
34 extern Boolean CheckOtherMonitorsOn(SubpanelData *);
35
36
37
38 /*  This define is used as the file name and location of the session  */
39 /*  file needed by the front panel to store its across session data.  */
40
41 static char * SESSION_FILE = "/.dt/sessions/dtwmfp.session";
42 static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
43
44
45 extern String unpost_arrow_image;
46 extern String unpost_monitor_arrow_image;
47
48 #define MAX_PATH        1024
49
50
51 /************************************************************************
52  *
53  *  SessionFileGetName
54  *      Generate the name of the session file to be used to read and
55  *      write the front panel session information.
56  *
57  ************************************************************************/
58  
59 static char *
60 SessionFileGetName ()
61
62
63 {
64    char * home_dir;
65    char * file_name;
66    struct passwd * pw_info;
67    
68
69    /*  Get the home directory used to build the path to the session file.  */
70
71    if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
72    {
73       pw_info = getpwuid (getuid());
74       home_dir = pw_info->pw_dir;
75    }
76
77    file_name = XtMalloc (strlen (home_dir) + strlen (SESSION_FILE) + 1);
78    sprintf (file_name, "%s%s", home_dir, SESSION_FILE);
79    
80    return (file_name);
81 }
82
83
84
85
86 /************************************************************************
87  *
88  *  SessionRestoreData
89  *      This function reads the front panels session file and applies
90  *      the data to the already created front panel.
91  *
92  ************************************************************************/
93
94 void
95 SessionRestoreData ()
96
97
98 {
99    FILE * fd;
100
101    char * session_file;
102    
103    BoxData * box_data;
104    ControlData * control_data;
105
106    SubpanelData ** subpanel_data = NULL;
107    int subpanel_count = 0;
108    int max_subpanel_count = 0;
109    
110    int subpanel_posted_count = 0;
111    int subpanel_default_count = 0;
112
113    char name_buffer1[256];
114    char name_buffer2[256];
115    char name_buffer3[256];
116
117    struct stat stat_info;
118
119    int     parent_component_type;
120    int     component_type;
121    int     delete_value;
122    Boolean delete;
123
124    int dynamic_data_count;
125    
126    int subpanel_x;
127    int subpanel_y;
128    int subpanel_torn;
129
130    DtWmHints vHints;
131    
132    Boolean have_it;
133    
134    Dimension width;
135    Dimension new_width;
136    Widget    parent;
137    
138    int mapped;
139
140    int i, j, k, l;
141    Arg al[2];
142
143    
144    session_file = SessionFileGetName ();
145
146
147    if ((fd = fopen (session_file, "r")) != NULL)
148    {
149       /*  Get the full list of subpanels  */
150       
151       for (i = 0; i < panel.box_data_count; i++)
152       {
153          box_data = panel.box_data[i];
154          
155          for (j = 0; j < box_data->control_data_count; j++)
156          {
157             control_data = box_data->control_data[j];
158             
159             if (control_data->subpanel_data != NULL)
160             {
161                if (subpanel_count == max_subpanel_count)
162                {
163                   max_subpanel_count += 10;
164                   subpanel_data = (SubpanelData **)
165                     XtRealloc ((char *) subpanel_data, 
166                                sizeof (SubpanelData **) * max_subpanel_count);
167                }
168
169                subpanel_data[subpanel_count] = control_data->subpanel_data;
170                subpanel_count++;
171             }
172          }
173       }
174
175
176       /*  Get the count of the number of subpanels to be posted.  */
177
178       fscanf (fd, "%d", &subpanel_posted_count);         
179
180
181       /*  If the count is greater than 0, read in the list of subpanel  */
182       /*  names, compare them with the list of subpanels and post the   */
183       /*  appropriate ones.                                             */
184          
185       for (i = 0; i < subpanel_posted_count; i++)
186       {
187          fscanf (fd, "%s%d%d%d", 
188                  name_buffer1, &subpanel_x, &subpanel_y, &subpanel_torn);
189             
190          for (j = 0; j < subpanel_count; j++)
191          {
192             if (strcmp (name_buffer1,
193                         subpanel_data[j]->
194                         element_values[SUBPANEL_NAME].parsed_value) == 0)
195             {
196                /*  If the subpanel is torn, modify the window manager    */
197                /*  behavior hints so that it can be positioned properly  */
198                /*  and does not slide up.                                */
199                
200                if (subpanel_torn != 0)
201                {
202                   subpanel_data[j]->torn = True;
203
204                   vHints.flags = 
205                      DtWM_HINTS_BEHAVIORS | DtWM_HINTS_ATTACH_WINDOW;
206                   vHints.behaviors = 
207                      DtWM_BEHAVIOR_PANEL | DtWM_BEHAVIOR_SUBPANEL | 
208                                            DtWM_BEHAVIOR_SUB_RESTORED;
209                   vHints.attachWindow = XtWindow (panel.shell);
210
211                   _DtWsmSetDtWmHints (XtDisplay (panel.shell),
212                                       XtWindow (subpanel_data[j]->shell), 
213                                       &vHints);
214                }
215
216
217                /*  Manage and position the form and shell of the subpanel  */
218                /*  Note: this is a close copy of the ArrowCB posting       */
219                /*  function logic.                                         */
220                
221                XtSetMappedWhenManaged (subpanel_data[j]->shell, False);
222                XtManageChild (subpanel_data[j]->form);
223
224                XtSetArg (al[0], XmNx, subpanel_x);
225                XtSetArg (al[1], XmNy, subpanel_y);
226                XtSetValues (subpanel_data[j]->form, al, 2);
227
228                XtManageChild (subpanel_data[j]->shell);
229                XtSetMappedWhenManaged (subpanel_data[j]->shell, True);
230
231                if (!CheckOtherMonitorsOn(subpanel_data[j]))
232                   XtSetArg (al[0], XmNimageName, unpost_arrow_image);
233                else
234                   XtSetArg (al[0], XmNimageName, unpost_monitor_arrow_image);
235                XtSetValues(subpanel_data[j]->parent_control_data->arrow, al, 1);
236             }
237          }
238       }  
239
240
241       /*  Get the count of the number of subpanel controls to be  */
242       /*  toggled into the main panel.                            */
243          
244       fscanf (fd, "%d", &subpanel_default_count);
245
246
247       /*  If the count is greater than 0, read in the list of subpanel  */
248       /*  names, and control_names and compare them with the list of    */
249       /*  subpanels and their controls.  Toggle the proper control.     */
250
251       for (i = 0; i < subpanel_default_count; i++)
252       {
253          fscanf (fd, "%s%s", name_buffer1, name_buffer2);
254             
255          for (j = 0; j < subpanel_count; j++)
256          {
257             if (strcmp (name_buffer1,
258                         subpanel_data[j]->
259                         element_values[SUBPANEL_NAME].parsed_value) == 0)
260             {
261                for (k = 0; k < subpanel_data[j]->control_data_count; k++)
262                {
263                   if (strcmp (name_buffer2,
264                               subpanel_data[j]->control_data[k]->
265                               element_values[CONTROL_NAME].parsed_value) == 0)
266                   {
267                      /*  use the difference in width of the old and new  */
268                      /*  main controls to adjust the parent form.  This  */
269                      /*  should not be necessary but form is buggy.      */
270
271                      width = XtWidth(subpanel_data[j]->parent_control_data->icon);
272
273                      ToggleDefaultControl(subpanel_data[j]->parent_control_data,
274                                           subpanel_data[j],
275                                           subpanel_data[j]->control_data[k]);
276
277                      new_width = XtWidth (subpanel_data[j]->parent_control_data->icon);
278
279                      parent = XtParent (subpanel_data[j]->parent_control_data->icon);
280                      XtSetArg (al[0], XmNwidth, XtWidth (parent) + new_width - width);
281                      XtSetValues (parent, al, 1);
282                   }
283                }
284             }
285          }
286       }  
287
288    
289       /*  Read in the count of the number of dynamic component records  */
290       
291       fscanf (fd, "%d", &panel.dynamic_data_count);
292       panel.max_dynamic_data_count = panel.dynamic_data_count;
293
294       if (panel.dynamic_data_count > 0) {
295         panel.dynamic_data_list = (DynamicComponent **)
296           XtMalloc (sizeof (DynamicComponent **) * panel.max_dynamic_data_count);
297       }
298
299       dynamic_data_count = 0;
300       
301
302       /*  Loop through and read all of the records  */
303       
304       for (i = 0; i < panel.dynamic_data_count; i++)
305       {
306          fscanf(fd, "%s%s%d%s%d%d", name_buffer1, name_buffer2, &component_type,
307                 name_buffer3, &parent_component_type, &delete_value);
308
309
310          /*  Stat the file name to see if it still exists.  If not,    */
311          /*  continue at the next iteration of the loop.  This has     */
312          /*  the effect of not putting the data into the dynamic list  */
313          /*  so that it will not be written on the next shutdown.      */
314          
315          if (lstat (name_buffer1, &stat_info) != 0)
316             continue;
317
318
319          delete = False;
320          if (delete_value == 1) delete = True;
321
322
323          /*  Loop through the subpanels and verify that each of the    */
324          /*  records matches component within the hierarchy.  If not,  */
325          /*  do not put the record in the list.                        */
326       
327          for (j = 0; j < subpanel_count; j++)
328          {
329             have_it = False;
330             
331
332             /*  If the data is a reference to a deleted component, put   */
333             /*  it in the list.  If it is a subpanel, verify that there  */
334             /*  is a subpanel of that name and a main control parent of  */
335             /*  the correct name.  If it is a control, reloop through    */
336             /*  the subpanel set a look for a control which matches the  */
337             /*  name and a subpanel which matches the parent name.       */
338
339             if (delete)
340                have_it = True;
341             else if (component_type == SUBPANEL && 
342                      strcmp (subpanel_data[j]->
343                              element_values[SUBPANEL_NAME].parsed_value,
344                              name_buffer2) == 0 &&
345                      strcmp (subpanel_data[j]->
346                              element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
347                              name_buffer3) == 0)
348             {
349                have_it = True;
350             }
351             else
352             {
353                if (parent_component_type == SUBPANEL)
354                {
355                   for (k = 0; k < subpanel_count; k++)
356                   {
357                      if (strcmp (subpanel_data[k]->
358                          element_values[SUBPANEL_NAME].parsed_value,
359                          name_buffer3) == 0)
360                      {
361                         for (l = 0; l < subpanel_data[k]->control_data_count; l++)
362                         {
363                            if (strcmp (subpanel_data[k]->control_data[l]->
364                                element_values[CONTROL_NAME].parsed_value,
365                                name_buffer2) == 0)
366                            {
367                               have_it = True;
368                               break;
369                            }
370                         }
371                      }
372
373                      if (have_it) 
374                         break;
375                   }
376                }
377                else if (parent_component_type == BOX)
378                {
379                   for (k = 0; k < panel.box_data_count; k++)
380                   {
381                      if (strcmp (panel.box_data[k]->
382                          element_values[BOX_NAME].parsed_value,
383                          name_buffer3) == 0)
384                      {
385                         for (l = 0; l < panel.box_data[k]->control_data_count; l++)
386                         {
387                            if (strcmp (panel.box_data[k]->control_data[l]->
388                                element_values[CONTROL_NAME].parsed_value,
389                                name_buffer2) == 0)
390                            {
391                               have_it = True;
392                               break;
393                            }
394                         }
395                      }
396
397                      if (have_it) 
398                         break;
399                   }
400                }
401             }       
402
403             if (have_it)
404             {
405                panel.dynamic_data_list[dynamic_data_count] = 
406                   (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
407
408                panel.dynamic_data_list[dynamic_data_count]->file_name = XtNewString (name_buffer1);
409                panel.dynamic_data_list[dynamic_data_count]->component_name = XtNewString (name_buffer2);
410                panel.dynamic_data_list[dynamic_data_count]->component_type = component_type;
411                panel.dynamic_data_list[dynamic_data_count]->parent_name = XtNewString (name_buffer3);
412                panel.dynamic_data_list[dynamic_data_count]->parent_type = parent_component_type;
413                panel.dynamic_data_list[dynamic_data_count]->delete = delete;
414
415                dynamic_data_count++;
416
417                break;
418             }
419          }
420       }
421
422       panel.dynamic_data_count = dynamic_data_count;
423
424    
425       /*  Read whether the front panel is iconic or not and set the  */
426       /*  hints on the shell appropriately.                          */
427       
428       if (fscanf (fd, "%d", &mapped) == 1)
429       {
430          if (mapped == 0)
431             XIconifyWindow (XtDisplay(panel.shell), XtWindow(panel.shell),
432                             XScreenNumberOfScreen (XtScreen (panel.shell)));
433       }
434
435       fclose (fd);
436    }
437
438
439    if (subpanel_data)
440       XtFree ((char *) subpanel_data); 
441
442    XtFree (session_file);
443 }
444
445
446
447
448
449 /************************************************************************
450  *
451  *  WmFPSessionSaveData
452  *      This function calculates and save the front panels session data
453  *      needed for the next restart.  It is called from the window manager
454  *      in its SaveResources function.
455  *
456  ************************************************************************/
457
458 void
459 WmFrontPanelSessionSaveData ()
460
461
462 {
463    FILE * fd;
464
465    char * session_file;
466    Boolean written = False;
467    
468    BoxData * box_data;
469    ControlData * control_data;
470
471    SubpanelData ** subpanel_data = NULL;
472    int subpanel_count = 0;
473    int max_subpanel_count = 0;
474    
475    int subpanel_posted_count = 0;
476    int subpanel_default_count = 0;
477
478    XWindowAttributes window_attributes;
479
480    Arg al[2];
481
482    int i,j;
483
484
485    /*  Set the session file name and open the file  */
486
487    session_file = SessionFileGetName ();
488
489    if ((fd = fopen (session_file, "w")) != NULL)
490    {
491
492       /*  Get the full list of subpanels  */
493       
494       for (i = 0; i < panel.box_data_count; i++)
495       {
496          box_data = panel.box_data[i];
497          
498          for (j = 0; j < box_data->control_data_count; j++)
499          {
500             control_data = box_data->control_data[j];
501             
502             if (control_data->subpanel_data != NULL)
503             {
504                if (subpanel_count == max_subpanel_count)
505                {
506                   max_subpanel_count += 10;
507                   subpanel_data = (SubpanelData **)
508                     XtRealloc ((char *) subpanel_data, 
509                                sizeof (SubpanelData **) * max_subpanel_count);
510                }
511
512                subpanel_data[subpanel_count] = control_data->subpanel_data;
513
514                if (XtIsManaged (subpanel_data[subpanel_count]->shell))
515                   subpanel_posted_count++;
516
517                if (subpanel_data[subpanel_count]->default_control !=
518                    subpanel_data[subpanel_count]->parent_control_data)
519                   subpanel_default_count++;
520
521                subpanel_count++;
522             }
523          }
524       }
525        
526
527       /*  Save off the list of subpanels that are posted  */
528
529       fprintf (fd, "%d\n", subpanel_posted_count);
530
531       if (subpanel_posted_count > 0)
532       {
533          for (i = 0; i < subpanel_count; i++)
534          {
535             if (XtIsManaged (subpanel_data[i]->shell))
536                fprintf (fd, "%s %d %d %d\n",
537                          subpanel_data[i]->
538                          element_values[SUBPANEL_NAME].parsed_value,
539                          XtX (subpanel_data[i]->shell),
540                          XtY (subpanel_data[i]->shell),
541                          (int) subpanel_data[i]->torn);
542          }
543       }
544             
545
546       /*  Save off the controls that have been toggled from the  */
547       /*  subpanel into the main panel.                          */
548
549       fprintf (fd, "%d\n", subpanel_default_count);
550
551       if (subpanel_default_count > 0)
552       {
553          for (i = 0; i < subpanel_count; i++)
554          {
555             if (subpanel_data[i]->default_control !=
556                 subpanel_data[i]->parent_control_data)
557             {
558                fprintf (fd, "%s %s\n", 
559                           subpanel_data[i]->
560                                     element_values[SUBPANEL_NAME].parsed_value,
561                           subpanel_data[i]->default_control->
562                                     element_values[CONTROL_NAME].parsed_value);
563                
564             }
565          }
566       }
567
568    
569       /*  Save off the dynamic component information  */
570       
571       fprintf (fd, "%d\n", panel.dynamic_data_count);
572       
573       for (i = 0; i < panel.dynamic_data_count; i++)
574       {
575          fprintf (fd, "%s %s %d %s %d %d\n", 
576                   panel.dynamic_data_list[i]->file_name,
577                   panel.dynamic_data_list[i]->component_name,
578                   panel.dynamic_data_list[i]->component_type,
579                   panel.dynamic_data_list[i]->parent_name,
580                   panel.dynamic_data_list[i]->parent_type,
581                   (int) panel.dynamic_data_list[i]->delete);
582       }
583
584
585       /*  Save off whether the front panel is iconfied or not.  */
586       
587       XGetWindowAttributes (XtDisplay (panel.shell), XtWindow (panel.shell),
588                             &window_attributes);
589
590       if (window_attributes.map_state == IsUnmapped)
591          fprintf (fd, "%d\n", 0);
592       else
593          fprintf (fd, "%d\n", 1);
594
595       fflush (fd);
596       fclose (fd);
597    }
598
599
600    if (subpanel_data)
601       XtFree ((char *) subpanel_data);
602
603    XtFree (session_file);
604 }
605
606
607
608
609 /************************************************************************
610  *
611  *  SessionAddFileData
612  *      This function adds a new session file record to the list 
613  *      attached to panel.  It is called when a new control or 
614  *      subpanel is dynamically added.
615  *
616  *  Inputs: file_name - the name of the file the component is stored in
617  *          component_name - the value of the name field of the component
618  *          component_type - a value of CONTROL or SUBPANEL
619  *          parent_name - the container of the component
620  *          parent_type - a value of SUBPANEL or CONTROL
621  *          delete - a Boolean indicating whether the component has been
622  *                   deleted.  This requires special handling on startup.
623  *
624  ************************************************************************/
625
626 void
627 SessionAddFileData (char  * file_name,
628                     char  * component_name,
629                     int     component_type,
630                     char  * parent_name,
631                     int     parent_type,
632                     Boolean delete)
633
634
635 {
636    int count = panel.dynamic_data_count;
637
638    if (count == panel.max_dynamic_data_count)
639    {
640        panel.max_dynamic_data_count += 10;
641        panel.dynamic_data_list = (DynamicComponent **)
642           XtRealloc ((char *) panel.dynamic_data_list,
643              sizeof (DynamicComponent **) * panel.max_dynamic_data_count);
644    }
645
646    panel.dynamic_data_list[count] = 
647       (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
648
649    panel.dynamic_data_list[count]->file_name = XtNewString (file_name);
650    panel.dynamic_data_list[count]->component_name = XtNewString (component_name);
651    panel.dynamic_data_list[count]->component_type = component_type;
652    panel.dynamic_data_list[count]->parent_name = XtNewString (parent_name);
653    panel.dynamic_data_list[count]->parent_type = parent_type;
654    panel.dynamic_data_list[count]->delete = (int) delete;
655    panel.dynamic_data_count++;
656 }
657
658
659
660
661 /************************************************************************
662  *
663  *  SessionDeleteFileData
664  *      This function deletes a session file record from the list 
665  *      attached to panel.  It is called when a componentent is deleted
666  *      from the front panel.
667  *
668  *  Inputs: file_name - The name of the file containing the component
669  *          definition.  This is used to look up in the session list.
670  *
671  ************************************************************************/
672
673 void
674 SessionDeleteFileData (char * file_name)
675
676
677 {
678    int i, j;
679    
680
681    /*  Loop through the dynamic data list and find the matching record  */
682    /*  Free the data attached to the record and the record.  Then move  */
683    /*  the list up to fill the empty space.                             */
684    
685    for (i = 0; i < panel.dynamic_data_count; i++)
686    {
687       if (strcmp (file_name, panel.dynamic_data_list[i]->file_name) == 0)
688       {
689          XtFree ((char *) panel.dynamic_data_list[i]->file_name);
690          XtFree ((char *) panel.dynamic_data_list[i]->component_name);
691          XtFree ((char *) panel.dynamic_data_list[i]->parent_name);
692          XtFree ((char *) panel.dynamic_data_list[i]);
693          
694          for (j = i; j < panel.dynamic_data_count - 1; j++)
695             panel.dynamic_data_list[j] = panel.dynamic_data_list[j + 1];
696
697          panel.dynamic_data_count--;
698
699          break;
700       }
701    }
702 }
703
704
705
706
707 /************************************************************************
708  *
709  *  SessionFileNameLookup
710  *      This function locates and returns the name of a dynamic component
711  *      .fp file.
712  *
713  *  Inputs: component_name - the name of the dynamic component.
714  *          component_type - the type (CONTROL, SUBPANEL) of the component.
715  *          parent_name - the name of the container of the component.
716  *          parent_type - the type (SUBPANEL, CONTROL) of the parent.
717  *
718  *  Outputs: The file name of the dynamic component file or NULL if not found.
719  *
720  ************************************************************************/
721
722 char *
723 SessionFileNameLookup (char * component_name,
724                        int    component_type,
725                        char * parent_name,
726                        int    parent_type)
727
728
729 {
730    int i;
731    
732
733    /*  Loop through the dynamic data list and find the matching record  */
734    /*  Return the file name when found or NULL if not found             */
735    /*  the list up to fill the empty space.                             */
736    
737    for (i = 0; i < panel.dynamic_data_count; i++)
738    {
739       if (strcmp (component_name, 
740                   panel.dynamic_data_list[i]->component_name) == 0     &&
741           component_type == panel.dynamic_data_list[i]->component_type &&
742           strcmp (parent_name, 
743                   panel.dynamic_data_list[i]->parent_name) == 0        &&
744           parent_type == panel.dynamic_data_list[i]->parent_type)
745       {
746          return (panel.dynamic_data_list[i]->file_name);
747       }
748    }
749
750    return ((char *) NULL);
751 }
752
753 /************************************************************************
754  *
755  *  SessionDeleteAll
756  *      This function deletes all of the session file records from the list 
757  *      attached to panel.  It is called when a request is made to restore
758  *      the default front panel.
759  *
760  *  Inputs: None
761  *
762  ************************************************************************/
763
764 void
765 SessionDeleteAll(void)
766 {
767    DIR *dir;
768    struct dirent *entry;          /* directory entry */
769    char srcname[MAX_PATH];
770    int srclen;
771    char * home_dir;
772    char * fp_dir;
773    struct passwd * pw_info;
774    int i;
775
776
777    /*  Get the home directory used to build the path to the session file.  */
778
779    if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
780    {
781       pw_info = getpwuid (getuid());
782       home_dir = pw_info->pw_dir;
783    }
784
785   /* Add path to fp_dynamic directory */
786    fp_dir = XtMalloc (strlen(home_dir) + strlen(TYPES_DIR) + 1);
787    sprintf (fp_dir, "%s%s", home_dir, TYPES_DIR);
788
789     
790   /* Open the fp_dynamic directory */
791    dir = opendir(fp_dir);
792
793    if (dir == NULL)
794      return;
795
796   /* prepare source name */
797    strcpy(srcname, fp_dir);
798    srclen = strlen(fp_dir);
799    if (srcname[srclen - 1] != '/')
800      srcname[srclen++] = '/';
801
802   /*  Loop through all the files in the fp_dyamic directory and
803    *  remove them.
804    */
805
806    while ((entry = readdir(dir)) != NULL)
807    {
808       if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
809          continue;
810       strcpy(srcname + srclen, entry->d_name);
811       remove (srcname);
812    }
813 }
814