1 /*****************************************************************************
2  ** File          : doubleclick.c                                           **
3  ** Purpose       : Initialise and Realise double click dialog options      **
4  ** Author        : Jonathan Abbey ARL:UT                                   **
5  ** Date          : Aug 1991                                                **
6  ** Documentation : Xdtm Design Folder                                      **
7  ** Related Files :                                                         **
8  ** Changes       : 18-04-92, Edward Groenendaal                            **
9  **                 Added #if NeedFunctionPrototypes stuff                  **
10  **                 25-05-92, Edward Groenendaal                            **
11  **                 Added support for multiple instances                    **
12  **                 June 20, 1992, Ramon Santiago                           **
13  **                 Changed all XtCreate calls to XtVaCreate calls.         **
14  **                 Changed all caddr_t to XtPointer.                       **
15  **                 Removed some lint.                                      **
16  **                 Modified some variable names, and moved language        **
17  **                 specific strings to app-defaults file.                  **
18  ****************************************************************************/
19 
20 /*
21 #define DEBUG 1
22 */
23 
24 #include "xdtm.h"
25 #include "menus.h"
26 #include "parse.h"		  /* AppProgram, etc. */
27 #include "Ext/appl.h"
28 #include <X11/Shell.h>
29 #include <X11/Xaw/Label.h>
30 #include <X11/Xaw/Command.h>
31 #include <X11/Xaw/AsciiText.h>
32 #include "Xedw/XedwForm.h"
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <sys/time.h>
37 #include <grp.h>
38 #include <sys/param.h>
39 #include <pwd.h>
40 #include <unistd.h> /* for R_OK */
41 #ifdef alliant
42 #include <a.out.h>            /* Alliant FX series magic number file */
43 #endif
44 
45 #ifndef NGROUPS
46 #define NGROUPS 255 /* Number of groups */
47 #endif
48 
49 /* current_mode controls the icon display in the display manager.
50    We need to change it so that we can get an icon in our
51    doubleclick dialog box even if the display manager is in
52    non-icon mode. */
53 
54 extern Icon_mode current_mode;
55 
56 /* The Filestatus structure is used to keep track of
57    elements of filestat that the user is capable of
58    changing through the doubleclick dialog box. */
59 
60 typedef struct filestatus {
61   u_short mode;
62   char filename[80];
63   char owner[16];
64   char group[16];
65 } Filestatus;
66 
67 /* applist is a linked list of nodes that keep track of information for
68    process started from the doubleclick requester. */
69 
70 typedef struct appnode {
71   AppProgram node;
72   struct appnode *next;
73 } AppNode;
74 
75 
76 /*  #define's for undo_func() */
77 
78 #define RESET 0
79 #define UNDO  1
80 
81 /* #define's for update_buttons() */
82 
83 #define INIT 	0
84 #define UNDO    1
85 #define UPDATE  2
86 #define TEMP    3
87 
88 /* Translation table for text widgets */
89 
90 static char textWidgetTranslations [] = "#override\n\
91     <Key>Return : no-op(RingBell)\n\
92     <Key>Up : no-op()\n\
93     <Key>Down : no-op()\n\
94     <Key>space : no-op(RingBell)\n\
95     <Btn1Motion> : no-op()\n\
96     <Btn2Down> : no-op()\n\
97     <Btn3Down> : no-op()\n\
98     <Btn3Motion> : no-op()\n\
99     <Btn3Up> : no-op()\n\
100     <Btn1Up> : no-op()";  /* If we can't have a mac, then we can't have
101 			     any sort of drag selection at all.  It just
102 			     confuses our users. */
103 
104 XtTranslations textWidgettranslations;
105 
106 XawTextSelectType no_extended_select [] = {XawselectPosition,XawselectNull};
107 
108 /* Define permission bits */
109 
110 #define IREAD  0400
111 #define IWRITE 0200
112 #define IEXEC  0100
113 #define GREAD  0040
114 #define GWRITE 0020
115 #define GEXEC  0010
116 #define AREAD  0004
117 #define AWRITE 0002
118 #define AEXEC  0001
119 
120 /* Button indices */
121 
122 #define FIRSTBUTTON 0
123 #define LASTBUTTON  11
124 
125 typedef enum {
126   rown = 0, rgrp, roth, wown, wgrp, woth, xown, xgrp, xoth,
127   uid_but, gid_but, stky_but
128 } Buttons;
129 
130 struct buttontype {
131   u_short bitmask;
132   Widget  widget;
133   int     state;
134 };
135 
136 /* SetButton (button_enum) -- sets the bitmap imagery for the widget
137    corresponding to the enum index b, according to the bit in filestat.st_mode
138    defined in button[]. */
139 
140 #define SetButton(b) \
141 { \
142   XtVaSetValues( \
143       current->button[b].widget, \
144           XtNbitmap, (current->filestat.st_mode & current->button[b].bitmask) ? tick : emptytick, \
145 	  NULL ) ; \
146   current->button[b].state = (current->filestat.st_mode & current->button[b].bitmask); \
147 }
148 
149 
150 typedef struct fileinfo {
151   /* Used for callbacks */
152   int mode;
153 
154   /* Data about instance */
155   struct stat filestat;
156   AppNode *applist;
157   Filestatus laststat;
158   Filestatus oldstat;
159   char *filedate;          /* 26 */
160   char *filesize;          /* 10 */
161   XdtmList *xdtmlist_element;
162   char *edit_filename;     /* 255 */
163   char *edit_owner;        /* 255 */
164   char *edit_group;        /* 255 */
165   char *dc_fullname;       /* 255 */
166   char *dc_filename;       /* 255 */
167   char *dc_path;           /* 255 */
168   char *eb_input;          /* 255 */
169   char *eb_output;         /* 255 */
170   char *eb_error;          /* 255 */
171   int file_editable;       /* FALSE */
172   int file_edited;         /* FALSE */
173 
174   /* Widgets */
175   Widget fileInfoDialog;
176   Widget form;
177   Widget form1;
178   Widget form1a;
179   Widget form1b;
180   Widget form1c;
181   Widget form2;
182   Widget form2a;
183   Widget form2a1;
184   Widget form2a2;
185   Widget form2a3;
186   Widget form2a4;
187   Widget form2a5;
188   Widget form2a6;
189   Widget form2b;
190   Widget form3;
191 
192 
193   /* form 1a widgets */
194 
195   Widget form1a_label_icon;
196   Widget form1a_text_filename;
197   Widget form1a_text_filename_src;
198 
199   /* form 1b widgets */
200 
201   Widget form1b_label_date;
202   Widget form1b_label_size;
203   Widget form1b_label_datelabel;
204   Widget form1b_label_sizelabel;
205 
206   /* form 1c widgets */
207 
208   Widget form1c_label_owner;
209   Widget form1c_text_owner;
210   Widget form1c_text_owner_src;
211   Widget form1c_label_group;
212   Widget form1c_text_group;
213   Widget form1c_text_group_src;
214 
215   /* form2a widgets */
216 
217   Widget form2a_label_permissions;
218 
219   Widget form2a1_label_blank;
220   Widget form2a1_label_owner;
221   Widget form2a1_label_group;
222   Widget form2a1_label_other;
223 
224   Widget form2a2_label_read;
225   Widget form2a2_button_rown;
226   Widget form2a2_button_rgrp;
227   Widget form2a2_button_roth;
228 
229   Widget form2a3_label_write;
230   Widget form2a3_button_wown;
231   Widget form2a3_button_wgrp;
232   Widget form2a3_button_woth;
233 
234   Widget form2a4_label_exec;
235   Widget form2a4_button_xown;
236   Widget form2a4_button_xgrp;
237   Widget form2a4_button_xoth;
238 
239   Widget form2a5_label_blank;
240   Widget form2a5_label_setuid;
241   Widget form2a5_label_setgid;
242   Widget form2a5_label_sticky;
243 
244   Widget form2a6_label_blank;
245   Widget form2a6_button_setuid;
246   Widget form2a6_button_setgid;
247   Widget form2a6_button_sticky;
248 
249   /* form 2b widgets */
250 
251   Widget form2b_command_update;
252   Widget form2b_command_undo;
253   Widget form2b_command_reset;
254 
255   /* form3 command widgets */
256 
257   Widget form3_command_done;
258   Widget form3_command_view;
259   Widget form3_command_edit;
260   Widget form3_command_execwin;
261   Widget form3_command_execback;
262   Widget form3_command_help;
263 
264   /* Execute in background popup */
265 
266   Widget eb_popup;
267   Widget ebform;
268   Widget ebform1;
269   Widget ebform2;
270   Widget eblabeltitle;
271   Widget eblabelsubtitle;
272   Widget eblabelinput;
273   Widget eblabeloutput;
274   Widget eblabelerror;
275   Widget ebtextinput;
276   Widget ebtextoutput;
277   Widget ebtexterror;
278   Widget ebcommandcancel;
279   Widget ebcommandok;
280 
281   /* Verify Quit Popup */
282 
283   Widget verify_popup;
284   Widget verify_form;
285   Widget verify_label;
286   Widget verify_yes;
287   Widget verify_no;
288   Widget verify_cancel;
289 
290   struct buttontype button[LASTBUTTON+1];
291 } Fileinfo;
292 
293 typedef struct {
294   Fileinfo *fileinfo;
295   int mode;
296   Buttons select;
297 } InfoButtons;
298 
299 typedef struct fileinfoelement {
300   Fileinfo *fileinfo;
301   struct fileinfoelement *next;
302 } Fileinfoelement;
303 
304 Fileinfoelement *Fileinfolist;
305 
306 Widget toplevel;
307 
308 /* external and forward functions definitions */
309 #if NeedFunctionPrototypes
310   void cancel_func(Widget, XtPointer, XtPointer);
311   private AppProgram *compute_appnode(String, Fileinfo*);
312   void dcbutton_toggled(Widget, InfoButtons *, XtPointer);
313   void destroy_doubleclick_dialog(Widget, Fileinfo *, XtPointer);
314   extern Boolean directoryManagerNewDirectory(String);
315   extern void displayfile(String, String, String, XtGrabKind);
316   extern void editfile(String);
317   void execback_popdown(Widget, InfoButtons *, XtPointer);
318   void execback_realize(Widget, Fileinfo *, XtPointer);
319   public int execute (String, String, String, Boolean, AppProgram *);
320   void execwin_func(Widget, Fileinfo *, XtPointer);
321   void free_info(Widget, InfoButtons *, XtPointer);
322   extern Boolean getIconType(String, String, XdtmList *);
323   int group_number(char *);
324   void help_func(Widget, XtPointer, XtPointer);
325   public void ioerr_dialog(int);
326   private void load_text(Widget, char *);
327   public void popup_verify_app(AppProgram *);
328   public void realize_dialog(Widget, Widget, XtGrabKind, XtEventHandler, XtPointer);
329   public void run_app(AppProgram *, char *, char *, char *);
330   extern void setCursor(Cursor);
331   private void set_icon(Fileinfo*);
332   private void set_size_date(Fileinfo*);
333   void text_callback(Widget, Fileinfo *, XtPointer);
334   void verify_callback(Widget, Fileinfo *, XtPointer);
335   void undo_func(Widget, InfoButtons*, XtPointer);
336   private void update_buttons(int, Fileinfo*);
337   void update_func(Widget, Fileinfo *, XtPointer);
338   int user_is_member(gid_t);
339   void view_func(Widget, Fileinfo *, XtPointer);
340 #else
341   void cancel_func();
342   private AppProgram *compute_appnode();
343   void dcbutton_toggled();
344   void destroy_doubleclick_dialog();
345   extern Boolean directoryManagerNewDirectory();
346   extern void displayfile();
347   extern void editfile();
348   void execback_popdown();
349   void execback_realize();
350   public int execute ();
351   void execwin_func();
352   void free_info();
353   extern Boolean getIconType();
354   int group_number();
355   void help_func();
356   public void ioerr_dialog();
357   private void load_text();
358   public void popup_verify_app();
359   public void realize_dialog();
360   public void run_app();
361   extern void setCursor();
362   private void set_icon();
363   private void set_size_date();
364   void text_callback();
365   void verify_callback();
366   void undo_func();
367   private void update_buttons();
368   void update_func();
369   int user_is_member();
370   void view_func();
371 #endif
372 
373 /*****************************************************************************
374  *                          init_doubleclick_dialog                          *
375  *****************************************************************************/
init_doubleclick(top)376 public void init_doubleclick(top)
377 Widget top;
378 {
379   /* Not much to do here now.. just make sure we've got the top Widget ready
380    * for later;
381    */
382   toplevel = top;
383   Fileinfolist = NULL;
384 }
385 
386 /*****************************************************************************
387  *                               create_doubleclick                          *
388  *****************************************************************************/
create_doubleclick()389 public Fileinfo *create_doubleclick()
390 {
391   Fileinfo *current;
392   InfoButtons *infobutton;
393 
394   static String permLabel = "Permissions";
395   static String readLabel = "Read";
396   static String writeLabel = "Write";
397   static String execLabel = "Execute";
398   static String ownerLabel = "Owner";
399   static String groupLabel = "Group";
400   static String otherLabel = "Other";
401 
402   /* OK lets create a new Fileinfo */
403   if (Fileinfolist == NULL) {
404     /* List is empty */
405     Fileinfolist = (Fileinfoelement*) XtMalloc(sizeof(Fileinfoelement));
406     current = Fileinfolist->fileinfo = (Fileinfo*) XtMalloc(sizeof(Fileinfo));
407     Fileinfolist->next = NULL;
408   } else {
409     /* Find end of list */
410     Fileinfoelement *p = Fileinfolist;
411     while (p->next != NULL)
412       p = p->next;
413     p->next = (Fileinfoelement*) XtMalloc(sizeof(Fileinfoelement));
414     current = p->next->fileinfo = (Fileinfo*) XtMalloc(sizeof(Fileinfo));
415     p->next->next = NULL;
416   }
417 
418   /* Initialise Fileinfo structure */
419   current->filedate = (char*) XtMalloc(sizeof(char)*26);
420   current->filesize = (char*) XtMalloc(sizeof(char)*10);
421   current->edit_filename = (char*) XtMalloc(sizeof(char)*255);
422   current->edit_owner = (char*) XtMalloc(sizeof(char)*255);
423   current->edit_group = (char*) XtMalloc(sizeof(char)*255);
424   current->dc_fullname = (char*) XtMalloc(sizeof(char)*255);
425   current->dc_filename = (char*) XtMalloc(sizeof(char)*255);
426   current->dc_path = (char*) XtMalloc(sizeof(char)*255);
427   current->eb_input = (char*) XtMalloc(sizeof(char)*255);
428   current->eb_output = (char*) XtMalloc(sizeof(char)*255);
429   current->eb_error = (char*) XtMalloc(sizeof(char)*255);
430   current->file_editable = FALSE;
431   current->file_edited = FALSE;
432   current->xdtmlist_element = (XdtmList*) XtMalloc(sizeof(XdtmList));
433 
434   /* Purify complains about uninitialized memory read, so initialize... */
435   current->filedate[0] = 0;
436   current->filesize[0] = 0;
437   current->edit_filename[0] = 0;
438   current->edit_owner[0] = 0;
439   current->edit_group[0] = 0;
440   current->dc_fullname[0] = 0;
441   current->xdtmlist_element->string = NULL;
442   current->xdtmlist_element->icon = DUMMY;
443   current->xdtmlist_element->user_data = NULL;
444 
445   textWidgettranslations = XtParseTranslationTable(textWidgetTranslations);
446 
447   /* Create main doubleclick pop-up shell widget */
448 
449   current->fileInfoDialog =
450     XtVaCreatePopupShell(
451         "fileInfoDialog",
452 	transientShellWidgetClass,
453 	toplevel,
454 	    NULL ) ;
455 
456   /* Create main form widget for popup */
457 
458   current->form =
459     XtVaCreateManagedWidget(
460         "form",
461 	xedwFormWidgetClass,
462 	current->fileInfoDialog,
463 	    NULL ) ;
464 
465   /* Form 1 */
466 
467   current->form1 =
468     XtVaCreateManagedWidget(
469         "form1",
470 	xedwFormWidgetClass,
471 	current->form,
472 	    XtNborderWidth, 1,
473 	    XtNfullWidth, True,
474 	    XtNresizable, True,
475 	    NULL ) ;
476 
477   /* Form 1a */
478 
479   current->form1a =
480     XtVaCreateManagedWidget(
481         "form1a",
482 	xedwFormWidgetClass,
483 	current->form1,
484 	    XtNfullHeight, True,
485 	    XtNfullWidth, False,
486 	    XtNborderWidth, 0,
487 	    XtNresizable, True,
488 	    NULL ) ;
489 
490   /** Widgets for Form 1a **/
491 
492   current->form1a_label_icon =
493     XtVaCreateManagedWidget(
494         "form1a_label_icon",
495 	labelWidgetClass,
496 	current->form1a,
497 	    XtNborderWidth, 0,
498 	    NULL ) ;
499 
500   current->form1a_text_filename =
501     XtVaCreateManagedWidget(
502         "form1a_text_filename",
503 	asciiTextWidgetClass,
504 	current->form1a,
505 	    XtNborderWidth, 1,
506 	    XtNfromVert, current->form1a_label_icon,
507 	    XtNstring, current->edit_filename,
508 	    XtNeditType, XawtextEdit,
509 	    XtNselectTypes, no_extended_select,
510 	    XtNlength, 255,
511 	    XtNuseStringInPlace, True,
512 	    NULL ) ;
513 
514   XtVaGetValues(
515       current->form1a_text_filename,
516           XtNtextSource, &(current->form1a_text_filename_src),
517 	  NULL ) ;
518 
519   XtAddCallback(current->form1a_text_filename_src, XtNcallback,
520 		(XtCallbackProc)text_callback, (XtPointer)current);
521   XtOverrideTranslations(current->form1a_text_filename,
522 			 textWidgettranslations);
523 
524   /* Form 1b */
525 
526   current->form1b =
527     XtVaCreateManagedWidget(
528         "form1b",
529 	xedwFormWidgetClass,
530 	current->form1,
531 	    XtNfullHeight, True,
532 	    XtNborderWidth, 0,
533 	    XtNfromHoriz, current->form1a,
534 	    XtNresizable, True,
535 	    NULL ) ;
536 
537   /** Widgets for Form 1b **/
538 
539   current->form1b_label_sizelabel =
540     XtVaCreateManagedWidget(
541         "form1b_label_sizelabel",
542 	labelWidgetClass,
543 	current->form1b,
544 	    XtNlabel, "File Size: ",
545 	    XtNborderWidth, 0,
546 	    NULL ) ;
547 
548   current->form1b_label_size =
549     XtVaCreateManagedWidget(
550         "form1b_label_size",
551 	labelWidgetClass,
552 	current->form1b,
553 	    XtNlabel, current->filesize,
554 	    XtNborderWidth, 0,
555 	    XtNfromHoriz, current->form1b_label_sizelabel,
556 	    XtNjustify, XtJustifyLeft,
557 	    XtNinternalWidth, 0,
558 	    XtNresizable, True,
559 	    NULL ) ;
560 
561   current->form1b_label_datelabel =
562     XtVaCreateManagedWidget(
563         "form1b_label_datelabel",
564 	labelWidgetClass,
565 	current->form1b,
566 	    XtNlabel, "File Date: ",
567 	    XtNborderWidth, 0,
568 	    XtNfromVert, current->form1b_label_sizelabel,
569 	    NULL ) ;
570 
571   current->form1b_label_date =
572     XtVaCreateManagedWidget(
573         "form1b_label_date",
574 	labelWidgetClass,
575 	current->form1b,
576 	    XtNlabel, current->filedate,
577 	    XtNborderWidth, 0,
578 	    XtNfromVert, current->form1b_label_sizelabel,
579 	    XtNfromHoriz, current->form1b_label_datelabel,
580 	    XtNjustify, XtJustifyLeft,
581 	    XtNinternalWidth, 0,
582 	    NULL ) ;
583 
584   /* Form 1c */
585 
586   current->form1c =
587     XtVaCreateManagedWidget(
588         "form1b",
589 	xedwFormWidgetClass,
590 	current->form1,
591 	    XtNfullHeight, True,
592 	    XtNborderWidth, 0,
593 	    XtNfromHoriz, current->form1b,
594 	    XtNresizable, True,
595 	    NULL ) ;
596 
597   /** Widgets for Form 1c **/
598 
599   current->form1c_label_owner =
600     XtVaCreateManagedWidget(
601         "form1c_label_owner",
602 	labelWidgetClass,
603 	current->form1c,
604 	    XtNborderWidth, 0,
605 	    XtNlabel, "Owner:",
606 	    XtNjustify, XtJustifyRight,
607 	    NULL ) ;
608 
609   current->form1c_text_owner =
610     XtVaCreateManagedWidget(
611         "form1c_text_owner",
612 	asciiTextWidgetClass,
613 	current->form1c,
614 	    XtNborderWidth, 1,
615 	    XtNfromHoriz, current->form1c_label_owner,
616 	    XtNstring, current->edit_owner,
617 	    XtNeditType, XawtextEdit,
618 	    XtNlength, 255,
619 	    XtNuseStringInPlace, True,
620 	    XtNselectTypes, no_extended_select,
621 	    NULL ) ;
622 
623   XtVaGetValues(
624       current->form1c_text_owner,
625           XtNtextSource, &(current->form1c_text_owner_src),
626 	  NULL ) ;
627 
628   XtAddCallback(current->form1c_text_owner_src, XtNcallback,
629 		(XtCallbackProc)text_callback, (XtPointer)current);
630   XtOverrideTranslations(current->form1c_text_owner, textWidgettranslations);
631 
632   current->form1c_label_group =
633     XtVaCreateManagedWidget(
634         "form1c_label_group",
635 	labelWidgetClass,
636 	current->form1c,
637 	    XtNborderWidth, 0,
638 	    XtNfromVert, current->form1c_label_owner,
639 	    XtNlabel, "Group:",
640 	    XtNjustify, XtJustifyRight,
641 	    NULL ) ;
642 
643   current->form1c_text_group =
644     XtVaCreateManagedWidget(
645         "form1c_text_group",
646 	asciiTextWidgetClass,
647         current->form1c,
648 	    XtNborderWidth, 1,
649 	    XtNfromHoriz, current->form1c_label_group,
650 	    XtNfromVert, current->form1c_text_owner,
651 	    XtNselectTypes, no_extended_select,
652 	    XtNstring, current->edit_group,
653 	    XtNeditType, XawtextEdit,
654 	    XtNlength, 255,
655 	    XtNuseStringInPlace, True,
656 	    NULL ) ;
657 
658   XtVaGetValues(
659       current->form1c_text_group,
660           XtNtextSource, &(current->form1c_text_group_src),
661 	  NULL ) ;
662 
663   XtAddCallback(current->form1c_text_group_src, XtNcallback,
664 		(XtCallbackProc)text_callback, (XtPointer)current);
665   XtOverrideTranslations(current->form1c_text_group, textWidgettranslations);
666 
667   /* Form 2 */
668 
669   current->form2 =
670     XtVaCreateManagedWidget(
671         "form2",
672 	xedwFormWidgetClass,
673 	current->form,
674 	    XtNfullWidth, True,
675 	    XtNfromVert, current->form1,
676 	    XtNborderWidth, 0,
677 	    NULL ) ;
678 
679   /** Widgets for Form 2 **/
680 
681   current->form2a =
682     XtVaCreateManagedWidget(
683         "form2a",
684 	xedwFormWidgetClass,
685 	current->form2,
686 	    XtNfullHeight, True,
687 	    XtNborderWidth, 1,
688 	    NULL ) ;
689 
690   /** Widgets for Form 2a */
691 
692   current->form2a_label_permissions =
693     XtVaCreateManagedWidget(
694         "form2a_label_permissions",
695 	labelWidgetClass,
696 	current->form2a,
697 	    XtNlabel, permLabel,
698 	    XtNborderWidth, 0,
699 	    XtNfullWidth, True,
700 	    NULL );
701 
702   /* Form 2a1 */
703 
704   current->form2a1 =
705     XtVaCreateManagedWidget(
706         "form2a1",
707 	xedwFormWidgetClass,
708 	current->form2a,
709 	    XtNborderWidth, 0,
710 	    XtNfromVert, current->form2a_label_permissions,
711 	    NULL ) ;
712 
713   /** Widgets for Form 2a1 **/
714 
715   current->form2a1_label_blank =
716     XtVaCreateManagedWidget(
717         "form2a1_label_blank",
718 	labelWidgetClass,
719 	current->form2a1,
720 	    XtNlabel, " ", /* Empty label to hold space in form */
721 	    XtNborderWidth, 0,
722 	    NULL ) ;
723 
724   current->form2a1_label_owner =
725     XtVaCreateManagedWidget(
726         "form2a1_label_owner",
727 	labelWidgetClass,
728 	current->form2a1,
729 	    XtNlabel, ownerLabel,
730 	    XtNfromVert, current->form2a1_label_blank,
731 	    XtNborderWidth, 0,
732 	    NULL ) ;
733 
734   current->form2a1_label_group =
735     XtVaCreateManagedWidget(
736         "form2a1_label_owner",
737 	labelWidgetClass,
738 	current->form2a1,
739 	    XtNlabel, groupLabel,
740 	    XtNfromVert, current->form2a1_label_owner,
741 	    XtNborderWidth, 0,
742 	    NULL ) ;
743 
744   current->form2a1_label_other =
745     XtVaCreateManagedWidget(
746         "form2a1_label_other",
747 	labelWidgetClass,
748 	current->form2a1,
749 	    XtNlabel, otherLabel,
750 	    XtNborderWidth, 0,
751 	    XtNfromVert, current->form2a1_label_group,
752 	    NULL ) ;
753 
754   /* Form 2a2 */
755 
756   current->form2a2 =
757     XtVaCreateManagedWidget(
758         "form2a2",
759 	xedwFormWidgetClass,
760 	current->form2a,
761             XtNfromHoriz, current->form2a1,
762 	    XtNfromVert, current->form2a_label_permissions,
763 	    XtNborderWidth, 0,
764 	    NULL ) ;
765 
766   /** Widgets for Form 2a2 **/
767 
768   current->form2a2_label_read =
769     XtVaCreateManagedWidget(
770         "form2a2_label_read",
771 	labelWidgetClass,
772 	current->form2a2,
773 	    XtNlabel, readLabel,
774 	    XtNborderWidth, 0,
775 	    XtNjustify, XtJustifyLeft,
776 	    XtNinternalWidth, 0,
777 	    NULL ) ;
778 
779   current->form2a2_button_rown =
780     XtVaCreateManagedWidget(
781         "form2a2_button_rown",
782         commandWidgetClass,
783 	current->form2a2,
784 	    XtNfromVert, current->form2a2_label_read,
785 	    NULL ) ;
786 
787   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
788   infobutton->fileinfo = current;
789   infobutton->select = rown;
790   XtAddCallback(current->form2a2_button_rown, XtNcallback,
791 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
792   XtAddCallback(current->form2a2_button_rown, XtNdestroyCallback,
793 		(XtCallbackProc)free_info, (XtPointer)infobutton);
794 
795   current->form2a2_button_rgrp =
796     XtVaCreateManagedWidget(
797         "form2a2_button_rgrp",
798 	commandWidgetClass,
799 	current->form2a2,
800 	    XtNfromVert, current->form2a2_button_rown,
801 	    NULL ) ;
802 
803   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
804   infobutton->fileinfo = current;
805   infobutton->select = rgrp;
806   XtAddCallback(current->form2a2_button_rgrp, XtNcallback,
807 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
808   XtAddCallback(current->form2a2_button_rgrp, XtNdestroyCallback,
809 		(XtCallbackProc)free_info, (XtPointer)infobutton);
810 
811   current->form2a2_button_roth =
812     XtVaCreateManagedWidget(
813         "form2a2_button_roth",
814 	commandWidgetClass,
815 	current->form2a2,
816 	    XtNfromVert, current->form2a2_button_rgrp,
817 	    NULL ) ;
818 
819   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
820   infobutton->fileinfo = current;
821   infobutton->select = roth;
822   XtAddCallback(current->form2a2_button_roth, XtNcallback,
823 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
824   XtAddCallback(current->form2a2_button_roth, XtNdestroyCallback,
825 		(XtCallbackProc)free_info, (XtPointer)infobutton);
826 
827   /* Form 2a3 */
828 
829   current->form2a3 =
830     XtVaCreateManagedWidget(
831         "form2a3",
832 	xedwFormWidgetClass,
833 	current->form2a,
834 	    XtNfromHoriz, current->form2a2,
835 	    XtNfromVert, current->form2a_label_permissions,
836 	    XtNborderWidth, 0,
837 	    NULL ) ;
838 
839   /** Widgets for Form 2a3 **/
840 
841   current->form2a3_label_write =
842     XtVaCreateManagedWidget(
843         "form2a3_label_write",
844 	labelWidgetClass,
845 	current->form2a3,
846 	    XtNlabel, writeLabel,
847 	    XtNjustify, XtJustifyLeft,
848 	    XtNborderWidth, 0,
849 	    XtNinternalWidth, 0,
850 	    NULL ) ;
851 
852   current->form2a3_button_wown =
853     XtVaCreateManagedWidget(
854         "form2a3_button_wown",
855 	commandWidgetClass,
856 	current->form2a3,
857 	    XtNfromVert, current->form2a3_label_write,
858 	    NULL ) ;
859 
860   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
861   infobutton->fileinfo = current;
862   infobutton->select = wown;
863   XtAddCallback(current->form2a3_button_wown, XtNcallback,
864 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
865   XtAddCallback(current->form2a3_button_wown, XtNdestroyCallback,
866 		(XtCallbackProc)free_info, (XtPointer)infobutton);
867 
868   current->form2a3_button_wgrp =
869     XtVaCreateManagedWidget(
870         "form2a3_button_wgrp",
871 	commandWidgetClass,
872 	current->form2a3,
873 	    XtNfromVert, current->form2a3_button_wown,
874 	    NULL ) ;
875 
876   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
877   infobutton->fileinfo = current;
878   infobutton->select = wgrp;
879   XtAddCallback(current->form2a3_button_wgrp, XtNcallback,
880 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
881   XtAddCallback(current->form2a3_button_wgrp, XtNdestroyCallback,
882 		(XtCallbackProc)free_info, (XtPointer)infobutton);
883 
884   current->form2a3_button_woth =
885     XtVaCreateManagedWidget(
886         "form2a3_button_woth",
887 	commandWidgetClass,
888 	current->form2a3,
889 	    XtNfromVert, current->form2a3_button_wgrp,
890 	    NULL ) ;
891 
892   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
893   infobutton->fileinfo = current;
894   infobutton->select = woth;
895   XtAddCallback(current->form2a3_button_woth, XtNcallback,
896 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
897   XtAddCallback(current->form2a3_button_woth, XtNdestroyCallback,
898 		(XtCallbackProc)free_info, (XtPointer)infobutton);
899 
900   /* Form 2a4 */
901 
902   current->form2a4 =
903     XtVaCreateManagedWidget(
904         "form2a4",
905 	xedwFormWidgetClass,
906 	current->form2a,
907 	    XtNfromHoriz, current->form2a3,
908 	    XtNfromVert, current->form2a_label_permissions,
909 	    XtNborderWidth, 0,
910 	    NULL ) ;
911 
912   /** Widgets for Form 2a4 **/
913 
914   current->form2a4_label_exec =
915     XtVaCreateManagedWidget(
916         "form2a4_label_exec",
917 	labelWidgetClass,
918 	current->form2a4,
919 	    XtNlabel, execLabel,
920 	    XtNborderWidth, 0,
921 	    XtNjustify, XtJustifyLeft,
922 	    XtNinternalWidth, 0,
923 	    NULL ) ;
924 
925   current->form2a4_button_xown =
926     XtVaCreateManagedWidget(
927         "form2a4_button_xown",
928 	commandWidgetClass,
929 	current->form2a4,
930 	    XtNfromVert, current->form2a4_label_exec,
931 	    NULL ) ;
932 
933   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
934   infobutton->fileinfo = current;
935   infobutton->select = xown;
936   XtAddCallback(current->form2a4_button_xown, XtNcallback,
937 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
938   XtAddCallback(current->form2a4_button_xown, XtNdestroyCallback,
939 		(XtCallbackProc)free_info, (XtPointer)infobutton);
940 
941   current->form2a4_button_xgrp =
942     XtVaCreateManagedWidget(
943         "form2a4_button_xgrp",
944 	commandWidgetClass,
945 	current->form2a4,
946             XtNfromVert, current->form2a4_button_xown,
947 	    NULL ) ;
948 
949   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
950   infobutton->fileinfo = current;
951   infobutton->select = xgrp;
952   XtAddCallback(current->form2a4_button_xgrp, XtNcallback,
953 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
954   XtAddCallback(current->form2a4_button_xgrp, XtNdestroyCallback,
955 		(XtCallbackProc)free_info, (XtPointer)infobutton);
956 
957   current->form2a4_button_xoth =
958     XtVaCreateManagedWidget(
959         "form2a4_button_xoth",
960 	commandWidgetClass,
961 	current->form2a4,
962 	    XtNfromVert, current->form2a4_button_xgrp,
963 	    NULL ) ;
964 
965   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
966   infobutton->fileinfo = current;
967   infobutton->select = xoth;
968   XtAddCallback(current->form2a4_button_xoth, XtNcallback,
969 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
970   XtAddCallback(current->form2a4_button_xoth, XtNdestroyCallback,
971 		(XtCallbackProc)free_info, (XtPointer)infobutton);
972 
973   /* Form 2a5 */
974 
975   current->form2a5 =
976     XtVaCreateManagedWidget(
977         "form2a5",
978 	xedwFormWidgetClass,
979 	current->form2a,
980 	    XtNfromHoriz, current->form2a4,
981 	    XtNfromVert, current->form2a_label_permissions,
982 	    XtNborderWidth, 0,
983 	    NULL ) ;
984 
985   /** Widgets for Form 2a5 **/
986 
987   current->form2a5_label_blank =
988     XtVaCreateManagedWidget(
989         "form2a5_label_blank",
990 	labelWidgetClass,
991 	current->form2a5,
992 	    XtNlabel," ", /* Empty label to hold space in form */
993 	    XtNborderWidth, 0,
994 	    NULL ) ;
995 
996   current->form2a5_label_setuid =
997     XtVaCreateManagedWidget(
998         "form2a5_label_setuid",
999 	labelWidgetClass,
1000 	current->form2a5,
1001 	    XtNlabel, "SetUID",
1002 	    XtNfromVert, current->form2a5_label_blank,
1003 	    XtNborderWidth, 0,
1004 	    NULL ) ;
1005 
1006   current->form2a5_label_setgid =
1007     XtVaCreateManagedWidget(
1008         "form2a5_label_setgid",
1009 	labelWidgetClass,
1010 	current->form2a5,
1011 	    XtNlabel, "SetGID",
1012 	    XtNfromVert, current->form2a5_label_setuid,
1013 	    XtNborderWidth, 0,
1014 	    NULL );
1015 
1016   current->form2a5_label_sticky =
1017     XtVaCreateManagedWidget(
1018         "form2a5_label_sticky",
1019 	labelWidgetClass,
1020 	current->form2a5,
1021 	    XtNlabel, "Sticky",
1022 	    XtNfromVert, current->form2a5_label_setgid,
1023 	    XtNborderWidth, 0,
1024 	    NULL );
1025 
1026   /* Form 2a6 */
1027 
1028   current->form2a6 =
1029     XtVaCreateManagedWidget(
1030         "form2a6",
1031         xedwFormWidgetClass,
1032 	current->form2a,
1033             XtNfromHoriz, current->form2a5,
1034 	    XtNfromVert, current->form2a_label_permissions,
1035 	    XtNborderWidth, 0,
1036 	    NULL ) ;
1037 
1038   /** Widgets for Form 2a6 **/
1039 
1040   current->form2a6_label_blank =
1041     XtVaCreateManagedWidget(
1042         "form2a6_label_blank",
1043 	labelWidgetClass,
1044 	current->form2a6,
1045 	    XtNlabel," ", /* Empty label to hold space in form */
1046 	    XtNborderWidth, 0,
1047 	    NULL ) ;
1048 
1049   current->form2a6_button_setuid =
1050     XtVaCreateManagedWidget(
1051         "form2a6_button_setuid",
1052 	commandWidgetClass,
1053 	current->form2a6,
1054 	    XtNfromVert, current->form2a6_label_blank,
1055 	    NULL ) ;
1056 
1057   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
1058   infobutton->fileinfo = current;
1059   infobutton->select = uid_but;
1060   XtAddCallback(current->form2a6_button_setuid, XtNcallback,
1061 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
1062   XtAddCallback(current->form2a6_button_setuid, XtNdestroyCallback,
1063 		(XtCallbackProc)free_info, (XtPointer)infobutton);
1064 
1065   current->form2a6_button_setgid =
1066     XtVaCreateManagedWidget(
1067         "form2a6_button_setgid",
1068 	commandWidgetClass,
1069 	current->form2a6,
1070 	    XtNfromVert, current->form2a6_button_setuid,
1071 	    NULL ) ;
1072 
1073   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
1074   infobutton->fileinfo = current;
1075   infobutton->select = gid_but;
1076   XtAddCallback(current->form2a6_button_setgid, XtNcallback,
1077 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
1078   XtAddCallback(current->form2a6_button_setgid, XtNdestroyCallback,
1079 		(XtCallbackProc)free_info, (XtPointer)infobutton);
1080 
1081   current->form2a6_button_sticky =
1082     XtVaCreateManagedWidget(
1083         "form2a6_button_sticky",
1084 	commandWidgetClass,
1085 	current->form2a6,
1086 	    XtNfromVert, current->form2a6_button_setgid,
1087 	    NULL ) ;
1088 
1089   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
1090   infobutton->fileinfo = current;
1091   infobutton->select = stky_but;
1092   XtAddCallback(current->form2a6_button_sticky, XtNcallback,
1093 		(XtCallbackProc)dcbutton_toggled, (XtPointer)infobutton);
1094   XtAddCallback(current->form2a6_button_sticky, XtNdestroyCallback,
1095 		(XtCallbackProc)free_info, (XtPointer)infobutton);
1096 
1097   /* Form 2b */
1098 
1099   current->form2b =
1100     XtVaCreateManagedWidget(
1101         "form2b",
1102 	xedwFormWidgetClass,
1103 	current->form2,
1104 	    XtNfullHeight, True,
1105 	    XtNfromHoriz, current->form2a,
1106 	    XtNborderWidth, 0,
1107 	    XtNheightLinked, current->form2a6,
1108 	    NULL ) ;
1109 
1110   /** Widgets for Form 2b **/
1111 
1112   current->form2b_command_update =
1113     XtVaCreateManagedWidget(
1114         "form2b_command_update",
1115 	commandWidgetClass,
1116 	current->form2b,
1117 	    XtNlabel, "Update",
1118 	    XtNfullWidth, True,
1119 	    NULL ) ;
1120 
1121   XtAddCallback(current->form2b_command_update, XtNcallback,
1122 		(XtCallbackProc)update_func, (XtPointer)current);
1123 
1124   current->form2b_command_undo =
1125     XtVaCreateManagedWidget(
1126         "form2b_command_undo",
1127 	commandWidgetClass,
1128 	current->form2b,
1129 	    XtNlabel, "Undo",
1130 	    XtNfromVert, current->form2b_command_update,
1131 	    XtNfullWidth, True,
1132 	    NULL ) ;
1133 
1134   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
1135   infobutton->fileinfo = current;
1136   infobutton->mode = UNDO;
1137   XtAddCallback(current->form2b_command_undo, XtNcallback,
1138 		(XtCallbackProc)undo_func, (XtPointer)infobutton);
1139   XtAddCallback(current->form2b_command_undo, XtNdestroyCallback,
1140 		(XtCallbackProc)free_info, (XtPointer)infobutton);
1141 
1142   current->form2b_command_reset =
1143     XtVaCreateManagedWidget(
1144         "form2b_command_reset",
1145 	commandWidgetClass,
1146 	current->form2b,
1147 	    XtNlabel, "Reset",
1148 	    XtNfromVert, current->form2b_command_undo,
1149 	    XtNfullWidth, True,
1150 	    NULL ) ;
1151 
1152   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
1153   infobutton->fileinfo = current;
1154   infobutton->mode = RESET;
1155   XtAddCallback(current->form2b_command_reset, XtNcallback,
1156 		(XtCallbackProc)undo_func, (XtPointer)infobutton);
1157   XtAddCallback(current->form2b_command_reset, XtNdestroyCallback,
1158 		(XtCallbackProc)free_info, (XtPointer)infobutton);
1159 
1160   /* Form 3 */
1161 
1162   current->form3 =
1163     XtVaCreateManagedWidget(
1164         "form3",
1165         xedwFormWidgetClass,
1166 	current->form,
1167 	    XtNfullWidth, True,
1168 	    XtNborderWidth, 1,
1169 	    XtNfromVert, current->form2,
1170 	    NULL ) ;
1171 
1172   /** Widgets for Form 3 **/
1173 
1174   current->form3_command_done =
1175     XtVaCreateManagedWidget(
1176         "form3_command_done",
1177 	commandWidgetClass,
1178 	current->form3,
1179 	    XtNlabel, "DONE",
1180 	    NULL ) ;
1181 
1182   XtAddCallback(current->form3_command_done, XtNcallback,
1183 		(XtCallbackProc)destroy_doubleclick_dialog,
1184 		(XtPointer)current);
1185 
1186   current->form3_command_view =
1187     XtVaCreateManagedWidget(
1188         "form3_command_view",
1189 	commandWidgetClass,
1190 	current->form3,
1191 	    XtNlabel, " View ",
1192 	    XtNfromHoriz, current->form3_command_done,
1193 	    NULL ) ;
1194 
1195   XtAddCallback(current->form3_command_view, XtNcallback,
1196 		(XtCallbackProc)view_func, (XtPointer)current);
1197 
1198   current->form3_command_edit =
1199     XtVaCreateManagedWidget(
1200         "form3_command_edit",
1201 	commandWidgetClass,
1202 	current->form3,
1203 	    XtNlabel, " Edit ",
1204 	    XtNfromHoriz, current->form3_command_view,
1205 	    NULL ) ;
1206 
1207   XtAddCallback(current->form3_command_edit, XtNcallback,
1208 		(XtCallbackProc)view_func, (XtPointer)current);
1209 
1210   current->form3_command_execwin =
1211     XtVaCreateManagedWidget(
1212         "form3_command_execwin",
1213 	commandWidgetClass,
1214 	current->form3,
1215 	    XtNlabel, "Execute in Window",
1216 	    XtNfromHoriz, current->form3_command_edit,
1217 	    NULL ) ;
1218 
1219   XtAddCallback(current->form3_command_execwin, XtNcallback,
1220 		(XtCallbackProc)execwin_func, (XtPointer)current);
1221 
1222   current->form3_command_execback =
1223     XtVaCreateManagedWidget(
1224         "form3_command_execback",
1225 	commandWidgetClass,
1226 	current->form3,
1227 	    XtNlabel, "Execute in Background",
1228 	    XtNfromHoriz, current->form3_command_execwin,
1229 	    NULL ) ;
1230 
1231   XtAddCallback(current->form3_command_execback, XtNcallback,
1232 		(XtCallbackProc)execback_realize, (XtPointer)current);
1233 
1234   current->form3_command_help =
1235     XtVaCreateManagedWidget(
1236         "form3_command_help",
1237 	commandWidgetClass,
1238 	current->form3,
1239 	    XtNlabel, "Help",
1240 	    XtNfromHoriz, current->form3_command_execback,
1241 	    NULL ) ;
1242 
1243   XtAddCallback(current->form3_command_help, XtNcallback,
1244 		(XtCallbackProc)help_func, (XtPointer)current);
1245 
1246   /* Execute in background popup initialization */
1247 
1248   current->eb_popup =
1249     XtVaCreatePopupShell(
1250         "eb_popup",
1251 	transientShellWidgetClass,
1252 	current->fileInfoDialog,
1253 	    NULL ) ;
1254 
1255   current->ebform =
1256     XtVaCreateManagedWidget(
1257         "ebform",
1258 	xedwFormWidgetClass,
1259 	current->eb_popup,
1260 	    XtNborderWidth, 1,
1261 	    NULL ) ;
1262 
1263   current->eblabeltitle =
1264     XtVaCreateManagedWidget(
1265         "eblabeltitle",
1266 	labelWidgetClass,
1267 	current->ebform,
1268 	    XtNlabel, "Execute in Background",
1269 	    XtNjustify, XtJustifyCenter,
1270 	    XtNborderWidth, 1,
1271 	    XtNfullWidth, True,
1272 	    NULL ) ;
1273 
1274   current->eblabelsubtitle =
1275     XtVaCreateManagedWidget(
1276         "eblabelsubtitle",
1277 	labelWidgetClass,
1278 	current->ebform,
1279 	    XtNlabel, "Set I/O Redirection",
1280 	    XtNfromVert, current->eblabeltitle,
1281 	    XtNjustify, XtJustifyCenter,
1282 	    XtNborderWidth, 0,
1283 	    XtNfullWidth, True,
1284 	    NULL ) ;
1285 
1286   current->ebform1 =
1287     XtVaCreateManagedWidget(
1288         "ebform1",
1289 	xedwFormWidgetClass,
1290 	current->ebform,
1291 	    XtNborderWidth, 0,
1292 	    XtNfromVert, current->eblabelsubtitle,
1293 	    NULL ) ;
1294 
1295   current->ebform2 =
1296     XtVaCreateManagedWidget(
1297         "ebform2",
1298 	xedwFormWidgetClass,
1299 	current->ebform,
1300 	    XtNborderWidth, 0,
1301 	    XtNfromHoriz, current->ebform1,
1302 	    XtNfromVert, current->eblabelsubtitle,
1303 	    XtNheightLinked, current->ebform1,
1304 	    NULL ) ;
1305 
1306   current->eblabelinput =
1307     XtVaCreateManagedWidget(
1308         "eblabelinput",
1309 	labelWidgetClass,
1310 	current->ebform1,
1311 	    XtNlabel, "Input:",
1312 	    XtNborderWidth, 0,
1313 	    XtNjustify, XtJustifyRight,
1314 	    XtNfullWidth, True,
1315 	    NULL ) ;
1316 
1317   strcpy(current->eb_input, "/dev/null");
1318   strcpy(current->eb_output, current->eb_input);
1319   strcpy(current->eb_error, current->eb_input);
1320 
1321   current->ebtextinput =
1322     XtVaCreateManagedWidget(
1323         "ebtextinput",
1324 	asciiTextWidgetClass,
1325 	current->ebform2,
1326             XtNstring, current->eb_input,
1327 	    XtNeditType, XawtextEdit,
1328 	    XtNlength, 255,
1329 	    XtNuseStringInPlace, True,
1330 	    NULL ) ;
1331 
1332   XtOverrideTranslations(current->ebtextinput, textWidgettranslations);
1333 
1334   current->eblabeloutput =
1335     XtVaCreateManagedWidget(
1336         "eblabeloutput",
1337 	labelWidgetClass,
1338 	current->ebform1,
1339 	    XtNlabel, "Output:",
1340 	    XtNfromVert, current->eblabelinput,
1341 	    XtNfullWidth, True,
1342 	    XtNjustify, XtJustifyRight,
1343 	    XtNborderWidth, 0,
1344 	    NULL ) ;
1345 
1346   current->ebtextoutput =
1347     XtVaCreateManagedWidget(
1348         "ebtextoutput",
1349 	asciiTextWidgetClass,
1350 	current->ebform2,
1351 	    XtNstring, current->eb_output,
1352 	    XtNeditType, XawtextEdit,
1353 	    XtNfromVert, current->ebtextinput,
1354 	    XtNlength, 255,
1355 	    XtNuseStringInPlace, True,
1356 	    NULL ) ;
1357 
1358   XtOverrideTranslations(current->ebtextoutput, textWidgettranslations);
1359 
1360   current->eblabelerror =
1361     XtVaCreateManagedWidget(
1362         "eblabelerror",
1363 	labelWidgetClass,
1364 	current->ebform1,
1365 	    XtNlabel, "Error:",
1366 	    XtNfromVert, current->eblabeloutput,
1367 	    XtNfullWidth, True,
1368 	    XtNjustify, XtJustifyRight,
1369 	    XtNborderWidth, 0,
1370 	    NULL ) ;
1371 
1372   current->ebtexterror =
1373     XtVaCreateManagedWidget(
1374         "ebtexterror",
1375 	asciiTextWidgetClass,
1376 	current->ebform2,
1377 	    XtNfromVert, current->ebtextoutput,
1378 	    XtNstring, current->eb_error,
1379 	    XtNeditType, XawtextEdit,
1380 	    XtNlength, 255,
1381 	    XtNuseStringInPlace, True,
1382 	    NULL ) ;
1383 
1384   XtOverrideTranslations(current->ebtexterror, textWidgettranslations);
1385 
1386   current->ebcommandok =
1387     XtVaCreateManagedWidget(
1388         "ebcommandok",
1389 	commandWidgetClass,
1390 	current->ebform,
1391             XtNfromVert, current->ebform2,
1392 	    XtNlabel, "OK",
1393 	    NULL ) ;
1394 
1395   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
1396   infobutton->fileinfo = current;
1397   infobutton->select = 1;
1398   XtAddCallback(current->ebcommandok, XtNcallback,
1399 		(XtCallbackProc)execback_popdown, (XtPointer)infobutton);
1400   XtAddCallback(current->ebcommandok, XtNdestroyCallback,
1401 		(XtCallbackProc)free_info, (XtPointer)infobutton);
1402 
1403   current->ebcommandcancel =
1404     XtVaCreateManagedWidget(
1405         "ebcommandcancel",
1406 	commandWidgetClass,
1407 	current->ebform,
1408 	    XtNfromVert, current->ebform1,
1409 	    XtNfromHoriz, current->ebcommandok,
1410 	    XtNlabel, "Cancel",
1411 	    NULL ) ;
1412 
1413   infobutton = (InfoButtons*) XtMalloc(sizeof(InfoButtons));
1414   infobutton->fileinfo = current;
1415   infobutton->select = 0;
1416   XtAddCallback(current->ebcommandcancel, XtNcallback,
1417 		(XtCallbackProc)execback_popdown, (XtPointer)infobutton);
1418   XtAddCallback(current->ebcommandcancel, XtNdestroyCallback,
1419 		(XtCallbackProc)free_info, (XtPointer)infobutton);
1420 
1421   /* Verify Quit PopUp */
1422 
1423   current->verify_popup =
1424     XtVaCreatePopupShell(
1425         "Verify Done",
1426 	transientShellWidgetClass,
1427         current->fileInfoDialog,
1428 	    NULL ) ;
1429 
1430   current->verify_form =
1431     XtVaCreateManagedWidget(
1432         "verify_form",
1433 	xedwFormWidgetClass,
1434 	current->verify_popup,
1435 	    XtNborderWidth, 1,
1436 	    NULL ) ;
1437 
1438   current->verify_label =
1439     XtVaCreateManagedWidget(
1440         "verify_label",
1441 	labelWidgetClass,
1442 	current->verify_form,
1443 	    XtNlabel, "Save changes?",
1444 	    XtNborderWidth, 0,
1445 	    NULL ) ;
1446 
1447   current->verify_yes =
1448     XtVaCreateManagedWidget(
1449         "verify_yes",
1450 	commandWidgetClass,
1451 	current->verify_form,
1452 	    XtNlabel, "Yes",
1453 	    XtNborderWidth, 1,
1454 	    XtNfromVert, current->verify_label,
1455 	    NULL ) ;
1456 
1457   XtAddCallback(current->verify_yes, XtNcallback,
1458 		(XtCallbackProc)verify_callback, (XtPointer)current);
1459 
1460   current->verify_no =
1461     XtVaCreateManagedWidget(
1462         "verify_no",
1463 	commandWidgetClass,
1464 	current->verify_form,
1465 	    XtNlabel, "No",
1466 	    XtNborderWidth, 1,
1467 	    XtNfromVert, current->verify_label,
1468 	    XtNfromHoriz, current->verify_yes,
1469 	    NULL ) ;
1470 
1471   XtAddCallback(current->verify_no, XtNcallback,
1472 		(XtCallbackProc)verify_callback, (XtPointer)current);
1473 
1474   current->verify_cancel =
1475     XtVaCreateManagedWidget(
1476         "verify_cancel",
1477 	commandWidgetClass,
1478 	current->verify_form,
1479 	    XtNlabel, "Cancel",
1480 	    XtNborderWidth, 1,
1481 	    XtNfromVert, current->verify_label,
1482 	    XtNfromHoriz, current->verify_no,
1483 	    NULL ) ;
1484 
1485   XtAddCallback(current->verify_cancel, XtNcallback,
1486 		(XtCallbackProc)verify_callback, (XtPointer)current);
1487 
1488   current->button[rown].bitmask = IREAD;
1489   current->button[rown].widget = current->form2a2_button_rown;
1490   current->button[rown].state = FALSE;
1491   current->button[rgrp].bitmask = GREAD;
1492   current->button[rgrp].widget = current->form2a2_button_rgrp;
1493   current->button[rgrp].state = FALSE;
1494   current->button[roth].bitmask = AREAD;
1495   current->button[roth].widget = current->form2a2_button_roth;
1496   current->button[roth].state = FALSE;
1497   current->button[wown].bitmask = IWRITE;
1498   current->button[wown].widget = current->form2a3_button_wown;
1499   current->button[wown].state = FALSE;
1500   current->button[wgrp].bitmask = GWRITE;
1501   current->button[wgrp].widget = current->form2a3_button_wgrp;
1502   current->button[wgrp].state = FALSE;
1503   current->button[woth].bitmask = AWRITE;
1504   current->button[woth].widget = current->form2a3_button_woth;
1505   current->button[woth].state = FALSE;
1506   current->button[xown].bitmask = IEXEC;
1507   current->button[xown].widget = current->form2a4_button_xown;
1508   current->button[xown].state = FALSE;
1509   current->button[xgrp].bitmask = GEXEC;
1510   current->button[xgrp].widget = current->form2a4_button_xgrp;
1511   current->button[xgrp].state = FALSE;
1512   current->button[xoth].bitmask = AEXEC;
1513   current->button[xoth].widget = current->form2a4_button_xoth;
1514   current->button[xoth].state = FALSE;
1515   current->button[uid_but].bitmask = S_ISUID;
1516   current->button[uid_but].widget = current->form2a6_button_setuid;
1517   current->button[uid_but].state = FALSE;
1518   current->button[gid_but].bitmask = S_ISGID;
1519   current->button[gid_but].widget = current->form2a6_button_setgid;
1520   current->button[gid_but].state = FALSE;
1521   current->button[stky_but].bitmask = S_ISVTX;
1522   current->button[stky_but].widget = current->form2a6_button_sticky;
1523   current->button[stky_but].state = FALSE;
1524 
1525   /* Initialize applist */
1526 
1527   current->applist = NULL;
1528 
1529   return(current);
1530 }
1531 
1532 /*****************************************************************************
1533  *                         WM_destroy_doubleclick_dialog                     *
1534  *****************************************************************************/
1535 #if NeedFunctionPrototypes
WM_destroy_doubleclick_dialog(Widget w,Fileinfo * current,XEvent * event,Boolean * dispatch)1536 private void WM_destroy_doubleclick_dialog(Widget w,
1537 					   Fileinfo *current,
1538 					   XEvent *event,
1539 					   Boolean *dispatch)
1540 #else
1541 private void WM_destroy_doubleclick_dialog(w, current, event, dispatch)
1542      Widget w;
1543      Fileinfo *current;
1544      XEvent *event;
1545      Boolean *dispatch;
1546 #endif
1547 {
1548     extern Atom protocols[2]; /* defined in dialogs.c */
1549 
1550     if ((event->xclient.message_type == protocols[1]) &&
1551 	(event->xclient.data.l[0] == protocols[0]))
1552     /* the widget got a kill signal */
1553     {
1554 	/* Directly call callback of Done button */
1555 	destroy_doubleclick_dialog(current->form3_command_done, current, NULL);
1556     }
1557 }
1558 
1559 /*****************************************************************************
1560  *                            doubleclick_dialog                             *
1561  *****************************************************************************/
doubleclick_dialog(filename,path)1562 public void doubleclick_dialog(filename, path)
1563 String filename, path;
1564 {
1565   Fileinfo *current;
1566 
1567   current = create_doubleclick();
1568 
1569   strcpy(current->dc_filename, filename);
1570   strcpy(current->dc_path, path);
1571   if (strcmp(current->dc_path, "/") != 0)
1572     strcat(current->dc_path, "/");
1573 
1574   strcpy(current->dc_fullname,current->dc_path);
1575   strcat(current->dc_fullname,filename);
1576 
1577   strcpy(current->edit_filename, filename);
1578 
1579   /* Load filename widget */
1580 
1581   XtVaSetValues(
1582       current->form1a_text_filename,
1583           XtNstring, current->edit_filename,
1584 	  NULL ) ;
1585 
1586   /* Stat our file for permission and owner/group information */
1587 
1588   if (stat(current->dc_fullname, &(current->filestat)) == -1) {
1589     fprintf(stderr, "File status unreadable!\n");
1590   } else {
1591       struct passwd *pw;
1592       struct group *grp;
1593 
1594 
1595     /* Save the initial stat information for undo */
1596 
1597     current->oldstat.mode = current->laststat.mode = current->filestat.st_mode;
1598 
1599     /* Load the name of the owner of the file into the owner text widget */
1600     if ((pw = (struct passwd*)getpwuid(current->filestat.st_uid)) != NULL)
1601       strcpy(current->edit_owner, pw->pw_name);
1602     else sprintf(current->edit_owner, "%d",
1603 		 (short)current->filestat.st_uid);
1604 
1605 
1606     XtVaSetValues(
1607         current->form1c_text_owner,
1608 	    XtNstring, current->edit_owner,
1609 	    NULL ) ;
1610 
1611     /* Load the name of the group of the file into the group text widget */
1612     if ((grp = (struct group*)getgrgid(current->filestat.st_gid)) != NULL)
1613       strcpy(current->edit_group, grp->gr_name);
1614     else sprintf(current->edit_group, "%d",
1615 		 (short)current->filestat.st_gid);
1616 
1617 
1618     XtVaSetValues(
1619         current->form1c_text_group,
1620 	    XtNstring, current->edit_group,
1621 	    NULL ) ;
1622 
1623     /* Save filename, owner and group into last_* and old_* buffers for
1624        posterity. */
1625 
1626     strcpy(current->oldstat.filename, current->edit_filename);
1627     strcpy(current->oldstat.owner, current->edit_owner);
1628     strcpy(current->oldstat.group, current->edit_group);
1629 
1630     strcpy(current->laststat.filename, current->edit_filename);
1631     strcpy(current->laststat.owner, current->edit_owner);
1632     strcpy(current->laststat.group, current->edit_group);
1633 
1634     /* Load the proper icon for the icon_label */
1635 
1636     set_icon(current);
1637 
1638     /* Load the file modification date and size */
1639 
1640     set_size_date(current);
1641 
1642     /* Set the buttons and command widgets */
1643 
1644     update_buttons(INIT, current);
1645 
1646     /* Put the dialog on screen */
1647 
1648     XtRealizeWidget(current->fileInfoDialog);
1649 
1650     XawTextSetInsertionPoint(current->form1a_text_filename,
1651 			     strlen(current->edit_filename));
1652     XawTextSetInsertionPoint(current->form1c_text_owner,
1653 			     strlen(current->edit_owner));
1654     XawTextSetInsertionPoint(current->form1c_text_group,
1655 			     strlen(current->edit_group));
1656 
1657     realize_dialog(current->fileInfoDialog, NULL, XtGrabNone,
1658 		   (XtEventHandler)WM_destroy_doubleclick_dialog, current);
1659 
1660   }  /* end of if (stat(dc_fullname, &filestat) == -1) */
1661 }
1662 
1663 /*****************************************************************************
1664  *                            update_buttons                                 *
1665  *****************************************************************************/
update_buttons(mode,current)1666 private void update_buttons(mode, current)
1667 int mode;
1668 Fileinfo *current;
1669 {
1670   static uid_t uid, euid;     /* user and effective user id's for program */
1671   Cardinal i;
1672   struct stat dirstat;
1673 
1674 #define CHANGED(b) (current->button[b].state != (current->button[b].bitmask & current->filestat.st_mode))
1675 #define USEREXEC  (current->filestat.st_mode & IEXEC)
1676 #define USERREAD  (current->filestat.st_mode & IREAD)
1677 #define USERWRITE (current->filestat.st_mode & IWRITE)
1678 #define GROUPEXEC  (current->filestat.st_mode & GEXEC)
1679 #define GROUPREAD  (current->filestat.st_mode & GREAD)
1680 #define GROUPWRITE (current->filestat.st_mode & GWRITE)
1681 #define OTHEREXEC    (current->filestat.st_mode & AEXEC)
1682 #define OTHERREAD    (current->filestat.st_mode & AREAD)
1683 #define OTHERWRITE   (current->filestat.st_mode & AWRITE)
1684 #define ANYEXEC    (current->filestat.st_mode & (IEXEC | GEXEC | AEXEC))
1685 #define REGULAR    ((current->filestat.st_mode & S_IFMT) == S_IFREG)
1686 #define SYMLINK    ((current->filestat.st_mode & S_IFMT) == S_IFLNK)
1687 #define DIRECTORY  ((current->filestat.st_mode & S_IFMT) == S_IFDIR)
1688 
1689 #define D_USERWRITE  (dirstat.st_mode & IWRITE)
1690 #define D_GROUPWRITE (dirstat.st_mode & GWRITE)
1691 #define D_OTHERWRITE (dirstat.st_mode & AWRITE)
1692 #define D_STICKY     (dirstat.st_mode & S_ISVTX)
1693 
1694   /* Force all buttons to be initialized. */
1695 
1696   if (mode == INIT) for (i= FIRSTBUTTON; i <= LASTBUTTON; i++)
1697                         current->button[i].state = -1;
1698 
1699   if (mode == INIT || mode == UNDO) {
1700     if CHANGED(rown)     SetButton(rown);
1701     if CHANGED(rgrp)     SetButton(rgrp);
1702     if CHANGED(roth)     SetButton(roth);
1703     if CHANGED(wown)     SetButton(wown);
1704     if CHANGED(wgrp)     SetButton(wgrp);
1705     if CHANGED(woth)     SetButton(woth);
1706     if CHANGED(xown)     SetButton(xown);
1707     if CHANGED(xgrp)     SetButton(xgrp);
1708     if CHANGED(xoth)     SetButton(xoth);
1709     if CHANGED(uid_but)  SetButton(uid_but);
1710     if CHANGED(gid_but)  SetButton(gid_but);
1711     if CHANGED(stky_but) SetButton(stky_but);
1712   }
1713 
1714   if (mode == INIT) {
1715 
1716     if (stat(current->dc_path, &dirstat) == -1) {
1717       fprintf(stderr, "Can't stat %s.\n", current->dc_path);
1718     }
1719 
1720     /* Set up the default button sensitivity */
1721 
1722     uid = getuid();
1723     euid = geteuid();
1724 
1725     XtVaSetValues(current->form2b_command_reset, XtNsensitive, False, NULL);
1726     XtVaSetValues(current->form2b_command_undo, XtNsensitive, False, NULL);
1727     XtVaSetValues(current->form2b_command_update, XtNsensitive, False, NULL);
1728 
1729     /* Assume we can modify permissions until proven otherwise.
1730        Note that we only do this at INIT, as we are assuming
1731        that the user can't change his any of his identities
1732        during his usage of this dialog box.  So the section
1733        that handles root user access won't set any of these to
1734        true, since it assumes that they couldn't have been
1735        set to false, since the user must have always been
1736        root. */
1737 
1738     XtVaSetValues(current->form2a2_button_rown, XtNsensitive, True, NULL);
1739     XtVaSetValues(current->form2a2_button_rgrp, XtNsensitive, True, NULL);
1740     XtVaSetValues(current->form2a2_button_roth, XtNsensitive, True, NULL);
1741     XtVaSetValues(current->form2a3_button_wown, XtNsensitive, True, NULL);
1742     XtVaSetValues(current->form2a3_button_wgrp, XtNsensitive, True, NULL);
1743     XtVaSetValues(current->form2a3_button_woth, XtNsensitive, True, NULL);
1744     XtVaSetValues(current->form2a4_button_xown, XtNsensitive, True, NULL);
1745     XtVaSetValues(current->form2a4_button_xgrp, XtNsensitive, True, NULL);
1746     XtVaSetValues(current->form2a4_button_xoth, XtNsensitive, True, NULL);
1747     XtVaSetValues(current->form2a6_button_setuid, XtNsensitive, True, NULL);
1748     XtVaSetValues(current->form2a6_button_setgid, XtNsensitive, True, NULL);
1749     XtVaSetValues(current->form2a6_button_sticky, XtNsensitive, True, NULL);
1750     XtVaSetValues(current->form1a_text_filename, XtNsensitive, True, NULL);
1751     XtVaSetValues(current->form1c_text_owner, XtNsensitive, True, NULL);
1752     XtVaSetValues(current->form1c_text_group, XtNsensitive, True, NULL);
1753     XawTextDisplayCaret(current->form1a_text_filename, True);
1754     XawTextDisplayCaret(current->form1c_text_owner, True);
1755     XawTextDisplayCaret(current->form1c_text_group, True);
1756   }
1757 
1758   if (!uid || !euid)    /* We're root */
1759     {
1760       if (ANYEXEC && (REGULAR || SYMLINK))
1761 	{
1762 	  if (mode == UPDATE || mode == UNDO || mode == INIT)
1763 	    {
1764 	      XtVaSetValues(current->form3_command_execwin,
1765 			    XtNsensitive, True, NULL);
1766 	      XtVaSetValues(current->form3_command_execback,
1767 			    XtNsensitive, True, NULL);
1768 	    }
1769 	  XtVaSetValues(current->form2a6_button_sticky,
1770 			XtNsensitive, True, NULL);
1771 	}
1772       else
1773 	{
1774 	  if (mode == UPDATE || mode == UNDO || mode == INIT)
1775 	    {
1776 	      XtVaSetValues(current->form3_command_execwin,
1777 			    XtNsensitive, False, NULL);
1778 	      XtVaSetValues(current->form3_command_execback,
1779 			    XtNsensitive, False, NULL);
1780 	    }
1781 	  if (!DIRECTORY)
1782 	    {
1783 	      XtVaSetValues(current->form2a6_button_sticky,
1784 			    XtNsensitive, False, NULL);
1785 	      current->filestat.st_mode &= ~S_ISVTX;
1786 	      SetButton(stky_but);
1787 	    }
1788 	}
1789 
1790       /* The setgid and setuid bits may only be on if the corresponding execute
1791 	 bit is on. We check those bits here, even though they don't affect the
1792 	 root user's ability to do anything else. */
1793 
1794       if (USEREXEC && (REGULAR || SYMLINK))
1795 	{
1796 	  XtSetSensitive(current->form2a6_button_setuid, True);
1797 	}
1798       else
1799 	{
1800 	  current->filestat.st_mode &= ~S_ISUID;
1801 	  SetButton(uid_but);
1802 	  XtSetSensitive(current->form2a6_button_setuid, False);
1803 	}
1804 
1805       if (GROUPEXEC && (REGULAR || SYMLINK))
1806 	{
1807 	  XtSetSensitive(current->form2a6_button_setgid, True);
1808 	}
1809       else
1810 	{
1811 	  current->filestat.st_mode &= ~S_ISGID;
1812 	  SetButton(gid_but);
1813 	  XtSetSensitive(current->form2a6_button_setgid, False);
1814 	}
1815 
1816       if (DIRECTORY)
1817 	{
1818 	  XtSetSensitive(current->form3_command_view, False);
1819 	  XtSetSensitive(current->form3_command_edit, False);
1820 	  XtSetSensitive(current->form2a6_button_sticky, True);
1821 	}
1822       else
1823 	{
1824 	  XtSetSensitive(current->form3_command_view, True);
1825 	  XtSetSensitive(current->form3_command_edit, True);
1826 	}
1827 
1828     /* If we can view the file, (the file is not a directory)
1829        We can edit the file regardless of permission bits */
1830 
1831       current->file_editable = TRUE;
1832     }
1833   else    /* Oops, we're not root */
1834     {
1835       if (mode == INIT)
1836 	{
1837 	  /* If we don't have write permission in this directory,
1838 	     we can't rename the file. */
1839 
1840 	  if ((uid == dirstat.st_uid) || (euid == dirstat.st_uid))
1841 	    {
1842 	      if (!D_USERWRITE)
1843 		{
1844 		  XtSetSensitive(current->form1a_text_filename, False);
1845 		  XawTextDisplayCaret(current->form1a_text_filename, False);
1846 		}
1847 	    }
1848 	  else if (user_is_member(dirstat.st_gid))
1849 	    {
1850 	      if (!D_GROUPWRITE || D_STICKY)
1851 		{
1852 		  XtSetSensitive(current->form1a_text_filename, False);
1853 		  XawTextDisplayCaret(current->form1a_text_filename, False);
1854 		}
1855 	    }
1856 	  else if (!D_OTHERWRITE || D_STICKY)
1857 	    {
1858 	      XtSetSensitive(current->form1a_text_filename, False);
1859 	      XawTextDisplayCaret(current->form1a_text_filename, False);
1860 	    }
1861 
1862 	  /* Non-root, can't chown */
1863 
1864 	  XtVaSetValues(
1865 	      current->form1c_text_owner,
1866 	          XtNsensitive, False,
1867 		  XtNeditType, XawtextRead,
1868 		  NULL ) ;
1869 	  XawTextDisplayCaret(current->form1c_text_owner, False);
1870 
1871 	  if (!DIRECTORY)
1872 	    {
1873 	      current->filestat.st_mode &= ~S_ISVTX;  /* Turn off sticky */
1874 	      SetButton(stky_but);
1875 	      XtSetSensitive(current->form2a6_button_sticky, False);
1876 	    }
1877 	}
1878 
1879       if ((uid == current->filestat.st_uid) ||
1880 	  (euid == current->filestat.st_uid))
1881 	{
1882 
1883       /* We are the owner of the file.  Let's see how our permissions
1884 	 affect our possible commands, and turn off ones that do
1885 	 not apply with the current permissions. */
1886 
1887       if (USEREXEC && (REGULAR || SYMLINK))
1888 	{
1889 	  if (mode == UPDATE || mode == UNDO || mode == INIT)
1890 	    {
1891 	      XtVaSetValues(current->form3_command_execwin,
1892 			    XtNsensitive, True, NULL);
1893 	      XtVaSetValues(current->form3_command_execback,
1894 			    XtNsensitive, True, NULL);
1895 	    }
1896 	  XtVaSetValues(current->form2a6_button_setuid,
1897 			XtNsensitive, True, NULL);
1898 	}
1899       else
1900 	{
1901 	  if (mode == UPDATE || mode == UNDO || mode == INIT)
1902 	    {
1903 	      XtVaSetValues(current->form3_command_execback,
1904 			    XtNsensitive, False, NULL);
1905 	      XtVaSetValues(current->form3_command_execwin,
1906 			    XtNsensitive, False, NULL);
1907 	    }
1908 	  current->filestat.st_mode &= ~S_ISUID; /* Turn off Setuid */
1909 	  SetButton(uid_but);
1910 	  XtVaSetValues(current->form2a6_button_setuid,
1911 			XtNsensitive, False, NULL);
1912 	}
1913       if (GROUPEXEC && (REGULAR || SYMLINK))
1914 	{
1915 	  XtSetSensitive(current->form2a6_button_setgid, True);
1916 	}
1917       else /* Group exec permission is off */
1918 	{
1919 	  current->filestat.st_mode &= ~S_ISGID; /* Turn off Setgid */
1920 	  SetButton(gid_but);
1921 	  XtSetSensitive(current->form2a6_button_setgid, False);
1922 	}
1923 
1924       if (mode == UPDATE || mode == UNDO || mode == INIT)
1925 	{
1926 	  if (USERREAD && (REGULAR || SYMLINK))
1927 	    {
1928 	      XtSetSensitive(current->form3_command_view, True);
1929 	    }
1930 	  else
1931 	    {
1932 	      XtSetSensitive(current->form3_command_view, False);
1933 	      XtSetSensitive(current->form3_command_edit, False);
1934 	    }
1935 	  if (!USERWRITE && (REGULAR || SYMLINK))
1936 	    {
1937 	      XtSetSensitive(current->form3_command_edit, False);
1938 	      current->file_editable = FALSE;
1939 	    }
1940 	  else if (USERREAD && (REGULAR || SYMLINK))
1941 	    {
1942 	      XtSetSensitive(current->form3_command_edit, True);
1943 	      current->file_editable = TRUE;
1944 	    }
1945 	  else
1946 	    XtSetSensitive(current->form3_command_edit, False);
1947 	}
1948 
1949       /* End of owner permission handling section */
1950 
1951     } else /* not owner or root */ {
1952 
1953       /* We're not root, and we don't own the file,
1954 	 so we can't change the permissions. */
1955 
1956       if (mode == INIT)
1957 	{
1958 	/* Again, we do this only at INIT time, and we
1959 	   assume throughout this function that these values
1960 	   will remain unchanged for the duration of this
1961 	   dialog box. */
1962 
1963 	XtVaSetValues(current->form2a2_button_rown, XtNsensitive, False, NULL);
1964 	XtVaSetValues(current->form2a2_button_rgrp, XtNsensitive, False, NULL);
1965 	XtVaSetValues(current->form2a2_button_roth, XtNsensitive, False, NULL);
1966 	XtVaSetValues(current->form2a3_button_wown, XtNsensitive, False, NULL);
1967 	XtVaSetValues(current->form2a3_button_wgrp, XtNsensitive, False, NULL);
1968 	XtVaSetValues(current->form2a3_button_woth, XtNsensitive, False, NULL);
1969 	XtVaSetValues(current->form2a4_button_xown, XtNsensitive, False, NULL);
1970 	XtVaSetValues(current->form2a4_button_xgrp, XtNsensitive, False, NULL);
1971 	XtVaSetValues(current->form2a4_button_xoth, XtNsensitive, False, NULL);
1972 	XtVaSetValues(current->form2a6_button_setuid, XtNsensitive, False,
1973 		      NULL);
1974 	XtVaSetValues(current->form2a6_button_setgid, XtNsensitive, False,
1975 		      NULL);
1976 	XtVaSetValues(current->form2a6_button_sticky, XtNsensitive, False,
1977 		      NULL);
1978 	XtVaSetValues(current->form1c_text_group, XtNsensitive, False, NULL);
1979 	XawTextDisplayCaret(current->form1c_text_group, False);
1980       }
1981 
1982       /* Since we're not root and don't own the file,
1983 	 we don't have to worry about making changes to
1984 	 the setgid and setuid buttons in response to your
1985 	 run of the mill permission button clicks.  So,
1986 	 all _group_ and _other_ permission handling will
1987 	 be done only if we are in UPDATE, UNDO, or INIT mode. */
1988 
1989       if (mode == UPDATE || mode == UNDO || mode == INIT)
1990 	{
1991 	  if (user_is_member(current->filestat.st_gid))
1992 	    {
1993 	      /* We're in the file's group */
1994 
1995 	      if (GROUPEXEC && (REGULAR || SYMLINK))
1996 		{
1997 		  XtSetSensitive(current->form3_command_execwin, True);
1998 		  XtSetSensitive(current->form3_command_execback, True);
1999 		}
2000 	      else
2001 		{
2002 		  XtSetSensitive(current->form3_command_execwin, False);
2003 		  XtSetSensitive(current->form3_command_execback, False);
2004 		}
2005 	      if (GROUPREAD && (REGULAR || SYMLINK))
2006 		{
2007 		  XtSetSensitive(current->form3_command_view, True);
2008 		}
2009 	      else
2010 		{
2011 		  XtSetSensitive(current->form3_command_view, False);
2012 		  XtSetSensitive(current->form3_command_edit, False);
2013 		}
2014 	      if (!GROUPWRITE)
2015 		{
2016 		  XtSetSensitive(current->form3_command_edit, False);
2017 		  current->file_editable = FALSE;
2018 		}
2019 	      else if (GROUPREAD && (REGULAR || SYMLINK))
2020 		{
2021 		  XtSetSensitive(current->form3_command_edit, True);
2022 		  current->file_editable = TRUE;
2023 		}
2024 
2025 	      /* End of group permission handling */
2026 	    }
2027 	  else
2028 	    {
2029 	      /* We're not owner or in group */
2030 
2031 	      if (OTHEREXEC && (REGULAR || SYMLINK))
2032 		{
2033 		  XtSetSensitive(current->form3_command_execwin, True);
2034 		  XtSetSensitive(current->form3_command_execback, True);
2035 		}
2036 	      else
2037 		{
2038 		  XtSetSensitive(current->form3_command_execwin, False);
2039 		  XtSetSensitive(current->form3_command_execback, False);
2040 		}
2041 	      if (OTHERREAD && (REGULAR || SYMLINK))
2042 		{
2043 		  XtSetSensitive(current->form3_command_view, True);
2044 		}
2045 	      else
2046 		{
2047 		  XtSetSensitive(current->form3_command_view, False);
2048 		  XtSetSensitive(current->form3_command_edit, False);
2049 		}
2050 
2051 	      if (!OTHERWRITE)
2052 		{
2053 		  XtSetSensitive(current->form3_command_edit, False);
2054 		  current->file_editable = FALSE;
2055 		}
2056 	      else if (OTHERREAD && (REGULAR || SYMLINK))
2057 		{
2058 		  XtSetSensitive(current->form3_command_edit, True);
2059 		  current->file_editable = TRUE;
2060 		}
2061 
2062 	      /* End of other permissions handling */
2063 	    }
2064 
2065 	  /* End of the UPDATE, UNDO, INIT test that surrounds
2066 	     all group and other permission handling */
2067 	}
2068       /* End of non-root handling */
2069     }
2070     /* End of main body.. starting with if (!uid || !euid) */
2071   }
2072 
2073   /* We don't want to allow folks to rename '.' or '..' */
2074 
2075   if (!strcmp(".", current->dc_filename) ||
2076       !strcmp("..", current->dc_filename))
2077     {
2078       XawTextDisplayCaret(current->form1a_text_filename, False);
2079       XtSetSensitive(current->form1a_text_filename, False);
2080     }
2081 }
2082 
2083 /*****************************************************************************
2084  *                                verify_callback                            *
2085  *****************************************************************************/
2086 /*ARGSUSED*/
verify_callback(w,current,call_data)2087 void verify_callback(w, current, call_data)
2088 Widget w;
2089 Fileinfo *current;
2090 XtPointer call_data;
2091 {
2092   extern Cursor left_ptr;
2093 
2094   if (w == current->verify_cancel)
2095     XtPopdown(current->verify_popup);
2096   else
2097     {
2098       if (w == current->verify_yes)
2099 	update_func(w, (XtPointer)current, 0);
2100 
2101       XtPopdown(current->verify_popup);
2102       XtPopdown(current->fileInfoDialog);
2103 
2104       if ((current->laststat.mode != current->oldstat.mode) ||
2105 	  (strcmp(current->laststat.filename, current->oldstat.filename)) ||
2106 	  (strcmp(current->laststat.owner, current->oldstat.owner)) ||
2107 	  (strcmp(current->laststat.group, current->oldstat.group)) ||
2108 	  (current->file_edited && (current_mode.mode != Icons)))
2109       {
2110 	  char path[255];
2111 	  int len = strlen(current->dc_path);
2112 
2113 	  strcpy(path, current->dc_path);
2114 
2115 	  if ((strcmp(path, "/") != 0) && (path[len-1] == '/'))
2116 	    path[len-1] = 0;
2117 	  directoryManagerNewDirectory(path);
2118       }
2119 
2120       /* We can finally let the main interface go back to the non-busy cursor. */
2121 
2122       setCursor(left_ptr);
2123     }
2124 }
2125 
2126 /*****************************************************************************
2127  *                            destroy_doubleclick_dialog                     *
2128  *****************************************************************************/
2129 /*ARGSUSED*/
destroy_doubleclick_dialog(w,current,call_data)2130 void destroy_doubleclick_dialog(w, current, call_data)
2131 Widget w;
2132 Fileinfo *current;
2133 XtPointer call_data;
2134 {
2135   extern Cursor left_ptr;
2136 
2137   /* Popdown the doubleclick dialog */
2138 
2139   if ((current->filestat.st_mode != current->laststat.mode) ||
2140       (strcmp(current->edit_filename, current->laststat.filename)) ||
2141       (strcmp(current->edit_group, current->laststat.group)) ||
2142       (strcmp(current->edit_owner, current->laststat.owner))) {
2143     realize_dialog(current->verify_popup, NULL, XtGrabNonexclusive,
2144 		   NULL, NULL);
2145   } else {
2146     Fileinfoelement *c = Fileinfolist;
2147     Fileinfoelement *p;
2148 
2149     XtPopdown(current->fileInfoDialog);
2150 
2151     if ((current->laststat.mode != current->oldstat.mode) ||
2152 	(strcmp(current->laststat.filename, current->oldstat.filename)) ||
2153 	(strcmp(current->laststat.owner, current->oldstat.owner)) ||
2154 	(strcmp(current->laststat.group, current->oldstat.group))
2155 	)
2156       {
2157 	  char path[255];
2158 	  int len = strlen(current->dc_path);
2159 
2160 	  strcpy(path, current->dc_path);
2161 
2162 	  if ((strcmp(path, "/") != 0) && (path[len-1] == '/'))
2163 	    path[len-1] = 0;
2164 	  directoryManagerNewDirectory(path);
2165       }
2166 
2167     setCursor(left_ptr);
2168 
2169     /* Destroy all the widgets.. I could do this via just destroying the fileInfoDialog,
2170      * but I prefer to do it in a few seperate stages.
2171      */
2172     XtDestroyWidget(current->eb_popup);
2173     XtDestroyWidget(current->verify_popup);
2174     XtDestroyWidget(current->form1);
2175     XtDestroyWidget(current->form2);
2176     XtDestroyWidget(current->form3);
2177     XtDestroyWidget(current->fileInfoDialog);
2178 
2179     /* delete all the memory associated with this instance of a double-click
2180      * then delete the Widgets them selves.
2181      */
2182     XtFree(current->filedate);
2183     XtFree(current->filesize);
2184     XtFree(current->edit_filename);
2185     XtFree(current->edit_owner);
2186     XtFree(current->edit_group);
2187     XtFree(current->dc_fullname);
2188     XtFree(current->dc_filename);
2189     XtFree(current->dc_path);
2190     XtFree(current->eb_input);
2191     XtFree(current->eb_output);
2192     XtFree(current->eb_error);
2193     XtFree((char *)current->xdtmlist_element);
2194 
2195     /* Now we must delete this instance from our Fileinfolist, then free it */
2196     p = c;
2197     while (c != NULL && c->fileinfo != current) {
2198       /* This node is valid AND This node is NOT the current one.
2199        * Let's try the next node.
2200        */
2201       p = c;        /* A pointer to the predecessor */
2202       c = c->next;
2203     }
2204     if (c == NULL) {
2205       /* We did NOT find the node in the list.. Mmmm VERY strange, in fact
2206        * stange enough for me to print a cryptic error message.
2207        */
2208       fprintf(stderr, "xdtm: Warning: permissions dialog not found in list when free'd\n");
2209     } else {
2210       /* OK we must have found it, let's take it out of the list. */
2211       if (Fileinfolist == c) {
2212 	/* ah.. first element in the list.. OK.. if there are any more nodes
2213 	 * in the list then set the Fileinfolist to the second one.. if not
2214 	 * delete the whole bloody list.
2215 	 */
2216 	if (c->next == NULL) {
2217 	  /* We are the only element in the list.. trash it!! */
2218 	  XtFree((char *)Fileinfolist);
2219 	  Fileinfolist = NULL;
2220 	} else {
2221 	  /* There are more.. */
2222 	  Fileinfolist = c->next;
2223 	  XtFree((char *)c);
2224 	}
2225       } else {
2226 	/* We are in the middle of end of the list */
2227 	p->next = c->next;
2228 	XtFree((char *)c);
2229       }
2230     }
2231     /* We ALWAYS want to free the current node anyway */
2232     XtFree((char *)current);
2233   }
2234 }
2235 
2236 /*****************************************************************************
2237  *                                  free_info                                *
2238  *****************************************************************************/
2239 /*ARGSUSED*/
free_info(w,infobutton,call_data)2240 void free_info(w, infobutton, call_data)
2241 Widget w;
2242 InfoButtons *infobutton;
2243 XtPointer call_data;
2244 {
2245   XtFree((char *)infobutton);
2246 }
2247 
2248 /*****************************************************************************
2249  *                             dcbutton_toggled                              *
2250  *****************************************************************************/
2251 /*ARGSUSED*/
dcbutton_toggled(w,infobutton,call_data)2252 void dcbutton_toggled(w, infobutton, call_data)
2253 Widget w;
2254 InfoButtons *infobutton;
2255 XtPointer call_data;
2256 {
2257   Buttons select;
2258   Fileinfo *current;
2259 
2260   select = infobutton->select;
2261   current = infobutton->fileinfo;
2262   if (current->filestat.st_mode & current->button[select].bitmask) {
2263     current->filestat.st_mode &= ~current->button[select].bitmask;
2264   } else {
2265     current->filestat.st_mode |= current->button[select].bitmask;
2266   }
2267   SetButton(select);
2268 
2269   /* If we've toggled the buttons around such that we are in
2270      the state we were in when we last wrote the permissions
2271      out, dim the update button to let the user know we
2272      are paying attention. */
2273 
2274   if ((current->filestat.st_mode == current->laststat.mode) &&
2275       (!strcmp(current->edit_filename, current->laststat.filename)) &&
2276       (!strcmp(current->edit_owner, current->laststat.owner)) &&
2277       (!strcmp(current->edit_group, current->laststat.group))) {
2278     XtVaSetValues(current->form2b_command_update, XtNsensitive, False, NULL);
2279     XtVaSetValues(current->form2b_command_undo, XtNsensitive, False, NULL);
2280   } else {
2281     XtVaSetValues(current->form2b_command_update, XtNsensitive, True, NULL);
2282     XtVaSetValues(current->form2b_command_undo, XtNsensitive, True, NULL);
2283   }
2284 
2285   if ((current->filestat.st_mode == current->oldstat.mode) &&
2286       (!strcmp(current->edit_filename, current->oldstat.filename)) &&
2287       (!strcmp(current->edit_owner, current->oldstat.owner)) &&
2288       (!strcmp(current->edit_group, current->oldstat.group))) {
2289     XtVaSetValues(current->form2b_command_reset, XtNsensitive, False, NULL);
2290   } else {
2291     XtVaSetValues(current->form2b_command_reset, XtNsensitive, True, NULL);
2292   }
2293 
2294   update_buttons(TEMP, current);
2295 }
2296 
2297 /*****************************************************************************
2298  *                             text_callback                                 *
2299  *****************************************************************************/
2300 /*ARGSUSED*/
text_callback(w,current,call_data)2301 void text_callback(w, current, call_data)
2302 Widget w;
2303 Fileinfo *current;
2304 XtPointer call_data;
2305 {
2306 
2307   XtSetSensitive(current->form2b_command_update, True);
2308   XtSetSensitive(current->form2b_command_undo, True);
2309   XtSetSensitive(current->form2b_command_reset, True);
2310 
2311   if (w == current->form1c_text_group_src)
2312     {
2313       /* Turn off group set id if group name is changed. */
2314 
2315       current->filestat.st_mode &= ~S_ISGID;
2316       SetButton(gid_but);
2317     }
2318   else if (w == current->form1c_text_owner_src)
2319     {
2320       /* Turn off user set id if group name is changed */
2321 
2322       current->filestat.st_mode &= ~S_ISUID;
2323       SetButton(uid_but);
2324     }
2325   else if (w != current->form1a_text_filename_src)
2326     {
2327       fprintf(stderr, "Mystery text call-back!\n");
2328     }
2329 }
2330 
2331 /*****************************************************************************
2332  *                             cancel_func                                   *
2333  *****************************************************************************/
2334 /*ARGSUSED*/
cancel_func(w,client_data,call_data)2335 void cancel_func(w, client_data, call_data)
2336 Widget w;
2337 XtPointer client_data;
2338 XtPointer call_data;
2339 {
2340 }
2341 
2342 /*****************************************************************************
2343  *                             view_func                                     *
2344  *****************************************************************************/
2345 /*ARGSUSED*/
view_func(w,current,call_data)2346 void view_func(w, current, call_data)
2347 Widget w;
2348 Fileinfo *current;
2349 XtPointer call_data;
2350 {
2351   int localdescrip;
2352 #ifdef alliant
2353   int status;
2354   short magic_number;
2355 #endif
2356 
2357   if (current->file_editable && (w == current->form3_command_edit)) {
2358     if ((localdescrip = open(current->dc_fullname, O_RDWR, 0644)) == -1)
2359       ioerr_dialog(errno);
2360     else {
2361 
2362       /* Each processor has different magic numbers, therefore I won't
2363        * bother with trying to catch the editing of a binary file other
2364        * than for the alliant which I suppose must be Jon's machine.
2365        */
2366 
2367 #ifdef alliant
2368       status = read(localdescrip, &magic_number, sizeof(short));
2369       if (status == -1) ioerr_dialog(errno);
2370       else if (magic_number == AVMAGIC) {
2371 	alert_dialog("Can't edit a binary executable!", NULL, "Cancel");
2372 	close(localdescrip);
2373       } else if (magic_number == ACMAGIC) {
2374 	alert_dialog("Can't edit a binary object file!", NULL, "Cancel");
2375 	close(localdescrip);
2376       } else if ((magic_number == OMAGIC) ||
2377 		 (magic_number == NMAGIC) ||
2378 		 (magic_number == ZMAGIC)) {
2379 	alert_dialog("Can't edit binary load file!", NULL, "Cancel");
2380 	close(localdescrip);
2381       } else {
2382 
2383 #endif
2384 	close(localdescrip);
2385 	editfile(current->dc_fullname);
2386 	current->file_edited = 1;
2387 #ifdef alliant
2388       }
2389 #endif
2390     }
2391   } else /* We are in non file_editable mode */ {
2392     if ((localdescrip = open(current->dc_fullname, O_RDONLY, 0644)) == -1)
2393       ioerr_dialog(errno);
2394     else /* We can open the file. */ {
2395 
2396 
2397 #ifdef alliant
2398       status = read(localdescrip, &magic_number, sizeof(short));
2399 
2400       if (status == -1) ioerr_dialog(errno);
2401       else if (magic_number == AVMAGIC) {
2402 	alert_dialog("Can't view a binary executable!", NULL, "Cancel");
2403 	close(localdescrip);
2404       } else if (magic_number == ACMAGIC) {
2405 	alert_dialog("Can't view a binary object file!", NULL, "Cancel");
2406 	close(localdescrip);
2407       } else if ((magic_number == OMAGIC) ||
2408 		 (magic_number == NMAGIC) ||
2409 		 (magic_number == ZMAGIC)) {
2410 	alert_dialog("Can't view binary load file!", NULL, "Cancel");
2411 	close(localdescrip);
2412       } else {
2413 
2414 #endif
2415 	close(localdescrip);
2416 	displayfile(current->dc_fullname, NULL, NULL, XtGrabNone);
2417 	/* Close the double_click popup, otherwise no movement can occur in
2418 	 * the file being viewed.
2419 	 */
2420 	/* destroy_doubleclick_dialog(NULL, NULL, NULL); */
2421 #ifdef alliant
2422       }
2423 #endif
2424     }
2425   }
2426 }
2427 
2428 /*****************************************************************************
2429  *                             ioerr_dialog                                  *
2430  *****************************************************************************/
ioerr_dialog(errnum)2431 public void ioerr_dialog(errnum)
2432 int errnum;
2433 {
2434   /* Yo Jon I like it.. Eddy. */
2435 
2436   switch( errnum )
2437     {
2438       case ENOTDIR :
2439 	/* FALL THROUGH */
2440 
2441       case EINVAL :
2442 	/* FALL THROUGH */
2443 
2444       case ENAMETOOLONG :
2445 	alert_dialog("Invalid filename error", NULL, NULL);
2446       break ;
2447 
2448       case ENOENT :
2449 	alert_dialog("Component of path or", "file does not exist", NULL);
2450       break ;
2451 
2452       case EACCES :
2453 	alert_dialog("Permission denied", NULL, NULL);
2454       break;
2455 
2456 #ifndef TRUE_SYSV
2457       case ELOOP :
2458 	alert_dialog("Symbolic link loop in path", NULL, NULL);
2459       break ;
2460 #endif
2461 
2462       case EISDIR :
2463 	alert_dialog("Tried to write to directory file", NULL, NULL);
2464       break;
2465 
2466       case EROFS:
2467 	alert_dialog("Can't write to file;", " File is on a read-only file system", NULL);
2468       break;
2469 
2470       case EMFILE:
2471 	alert_dialog("Too many open file descriptors", NULL, NULL);
2472       break;
2473 
2474       case ENFILE:
2475 	alert_dialog("System file table is full", NULL, NULL);
2476       break;
2477 
2478       case ENXIO:
2479 	alert_dialog("Device driver missing", NULL, NULL);
2480       break;
2481 
2482       case ENOSPC:
2483 	alert_dialog("No space to create file", NULL, NULL);
2484       break;
2485 
2486 #ifdef EDQUOT
2487       case EDQUOT:
2488 	alert_dialog("Quota over limit", NULL, NULL);
2489       break;
2490 #endif
2491 
2492       case EIO:
2493 	alert_dialog("I/O error while allocating inode", NULL, NULL);
2494       break;
2495 
2496       case ETXTBSY:
2497 	alert_dialog("File is currently executing", NULL, NULL);
2498       break;
2499 
2500       case EFAULT:
2501 	alert_dialog("Path points outside address space", NULL, NULL);
2502       break;
2503 
2504       case EEXIST:
2505 	alert_dialog("File already exists", NULL, NULL);
2506       break;
2507 
2508 #ifndef TRUE_SYSV
2509       case EOPNOTSUPP :
2510 	alert_dialog("Can't open a socket", NULL, NULL);
2511       break;
2512 #endif
2513     }
2514 }
2515 /*****************************************************************************
2516  *                             execwin_func                                  *
2517  *****************************************************************************/
2518 /*ARGSUSED*/
execwin_func(w,current,call_data)2519 void execwin_func(w, current, call_data)
2520 Widget w;
2521 Fileinfo *current;
2522 XtPointer call_data;
2523 {
2524   extern Cursor busy;
2525 
2526   AppProgram *node;
2527 
2528   XtVaSetValues( current->fileInfoDialog, XtNcursor, busy, NULL ) ;
2529 
2530 #ifdef DEBUG
2531   fprintf(stderr, "eb_input = %s\neb_output = %s\neb_error = %s\n",
2532 	  current->eb_input, current->eb_output, current->eb_error);
2533 #endif
2534 
2535   /* compute_appnode loads node->string and node->program with
2536      dc_fullname. */
2537 
2538   node = compute_appnode(current->dc_fullname, current);
2539 
2540   /* say we want a pseudo-terminal */
2541   node->termopts = TERM;
2542 
2543 #ifdef DEBUG
2544   fprintf(stderr, "execwin_func : node->program = %s\n",node->program);
2545   fprintf(stderr, "execwin_func : running...\n");
2546 #endif
2547 
2548   /* Is a version is already running */
2549   if (node->count)
2550     popup_verify_app(node);
2551   else
2552     run_app(node, current->eb_input, current->eb_output, current->eb_error);
2553 
2554 #ifdef DEBUG
2555   fprintf(stderr, "execwin_func : whew..\n");
2556 #endif
2557 
2558   XtVaSetValues(
2559       current->fileInfoDialog,
2560           XtNcursor, NULL,
2561 	  NULL ) ;
2562 }
2563 
2564 /*****************************************************************************
2565  *                          WM_execback_popdown                              *
2566  *****************************************************************************/
2567 #if NeedFunctionPrototypes
WM_execback_popdown(Widget w,Fileinfo * current,XEvent * event,Boolean * dispatch)2568 private void WM_execback_popdown(Widget w,
2569 				 Fileinfo *current,
2570 				 XEvent *event,
2571 				 Boolean *dispatch)
2572 #else
2573 private void WM_execback_popdown(w, current, event, dispatch)
2574      Widget w;
2575      Fileinfo *current;
2576      XEvent *event;
2577      Boolean *dispatch;
2578 #endif
2579 {
2580     extern Atom protocols[2]; /* defined in dialogs.c */
2581 
2582     if (event->xclient.message_type == protocols[1] &&
2583 	event->xclient.data.l[0] == protocols[0])
2584     /* the widget got a kill signal */
2585     {
2586 	/* call callbacks on Cancel button */
2587 	XtCallCallbacks(current->ebcommandcancel, XtNcallback, NULL);
2588     }
2589 }
2590 
2591 /*****************************************************************************
2592  *                             execback_realize                              *
2593  *****************************************************************************/
2594 /*ARGSUSED*/
execback_realize(w,current,call_data)2595 void execback_realize(w, current, call_data)
2596 Widget w;
2597 Fileinfo *current;
2598 XtPointer call_data;
2599 {
2600 
2601   XawTextSetInsertionPoint(current->ebtextinput, strlen(current->eb_input));
2602   XawTextSetInsertionPoint(current->ebtextoutput, strlen(current->eb_output));
2603   XawTextSetInsertionPoint(current->ebtexterror, strlen(current->eb_error));
2604 
2605   realize_dialog(current->eb_popup, NULL, XtGrabNonexclusive,
2606 		 (XtEventHandler)WM_execback_popdown, current);
2607 }
2608 
2609 /*****************************************************************************
2610  *                             execback_popdown                              *
2611  *****************************************************************************/
2612 /*ARGSUSED*/
execback_popdown(w,infobutton,call_data)2613 void execback_popdown(w, infobutton, call_data)
2614 Widget w;
2615 InfoButtons *infobutton;
2616 XtPointer call_data;
2617 {
2618   AppProgram *node;
2619   Fileinfo *current;
2620 
2621   current = infobutton->fileinfo;
2622 
2623   XtPopdown (current->eb_popup);
2624 
2625   /* fprintf(stderr, "eb_input = %s\neb_output = %s\neb_error = %s\n", eb_input,
2626      eb_output, eb_error); */
2627 
2628   if (infobutton->select == 1) {
2629     extern Cursor busy;
2630 
2631     XtVaSetValues( current->fileInfoDialog, XtNcursor, busy, NULL ) ;
2632 
2633     node = compute_appnode(current->dc_fullname, current);
2634     if (node->count)
2635       popup_verify_app(node);
2636     else
2637       run_app(node, current->eb_input, current->eb_output, current->eb_error);
2638 
2639     XtVaSetValues( current->fileInfoDialog, XtNcursor, NULL, NULL ) ;
2640   }
2641 }
2642 
2643 /*****************************************************************************
2644  *                             compute_appnode                               *
2645  *  	      	      	      	      	      	      	      	      	     *
2646  * compute_appnode is used to find or generate an AppProgram node for	     *
2647  * <programname>.  The AppProgram node is used in the application manager,   *
2648  * which keeps a list of currently running processes.  The AppProgram node   *
2649  * holds four pieces of information relevant to our purposes here. 	     *
2650  *									     *
2651  * node->string 							     *
2652  *   contains the name of the program we are executing. In this case, this   *
2653  *   includes the complete path to the file as well as the filename itself.  *
2654  *   e.g., /usr/bin/X11/xcolors.  This field is used to test for the identity*
2655  *   of the program being run.  Routines which check to see if the user	     *
2656  *   already has a copy of the program running check this field.	     *
2657  *   This field is a label only, and need not contain the actual command     *
2658  *   used to invoke the program.					     *
2659  *									     *
2660  *   The application manager knows that we provide a fully specified path in *
2661  *   our identity field.  If it sees node->options == IGNORE_SEL, it will    *
2662  *   take that as a sign that the node is ours, and will only display the    *
2663  *   last component of node->string in process lists.                        *
2664  *									     *
2665  * node->program							     *
2666  *   contains the actual command used to invoke the program. 		     *
2667  *		      	      	      	      	      	      	      	     *
2668  * node->options							     *
2669  *   if IGNORE_SEL, application manager will not try to parse arguments for  *
2670  *   us, and will only display the last component of node->string in process *
2671  *   lists.                                                                  *
2672  *									     *
2673  * node->count                                                               *
2674  *   maintains a count of the number of invokations of node->string running. *
2675  * 									     *
2676  * 									     *
2677  * 									     *
2678  * Note: We never delete nodes.  The assumption is that the user won't run   *
2679  * five unique bajillion programs.  Things get more complex if he does.      *
2680  *									     *
2681  *****************************************************************************/
compute_appnode(programname,current)2682 private AppProgram *compute_appnode(programname, current)
2683 String programname;
2684 Fileinfo *current;
2685 {
2686   AppNode *ptr, *newptr;
2687   char *newstring ;
2688 
2689   ptr = current->applist;
2690 
2691 #ifdef DEBUG
2692   fprintf(stderr, "compute_appnode : starting %s\n", programname);
2693   fprintf(stderr,"compute_appnode : traversing dirman process list\n");
2694 #endif
2695 
2696   /* Let's see if we've already allocated a node to handle this
2697      program. */
2698 
2699   while (ptr && strcmp(ptr->node.string, programname)) {
2700 
2701 #ifdef DEBUG
2702     fprintf(stderr, "compute_appnode : node.string = %s\n", ptr->node.string);
2703     fprintf(stderr, "compute_appnode : node.count = %d\n", ptr->node.count);
2704 #endif
2705 
2706     ptr = ptr->next;
2707   }
2708 
2709 #ifdef DEBUG
2710   fprintf(stderr,"compute_appnode : done traversing dirman process list\n");
2711 #endif
2712 
2713   if (ptr) {
2714 
2715     /* We don't want to change node.string, as that is
2716        our tag, but we do want to make sure our invocation
2717        is updated. */
2718 
2719 #ifdef DEBUG
2720     fprintf(stderr, "compute_appnode : found existing node.\n\
2721 compute_appnode : node->program = %s\n",ptr->node.program);
2722 #endif
2723 
2724     if (ptr->node.program) XtFree(ptr->node.program);
2725 
2726     newstring = (char *) XtMalloc(strlen(programname));
2727     if (!newstring) {
2728       fprintf(stderr, "compute_appnode : newstring XtMalloc\n");
2729       exit(-1);
2730     }
2731     ptr->node.program = strcpy(newstring, programname);
2732 
2733 #ifdef DEBUG
2734     fprintf(stderr, "\ncompute_appnode : programname = %s\n", programname);
2735     fprintf(stderr, "compute_appnode : now node->program = %s\n", ptr->node.program);
2736 #endif
2737 
2738     return &(ptr->node);
2739   }
2740 
2741   /* Otherwise allocate node, insert at the head of the list */
2742 
2743 #ifdef DEBUG
2744   fprintf(stderr, "compute_appnode : allocating new node\n");
2745 #endif
2746 
2747   newptr = (AppNode *) XtMalloc(sizeof(AppNode));
2748 
2749 #ifdef DEBUG
2750   fprintf(stderr, "compute_appnode : newly minted node, node.program = %d\n",newptr->node.program);
2751 #endif
2752 
2753   if (!newptr) {
2754     fprintf(stderr, "compute_appnode: Error in XtMalloc!\n");
2755     exit(-1);
2756   }
2757 
2758   /* New node */
2759 
2760   newstring = (char *) XtMalloc(strlen(programname));
2761   newptr->node.string = strcpy(newstring, programname);
2762   newptr->node.program = newptr->node.string;
2763   newptr->node.count = 0;
2764   newptr->node.icon = (Pixmap)NULL;
2765   newptr->node.options = IGNORE_SEL;
2766 
2767   /* We'll insert it at the head of the list.. older progs
2768      will take longer to search for. */
2769 
2770   newptr->next = current->applist;
2771   current->applist = newptr;
2772 
2773   return &(newptr->node);
2774 }
2775 
2776 /*****************************************************************************
2777  *                             update_func                                   *
2778  *****************************************************************************/
2779 /*ARGSUSED*/
update_func(w,current,call_data)2780 void update_func(w, current, call_data)
2781 Widget w;
2782 Fileinfo *current;
2783 XtPointer call_data;
2784 {
2785   int group;
2786   struct passwd *pass;
2787   struct stat dummy_stat;
2788 
2789   if (strcmp(current->edit_group, current->laststat.group))
2790     if ((group = group_number(current->edit_group)) == -1) {
2791       alert_dialog("Error", "Invalid group name.", NULL);
2792       strcpy(current->edit_group, current->laststat.group);
2793       load_text(current->form1c_text_group, current->edit_group);
2794     } else if (chown(current->dc_fullname, -1, group) == -1) {
2795       if (errno == EPERM)
2796 	alert_dialog("Not a member of group requested", NULL, NULL);
2797       else alert_dialog("Error in chown(group)", NULL, NULL);
2798       strcpy(current->edit_group, current->laststat.group);
2799       load_text(current->form1c_text_group, current->edit_group);
2800     } else strcpy(current->laststat.group, current->edit_group);
2801 
2802   if (strcmp(current->edit_filename, current->laststat.filename)) {
2803     char temp_name[1024], temp_name2[1024];
2804     strcpy(temp_name, current->dc_path);
2805     strcpy(temp_name2, current->dc_path);
2806     if (!stat(strcat(temp_name, current->edit_filename), &dummy_stat)) {
2807       char tempstring[80];
2808       ioerr_dialog(errno);
2809       sprintf(tempstring, "File %s already exists!",current->edit_filename);
2810       alert_dialog(tempstring, NULL, NULL);
2811       strcpy(current->edit_filename, current->laststat.filename);
2812       load_text(current->form1a_text_filename, current->edit_filename);
2813     } else if (rename(strcat(temp_name2, current->laststat.filename),
2814 		      temp_name) == -1) {
2815       alert_dialog("Error in rename", NULL, NULL);
2816       strcpy(current->edit_filename, current->laststat.filename);
2817       load_text(current->form1a_text_filename, current->edit_filename);
2818     } else /* Success! */ {
2819       strcpy(current->laststat.filename, current->edit_filename);
2820       strcpy(current->dc_filename, current->edit_filename);
2821       strcpy(current->dc_fullname, current->dc_path);
2822       strcat(current->dc_fullname, current->dc_filename);
2823     }
2824   }
2825 
2826   if (strcmp(current->edit_owner, current->laststat.owner))
2827     if (!(pass=(getpwnam(current->edit_owner))) &&
2828 	!(pass=(getpwuid((uid_t)atoi(current->edit_owner))))) {
2829       alert_dialog("No such user", current->edit_owner, NULL);
2830       strcpy(current->edit_owner, current->laststat.owner);
2831       load_text(current->form1c_text_owner, current->edit_owner);
2832       return;
2833     } else if (chown(current->dc_fullname, pass->pw_uid, -1) == -1) {
2834       alert_dialog("Error in chown(user)", NULL, NULL);
2835       strcpy(current->edit_owner, current->laststat.owner);
2836       load_text(current->form1c_text_owner, current->edit_owner);
2837       return;
2838     } else strcpy(current->laststat.owner, current->edit_owner);
2839 
2840   /* Mark the update button as inoperative */
2841 
2842   XtVaSetValues(
2843       current->form2b_command_update,
2844           XtNsensitive, False,
2845 	  NULL ) ;
2846 
2847   update_buttons(UPDATE, current);
2848 
2849   chmod(current->dc_fullname, current->filestat.st_mode);
2850 
2851   /* Read the file status so we'll have the updated file
2852      modification time, etc. */
2853 
2854   if (stat(current->dc_fullname, &current->filestat) == -1) {
2855     fprintf(stderr, "doubleclick:update_func:File status unreadable!\n");
2856   }
2857 
2858   set_icon(current);
2859 
2860   /* If our update takes us back to our initial mode, clear
2861      both undo buttons, else just clear our our undo button. */
2862 
2863 
2864   XtSetSensitive(current->form2b_command_reset,
2865    (
2866     ((current->laststat.mode = current->filestat.st_mode) == current->oldstat.mode) &&
2867     !strcmp(current->edit_filename, current->oldstat.filename) &&
2868     !strcmp(current->edit_group, current->oldstat.group) &&
2869     !strcmp(current->edit_owner, current->oldstat.owner)
2870    ) ? False : True);
2871 
2872   XtSetSensitive(current->form2b_command_undo, False);
2873 
2874   set_size_date(current);
2875 }
2876 
2877 /*****************************************************************************
2878  *                             undo_func                                     *
2879  *****************************************************************************/
2880 /*ARGSUSED*/
undo_func(w,infobutton,call_data)2881 void undo_func(w, infobutton, call_data)
2882 Widget w;
2883 InfoButtons *infobutton;
2884 XtPointer call_data;
2885 {
2886   int group;
2887   struct passwd *pass;
2888   Fileinfo *current;
2889   int mode;
2890 
2891   mode = infobutton->mode;
2892   current = infobutton->fileinfo;
2893 
2894   switch(mode) {
2895   case RESET:
2896     current->laststat.mode = current->filestat.st_mode = current->oldstat.mode;
2897 
2898     if (strcmp(current->laststat.group, current->oldstat.group)) {
2899       if ((group = group_number(current->oldstat.group)) == -1) {
2900 	alert_dialog("Error", "Impossibly Invalid group name.", NULL);
2901 	strcpy(current->edit_group, current->laststat.group);
2902 	load_text(current->form1c_text_group, current->edit_group);
2903       } else if (chown(current->dc_fullname, -1, group) == -1) {
2904 	alert_dialog("Error in resetting group (chown)", NULL, NULL);
2905 	strcpy(current->edit_group, current->laststat.group);
2906 	load_text(current->form1c_text_group, current->edit_group);
2907       } else /* Success! */ {
2908 	strcpy(current->edit_group, current->oldstat.group);
2909 	strcpy(current->laststat.group, current->edit_group);
2910 	load_text(current->form1c_text_group, current->edit_group);
2911       }
2912     } else if (strcmp(current->edit_group, current->oldstat.group)) {
2913       strcpy(current->edit_group, current->oldstat.group);
2914       load_text(current->form1c_text_group, current->edit_group);
2915     }
2916 
2917     if (strcmp(current->laststat.filename, current->oldstat.filename))
2918       {
2919 	char temp_name[1024], temp_name2[1024];
2920 	strcpy(temp_name, current->dc_path);
2921 	strcpy(temp_name2, current->dc_path);
2922 	if (rename(strcat(temp_name, current->laststat.filename),
2923 		   strcat(temp_name2, current->oldstat.filename)) == -1) {
2924 	  alert_dialog("Error in resetting filename", NULL, NULL);
2925 	  strcpy(current->edit_filename, current->laststat.filename);
2926 	  load_text(current->form1a_text_filename, current->edit_filename);
2927 	} else {
2928 	  strcpy(current->edit_filename, current->oldstat.filename);
2929 	  strcpy(current->laststat.filename, current->edit_filename);
2930 	  strcpy(current->dc_filename, current->edit_filename);
2931 	  strcpy(current->dc_fullname, current->dc_path);
2932 	  strcat(current->dc_fullname, current->dc_filename);
2933 	  load_text(current->form1a_text_filename, current->edit_filename);
2934 	}
2935       } else if (strcmp(current->edit_filename, current->oldstat.filename)) {
2936 	strcpy(current->edit_filename, current->oldstat.filename);
2937 	strcpy(current->dc_filename, current->edit_filename);
2938 	strcpy(current->dc_fullname, current->dc_path);
2939 	strcat(current->dc_fullname, current->dc_filename);
2940 	load_text(current->form1a_text_filename, current->edit_filename);
2941      }
2942 
2943     if (strcmp(current->laststat.owner, current->oldstat.owner)) {
2944       if (!(pass=(getpwnam(current->oldstat.owner)))) {
2945 	alert_dialog("Original user no longer exists!", NULL, NULL);
2946 	strcpy(current->edit_owner, current->laststat.owner);
2947 	load_text(current->form1c_text_owner, current->edit_owner);
2948       } else {
2949 	if (chown(current->dc_fullname, pass->pw_uid, -1) == -1) {
2950 	  alert_dialog("Error in resetting owner (chown)", NULL, NULL);
2951 	  strcpy(current->edit_owner, current->laststat.owner);
2952 	  load_text(current->form1c_text_owner, current->edit_owner);
2953 	} else /* Success! */ {
2954 	  strcpy(current->edit_owner, current->oldstat.owner);
2955 	  strcpy(current->laststat.owner, current->edit_owner);
2956 	  load_text(current->form1c_text_owner, current->edit_owner);
2957 	}
2958       }
2959     } else if (strcmp(current->edit_owner, current->oldstat.owner)) {
2960       strcpy(current->edit_owner, current->oldstat.owner);
2961       load_text(current->form1c_text_owner, current->edit_owner);
2962     }
2963 
2964     XtSetSensitive(current->form2b_command_reset, False);
2965     XtSetSensitive(current->form2b_command_undo, False);
2966     break;
2967 
2968   case UNDO:
2969     current->filestat.st_mode = current->laststat.mode;
2970 
2971     if (strcmp(current->edit_group, current->laststat.group)) {
2972       strcpy(current->edit_group, current->laststat.group);
2973       load_text(current->form1c_text_group, current->edit_group);
2974     }
2975 
2976     if (strcmp(current->edit_filename, current->laststat.filename)) {
2977       strcpy(current->edit_filename, current->laststat.filename);
2978       load_text(current->form1a_text_filename, current->edit_filename);
2979     }
2980 
2981     if (strcmp(current->edit_owner, current->laststat.owner)) {
2982       strcpy(current->edit_owner, current->laststat.owner);
2983       load_text(current->form1c_text_owner, current->edit_owner);
2984     }
2985 
2986     XtSetSensitive(current->form2b_command_undo, False);
2987     XtSetSensitive(current->form2b_command_reset,
2988       ((current->filestat.st_mode == current->oldstat.mode) &&
2989        !strcmp(current->edit_filename, current->oldstat.filename) &&
2990        !strcmp(current->edit_group, current->oldstat.group) &&
2991        !strcmp(current->edit_owner, current->oldstat.owner)) ? False : True);
2992   }
2993 
2994   /* Change the buttons back to their original state. */
2995 
2996   update_buttons(UNDO, current);
2997 
2998   XtSetSensitive(current->form2b_command_update, False);
2999 
3000   /* Restore the permissions on disk to their original state. */
3001 
3002   chmod(current->dc_fullname, current->filestat.st_mode);
3003 
3004   set_icon(current);
3005 
3006   set_size_date(current);
3007 
3008 }
3009 
3010 /*****************************************************************************
3011  *                             help_func                                     *
3012  *****************************************************************************/
3013 /*ARGSUSED*/
help_func(w,client_data,call_data)3014 void help_func(w, client_data, call_data)
3015 Widget w;
3016 XtPointer client_data;
3017 XtPointer call_data;
3018 {
3019     if (access(perm_help_file, R_OK) == 0)
3020       displayfile(perm_help_file, NULL, "xdtm permissions help", XtGrabNone);
3021     else
3022       alert_dialog("Help file not found at", perm_help_file, "Cancel");
3023 }
3024 
3025 /*****************************************************************************
3026  *                             group_number                                  *
3027  *****************************************************************************/
group_number(groupname)3028 int group_number(groupname)
3029 char *groupname;
3030 {
3031   struct group *group;
3032 
3033   setgrent ();
3034 
3035   if (!(group=getgrnam(groupname)) && !(group=getgrgid(atoi(groupname))))
3036     return (-1);
3037   else
3038     return (group->gr_gid);
3039 }
3040 
3041 /*****************************************************************************
3042  *                             user_is_member                                *
3043  *****************************************************************************/
user_is_member(gid)3044 int user_is_member( gid )
3045 gid_t gid ;
3046 {
3047 #ifdef SYSV
3048   gid_t gidset[NGROUPS];
3049 #else
3050   int gidset[NGROUPS];
3051 #endif
3052   int ngroups, i;
3053 
3054   /* Get the list of groups that the user is in. */
3055 
3056 #ifdef DEBUG
3057  fprintf(stderr, "Entering user_is_member()\n");
3058  fprintf(stderr, "gid = %d\n", gid);
3059  fflush(stderr);
3060  fprintf(stderr, "NGROUPS = %d\n", NGROUPS);
3061 #endif
3062 
3063   ngroups = getgroups(NGROUPS, gidset);
3064 
3065 #ifdef DEBUG
3066  fprintf(stderr, "Done getgroups\n");
3067 #endif
3068 
3069   /* If we were able to successfully get the groups,
3070      check to see if the user is a member of group
3071      number gid. */
3072 
3073   if (ngroups == -1) {
3074     fprintf(stderr, "xdtm: Error in reading groups in doubleclick.c:user_is_member \n");
3075   } else {
3076 #ifdef DEBUG
3077     fprintf(stderr, "ngroups = %d\n",ngroups);
3078     fflush(stderr);
3079 #endif
3080     for(i=0; i<ngroups; i++) {
3081 #ifdef DEBUG
3082       fprintf(stderr, "looping.. \n");
3083       fprintf(stderr, "gidset[%d] = %d\n", i, gidset[i]);
3084       fflush(stderr);
3085 #endif
3086       if (gidset[i] == gid) {
3087 #ifdef DEBUG
3088 	fprintf(stderr, "return(1)\n");
3089 	fflush(stderr);
3090 #endif
3091 	return 1;
3092       }
3093     }
3094   }
3095 #ifdef DEBUG
3096   fprintf(stderr, "returning 0\n");
3097   fflush(stderr);
3098 #endif
3099   return 0;
3100 }
3101 
3102 /*****************************************************************************
3103  *                             set_size_date                                 *
3104  *****************************************************************************/
set_size_date(current)3105 private void set_size_date(current)
3106 Fileinfo *current;
3107 {
3108   strcpy(current->filedate,ctime(&current->filestat.st_mtime));
3109   sprintf(current->filesize, "%9ld",current->filestat.st_size);
3110 
3111   XtVaSetValues(
3112       current->form1b_label_date,
3113           XtNlabel, current->filedate,
3114 	  NULL ) ;
3115 
3116   XtVaSetValues(
3117       current->form1b_label_size,
3118 	  XtNlabel, current->filesize,
3119 	  NULL ) ;
3120 }
3121 
3122 /*****************************************************************************
3123  *                             set_icon                                      *
3124  *****************************************************************************/
set_icon(current)3125 private void set_icon(current)
3126 Fileinfo *current;
3127 {
3128   Icon_mode save_mode;
3129 
3130   save_mode.mode = current_mode.mode;
3131 
3132   current_mode.mode = Icons;
3133 
3134   /* getIconType will overwrite xdtmlist_element->string, free it before */
3135   if (current->xdtmlist_element->string)
3136     XtFree(current->xdtmlist_element->string);
3137 
3138   if (!getIconType(current->dc_filename, current->dc_path,
3139 		   current->xdtmlist_element)) {
3140     fprintf(stderr, "doubleclick:File icon unreadable!\n");
3141     current->xdtmlist_element->icon = emptytick;
3142   }
3143 
3144   XtVaSetValues(
3145       current->form1a_label_icon,
3146           XtNbitmap, current->xdtmlist_element->icon,
3147 	  NULL ) ;
3148 
3149   current_mode.mode = save_mode.mode;
3150 }
3151 
3152 /*****************************************************************************
3153  *                             load_text                                     *
3154  *****************************************************************************/
load_text(w,string)3155 private void load_text(w, string)
3156 Widget w;
3157 char *string;
3158 {
3159   XtVaSetValues(
3160       w,
3161           XtNstring, string,
3162 	  NULL ) ;
3163 
3164   XawTextSetInsertionPoint(w, strlen(string));
3165 }
3166