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