1 /* wmisdn - an ISDN monitor applet for windowmaker/afterstep
2 * Copyright (c) 2000-2001 Tasho Statev Kaletha
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 /* these defaults can be changed by command line options. */
19 #define WINDOWMAKER false
20 #define USESHAPE false
22 #define CLASS "WMIsdn"
31 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
37 #include <netinet/in.h>
39 #include <asm/errno.h> /* for ENOTCONN */
44 #include <X11/Xutil.h>
45 #include <X11/Xproto.h>
47 #include <X11/extensions/shape.h>
49 #include <linux/isdn.h>
50 #include <linux/isdnif.h>
54 #include "optics/optics.h"
56 static Pixmap coverPixmap
;
57 static Pixmap unknownPixmap
;
58 static Pixmap dialingPixmap
;
59 static Pixmap offPixmap
;
60 static Pixmap disabledPixmap
;
61 static Pixmap statusPixmaps
[6];
62 static Pixmap incomingPixmap
, outgoingPixmap
, bundlingPixmap
, bundledPixmap
, slavePixmap
;
65 static Pixmap ledsPixmap
; /* a row of led symbols as shown by the var led_text below */
66 static Pixmap lampsPixmap
; /* a row of lamp images - green off, green on, yellow off, yellow on, red off, red on */
67 static Pixmap infoSWPixmap
; /* a row of arrows - left off, left on, right off, right on */
68 static Pixmap lampsSWPixmap
; /* a row of arrows - up off, up on, down off, down on */
70 #include "xpm/unknown.xpm"
71 #include "xpm/disabled.xpm"
72 #include "xpm/off.xpm"
73 #include "xpm/offline.xpm"
74 #include "xpm/dialing.xpm"
75 #include "xpm/incoming.xpm"
76 #include "xpm/outgoing.xpm"
77 #include "xpm/bundling.xpm"
78 #include "xpm/bundled.xpm"
79 #include "xpm/slave.xpm"
80 #include "xpm/raw.xpm"
81 #include "xpm/modem.xpm"
82 #include "xpm/online.xpm"
83 #include "xpm/voice.xpm"
84 #include "xpm/fax.xpm"
86 #include "xpm/cover.xpm"
87 #include "xpm/leds.xpm"
88 #include "xpm/lamps.xpm"
89 #include "xpm/lamps_sw.xpm"
90 #include "xpm/info_sw.xpm"
93 static Pixmap disp_info
; /* double buffer for the info panel */
94 static Pixmap disp
; /* for the main window */
95 static Pixmap dmsk
; /* clip mask for the main window */
97 /* For command line arguments */
98 #define MAX_ARG_LEN 256
99 static bool wmaker
= WINDOWMAKER
;
100 static bool ushape
= USESHAPE
;
101 static char txtdpy
[MAX_ARG_LEN
] = "";
102 static char txtfont
[MAX_ARG_LEN
] = "";
103 static int dialmode
= ISDN_NET_DM_AUTO
;
104 static char devices
[ISDN_MAX_CHANNELS
][MAX_ARG_LEN
];
105 static int selected_device
=-1; /* selected device, points to an element of devices[] */
106 static char scriptpath
[MAX_ARG_LEN
] = "/etc/isdn";
107 static int scriptmode
= 0;
108 static bool usescripts
= false;
109 static int maxscriptmode
= 0;
110 static char** scriptmodestrings
= NULL
;
111 static char *slave_pending
= NULL
;
113 /* atoms for deleting window */
114 static Atom _XA_GNUSTEP_WM_FUNC
;
115 static Atom WM_DELETE_WINDOW
;
117 /* global variables */
119 Window Win
[3]; /* 0 - main win, 1 - icon win (for wmaker), 2 - info panel */
123 XFontStruct
*textFont
=NULL
;
125 static char led_text
[] = "0123456789?/\\!@#$%^&*()_+-=\"~<>[]{}:. abcdefghijklmnopqrstuvwxyz";
128 static int rootUID
, rootGID
;
129 static bool infoPanelActive
= false;
130 static bool lampsActive
= false;
132 /* Der scriptmode wird als 2. Argument den Start-/Stopskripten uebergeben.
133 Aenderung mit mittlerer Maustaste auf InfoSw bei offenem Infopanel. */
135 #define ACTIVE 1 /* values are not only symbolc, but important for calculations! */
137 #define ID_LAMP_GREEN 0
138 #define ID_LAMP_YELLOW 1
139 #define ID_LAMP_RED 2
141 #define ID_SWITCH_INFO 10
142 #define ID_SWITCH_LAMPS 11
143 #define ID_SWITCH_STATUS 19
146 #define UPDATE_INTERVAL 20 /* how many 50 milisec intervalls to wait between updates */
147 #define STATUS_WARNING_SAT 5 /* how many times to display a warning upon failing to retrieve device stats */
151 #define STAT_DISABLED 1000
152 #define STAT_OFF 1001
153 #define STAT_DIALING 1002
154 #define STAT_UNKNOWN 2001
155 #define STAT_UNINITIALIZED 2002
157 #define SCRIPT_UP "wmisdn-up"
158 #define SCRIPT_DOWN "wmisdn-down"
159 #define SCRIPT_MODES "wmisdn-scriptmodes"
161 typedef enum mpppModeType
{ none
, master
, slave
};
169 mpppModeType mpppMode
;
170 char mpppPartner
[100];
171 } curStatus
= { STAT_UNINITIALIZED
, INCOMING
, false, "", none
, "" };
175 /* text i/o routines */
176 bool scanArgs(int argc
, char *argv
[]);
177 void printUsage( char *prog_name
);
179 void parseDeviceNames( char *name_list
);
180 void readScriptModes();
183 /* init/done routines */
184 void initXWin(int argc
, char *argv
[]);
186 void createMainWin( Window
*win
);
187 void createInfoPanel( Window
*win
);
190 void createRegions();
193 /* window routines */
194 void alignInfoPanel();
195 void getWindowPosition( Window win
, int *x
, int *y
);
196 void getWindowDimension( Window win
, int *w
, int *h
);
198 /* graphic routines */
199 unsigned long getColor(const char *colorname
);
200 void createPixmap(char *data
[], Pixmap
*image
, Pixmap
*mask
);
201 void loadLeds(char *data
[], Pixmap
*image
, const char *leds_color
, const char *back_color
);
202 void drawText( char *text
, Pixmap dst
, int x
, int y
, const char *color
=InfoTextColor
);
203 void drawLamp( int index
, int active
);
204 void drawDevice( int active
= INACTIVE
);
205 unsigned long mixColor( const char *colorname1
, int prop1
, const char *colorname2
, int prop2
);
207 /* interaction routines */
211 void repaint( Window win
, int x
, int y
, int w
, int h
);
212 void setStatusPixmap();
213 void updateInfoPanel();
214 void blankMainWin( int x
=0, int y
=0, int w
=MainWinDim
.w
, int h
=MainWinDim
.h
);
215 void pressLamp( int lamp
, int button
);
216 void pressStatusSw();
217 void activateLamps( bool active
);
220 /* region event handlers */
221 void mouseInLamp( int id
);
222 void mouseOutLamp( int id
);
223 void mouseClickLamp( int id
, unsigned int button
);
224 void mouseInInfoSw( int id
);
225 void mouseOutInfoSw( int id
);
226 void mouseClickInfoSw( int id
, unsigned int button
);
227 void mouseInLampsSw( int id
);
228 void mouseOutLampsSw( int id
);
229 void mouseClickLampsSw( int id
, unsigned int button
);
230 void mouseInDevice( int id
);
231 void mouseOutDevice( int id
);
232 void mouseClickDevice( int id
, unsigned int button
);
233 void mouseInStatusSw( int id
);
234 void mouseOutStatusSw( int id
);
235 void mouseClickStatusSw( int id
, unsigned int button
);
238 void selectNextDevice();
241 void exposeEvent( XExposeEvent
*xev
);
242 void pressEvent(XButtonEvent
*xev
);
243 void motionEvent( XMotionEvent
*xev
);
246 void getStatus( char *device
, isdnStatus
*stat
);
247 void getLocalIP( int *a
, int *b
, int *c
, int *d
);
248 inline void getRemoteIP( int *a
, int *b
, int *c
, int *d
);
249 inline void translateIP( struct sockaddr
*addr
, int *a
, int *b
, int *c
, int *d
);
250 int isdn_ioctl( int func
, void *arg
, const char *errmsg
, const char *filename
="/dev/isdnctrl" );
251 void isdnInitDefaultDialmode();
252 int getIpppNum( char *name
);
254 inline void set_slave_pending();
255 inline void clear_slave_pending();
256 inline bool is_slave_pending();
257 inline void manage_slave();
259 /* -------- Implementation ----------- */
261 int main(int argc
, char *argv
[])
264 rootUID
= geteuid(); rootGID
= getegid();
265 seteuid(getuid()); setegid(getgid());
268 if( !scanArgs(argc
, argv
) )
270 printUsage( argv
[0] );
275 initXWin(argc
, argv
);
279 disp
= XCreatePixmap(dpy
, Root
, MainWinDim
.w
, MainWinDim
.h
, DefaultDepth(dpy
,DefaultScreen(dpy
)));
280 disp_info
= XCreatePixmap(dpy
, Root
, InfoWinDim
.w
, InfoWinDim
.h
, DefaultDepth(dpy
,DefaultScreen(dpy
)));
284 gcm
= GCGraphicsExposures
|GCBackground
;
285 gcv
.graphics_exposures
= True
;
286 gcv
.background
= getColor( WindowBackgroundColor
);
287 if( strlen(txtfont
) != 0 )
289 textFont
= XLoadQueryFont( dpy
, txtfont
);
290 if( textFont
!= NULL
)
293 gcv
.font
= textFont
->fid
;
295 syslog( LOG_NOTICE
, "Couldn't load specified font" );
297 WinGC
= XCreateGC(dpy
, Root
, gcm
, &gcv
);
300 drawDevice(INACTIVE
);
301 activateLamps( lampsActive
);
305 if(!(wmaker
|| ushape
))
306 XSetClipMask(dpy
, WinGC
, dmsk
);
308 XShapeCombineMask(dpy
, Win
[activeWin
], ShapeBounding
, 0, 0, dmsk
, ShapeSet
);
310 XSetClipOrigin(dpy
, WinGC
, 0, 0);
311 XSetClipMask(dpy
, WinGC
, None
);
314 XSelectInput(dpy
, Win
[activeWin
], PointerMotionMask
| ButtonPress
| ExposureMask
);
315 XSelectInput(dpy
, Win
[2], ExposureMask
);
316 XMapWindow(dpy
, Win
[0]);
320 while(XPending(dpy
)){
321 XNextEvent(dpy
,&event
);
323 case ButtonPress
: pressEvent(&event
.xbutton
); break;
324 case MotionNotify
: motionEvent(&event
.xmotion
); break;
327 if((Atom
)event
.xclient
.data
.l
[0]==WM_DELETE_WINDOW
)
331 case Expose
: exposeEvent( &event
.xexpose
); break;
342 if( textFont
!= NULL
)
343 XFreeFont( dpy
, textFont
);
346 /* Free runtime pixmaps */
347 XFreePixmap(dpy
, disp_info
);
348 XFreePixmap(dpy
, disp
);
349 XFreePixmap(dpy
, dmsk
);
350 /* Finish with X stuff */
355 void initXWin(int argc
, char *argv
[])
357 if( (dpy
=XOpenDisplay(txtdpy
)) == NULL
)
359 fprintf(stderr
,"cannot open display!\n");
362 _XA_GNUSTEP_WM_FUNC
= XInternAtom(dpy
, "_GNUSTEP_WM_FUNCTION", false);
363 WM_DELETE_WINDOW
= XInternAtom(dpy
, "WM_DELETE_WINDOW", false);
364 Root
=DefaultRootWindow(dpy
);
365 createMainWin(&Win
[0]);
366 createMainWin(&Win
[1]);
367 createInfoPanel( &Win
[2] );
370 hints
.window_group
= Win
[0];
372 shints
.min_height
=64;
374 shints
.max_height
=64;
379 hints
.initial_state
= WithdrawnState
;
380 hints
.icon_window
= Win
[1];
381 hints
.flags
= WindowGroupHint
| StateHint
| IconWindowHint
;
382 shints
.flags
= PMinSize
| PMaxSize
| PPosition
;
386 hints
.initial_state
= NormalState
;
387 hints
.flags
= WindowGroupHint
| StateHint
;
388 shints
.flags
= PMinSize
| PMaxSize
;
391 XSetWMHints(dpy
, Win
[0], &hints
);
392 XSetWMNormalHints(dpy
, Win
[0], &shints
);
393 XSetCommand(dpy
, Win
[0], argv
, argc
);
394 XStoreName(dpy
, Win
[0], NAME
);
395 XSetIconName(dpy
, Win
[0], NAME
);
396 XSetWMProtocols(dpy
, Win
[activeWin
], &WM_DELETE_WINDOW
, 1);
401 XDestroyWindow(dpy
, Win
[0]);
402 XDestroyWindow(dpy
, Win
[1]);
403 XDestroyWindow(dpy
, Win
[2]);
409 createPixmap(cover_xpm
, &coverPixmap
, &dmsk
);
410 createPixmap(dialing_xpm
, &dialingPixmap
, NULL
);
411 createPixmap(unknown_xpm
, &unknownPixmap
, NULL
);
412 createPixmap(disabled_xpm
, &disabledPixmap
, NULL
);
413 createPixmap(off_xpm
, &offPixmap
, NULL
);
415 createPixmap(incoming_xpm
, &incomingPixmap
, NULL
);
416 createPixmap(outgoing_xpm
, &outgoingPixmap
, NULL
);
417 createPixmap(bundling_xpm
, &bundlingPixmap
, NULL
);
418 createPixmap(bundled_xpm
, &bundledPixmap
, NULL
);
419 createPixmap(slave_xpm
, &slavePixmap
, NULL
);
421 createPixmap(offline_xpm
, &statusPixmaps
[ISDN_USAGE_NONE
], NULL
);
422 createPixmap(raw_xpm
, &statusPixmaps
[ISDN_USAGE_RAW
], NULL
);
423 createPixmap(modem_xpm
, &statusPixmaps
[ISDN_USAGE_MODEM
], NULL
);
424 createPixmap(online_xpm
, &statusPixmaps
[ISDN_USAGE_NET
], NULL
);
425 createPixmap(voice_xpm
, &statusPixmaps
[ISDN_USAGE_VOICE
], NULL
);
426 createPixmap(fax_xpm
, &statusPixmaps
[ISDN_USAGE_FAX
], NULL
);
428 createPixmap(lamps_xpm
, &lampsPixmap
, NULL
);
429 createPixmap(info_sw_xpm
, &infoSWPixmap
, NULL
);
430 createPixmap(lamps_sw_xpm
, &lampsSWPixmap
, NULL
);
431 loadLeds( leds_xpm
, &ledsPixmap
, InfoTextColor
, WindowBackgroundColor
);
436 XFreePixmap(dpy
, coverPixmap
);
437 XFreePixmap(dpy
, dialingPixmap
);
438 XFreePixmap(dpy
, unknownPixmap
);
439 XFreePixmap(dpy
, disabledPixmap
);
440 XFreePixmap(dpy
, offPixmap
);
442 XFreePixmap(dpy
, incomingPixmap
);
443 XFreePixmap(dpy
, outgoingPixmap
);
444 XFreePixmap(dpy
, bundlingPixmap
);
445 XFreePixmap(dpy
, bundledPixmap
);
446 XFreePixmap(dpy
, slavePixmap
);
448 for( int i
=ISDN_USAGE_NONE
; i
< ISDN_USAGE_FAX
; i
++ )
449 XFreePixmap( dpy
, statusPixmaps
[i
] );
451 XFreePixmap(dpy
, ledsPixmap
);
452 XFreePixmap(dpy
, lampsPixmap
);
453 XFreePixmap(dpy
, infoSWPixmap
);
454 XFreePixmap(dpy
, lampsSWPixmap
);
457 void createMainWin( Window
*win
)
459 *win
= XCreateSimpleWindow(dpy
, Root
, 10, 10, MainWinDim
.w
, MainWinDim
.h
,0,0,0);
461 XClassHint classHint
;
462 classHint
.res_name
= NAME
;
463 classHint
.res_class
= CLASS
;
464 XSetClassHint(dpy
, *win
, &classHint
);
467 void createInfoPanel( Window
*win
)
469 *win
= XCreateSimpleWindow(dpy
, Root
, 10, 10, InfoWinDim
.w
, InfoWinDim
.h
,0,0,0);
472 shints
.flags
= PPosition
;
473 XSetWMNormalHints( dpy
, *win
, &shints
);
475 XClassHint classHint
;
476 classHint
.res_name
= "Info";
477 classHint
.res_class
= CLASS
;
478 XSetClassHint(dpy
, *win
, &classHint
);
485 region_add( Win
[activeWin
], ID_LAMP_GREEN
, LampsRect
[ID_LAMP_GREEN
].pos
.x
, LampsRect
[ID_LAMP_GREEN
].pos
.y
, LampsRect
[ID_LAMP_GREEN
].dim
.w
, LampsRect
[ID_LAMP_GREEN
].dim
.h
, mouseInLamp
, mouseOutLamp
, mouseClickLamp
);
486 region_add( Win
[activeWin
], ID_LAMP_YELLOW
, LampsRect
[ID_LAMP_YELLOW
].pos
.x
, LampsRect
[ID_LAMP_YELLOW
].pos
.y
, LampsRect
[ID_LAMP_YELLOW
].dim
.w
, LampsRect
[ID_LAMP_YELLOW
].dim
.h
, mouseInLamp
, mouseOutLamp
, mouseClickLamp
);
487 region_add( Win
[activeWin
], ID_LAMP_RED
, LampsRect
[ID_LAMP_RED
].pos
.x
, LampsRect
[ID_LAMP_RED
].pos
.y
, LampsRect
[ID_LAMP_RED
].dim
.w
, LampsRect
[ID_LAMP_RED
].dim
.h
, mouseInLamp
, mouseOutLamp
, mouseClickLamp
);
489 region_add( Win
[activeWin
], ID_SWITCH_INFO
, InfoSWRect
.pos
.x
, InfoSWRect
.pos
.y
, InfoSWRect
.dim
.w
, InfoSWRect
.dim
.h
, mouseInInfoSw
, mouseOutInfoSw
, mouseClickInfoSw
);
490 region_add( Win
[activeWin
], ID_SWITCH_LAMPS
, LampsSWRect
.pos
.x
, LampsSWRect
.pos
.y
, LampsSWRect
.dim
.w
, LampsSWRect
.dim
.h
, mouseInLampsSw
, mouseOutLampsSw
, mouseClickLampsSw
);
492 region_add( Win
[activeWin
], ID_DEVICE
, DeviceRect
.pos
.x
, DeviceRect
.pos
.y
, DeviceRect
.dim
.w
, DeviceRect
.dim
.h
, mouseInDevice
, mouseOutDevice
, mouseClickDevice
);
493 region_add( Win
[activeWin
], ID_SWITCH_STATUS
, StatusPixmapRect
.pos
.x
, StatusPixmapRect
.pos
.y
, StatusPixmapRect
.dim
.w
, StatusPixmapRect
.dim
.h
, mouseInStatusSw
, mouseOutStatusSw
, mouseClickStatusSw
);
496 bool validIppp( char *name
)
498 if( strlen(name
) < 5 )
500 if( strncmp( name
, "ippp", 4 ) != 0 )
502 for( char *p
=name
+4; *p
!= '\x0'; p
++ )
505 if( getIpppNum(name
) >= ISDN_MAX_CHANNELS
)
510 int getIpppNum( char *name
)
512 return atoi( name
+ 4 );
515 void selectNextDevice()
518 if( devices
[selected_device
][0] == 0 )
524 void printUsage( char *prog_name
)
526 fprintf( stderr
, "usage:\n\n %s [options]\n\noptions:\n\n", prog_name
);
527 fprintf( stderr
, " -h | -help | --help display this help screen\n");
528 fprintf( stderr
, " -w use WithdrawnState (for WindowMaker)\n" );
529 fprintf( stderr
, " -s shaped window\n" );
530 fprintf( stderr
, " -display display select target display (see X manual pages)\n" );
531 fprintf( stderr
, " -font font select the font for displaying status information\n" );
532 fprintf( stderr
, " -dialmode mode select dial mode for offline mode (auto or manual)\n" );
533 fprintf( stderr
, " -device device select ippp devices to monitor\n" );
534 fprintf( stderr
, " (a list of comma-separated device names is expected containing __no blanks__)\n" );
535 fprintf( stderr
, " -lamps activate the line control switches upon startup\n" );
536 fprintf( stderr
, " -usescripts use user scripts for dialing/hanging up instead of direct ioctl calls\n" );
537 fprintf( stderr
, " -path path select directory with the up-/down-scripts\n\n" );
542 fprintf( stderr
, "wmisdn v1.8 (C) 1999-2001 Tasho Statev Kaletha (kaletha@informatik.uni-bonn.de).\n\n" );
545 void parseDeviceNames( char *name_list
)
552 for( i
= 0; i
< ISDN_MAX_CHANNELS
; i
++ )
554 ptr2
= strchr(ptr1
,',');
556 ptr2
= &name_list
[strlen(name_list
)];
557 strncpy( devices
[i
], ptr1
, ptr2
-ptr1
);
558 devices
[i
][ptr2
-ptr1
] = 0;
560 if( !validIppp(devices
[i
]) )
561 fprintf( stderr
, "Warning : \"%s\" doesn't seem to be a valid ippp device. wmisdn may not work properly\n", devices
[i
] );
569 bool scanArgs(int argc
, char *argv
[])
571 bool dialmode_set
= false;
573 for(int i
=1;i
<argc
;i
++)
575 if(strcmp(argv
[i
],"-h")==0 || strcmp(argv
[i
],"-help")==0 || strcmp(argv
[i
],"--help")==0)
578 else if(strcmp(argv
[i
],"-w")==0)
580 else if(strcmp(argv
[i
],"-s")==0)
582 else if(strcmp(argv
[i
],"-lamps")==0)
584 else if(strcmp(argv
[i
],"-usescripts")==0)
587 else if(strcmp(argv
[i
],"-display")==0)
592 if( strlen(argv
[i
]) > MAX_ARG_LEN
-1 )
594 fprintf( stderr
, "Argument for -display option too long\n" );
597 sprintf(txtdpy
,"%s",argv
[i
]);
601 else if(strcmp(argv
[i
],"-font")==0)
606 if( strlen(argv
[i
]) > MAX_ARG_LEN
-1 )
608 fprintf( stderr
, "Argument for -font option too long\n" );
611 sprintf(txtfont
,"%s",argv
[i
]);
615 else if(strcmp(argv
[i
],"-dialmode")==0)
620 if( strcmp(argv
[i
], "auto")==0 )
621 dialmode
= ISDN_NET_DM_AUTO
;
622 else if( strcmp(argv
[i
], "manual")==0 )
623 dialmode
= ISDN_NET_DM_MANUAL
;
625 fprintf( stderr
, "Unknown dial mode \"%s\"\n", argv
[i
] );
631 else if(strcmp(argv
[i
],"-device")==0)
636 if( strlen(argv
[i
]) > MAX_ARG_LEN
-1 )
638 fprintf( stderr
, "Argument for -device option too long\n" );
641 parseDeviceNames( argv
[i
] );
645 else if(strcmp(argv
[i
],"-path")==0)
650 if( strlen(argv
[i
]) > MAX_ARG_LEN
-1 )
652 fprintf( stderr
, "Argument for -path option too long\n" );
655 strcpy( scriptpath
, argv
[i
] );
659 fprintf( stderr
, "Unknown option \"%s\"\n", argv
[i
] );
665 isdnInitDefaultDialmode();
666 if( selected_device
== -1 )
668 strcpy( devices
[0], "ippp0" );
676 /* Reads the string representations of the scriptmode parameter given to the up/down scripts
677 * and initializes the coresponding variables */
678 void readScriptModes()
682 sprintf( filename
, "%s/%s", scriptpath
, SCRIPT_MODES
);
683 FILE *f
= fopen( filename
, "r" );
684 /* init one default string if reading fails */
685 if( f
== NULL
|| (fgets(buf
,sizeof(buf
),f
) == NULL
) || !usescripts
)
689 syslog( LOG_NOTICE
, "Couldn't read script mode strings: %m" );
690 scriptmodestrings
= (char **)malloc( sizeof(char*) );
691 scriptmodestrings
[0] = (char *)malloc( sizeof("go online") );
692 strcpy(scriptmodestrings
[0], "go online" );
697 maxscriptmode
= -1; /* the first iteration sets it to 0 - first array index */
699 /* read the strings and put them into the scriptmodestrings array */
703 scriptmodestrings
= (char **)realloc( scriptmodestrings
, (maxscriptmode
+1)*sizeof(char*) );
704 scriptmodestrings
[maxscriptmode
] = (char *)malloc( strlen(buf
)+1 );
705 while( strchr(buf
,'\n') != NULL
)
706 *strchr(buf
,'\n') = '\0';
707 strcpy( scriptmodestrings
[maxscriptmode
], buf
);
708 } while( fgets(buf
,sizeof(buf
),f
) != NULL
);
712 void advanceScriptMode()
715 if(scriptmode
> maxscriptmode
)
721 * - if a lamp is pressed then the corresponding actions are taken.
722 * - outside a lamp the extended view is turned on or off
724 void pressEvent(XButtonEvent
*xev
)
726 if( region_in( xev
->window
, xev
->x
, xev
->y
) )
727 region_mouse_click( xev
->window
, xev
->x
, xev
->y
, xev
->button
);
731 * - draws a lamp in an active state if the pointer passes above it
733 void motionEvent( XMotionEvent
*xev
)
735 region_mouse_motion( xev
->window
, xev
->x
, xev
->y
);
738 void exposeEvent( XExposeEvent
*xev
)
740 repaint( xev
->window
, xev
->x
, xev
->y
, xev
->width
, xev
->height
);
743 void alignInfoPanel()
745 /* get the position of the main win */
746 int win_x
, win_y
, screen_w
, screen_h
, panel_x
, panel_y
;
747 getWindowPosition( Win
[activeWin
], &win_x
, &win_y
);
748 getWindowDimension( Root
, &screen_w
, &screen_h
);
749 /* find a suitable position for the info panel */
750 if( win_x
- InfoWinDim
.w
> 0 )
751 panel_x
= win_x
- InfoWinDim
.w
;
753 panel_x
= win_x
+ MainWinDim
.w
;
756 XMoveWindow( dpy
, Win
[2], panel_x
, panel_y
);
759 void mouseInLamp( int id
)
761 drawLamp( id
, ACTIVE
);
762 for( int i
=0; i
< 3; i
++ )
763 repaint( Win
[activeWin
], LampsRect
[i
].pos
.x
, LampsRect
[i
].pos
.y
, LampsRect
[i
].dim
.w
, LampsRect
[i
].dim
.h
);
766 void mouseOutLamp( int id
)
768 drawLamp( id
, INACTIVE
);
769 for( int i
=0; i
< 3; i
++ )
770 repaint( Win
[activeWin
], LampsRect
[i
].pos
.x
, LampsRect
[i
].pos
.y
, LampsRect
[i
].dim
.w
, LampsRect
[i
].dim
.h
);
773 void mouseClickLamp( int id
, unsigned int button
)
775 pressLamp( id
, button
);
779 inline void drawInfoSwitch( int active
)
781 int pixmap_index
= (infoPanelActive
? 2:0) + active
;
782 int offset_x
= pixmap_index
* InfoSWRect
.dim
.w
;
783 XCopyArea( dpy
, infoSWPixmap
, disp
, WinGC
, offset_x
, 0, InfoSWRect
.dim
.w
, InfoSWRect
.dim
.h
, InfoSWRect
.pos
.x
, InfoSWRect
.pos
.y
);
784 repaint( Win
[activeWin
], InfoSWRect
.pos
.x
, InfoSWRect
.pos
.y
, InfoSWRect
.dim
.w
, InfoSWRect
.dim
.h
);
787 void mouseInInfoSw( int id
)
789 drawInfoSwitch(ACTIVE
);
792 void mouseOutInfoSw( int id
)
794 drawInfoSwitch(INACTIVE
);
797 void mouseClickInfoSw( int id
, unsigned int button
)
799 if( !infoPanelActive
)
802 XMapWindow( dpy
, Win
[2] );
804 XUnmapWindow( dpy
, Win
[2] );
805 infoPanelActive
= !infoPanelActive
;
806 mouseInInfoSw( ID_SWITCH_INFO
);
810 inline void drawLampsSwitch( int active
)
812 int pixmap_index
= (lampsActive
? 2:0) + active
;
813 int offset_x
= pixmap_index
* LampsSWRect
.dim
.w
;
814 XCopyArea( dpy
, lampsSWPixmap
, disp
, WinGC
, offset_x
, 0, LampsSWRect
.dim
.w
, LampsSWRect
.dim
.w
, LampsSWRect
.pos
.x
, LampsSWRect
.pos
.y
);
815 repaint( Win
[activeWin
], LampsSWRect
.pos
.x
, LampsSWRect
.pos
.y
, LampsSWRect
.dim
.w
, LampsSWRect
.dim
.h
);
818 void mouseInLampsSw( int id
)
820 drawLampsSwitch(ACTIVE
);
823 void mouseOutLampsSw( int id
)
825 drawLampsSwitch(INACTIVE
);
828 void mouseClickLampsSw( int id
, unsigned int button
)
830 activateLamps( !lampsActive
);
831 mouseInLampsSw( ID_SWITCH_LAMPS
);
834 void activateLamps( bool active
)
838 drawLamp( 0, INACTIVE
);
839 drawLamp( 1, INACTIVE
);
840 drawLamp( 2, INACTIVE
);
841 region_enable( Win
[activeWin
], ID_LAMP_GREEN
);
842 region_enable( Win
[activeWin
], ID_LAMP_YELLOW
);
843 region_enable( Win
[activeWin
], ID_LAMP_RED
);
845 for( int i
=0; i
< 3; i
++ )
846 blankMainWin( LampsRect
[i
].pos
.x
, LampsRect
[i
].pos
.y
, LampsRect
[i
].dim
.w
, LampsRect
[i
].dim
.h
);
847 region_disable( Win
[activeWin
], ID_LAMP_GREEN
);
848 region_disable( Win
[activeWin
], ID_LAMP_YELLOW
);
849 region_disable( Win
[activeWin
], ID_LAMP_RED
);
851 lampsActive
= active
;
857 drawInfoSwitch( INACTIVE
);
858 drawLampsSwitch( INACTIVE
);
861 void mouseInDevice( int id
)
864 repaint( Win
[activeWin
], 0, 0, MainWinDim
.w
, MainWinDim
.h
);
867 void mouseOutDevice( int id
)
869 drawDevice(INACTIVE
);
870 repaint( Win
[activeWin
], 0, 0, MainWinDim
.w
, MainWinDim
.h
);
873 void mouseClickDevice( int id
, unsigned int button
)
876 mouseInDevice( ID_DEVICE
);
880 void drawDevice( int active
)
882 char *color
= active
== ACTIVE
? DeviceColorHigh
: DeviceColorLow
;
883 drawText( devices
[selected_device
], disp
, DeviceRect
.pos
.x
, DeviceRect
.pos
.y
, color
);
886 void mouseInStatusSw( int id
)
888 /* drawStatusSw( ACTIVE ); */
891 void mouseOutStatusSw( int id
)
893 /* drawStatusSw( INACTIVE ); */
896 void mouseClickStatusSw( int id
, unsigned int button
)
902 /* void drawStatusSw( int active ) */
904 void getWindowPosition( Window win
, int *x
, int *y
)
906 XWindowAttributes winAttr
;
909 XGetWindowAttributes( dpy
, win
, &winAttr
);
910 XTranslateCoordinates( dpy
, win
, winAttr
.root
,
911 -winAttr
.border_width
, -winAttr
.border_width
,
915 void getWindowDimension( Window win
, int *w
, int *h
)
917 XWindowAttributes winAttr
;
918 XGetWindowAttributes( dpy
, win
, &winAttr
);
922 void repaint( Window win
, int x
, int y
, int w
, int h
)
926 if( win
== Win
[activeWin
] )
928 else if( win
== Win
[2] )
931 syslog( LOG_DEBUG
, "Oops! Unknown window given to repaint\n" );
936 XCopyArea( dpy
, src
, win
, WinGC
, x
, y
, w
, h
, x
, y
);
942 repaint( Win
[activeWin
], 0, 0, MainWinDim
.w
, MainWinDim
.h
);
943 if( infoPanelActive
)
944 repaint( Win
[2], 0, 0, InfoWinDim
.w
, InfoWinDim
.h
);
949 static int ticker
= 0;
950 if( ticker
++ > UPDATE_INTERVAL
)
958 /* get ISDN device status and update windows as needed */
962 getStatus( devices
[selected_device
], &stat
);
963 if( memcmp(&curStatus
, &stat
, sizeof(stat
)) != 0 )
965 memcpy( &curStatus
, &stat
, sizeof(stat
) );
968 repaint( Win
[activeWin
], 0, 0, MainWinDim
.w
, MainWinDim
.h
);
971 repaint( Win
[2], 0, 0, InfoWinDim
.w
, InfoWinDim
.h
);
974 /* set the appropriate pixmap on the main window */
975 void setStatusPixmap()
977 Pixmap statusPixmap
, directionPixmap
;
979 if( curStatus
.usage
> ISDN_USAGE_NONE
&& curStatus
.usage
<= ISDN_USAGE_FAX
)
981 statusPixmap
= statusPixmaps
[curStatus
.usage
];
982 switch( curStatus
.mpppMode
)
984 case slave
: directionPixmap
= slavePixmap
; break;
985 case master
: if( curStatus
.bundled
== true ) { directionPixmap
= bundledPixmap
; break; }
986 if( is_slave_pending() ) { directionPixmap
= bundlingPixmap
; break; }
987 case none
: directionPixmap
= curStatus
.direction
== INCOMING
? incomingPixmap
: outgoingPixmap
; break;
988 default : syslog( LOG_DEBUG
, "Ooops! curStatus.direction has an invalid value\n" ); directionPixmap
= 0;
992 switch( curStatus
.usage
)
994 case STAT_OFF
: statusPixmap
= offPixmap
; break;
995 case ISDN_USAGE_NONE
: statusPixmap
= statusPixmaps
[ISDN_USAGE_NONE
]; break;
996 case STAT_DISABLED
: statusPixmap
= disabledPixmap
; break;
997 case STAT_DIALING
: statusPixmap
= dialingPixmap
; break;
998 case STAT_UNKNOWN
: statusPixmap
= unknownPixmap
; break;
999 default : syslog( LOG_DEBUG
, "Ooops! curStatus.usage has an invalid value\n" ); statusPixmap
= 0;
1001 directionPixmap
= 0;
1003 if( statusPixmap
!= 0 )
1004 XCopyArea(dpy
, statusPixmap
, disp
, WinGC
, StatusPixmapRect
.pos
.x
, StatusPixmapRect
.pos
.y
, StatusPixmapRect
.dim
.w
, StatusPixmapRect
.dim
.h
, StatusPixmapRect
.pos
.x
, StatusPixmapRect
.pos
.y
);
1005 if( directionPixmap
!= 0 )
1006 XCopyArea(dpy
, directionPixmap
, disp
, WinGC
, DirectionPixmapRect
.pos
.x
, DirectionPixmapRect
.pos
.y
, DirectionPixmapRect
.dim
.w
, DirectionPixmapRect
.dim
.h
, DirectionPixmapRect
.pos
.x
, DirectionPixmapRect
.pos
.y
);
1009 /* update the info panel */
1010 void updateInfoPanel()
1012 XSetForeground( dpy
, WinGC
, getColor(WindowBackgroundColor
) );
1013 XFillRectangle( dpy
, disp_info
, WinGC
, 0, 0, InfoWinDim
.w
, InfoWinDim
.h
);
1015 if( (curStatus
.usage
> ISDN_USAGE_NONE
&& curStatus
.usage
<= ISDN_USAGE_FAX
) || curStatus
.usage
== STAT_DIALING
)
1017 sprintf( line
, "peer phone: %s", curStatus
.peerPhone
);
1018 drawText( line
, disp_info
, 5, 5 );
1020 if( (curStatus
.usage
== ISDN_USAGE_NET
) && (curStatus
.mpppMode
!= slave
) )
1023 getLocalIP( &a
, &b
, &c
, &d
);
1024 sprintf( line
, "local ip : %d.%d.%d.%d", a
, b
, c
, d
);
1025 drawText( line
, disp_info
, 5, 20 );
1026 getRemoteIP( &a
, &b
, &c
, &d
);
1027 sprintf( line
, "remote ip: %d.%d.%d.%d", a
, b
, c
, d
);
1028 drawText( line
, disp_info
, 5, 35 );
1030 else if( curStatus
.usage
== STAT_OFF
)
1031 drawText( "dialing disabled", disp_info
, 5, 5 );
1032 else if( curStatus
.usage
== STAT_DISABLED
)
1033 drawText( "device disabled", disp_info
, 5, 5 );
1034 else if( curStatus
.usage
== ISDN_USAGE_NONE
)
1036 drawText( "not connected", disp_info
, 5, 5 );
1037 sprintf( line
, "action: %s", scriptmodestrings
[scriptmode
] );
1038 drawText( line
, disp_info
, 5, 20 );
1040 switch( curStatus
.mpppMode
)
1042 case none
: sprintf( line
, "bundling: none" ); break;
1043 case master
: sprintf( line
, "bundling: master of %s", curStatus
.mpppPartner
); break;
1044 case slave
: sprintf( line
, "bundling: slave of %s", curStatus
.mpppPartner
); break;
1046 drawText( line
, disp_info
, 5, 50 );
1049 void blankMainWin( int x
, int y
, int w
, int h
)
1051 XCopyArea(dpy
, coverPixmap
, disp
, WinGC
, x
, y
, w
, h
, x
, y
);
1054 unsigned long getColor( const char *colorname
)
1057 XWindowAttributes winattr
;
1058 XGetWindowAttributes(dpy
, Root
, &winattr
);
1060 XParseColor(dpy
, winattr
.colormap
, colorname
, &color
);
1061 color
.flags
=DoRed
| DoGreen
| DoBlue
;
1062 XAllocColor(dpy
, winattr
.colormap
, &color
);
1066 void createPixmap(char *data
[], Pixmap
*image
, Pixmap
*mask
)
1068 XpmAttributes pixatt
;
1070 pixatt
.exactColors
=false;
1071 pixatt
.closeness
=40000;
1072 pixatt
.valuemask
=XpmExactColors
| XpmCloseness
| XpmSize
;
1073 XpmCreatePixmapFromData(dpy
, Root
, data
, image
, mask
, &pixatt
);
1076 void loadLeds( char *data
[], Pixmap
*image
, const char *led_color
, const char *back_color
)
1078 XpmAttributes pixatt
;
1079 unsigned long color
[4];
1081 color
[0] = mixColor(led_color
, 0, back_color
, 100);
1082 color
[1] = mixColor(led_color
, 100, back_color
, 0);
1083 color
[2] = mixColor(led_color
, 60, back_color
, 40);
1084 color
[3] = mixColor(led_color
, 25, back_color
, 75);
1086 XpmColorSymbol xpmcsym
[4]={{"led_color_back", NULL
, color
[0] },
1087 {"led_color_high", NULL
, color
[1]},
1088 {"led_color_med", NULL
, color
[2]},
1089 {"led_color_low", NULL
, color
[3]}};
1092 pixatt
.numsymbols
= 4;
1093 pixatt
.colorsymbols
= xpmcsym
;
1094 pixatt
.exactColors
= false;
1095 pixatt
.closeness
= 40000;
1096 pixatt
.valuemask
= XpmColorSymbols
| XpmExactColors
| XpmCloseness
| XpmSize
;
1097 XpmCreatePixmapFromData(dpy
, Root
, data
, image
, NULL
, &pixatt
);
1100 unsigned long mixColor( const char *colorname1
, int prop1
, const char *colorname2
, int prop2
)
1102 XColor color
, color1
, color2
;
1103 XWindowAttributes winattr
;
1104 XGetWindowAttributes(dpy
, Root
, &winattr
);
1105 XParseColor(dpy
, winattr
.colormap
, colorname1
, &color1
);
1106 XParseColor(dpy
, winattr
.colormap
, colorname2
, &color2
);
1108 color
.red
=(color1
.red
*prop1
+color2
.red
*prop2
)/(prop1
+prop2
);
1109 color
.green
=(color1
.green
*prop1
+color2
.green
*prop2
)/(prop1
+prop2
);
1110 color
.blue
=(color1
.blue
*prop1
+color2
.blue
*prop2
)/(prop1
+prop2
);
1111 color
.flags
=DoRed
| DoGreen
| DoBlue
;
1112 XAllocColor(dpy
, winattr
.colormap
, &color
);
1116 /* draws text on dst using the led symbols from the leds pixmap */
1117 void leds_drawText( char *text
, Pixmap dst
, int x
, int y
, const char *color
)
1120 loadLeds( leds_xpm
, &leds_pixmap
, color
, WindowBackgroundColor
);
1126 led_ptr
= strchr( led_text
, tolower(*text
) );
1127 if( led_ptr
== NULL
)
1129 /*syslog( LOG_DEBUG, "Oops! Internal bug in drawText: No led symbol for char %c\n", *text );*/
1130 led_ptr
= strchr( led_text
, '?' );
1132 XCopyArea( dpy
, leds_pixmap
, dst
, WinGC
, (led_ptr
-led_text
)*LedDim
.w
, 0, LedDim
.w
, LedDim
.h
, x
, y
);
1136 XFreePixmap( dpy
, leds_pixmap
);
1139 /* draws text on dst using the X-Font from textFont */
1140 void font_drawText( char *text
, Pixmap dst
, int x
, int y
, const char *color
)
1142 XSetForeground( dpy
, WinGC
, getColor(color
) );
1143 XDrawImageString( dpy
, dst
, WinGC
, x
, y
+textFont
->ascent
/2, text
, strlen(text
) );
1146 void drawText( char *text
, Pixmap dst
, int x
, int y
, const char *color
)
1148 if( textFont
== NULL
)
1149 leds_drawText( text
, dst
, x
, y
, color
);
1151 font_drawText( text
, dst
, x
, y
, color
);
1154 /* draws the lamp in the specified state */
1155 void drawLamp( int lamp
, int active
)
1157 int disp_x
, disp_y
, lamp_x
=0;
1159 disp_x
= LampsRect
[lamp
].pos
.x
;
1160 disp_y
= LampsRect
[lamp
].pos
.y
;
1162 /* find the offset of the lamp pixmap in the pixmap of all lamps */
1163 for( int i
=0; i
< lamp
; i
++ )
1164 lamp_x
+= LampsRect
[i
].dim
.w
*2;
1165 lamp_x
+= active
*LampsRect
[lamp
].dim
.w
;
1167 XCopyArea( dpy
, lampsPixmap
, disp
, WinGC
, lamp_x
, 0, LampsRect
[lamp
].dim
.w
, LampsRect
[lamp
].dim
.h
, disp_x
, disp_y
);
1170 void isdnInitDefaultDialmode()
1175 isdn_net_ioctl_cfg cfg
;
1176 strcpy( cfg
.name
, devices
[selected_device
] );
1177 if( isdn_ioctl( IIOCNETGCF
, &cfg
, NULL
) != -1 )
1178 dialmode
= cfg
.dialmode
;
1180 dialmode
= ISDN_NET_DM_AUTO
; /* for the sake of cleanness, we'll get an error msg soon anyway */
1181 if( dialmode
== ISDN_NET_DM_OFF
)
1182 dialmode
= ISDN_NET_DM_AUTO
; /* use auto as default dialmode if device disabled */
1184 seteuid( getuid() );
1185 setegid( getgid() );
1188 int isdn_ioctl( int func
, void *arg
, const char *errmsg
, const char *filename
)
1190 int fd
= fd
= open( filename
, O_RDONLY
);
1193 if( errmsg
!= NULL
)
1194 syslog( LOG_NOTICE
, "Couldn't open %s : %m\n", filename
);
1198 int res
= ioctl( fd
, func
, arg
);
1199 if( res
== -1 && errmsg
!= NULL
)
1200 syslog( LOG_NOTICE
, "%s : %m\n", errmsg
);
1207 inline void isdn_dial()
1210 isdn_ioctl( IIOCNETDIL
, devices
[selected_device
], "Couldn't dial" );
1215 char command
[MAX_ARG_LEN
];
1217 strcpy(command
, scriptpath
);
1218 strcat(command
, "/");
1219 strcat(command
, SCRIPT_UP
);
1220 if ((handle
= open(command
, O_RDONLY
)) == -1)
1221 syslog( LOG_NOTICE
, "Couldn't open %s : %m\n", SCRIPT_UP
);
1224 sprintf(command
, "%s/%s %s %d 2>&1 | logger -t wmisdn.sh &", scriptpath
, SCRIPT_UP
, devices
[selected_device
], scriptmode
);
1231 inline void isdn_hangup()
1234 isdn_ioctl( IIOCNETHUP
, devices
[selected_device
], "Couldn't hang up" );
1238 char command
[MAX_ARG_LEN
];
1240 strcpy(command
, scriptpath
);
1241 strcat(command
, "/");
1242 strcat(command
, SCRIPT_DOWN
);
1244 if ((handle
= open(command
, O_RDONLY
)) == -1)
1245 syslog( LOG_NOTICE
, "Couldn't open %s : %m\n", SCRIPT_DOWN
);
1248 sprintf(command
, "%s/%s %s %d 2>&1 | logger -t wmisdn.sh &", scriptpath
, SCRIPT_DOWN
, devices
[selected_device
], scriptmode
);
1255 inline void isdn_enable()
1257 isdn_net_ioctl_cfg cfg
;
1258 strcpy( cfg
.name
, devices
[selected_device
] );
1259 if( isdn_ioctl( IIOCNETGCF
, &cfg
, "Error enabling dialing. Couldn't get dev cfg" ) != -1 )
1261 cfg
.dialmode
= dialmode
;
1262 isdn_ioctl( IIOCNETSCF
, &cfg
, "Error enabling dialing. Couldn't set dev cfg" );
1266 inline void isdn_disable()
1268 isdn_net_ioctl_cfg cfg
;
1269 strcpy( cfg
.name
, devices
[selected_device
] );
1270 if( isdn_ioctl( IIOCNETGCF
, &cfg
, "Error disabling dialing. Couldn't get dev cfg" ) != -1 )
1272 cfg
.dialmode
= ISDN_NET_DM_OFF
;
1273 isdn_ioctl( IIOCNETSCF
, &cfg
, "Error disabling dialing. Couldn't set dev cfg" );
1277 inline void isdn_dial_slave( char *master
)
1279 isdn_ioctl( IIOCNETALN
, master
, "Couldn't fire up slave" );
1282 inline void isdn_hangup_slave( char *master
)
1284 isdn_ioctl( IIOCNETDLN
, master
, "Couldn't hang up slave" );
1287 inline void set_slave_pending()
1289 slave_pending
= devices
[selected_device
];
1292 inline void clear_slave_pending()
1294 slave_pending
= NULL
;
1297 inline bool is_slave_pending()
1299 return slave_pending
!= NULL
;
1302 inline void manage_slave()
1304 if( is_slave_pending() )
1306 if( curStatus
.usage
== ISDN_USAGE_NET
)
1308 isdn_dial_slave(slave_pending
);
1309 clear_slave_pending();
1311 if( curStatus
.usage
== ISDN_USAGE_NONE
)
1312 clear_slave_pending();
1316 /* react upon a lamp press
1317 * - green opens a connection and sets the device in dial_auto mode
1318 * - yellow ends the connection and sets the device in dial_auto mode
1319 * - red ends the connection and sets the device in dial_off mode
1322 inline void _pressGreenLamp( int button
)
1324 /* middle button - just change the script mode */
1327 advanceScriptMode();
1330 /* online request of slave - add a channel to the master */
1331 if( curStatus
.mpppMode
== slave
)
1332 isdn_dial_slave( curStatus
.mpppPartner
);
1333 /* online request of master or non-bundled device */
1335 /* additional mppp-link requested - add a slave channel to the master (wait until master online) */
1336 if( (button
== 3) && (curStatus
.mpppMode
== master
) )
1337 set_slave_pending();
1338 /* if device is dialing or online - ignore button */
1339 if( curStatus
.usage
== STAT_DIALING
|| curStatus
.usage
== ISDN_USAGE_NET
)
1341 if( curStatus
.usage
== STAT_OFF
)
1347 inline void _pressYellowLamp( int button
)
1349 if( curStatus
.usage
== ISDN_USAGE_NONE
)
1351 if( curStatus
.usage
== STAT_OFF
)
1355 if( (button
== 3) || (button
== 1) && (curStatus
.mpppMode
== master
) )
1356 isdn_hangup_slave( devices
[selected_device
] );
1359 if( curStatus
.mpppMode
== slave
)
1360 isdn_hangup_slave( curStatus
.mpppPartner
);
1367 inline void _pressRedLamp( int button
)
1369 if( (curStatus
.usage
== STAT_OFF
) || (button
!= 1) )
1371 _pressYellowLamp( button
);
1375 void pressLamp( int lamp_id
, int button
)
1381 case ID_LAMP_GREEN
: _pressGreenLamp( button
);break;
1382 case ID_LAMP_YELLOW
: _pressYellowLamp( button
); break;
1383 case ID_LAMP_RED
: _pressRedLamp( button
); break;
1385 seteuid( getuid() );
1386 setegid( getgid() );
1389 /* activated when user clicks the status pixmap with the right button - switch online<->offline */
1390 void pressStatusSw()
1395 if( curStatus
.usage
== ISDN_USAGE_NONE
)
1397 else if(curStatus
.usage
== ISDN_USAGE_NET
)
1398 _pressYellowLamp(1);
1400 seteuid( getuid() );
1401 setegid( getgid() );
1405 /* Get the local/remote IP addresses of the devices[selected_device] */
1407 void getLocalIP( int *a
, int *b
, int *c
, int *d
)
1410 int fd
= socket( AF_INET
, SOCK_DGRAM
, 0 );
1412 strcpy( ifr
.ifr_ifrn
.ifrn_name
, devices
[selected_device
] );
1413 ifr
.ifr_ifru
.ifru_addr
.sa_family
= AF_INET
;
1414 int res
= ioctl(fd
, SIOCGIFADDR
, &ifr
);
1416 translateIP( &(ifr
.ifr_ifru
.ifru_addr
), a
, b
, c
, d
);
1419 syslog( LOG_NOTICE
, "Oops! Couldn't get local IP of device %s. ioctl() call failed : %m\n", devices
[selected_device
] );
1422 void getRemoteIP( int *a
, int *b
, int *c
, int *d
)
1425 int fd
= socket( AF_INET
, SOCK_DGRAM
, 0 );
1427 strcpy( ifr
.ifr_ifrn
.ifrn_name
, devices
[selected_device
] );
1428 ifr
.ifr_ifru
.ifru_addr
.sa_family
= AF_INET
;
1429 int res
= ioctl( fd
, SIOCGIFDSTADDR
, &ifr
);
1431 translateIP( &(ifr
.ifr_ifru
.ifru_addr
), a
, b
, c
, d
);
1434 syslog( LOG_NOTICE
, "Oops! Couldn't get remote IP of device %s. ioctl() call failed : %m\n", devices
[selected_device
]);
1437 /* extract the ip address from the addr struct asuming that it is a valid INET sockaddr */
1438 inline void translateIP( struct sockaddr
*addr
, int *a
, int *b
, int *c
, int *d
)
1440 struct sockaddr_in
* inet_addr
= (sockaddr_in
*)addr
;
1441 unsigned int ip
= inet_addr
->sin_addr
.s_addr
;
1442 *d
= (ip
>> 24) & 0xFF;
1443 *c
= (ip
>> 16) & 0xFF;
1444 *b
= (ip
>> 8 ) & 0xFF;
1448 /* extract the data from the 'key'-line of /dev/isdninfo for all 16 B-Channels */
1449 bool extractIsdnInfoData( const char *all_data
, const char *key
, char buffer
[ISDN_MAX_CHANNELS
][100] )
1451 char temp
[100]; /* buffer the key string */
1454 ptr
= strstr( all_data
, key
);
1457 syslog( LOG_NOTICE
, "Error getting status info. /dev/isdninfo doesn't contain a '%s' line\n", key
);
1460 sscanf( ptr
, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
1462 buffer
[0], buffer
[1], buffer
[2], buffer
[3],
1463 buffer
[4], buffer
[5], buffer
[6], buffer
[7],
1464 buffer
[8], buffer
[9], buffer
[10], buffer
[11],
1465 buffer
[12], buffer
[13], buffer
[14], buffer
[15] );
1470 bool getPeerPhone( char *ippp
, char *phone
)
1472 isdn_net_ioctl_phone ippp_phone
;
1475 strcpy( ippp_phone
.name
, ippp
);
1476 res
= isdn_ioctl( IIOCNETGPN
, &ippp_phone
, NULL
, "/dev/isdninfo" );
1479 if( errno
!= ENOTCONN
) /* device not connected - no real error */
1480 syslog( LOG_NOTICE
, "Error getting phone number for device %s: %m", ippp
);
1483 strcpy( phone
, ippp_phone
.phone
);
1487 bool findBChannel( char *phone
, char all_phones
[ISDN_MAX_CHANNELS
][100], int &channel
)
1489 for( int i
=0; i
< ISDN_MAX_CHANNELS
; i
++ )
1490 if( strcmp( all_phones
[i
], phone
) == 0 )
1495 syslog( LOG_NOTICE
, "Hmm!!?? That's strange! Device phone number %s couldn't be found in /dev/isdninfo", phone
);
1499 void getMPPPSettings( isdn_net_ioctl_cfg
*cfg
, isdnStatus
*stat
)
1501 stat
->mpppMode
= none
;
1502 if( strlen(cfg
->master
) != 0 )
1504 stat
->mpppMode
= slave
;
1505 strcpy( stat
->mpppPartner
, cfg
->master
);
1507 if( strlen(cfg
->slave
) != 0 )
1509 stat
->mpppMode
= master
;
1510 strcpy( stat
->mpppPartner
, cfg
->slave
);
1514 /* get the status of the ippp device:
1516 * - isOff if dialing is disabled
1517 * - isOffline if dialing is enabled but no connection is established
1518 * - isOnline if device has established a connection
1519 * - isDialing if device is dialing the remote but no connection is established
1520 * - isUnknown if no stat info available
1522 void getStatus( char *device
, isdnStatus
*stat
)
1524 isdn_net_ioctl_cfg cfg
;
1527 static int warning_count
=0;
1528 int channel
, channel_usage
;
1529 char channel_info
[ISDN_MAX_CHANNELS
][100];
1532 /* get ippp device config */
1535 strcpy( cfg
.name
, device
);
1536 res
= isdn_ioctl( IIOCNETGCF
, &cfg
, warning_count
< STATUS_WARNING_SAT
? "Error getting status info. Couldn't get device cfg" : (char *)NULL
);
1537 seteuid( getuid() );
1538 setegid( getgid() );
1540 stat
->usage
= STAT_UNKNOWN
;
1541 stat
->direction
= INCOMING
;
1549 if( cfg
.dialmode
== ISDN_NET_DM_OFF
)
1550 stat
->usage
= STAT_OFF
;
1552 stat
->usage
= ISDN_USAGE_NONE
;
1554 stat
->bundled
= false;
1555 getMPPPSettings( &cfg
, stat
);
1557 /* read the device flags from /dev/isdninfo */
1558 fd
= open( "/dev/isdninfo", O_RDONLY
|O_NDELAY
);
1561 syslog( LOG_NOTICE
, "Error getting status info. Couldn't open /dev/isdninfo : %m\n" );
1564 len
= read( fd
, buf
, sizeof(buf
)-1 );
1568 syslog( LOG_NOTICE
, "Error getting status info. Couldn't read from /dev/isdninfo : %m\n" );
1571 buf
[len
] = 0; /* terminate the string */
1573 if( !extractIsdnInfoData( buf
, "phone:", channel_info
) )
1575 if( !getPeerPhone( device
, stat
->peerPhone
) )
1577 if( !findBChannel( stat
->peerPhone
, channel_info
, channel
) )
1579 if( !extractIsdnInfoData( buf
, "usage:", channel_info
) )
1582 channel_usage
= atoi(channel_info
[channel
]);
1583 if( (channel_usage
& ISDN_USAGE_DISABLED
) != 0 )
1584 stat
->usage
= STAT_DISABLED
;
1586 stat
->usage
= channel_usage
& ISDN_USAGE_MASK
;
1587 stat
->direction
= (channel_usage
& ISDN_USAGE_OUTGOING
) == 0 ? INCOMING
: OUTGOING
;
1589 /* check if device is still dialing or already online */
1590 if( stat
->usage
== ISDN_USAGE_NET
)
1593 if( !extractIsdnInfoData( buf
, "flags:", channel_info
) )
1596 if( ((atoi(channel_info
[0]) >> channel
) & 1) == 0 )
1597 stat
->usage
= STAT_DIALING
;
1599 /* check for channel bundling */
1600 if( stat
->mpppMode
== master
)
1602 isdnStatus slaveStatus
;
1603 getStatus( stat
->mpppPartner
, &slaveStatus
);
1604 if( (stat
->usage
== slaveStatus
.usage
) && (stat
->direction
== slaveStatus
.direction
) &&
1605 (strcmp(stat
->peerPhone
,slaveStatus
.peerPhone
)==0) )
1606 stat
->bundled
= true;