1 /*
2  * TCPVIEW
3  *
4  * Author:	Martin Hunt
5  *		Networks and Distributed Computing
6  *		Computing & Communications
7  *		University of Washington
8  *		Administration Building, AG-44
9  *		Seattle, WA  98195
10  *		Internet: martinh@cac.washington.edu
11  *
12  *
13  * Copyright 1992 by the University of Washington
14  *
15  * Permission to use, copy, modify, and distribute this software and its
16  * documentation for any purpose and without fee is hereby granted, provided
17  * that the above copyright notice appears in all copies and that both the
18  * above copyright notice and this permission notice appear in supporting
19  * documentation, and that the name of the University of Washington not be
20  * used in advertising or publicity pertaining to distribution of the software
21  * without specific, written prior permission.  This software is made
22  * available "as is", and
23  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
24  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
26  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
27  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
28  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
29  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
30  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31  *
32  */
33 
34 #ifndef lint
35 static char rcsid[] =
36     "@(#) $Header: /usr/staff/martinh/tcpview/RCS/filter-stream.c,v 1.2 1993/04/22 20:19:39 martinh Exp $ (UW)";
37 #endif
38 
39 #include <stdio.h>
40 #include <string.h>
41 #include <math.h>
42 #include  <X11/Intrinsic.h>
43 #include  <X11/StringDefs.h>
44 #include  <Xm/Xm.h>
45 #include  <Xm/Frame.h>
46 #include  <Xm/MessageB.h>
47 #include  <Xm/RowColumn.h>
48 #include  <Xm/SeparatoG.h>
49 #include  <Xm/ToggleB.h>
50 #include  <Xm/BulletinB.h>
51 #include  <Xm/TextF.h>
52 #include  <Xm/SelectioB.h>
53 #include  <Xm/Form.h>
54 #include  <Xm/FileSB.h>
55 #include  "tcpview.h"
56 #include  "filter.h"
57 #include "motif.h"
58 
59 #ifdef __STDC__
60 void show_text( char *, char * );
61 static void help_callback( Widget, char *, caddr_t );
62 static void cancel_callback( Widget, char *, caddr_t );
63 static void dir_callback( Widget, caddr_t, caddr_t );
64 static void ooo_callback( Widget, caddr_t, caddr_t );
65 static void timeout_callback( Widget, caddr_t, caddr_t );
66 static void time_callback();
67 static void filtername_callback( Widget, char *, caddr_t);
68 static void filter_cancel_callback();
69 static void filter_ok_callback();
70 static void filterstream( Widget, char *, caddr_t );
71 static void update_external_filter(void);
72 static void ext_callback( Widget, char *, caddr_t );
73 static void extfil_callback( Widget, char *, caddr_t );
74 static void extfra_callback( Widget, char *, caddr_t );
75 static void data_callback( Widget, char *, caddr_t );
76 void update_fstr(struct filter *);
77 void redisplay_entire_list(void);
78 #else
79 void show_text();
80 static void help_callback();
81 static void cancel_callback();
82 static void dir_callback();
83 static void ooo_callback();
84 static void timeout_callback();
85 static void time_callback();
86 static void filtername_callback();
87 static void filter_cancel_callback();
88 static void filter_ok_callback();
89 static void filterstream();
90 static void update_external_filter();
91 static void ext_callback();
92 static void extfil_callback();
93 static void extfra_callback();
94 static void data_callback();
95 void update_fstr();
96 void redisplay_entire_list();
97 #endif /* __STDC__ */
98 
99 static u_short filter_direction=1;
100 static u_short DataFormat;
101 static char *DataFormatStr[] = { "BINARY","HEX" };
102 static Widget bb_widget, timeout_widget;
103 
104 extern char Fstr[];	/* filter-dialog.c */
105 static char *protostr[] = { "ALL","IP","ARP","RARP","ICMP","UDP","TCP" };
106 
107 char D_Src_Host[64], D_Dst_Host[64], D_Proto[8];
108 u_short D_Src_Port=0, D_Dst_Port=0;
109 
110 static u_short ExternalOn=0;
111 static u_short ExternalFil = 0;
112 static u_short ExternalFra = 0;
113 static Widget ExOn, ExFil, ExFilNam, ExFra, ExLab, ExtW[2], DataLab, DataPB;
114 static char ExFilterBName[32], ExFilterName[128], ExFileName[128];
115 static char *extstr1[] = { "DON'T"," DO " };
116 static char *extstr2[] = { "DATA", "FRAMES and DATA" };
117 static char *extstr3[] = { "FILTER", "FILE", "WINDOW" };
118 FILE *Xfile;
119 
120 /* These are global flags that determine if a packet is highlighted or not */
121 u_short HighlightTimeout, AssembleOOO;
122 u_short HighlightPacket = 0;
123 
124 /* Ho and Ht are the permanent state variables for highlighting */
125 static u_short Ho = 0;
126 static u_short Ht = 0;
127 
128 struct timeval Timeout;
129 
FilterStream(parent,nam,callback)130 void FilterStream(parent, nam, callback)
131      Widget parent;
132      char *nam;
133      void (*callback)();
134 {
135   Widget rb, rc, rd, frame, main_row;
136   Arg args[10];
137   int n;
138   char str[20];
139 
140   HighlightTimeout = Ht;
141   AssembleOOO = Ho;
142 
143   n=0;
144   XtSetArg( args[n], XmNautoUnmanage, False ); n++;
145   XtSetArg( args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL ); n++;
146   bb_widget = XmCreateBulletinBoardDialog (parent,"filterstream",args,n);
147 
148   n = 0;
149   XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
150   main_row = XmCreateRowColumn( bb_widget,"main",args,n);
151   XtManageChild( main_row );
152 
153   n=0;
154   CreateLabelWidget (main_row, "filterstreamlabel","  STREAM FILTER OPTIONS  ",args,n);
155 
156   n=0;
157   XtSetArg ( args[n], XmNshadowThickness, 4 ); n++;
158   frame = XmCreateFrame (main_row,"frame",args,n);
159   XtManageChild(frame);
160 
161   n = 0;
162   XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
163   rc = XmCreateRowColumn( frame,"row",args,n);
164   XtManageChild( rc );
165 
166   n=0;
167   CreateLabelWidget (rc, "xxx","  STREAM  ",args,n);
168 
169   rb = CreateRadioBox(rc, "dir");
170   CreateSimpleToggle( rb, "unidirectional",filter_direction==0,XmONE_OF_MANY,dir_callback,(caddr_t)0);
171   CreateSimpleToggle( rb, "bidirectional",filter_direction,XmONE_OF_MANY,dir_callback,(caddr_t)1);
172   XtManageChild( rb );
173 
174   /* create a new frame and options */
175   n=0;
176   XtSetArg ( args[n], XmNshadowThickness, 4 ); n++;
177   frame = XmCreateFrame (main_row,"frame",args,n);
178   XtManageChild(frame);
179 
180   n = 0;
181   XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
182   rc = XmCreateRowColumn( frame,"row",args,n);
183   XtManageChild( rc );
184 
185   n=0;
186   CreateLabelWidget (rc, "xxx","  TCP  OPTIONS  ",args,n);
187 
188   n = 0;
189   XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
190   rb = XmCreateRowColumn( rc,"other",args,n);
191   CreateSimpleToggle( rb, "Assemble Out-Of-Order Packets",AssembleOOO,XmN_OF_MANY,ooo_callback,0);
192   CreateSimpleToggle( rb, "Highlight Timeouts",HighlightTimeout,XmN_OF_MANY,
193 		     timeout_callback,(caddr_t)0);
194 
195   n=0;
196   XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
197   rd = XmCreateRowColumn( rb,"data",args,n);
198   XtManageChild( rd );
199   n=0;
200   (void)CreateLabelWidget( rd, "","Timeout Interval is ",args,n );
201   (void)sprintf(str,"%d.%d",Timeout.tv_sec,Timeout.tv_usec);
202   timeout_widget = CreateSimpleButton( rd, str, timeout_callback, (caddr_t)1 );
203   (void)CreateLabelWidget( rd, "","Seconds.",args, n );
204 
205   XtManageChild( rb );
206 
207   /** EXTERNAL FILTER **/
208   /* create a new frame and options */
209   n=0;
210   XtSetArg ( args[n], XmNshadowThickness, 4 ); n++;
211   frame = XmCreateFrame (main_row,"frame",args,n);
212   XtManageChild(frame);
213 
214   n = 0;
215   XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
216   rc = XmCreateRowColumn( frame,"row",args,n);
217   XtManageChild( rc );
218 
219   n=0;
220   CreateLabelWidget (rc, "xxx","  EXTERNAL FILTER  ",args,n);
221 
222   n=0;
223   XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
224   rb = XmCreateRowColumn( rc,"data",args,n);
225   XtManageChild( rb );
226 
227   n=0;
228   ExOn = CreateSimpleButton( rb, extstr1[ExternalOn], ext_callback, (caddr_t)0 );
229   ExtW[0] = CreateLabelWidget( rb, "","Send",args,n );
230   ExFra = CreateSimpleButton( rb, extstr2[ExternalFra], extfra_callback, (caddr_t)0 );
231   ExtW[1] = CreateLabelWidget( rb, "","To External",args,n );
232   ExFil = CreateSimpleButton( rb, extstr3[ExternalFil], extfil_callback, (caddr_t)0 );
233 
234   n=0;
235   XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
236   rb = XmCreateRowColumn( rc,"data",args,n);
237   XtManageChild( rb );
238 
239   n=0;
240   if( ExternalFil ) {
241     ExLab = CreateLabelWidget( rb, "", "External File Name", args, n );
242     if( *ExFileName=='\0')
243       strcpy( ExFileName, "foobar" );
244     ExFilNam= CreateSimpleButton( rb, ExFileName, filtername_callback, (caddr_t)0 );
245   } else {
246     ExLab = CreateLabelWidget( rb, "", "External Filter Name", args, n );
247     if( *ExFilterBName=='\0')
248       strcpy( ExFilterBName, "   " );
249     ExFilNam= CreateSimpleButton( rb, ExFilterBName, filtername_callback, (caddr_t)0 );
250   }
251 
252   n=0;
253   XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
254   rb = XmCreateRowColumn( rc,"data",args,n);
255   XtManageChild( rb );
256 
257   DataLab = CreateLabelWidget( rb, "", "Data Format", args, n );
258   DataPB = CreateSimpleButton( rb, DataFormatStr[DataFormat], data_callback, NULL );
259 
260   if( ExternalOn==0 ) {
261     for( n=0;n<2;n++ )
262       XtSetSensitive( ExtW[n], False );
263     XtSetSensitive( ExFra, False );
264     XtSetSensitive( ExFil, False );
265     XtSetSensitive( ExLab, False );
266   }
267   XtSetSensitive( ExFilNam, ExternalOn&&(ExternalFil<2) );
268   XtSetSensitive( DataLab, ExternalOn&&ExternalFil );
269   XtSetSensitive( DataPB, ExternalOn&&ExternalFil );
270 
271 
272   /* create FILTER, CANCEL, HELP buttons */
273 
274   /* create a form to hold OK, Cancel, and Help buttons */
275   n = 0;
276   rc = XtCreateManagedWidget("buttons",
277 	        xmFormWidgetClass,main_row,args,n);
278 
279   /* create 'Filter' pushbutton */
280   n = 0;
281 /*  XtSetArg( args[n], XmNshowAsDefault, 1 ); n++; */
282   XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
283   XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
284   XtSetArg (args[n], XmNrightPosition, 30); n++;
285   rb = CreatePushButton( rc, "Filter", "Filter" ,args, n, filterstream );
286 
287   /* Set OK button as default */
288   BulletinDefaultButton( bb_widget, rb );
289 
290   /* create 'Cancel' pushbutton */
291   n = 0;
292   XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
293   XtSetArg (args[n], XmNleftPosition, 35); n++;
294   XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
295   XtSetArg (args[n], XmNrightPosition, 65); n++;
296   (void)CreatePushButton( rc, "Cancel", "Cancel", args, n, cancel_callback );
297 
298   /* create 'Help' pushbutton */
299   n = 0;
300   XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
301   XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
302   XtSetArg (args[n], XmNleftPosition, 70); n++;
303   rb = CreatePushButton( rc, "Help", "Help", args, n, help_callback );
304 
305   /* turn off 'Help' pushbutton for now */
306   XtSetSensitive( rb, False  );
307   XtManageChild(rc);
308   XtManageChild(bb_widget);
309 }
310 
dir_callback(widget,data,foo)311 static void dir_callback( widget, data, foo )
312      Widget  widget;
313      caddr_t data;
314      caddr_t foo;
315 {
316   filter_direction = (int)data;
317 }       /* dir_callback */
318 
ooo_callback(widget,data,foo)319 static void ooo_callback( widget, data, foo )
320      Widget  widget;
321      caddr_t data;
322      caddr_t foo;
323 {
324   if( AssembleOOO ) {
325     AssembleOOO = 0;
326     aflag = 0;
327   } else {
328     AssembleOOO = 1;
329     aflag = 1;
330   }
331 }       /* ooo_callback */
332 
timeout_callback(widget,data,foo)333 static void timeout_callback( widget, data, foo )
334      Widget  widget;
335      caddr_t data;
336      caddr_t foo;
337 {
338   Widget w;
339   Arg args[2];
340   int n;
341   XmString ms;
342 
343   if( data ) {
344     /* request new timeout value */
345     ms = XmStringCreateSimple("Timeout value in seconds");
346     n = 0;
347     XtSetArg (args[n], XmNselectionLabelString, ms); n++;
348     XtSetArg( args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL ); n++;
349     w = XmCreatePromptDialog( bb_widget, "Timeout Selection",args,n);
350     XtAddCallback( w, XmNokCallback, time_callback, (caddr_t)0);
351     XtManageChild( w );
352     XmStringFree( ms );
353   } else {
354     /* just toggle HighlightTimeout */
355     if( HighlightTimeout )
356       HighlightTimeout = 0;
357     else
358       HighlightTimeout = 1;
359   }
360 }       /* timeout_callback */
361 
time_callback(widget,data,foo)362 static void time_callback( widget, data, foo )
363      Widget  widget;
364      char *data;
365      XmSelectionBoxCallbackStruct *foo;
366 {
367   char *string;
368   char str[20];
369   XtUnmanageChild(widget);
370 
371   XmStringGetLtoR( foo->value, XmSTRING_DEFAULT_CHARSET, &string);
372   Timeout.tv_sec = atoi(string);
373   Timeout.tv_usec = (atof(string) - (double)(Timeout.tv_sec))*1000000;
374   /* don't allow a timeout of <= 0.0 seconds */
375   if( (Timeout.tv_usec==0 && Timeout.tv_sec==0) ||
376      Timeout.tv_sec < 0 || Timeout.tv_usec < 0 ) {
377     Timeout.tv_sec = 1;
378     Timeout.tv_usec = 0;
379   }
380   sprintf(str,"%d.%d",Timeout.tv_sec,Timeout.tv_usec);
381   SetLabel(timeout_widget,str);
382 }
383 
help_callback(widget,name,call_data)384 static void help_callback( widget, name, call_data )
385      Widget  widget;
386      char    *name;
387      caddr_t call_data;
388 {
389 
390 }       /* help_callback */
391 
ext_callback(widget,name,call_data)392 static void ext_callback( widget, name, call_data )
393      Widget  widget;
394      char    *name;
395      caddr_t call_data;
396 {
397   if( ExternalOn )
398     ExternalOn = 0;
399   else
400     ExternalOn = 1;
401 
402   update_external_filter();
403 }       /* ext_callback */
404 
405 
data_callback(widget,name,call_data)406 static void data_callback( widget, name, call_data )
407      Widget  widget;
408      char    *name;
409      caddr_t call_data;
410 {
411   if( DataFormat )
412     DataFormat = 0;
413   else
414     DataFormat = 1;
415 
416   update_external_filter();
417 }       /* ext_callback */
418 
extfil_callback(widget,name,call_data)419 static void extfil_callback( widget, name, call_data )
420      Widget  widget;
421      char    *name;
422      caddr_t call_data;
423 {
424   if( ++ExternalFil == 3 )
425     ExternalFil = 0;
426   update_external_filter();
427 }       /* ext_callback */
428 
429 
extfra_callback(widget,name,call_data)430 static void extfra_callback( widget, name, call_data )
431      Widget  widget;
432      char    *name;
433      caddr_t call_data;
434 {
435   if( ExternalFra )
436     ExternalFra = 0;
437   else
438     ExternalFra = 1;
439 
440  update_external_filter();
441 }       /* ext_callback */
442 
443 
filterstream(parent,nam,foo)444 static void filterstream(parent, nam, foo)
445      Widget parent;
446      char *nam;
447      caddr_t foo;
448 {
449   struct filter filt;
450   struct address_filter *f;
451   int i;
452   char str[128], *temp, Xfilename[128];
453   extern char Viewer[];
454   void reset_tcp_assembly();
455 
456   XtUnmanageChild( bb_widget );
457   reset_tcp_assembly();
458 
459   if( D_Src_Port==0 && D_Dst_Port==0 )
460     return;
461 
462   f = &filt.addr[0];
463   f->level = 0;  /* IP */
464   strcpy(f->address1,D_Src_Host);
465   strcpy(f->address2,D_Dst_Host);
466   f->direction = filter_direction;
467   f->include = 1;
468   f->and = 1;
469 
470   filt.protocol = 0;
471   for(i=1;i<NUM_PROTOS;i++) {
472     if( !strcmp(D_Proto,protostr[i]) ) {
473       filt.protocol = 1<<i;
474       break;
475     }
476   }
477   filt.port = 0;
478   filt.addr[1].and = 0;	/* OFF */
479   update_fstr(&filt);
480   (void)sprintf(str," and ( port %u and %u )",D_Src_Port, D_Dst_Port);
481   strcat(Fstr,str);
482   /*  fprintf(stderr,"Fstr=%s\n",Fstr); */
483 
484   if( ExternalOn ) {
485     aflag = 1;		/* assemble the output */
486     if( ExternalFil==1 )   /* send to file */
487       strcpy(Xfilename,ExFileName);
488     else
489       strcpy(Xfilename,tmpnam(NULL));
490     Xfile = fopen( Xfilename, "a" );
491     if( Xfile==NULL ) {
492       xperror( Xfilename );
493       return;
494     }
495     Xflag = DataFormat;
496     if( ExternalFil == 0 ) /* Filter */
497       Xflag = Zflag = 1;
498     else if( ExternalFra ) 	    /* send frames and data */
499       Zflag = 1;
500     else
501       zflag = 1;
502 
503   }
504 
505   redisplay_entire_list();
506 
507   if( ExternalOn ) {
508     fclose( Xfile );
509     Xfile = NULL;
510     if( ExternalFil == 0 ) {	/* Filter */
511       /* open another temp file */
512       temp = tmpnam(NULL);
513       if( ExternalFra )
514 	sprintf( str, "cat %s | %s -f > %s\n",Xfilename,ExFilterName,temp );
515       else
516 	sprintf( str, "cat %s | %s > %s\n",Xfilename,ExFilterName,temp );
517       (void)system( str );
518       unlink( Xfilename );
519       strcpy( Xfilename, temp );
520     }
521     if( ExternalFil != 1 ) {
522       if( *Viewer == '*' ) {
523 	show_text( Xfilename, ExFilterBName );
524 	unlink( Xfilename );
525       } else {
526 	sprintf( str, "( %s %s ; rm %s ) &", Viewer, Xfilename, Xfilename );
527 	system( str );
528       }
529     }
530   }
531 
532   /* reset all global state variables */
533   *Fstr = '\0';
534   reset_tcp_assembly();
535   Ho = AssembleOOO;
536   Ht = HighlightTimeout;
537   AssembleOOO = 0;
538   HighlightTimeout = 0;
539   aflag = Zflag = zflag = Xflag = 0;
540 }
541 
542 static
cancel_callback(widget,name,foo)543 void cancel_callback( widget, name, foo )
544 Widget  widget;
545 char    *name;
546 caddr_t foo;
547 {
548   XtUnmanageChild( bb_widget );
549   AssembleOOO = 0;
550   HighlightTimeout = 0;
551   aflag = 0;
552 }
553 
update_external_filter()554 static void update_external_filter()
555 {
556   int n;
557 
558   SetLabel( ExOn, extstr1[ExternalOn] );
559   SetLabel( ExFra, extstr2[ExternalFra] );
560   SetLabel( ExFil, extstr3[ExternalFil] );
561 
562   if( ExternalFil ) {
563     SetLabel( ExLab, "External File Name" );
564     if( *ExFileName=='\0')
565       strcpy( ExFileName, "foobar" );
566     SetLabel( ExFilNam, ExFileName );
567   } else {
568     SetLabel( ExLab, "External Filter Name" );
569     if( *ExFilterBName=='\0')
570       strcpy( ExFilterBName, "   " );
571     SetLabel( ExFilNam, ExFilterBName );
572   }
573 
574   SetLabel( DataPB, DataFormatStr[DataFormat] );
575 
576   for( n=0;n<2;n++ )
577     XtSetSensitive( ExtW[n], ExternalOn );
578   XtSetSensitive( ExFra, ExternalOn );
579   XtSetSensitive( ExFil, ExternalOn );
580   XtSetSensitive( ExLab, ExternalOn&&(ExternalFil<2) );
581   XtSetSensitive( ExFilNam, ExternalOn&&(ExternalFil<2) );
582   XtSetSensitive( DataLab, ExternalOn&&ExternalFil);
583   XtSetSensitive( DataPB, ExternalOn&&ExternalFil);
584 }
585 
filtername_callback(widget,name,call_data)586 static void filtername_callback( widget, name, call_data )
587      Widget  widget;
588      char    *name;
589      caddr_t call_data;
590 {
591   Widget help, filew;
592   Arg args[5];
593   int t=0, n=0;
594   XmString xms;
595   extern char FilterDir[];
596 
597   if( !ExternalFil && *FilterDir ) {
598     xms = XmStringCreateSimple(FilterDir);
599     XtSetArg( args[n], XmNdirectory, xms); n++;
600     t = 1;
601   }
602   XtSetArg( args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL ); n++;
603   filew = XmCreateFileSelectionDialog( widget,"XX",args,n);
604   XtAddCallback(filew, XmNokCallback, filter_ok_callback, 0);
605   XtAddCallback(filew, XmNcancelCallback, filter_cancel_callback, 0);
606   help = XmFileSelectionBoxGetChild(filew,XmDIALOG_HELP_BUTTON);
607   XtUnmanageChild( help );
608   XtManageChild( filew );
609   if( t ) XmStringFree(xms);
610 
611 }       /* filtername_callback */
612 
613 
614 static
filter_cancel_callback(widget,name,foo)615 void filter_cancel_callback( widget, name, foo )
616 Widget  widget;
617 char    *name;
618 caddr_t foo;
619 {
620   XtUnmanageChild( widget );
621 }
622 
623 static
filter_ok_callback(widget,name,file_struct)624 void filter_ok_callback( widget, name, file_struct )
625 Widget  widget;
626 char    *name;
627 XmFileSelectionBoxCallbackStruct  *file_struct;
628 {
629   char    *string, *str;
630 
631   XmStringGetLtoR( file_struct->value,
632 		  XmSTRING_DEFAULT_CHARSET,
633 		  &string );
634 
635   XtUnmanageChild(widget);
636   if( ExternalFil==0 ) {	/* Filter */
637     strcpy( ExFilterName, string );
638     str = strrchr(string,'/');
639     if( *(++str) )
640       strcpy( ExFilterBName, str );
641   } else
642     strcpy(ExFileName, string );
643   update_external_filter();
644   XtFree(string);
645 }
646 
647 
648