2
* client.cpp - code for client-windows, which are displayed in several instances in the main-window of iTALC
5
* Copyright (c) 2004-2005 Tobias Doerffel <tobias@doerffel.de>
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
17
* You should have received a copy of the GNU General Public
18
* License along with this program (see COPYING); if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
* Boston, MA 02111-1307, USA.
27
#include <qpopupmenu.h>
28
#include <qdatetime.h>
29
#include <qmessagebox.h>
32
#include <qapplication.h>
33
#include <qfiledialog.h>
36
#include <qworkspace.h>
41
#include "rfb_connection.h"
42
#include "client_manager.h"
43
#include "text_input_dialog.h"
44
#include "cmd_input_dialog.h"
45
#include "msg_input_dialog.h"
48
#include "qimage_manips.h"
49
#include "system_environment.h"
50
#include "screenshot_list.h"
51
#include "qt3_compat.h"
52
//#include "client_viewer_widget.h"
57
#ifdef OLD_ROOT_WAKE_CODE
66
#include <sys/socket.h>
68
#include <sys/types.h>
69
#include <sys/ioctl.h>
73
#include <netpacket/packet.h>
74
#include <net/ethernet.h>
76
#include <netinet/ether.h>
82
//#define HARDCORE_DEBUG
85
const QSize DEFAULT_CLIENT_SIZE( 256, 192 );
89
const client::clientCommand client::s_commands[CMD_COUNT] =
92
{ NONE, &client::doNothing, client::tr(""), "", FALSE },
93
{ RELOAD, &client::reload, client::tr(""), "", TRUE },
95
{ START_FULLSCREEN_DEMO,&client::startFullScreenDemo,client::tr("Start fullscreen-demo"),"client_start_fullscreen_demo", FALSE },
96
{ START_DEMO, &client::startDemo, client::tr("Start window-demo"),"client_start_demo", FALSE },
97
{ STOP_DEMO, &client::stopDemo, client::tr("Stop demo"), "client_stop_demo", FALSE },
98
{ CLIENT_DEMO, &client::clientDemo, client::tr("Let client show demo"),"client_demo", FALSE },
99
{ WORK_ON_CLIENT,&client::workOnClient, client::tr("Help person"), "support", FALSE },
100
{ SEND_MESSAGE, &client::sendMessage, client::tr("Send message"), "client_msg", TRUE },
101
{ DISTRIBUTE_FILE,&client::distributeFile,client::tr("Distribute file"),"distribute_file", FALSE },
102
{ COLLECT_FILES,&client::collectFiles, client::tr("Collect files"), "collect_files", TRUE },
104
{ LOCK_X, &client::lockX, client::tr("Lock screen"), "client_lock_x", FALSE },
105
{ UNLOCK_X, &client::unlockX, client::tr("Unlock screen"), "client_unlock_x", FALSE },
107
{ RESTART_X, &client::restartX, client::tr("Restart X"), "client_restart_x", TRUE },
109
{ KILL_GAMES, &client::killGames, client::tr("Kill games"), "client_kill_games", FALSE },
110
{ KILL_BROWSERS,&client::killBrowsers, client::tr("Kill browsers"), "client_kill_browsers", TRUE },
111
{ SCREENSHOT, &client::screenShot, client::tr("Make screenshot"), "client_screenshot", TRUE },
113
{ EXEC_CMDS, &client::execCmds, client::tr("Execute commands/SSH"),"client_exec_cmds", FALSE },
114
{ EXEC_CMDS_IRFB,&client::execCmdsIRFB, client::tr("Execute commands/IRFB"), "client_exec_cmds", FALSE },
116
{ RUN_X_APP, &client::runXApp, client::tr("Run X-application"),"client_run_x_app", FALSE },
118
{ SSH_LOGIN, &client::SSHLogin, client::tr("Login with SSH"), "client_ssh_login", TRUE },
119
{ POWER_ON, &client::powerOn, client::tr("Power on"), "client_power_on", FALSE },
120
{ REBOOT, &client::reboot, client::tr("Reboot"), "client_reboot", FALSE },
121
{ POWER_OFF, &client::powerOff, client::tr("Power off"), "client_power_off", FALSE }
126
// resolve static symbols...
127
QMap<int, client *> client::s_idMap;
129
QImage * client::s_computerPowerOffImg = NULL;
130
QImage * client::s_noUserLoggedInImg = NULL;
131
QImage * client::s_demoRunningImg = NULL;
133
bool client::s_reloadScreenshotList = FALSE;
137
client::client( const QString & _ip, const QString & _mac, const QString & _name, classRoom * _class_room, int _id ) :
138
QWidget( italc::inst()->workspace(), _name, /*Qt::WNoAutoErase | */Qt::WStyle_Title ),
143
m_demoRunning( FALSE ),
145
m_makeScreenshot( FALSE ),
155
if (s_computerPowerOffImg == NULL)
157
s_computerPowerOffImg = new QImage( embed::getIconPixmap( "computer_power_off" ).convertToImage() );
159
if( s_noUserLoggedInImg == NULL )
161
s_noUserLoggedInImg = new QImage( embed::getIconPixmap( "no_user_logged_in" ).convertToImage() );
163
if( s_demoRunningImg == NULL )
165
s_demoRunningImg = new QImage( embed::getIconPixmap( "demo_running" ).convertToImage() );
168
m_classRoomItem = new classRoomItem( this, _class_room, m_name );
171
m_connection = new rfbConnection( m_ip );
173
setBackgroundMode( Qt::NoBackground );
174
setIcon( embed::getIconPixmap( "client_observed" ) );
176
QWhatsThis::add( this, tr( "This is a client-window. It either displays the screen of the according client or a message "
177
"about the state of this client (no user logged in/powered off) is shown. You can click with "
178
"the right mouse-button and an action-menu for this client will appear. You can also close this "
179
"client-window. To open it again, open the client-manager-workspace and search this client and "
180
"double-click it.\nYou can change the size of this (and all other visible) client-windows by "
181
"using the functions for increasing, decreasing or optimizing the client-window-size." ) );
183
setFixedSize( DEFAULT_CLIENT_SIZE/*clientManager::inst()->standardSize()*/ );
194
delete m_classRoomItem;
200
void client::resetConnection( void )
203
m_connection->resetConnection();
204
m_syncMutex.unlock();
210
bool client::userLoggedIn( void )
212
QMutexLocker ml( &m_syncMutex );
214
return( m_connection->connected() || m_connection->resetConnection( m_ip )/* || (int) system("if [ -z \"`ssh root@"+m_ip+" ps aux | grep kdeinit | grep -v grep`\" ] ; then\nexit 0\nelse\nexit 1\nfi") != 0*/ );
220
void client::processCmd( clientCmds _cmd, const QString & _u_data )
222
if( _cmd < 0 || _cmd >= CMD_COUNT )
226
#ifdef HARDCORE_DEBUG
227
printf( "client<%s,%s>::processCmd(...) -> %d\n", m_ip.ascii(), m_name.ascii(), (int) _cmd );
231
( this->*( client::s_commands[_cmd].m_exec ) )( _u_data );
233
#ifdef HARDCORE_DEBUG
234
printf( "client::processCmd(...) done\n" );
242
void client::update( void )
248
setCaption( m_user + "@" + fullName() );
255
void client::reload( const QString & _update )
257
#ifdef HARDCORE_DEBUG
260
printf ("Reloading client %s (%d) -> ", m_ip.ascii(), no);
262
bool available = FALSE;
267
if( m_connection->connected() || m_connection->resetConnection( m_ip ) == TRUE )
269
#ifdef HARDCORE_DEBUG
270
printf( "Connected -> Sending getUserRequest...\n" );
272
if( m_connection->sendGetUserRequest() )
274
#ifdef HARDCORE_DEBUG
275
printf ("sucessful -> ");
277
// we only send a framebuffer-update-request if no demo is running...
278
m_connection->handleServerMessages( m_demoRunning == FALSE );
279
#ifdef HARDCORE_DEBUG
280
printf( "handling done\n" );
285
#ifdef HARDCORE_DEBUG
286
printf( "not sucessful -> " );
289
m_user = m_connection->user();
290
#ifdef HARDCORE_DEBUG
291
printf( "user: %s\n", m_user.ascii() );
293
if( m_user != "" && m_demoRunning == FALSE )
297
QString real_name = systemEnvironment::realUserName( m_user );
299
if( QToolTip::textFor( this ) != real_name )
301
QToolTip::remove( this );
302
QToolTip::add( this, real_name );
305
else if( m_demoRunning == FALSE )
307
QImage temporary_image = QImage( size(), 32 );
308
// now scale the image and store the output to temporary_image
309
fastScaleImage( *s_noUserLoggedInImg, temporary_image );
310
m_msgImgMutex.lock();
311
// now copy temporary_image to msg-img
312
m_msgImg = temporary_image;
313
m_msgImgMutex.unlock();
317
QImage temporary_image = QImage( size(), 32 );
318
// now scale the image and store the output to temporary_image
319
fastScaleImage( *s_demoRunningImg, temporary_image );
320
m_msgImgMutex.lock();
321
// now copy temporary_image to msg-img
322
m_msgImg = temporary_image;
323
m_msgImgMutex.unlock();
328
// we got no m_connection to client... either the computer is not powered on or there's no m_user logged in...
329
// so check whether client is reachable
330
const QImage * i = NULL;
331
#ifdef HARDCORE_DEBUG
332
printf( "Not connected -> Sending PING...\n" );
334
if( systemEnvironment::hostAvailable( m_ip ) == FALSE )
336
#ifdef HARDCORE_DEBUG
337
printf( "failed -> computer powered off\n" );
339
i = s_computerPowerOffImg;
343
#ifdef HARDCORE_DEBUG
344
printf( "sucessful -> no m_user logged in\n" );
346
// no problems with ping, so ivs is not running -> no m_user logged in
347
i = s_noUserLoggedInImg;
351
m_msgImgMutex.lock();
353
if( i->width() > width() || i->height() > height() )
355
QImage temporary_image = QImage( size(), 32 );
356
#ifdef HARDCORE_DEBUG
357
printf( "Scaling msg\n" );
359
// now scale the image and store the output to temporary_image
360
fastScaleImage( *i, temporary_image );
361
#ifdef HARDCORE_DEBUG
362
printf( "Scaling msg done\n" );
364
// now copy temporary_image to msg-img
365
m_msgImg = temporary_image.copy();
371
m_msgImgMutex.unlock();
376
if( available == FALSE )
378
QToolTip::remove( this );
381
if( m_makeScreenshot == TRUE )
383
m_makeScreenshot = FALSE;
385
if( m_user != "" && m_connection->connected() )
388
QString txt = m_user + "@" + m_name + " (" + m_ip + ") " + QDate( QDate::currentDate() ).toString( Qt::ISODate ) +
389
" " + QTime( QTime::currentTime() ).toString( Qt::ISODate );
390
QString path = QDir::home().path()+SCREENSHOT_PATH;
391
if( QDir( path ).exists() == FALSE )
393
QDir::home().mkdir( SCREENSHOT_PATH, FALSE );
395
// construct filename
396
QString file_name = path + m_user + "_" + m_ip + "_" + QDate( QDate::currentDate() ).toString( Qt::ISODate ) +
397
"_" + QTime( QTime::currentTime() ).toString( Qt::ISODate ) + ".png";
399
const int FONT_SIZE = 20;
400
const int RECT_MARGIN = 10;
401
const int RECT_INNER_MARGIN = 5;
404
QPixmap screen( m_connection->unscaledScreen() );
406
QPixmap italc_icon( embed::getIconPixmap( "client_observed" ) );
408
QPainter p( &screen );
409
QFont fnt = p.font();
410
fnt.setPointSize( FONT_SIZE );
413
QFontMetrics fm( p.font() );
415
const int rx = RECT_MARGIN;
416
const int ry = screen.height() - RECT_MARGIN - 2*RECT_INNER_MARGIN - FONT_SIZE;
417
const int rw = RECT_MARGIN + 4*RECT_INNER_MARGIN + fm.size( SingleLine, txt ).width() + italc_icon.width();
418
const int rh = 2*RECT_INNER_MARGIN + FONT_SIZE;
419
const int ix = rx + RECT_INNER_MARGIN;
420
const int iy = ry + RECT_INNER_MARGIN;
421
const int tx = ix + italc_icon.width() + 2*RECT_INNER_MARGIN;
422
const int ty = ry + RECT_INNER_MARGIN + FONT_SIZE - 2;
424
p.fillRect( rx, ry, rw, rh, QBrush( QColor( 0xFF,0xFF,0xFF ), Dense3Pattern ) );
425
p.drawPixmap( ix, iy, italc_icon );
426
p.drawText( tx, ty, txt );
428
screen.save( file_name, "PNG", 50 );
430
s_reloadScreenshotList = TRUE;
437
m_syncMutex.unlock();
439
// update icon in client-manager which indicates current state
442
m_classRoomItem->setObserved( TRUE );
446
m_classRoomItem->setObserved( FALSE );
450
// if we are called out of draw-thread, we may update...
451
if( _update == CONFIRM_YES )
456
#ifdef HARDCORE_DEBUG
457
printf( "Reload done\n" );
466
void client::startFullScreenDemo( const QString & )
472
if( /*m_demoRunning == FALSE && */( m_connection->connected() || m_connection->resetConnection( m_ip ) == TRUE ) )
474
systemEnvironment::demoServer::allowClient( m_ip );
475
m_connection->startDemo( MASTER_HOST+"::"+DEMO_PORT, TRUE );
476
m_demoRunning = TRUE;
479
m_syncMutex.unlock();
485
void client::startDemo( const QString & )
491
if( /*m_demoRunning == FALSE &&*/ ( m_connection->connected() || m_connection->resetConnection( m_ip ) == TRUE ) )
493
systemEnvironment::demoServer::allowClient( m_ip );
494
m_connection->startDemo (MASTER_HOST+"::"+DEMO_PORT);
495
m_demoRunning = TRUE;
498
m_syncMutex.unlock();
504
void client::stopDemo( const QString & )
508
if( m_connection->connected() || m_connection->resetConnection(m_ip) == TRUE )
510
systemEnvironment::demoServer::denyClient( m_ip );
511
m_connection->stopDemo();
514
m_demoRunning = FALSE;
516
m_syncMutex.unlock();
522
void client::clientDemo( const QString & )
524
if( !clientManager::inst()->demoRunning() )
526
QMessageBox::information( this, tr( "No demo running" ), tr( "Before you allow a client to show a demo, you have to "
527
"start the demo-mode by clicking on the corresponding icon in the toolbar." ) );
538
void client::workOnClient( const QString & )
540
if( m_user != "" && m_user != "none" )
542
systemEnvironment::startClientViewer( m_ip, "\"" + systemEnvironment::realUserName( m_user ) + " (" + m_user + ")\"" );
544
// new clientViewerWidget( m_connection );
550
void client::sendMessage (const QString & _msg) {
556
msgInputDialog * msg_input_dialog = new msgInputDialog (msg, this);
557
if (msg_input_dialog->exec() == QDialog::Accepted && msg != "")
560
delete msg_input_dialog;
566
m_connection->sendMessage (_msg);
568
m_syncMutex.unlock ();
576
void client::distributeFile( const QString & _file )
578
/* QMessageBox::information( this, tr( "Function not implemented yet." ), tr( "This function is not completely implemented yet. This is why it is disabled at the moment." ), QMessageBox::Ok );
583
QFileDialog ofd( QDir::home().path(), QString::null, this, "", TRUE );
584
ofd.setMode( QFileDialog::ExistingFile );
585
ofd.setCaption( tr( "Select file to distribute" ) );
586
if( ofd.exec() == QDialog::Accepted )
588
distributeFile( ofd.selectedFile() );
593
systemEnvironment::distributeFile( _file, this );
594
//m_connection->postFile (_file);
595
m_syncMutex.unlock();
602
void client::collectFiles( const QString & _files )
604
/* QMessageBox::information( this, tr( "Function not implemented yet."), tr("This function is not completely implemented yet. This is why it is disabled at the moment."), QMessageBox::Ok);
610
textInputDialog file_name_input( tr( "Please enter the name of the file to be collected.\nOnly files located in the "
611
"PUBLIC-directory are allowed." ), fn, this );
612
file_name_input.setCaption( tr( "Collect files" ) );
614
if( file_name_input.exec() == QDialog::Accepted && fn != "" )
619
//m_syncMutex.lock ();
620
//m_connection->getFile (_file);
621
//m_syncMutex.unlock ();
624
systemEnvironment::collectFiles( _files, m_user );
632
void client::lockX( const QString & _confirm )
634
/* if (_confirm == CONFIRM_YES || _confirm == "") {
635
if (QMessageBox::question(this, tr("Lock screen"), tr("Are you sure want to lock the screen on selected client?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
641
m_connection->lockDisplay();
643
m_syncMutex.unlock();
649
void client::unlockX( const QString & _confirm )
651
/* if (_confirm == CONFIRM_YES || _confirm == "") {
652
if (QMessageBox::question(this, tr("Unlock screen"), tr("Are you sure want to unlock the screen on selected client?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
657
m_connection->unlockDisplay();
659
m_syncMutex.unlock();
666
void client::restartX( const QString & _confirm )
670
if( QMessageBox::warning( this, tr( "User logged in" ), tr( "Warning: you're trying to restart X on a client where a "
671
"user is logged in! Continue anyway?" ), QMessageBox::Yes, QMessageBox::No )
677
else if( _confirm == CONFIRM_YES || _confirm == "" )
679
if( QMessageBox::question( this, tr( "Restart X" ), tr( "Are you sure want to restart X on selected client?" ),
680
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
688
execCmds( "killall X" );
690
m_syncMutex.unlock();
697
void client::killGames( const QString & _confirm )
700
/* if (_confirm == CONFIRM_YES || _confirm == "") {
701
if (QMessageBox::question(this, tr("Kill games"), tr("Are you sure want to kill all games on selected client?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
705
"killall kasteroids\n"
706
"killall kfouleggs\n"
707
"killall kgoldrunner\n"
709
"killall ksmiletris\n"
711
"killall kspaceduel\n"
714
"killall kbackgammon\n"
715
"killall kblackbox\n"
716
"killall kmahjongg\n"
720
"killall kbattleship\n"
728
"killall kjumpingcube\n"
736
"killall ktuberling\n"
738
"killall frozen-bubble\n"
739
"killall cube_unix\n"
746
void client::killBrowsers( const QString & _confirm )
748
/* if (_confirm == CONFIRM_YES || _confirm == "") {
749
if (QMessageBox::question(this, tr("Kill Mozilla/FireFox"), tr("Are you sure want to kill Mozilla/FireFox on selected client?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
754
"killall firefox-bin\n"
756
"killall mozilla-bin\n"
759
// killing Konqueror is a tricky thing, because it's forked by kdeinit so just "killall konqueror" doesn't work
760
"ps -A -o pid,cmd | grep konqueror | grep -v 'grep konqueror' | while read i ; do kill `echo $i | cut -d ' ' -f 1` ; done\n"
761
// we'll also annoy the freaks ;-)
770
void client::screenShot( const QString & )
772
if( m_user == "" || !m_connection->connected() )
777
m_makeScreenshot = TRUE;
783
void client::execCmds( const QString & _cmds )
789
cmdInputDialog cmd_input_dialog( cmds, this );
790
if( cmd_input_dialog.exec() == QDialog::Accepted && cmds != "" )
795
systemEnvironment::execBg( "ssh root@" + m_ip + " << EOS\n" + _cmds + "\nexit\nEOS" );
802
void client::execCmdsIRFB( const QString & _cmds )
808
cmdInputDialog cmd_input_dialog( cmds, this );
809
if( cmd_input_dialog.exec() == QDialog::Accepted && cmds != "" )
810
execCmdsIRFB( cmds );
815
m_connection->execCmds( _cmds );
816
m_syncMutex.unlock();
825
void client::runXApp( const QString & _app )
831
textInputDialog app_input( tr( "Please enter the name of the application you want to run and redirect." ),
833
app_input.setCaption( tr( "Run application..." ) );
835
if( app_input.exec() == QDialog::Accepted && app_to_run != "" )
836
runXApp( app_to_run );
840
// no systemEnvironment-abstraction needed, because this function is only compiled under Linux
841
system( "xhost +"+m_ip );
842
execCmds( "export DISPLAY="+MASTER_HOST+":0.0\n"+_app+"\n" );
850
void client::SSHLogin( const QString & _user )
855
QString client_user = "root";
857
textInputDialog user_input( tr( "Please enter the user-name you want to login with." ), client_user, this );
858
user_input.setCaption( tr( "SSH-Login" ) );
859
if( user_input.exec() == QDialog::Accepted && client_user != "" )
860
SSHLogin( client_user );
864
systemEnvironment::execInTerminal( "ssh " + _user + "@" + m_ip );
872
void client::powerOn( const QString & )
874
#ifndef OLD_ROOT_WAKE_CODE
875
// TODO: replace this code with real c-code
876
// construct some python-code...
878
python_code += "import struct, socket\n";
879
python_code += "def WakeOnLan(ethernet_address):\n";
880
python_code += " addr_byte = ethernet_address.split(':')\n";
881
python_code += " hw_addr = struct.pack('BBBBBB', int(addr_byte[0], 16),\n";
882
python_code += " int(addr_byte[1], 16),\n";
883
python_code += " int(addr_byte[2], 16),\n";
884
python_code += " int(addr_byte[3], 16),\n";
885
python_code += " int(addr_byte[4], 16),\n";
886
python_code += " int(addr_byte[5], 16))\n";
887
python_code += " msg = '\\xff' * 6 + hw_addr * 16\n";
888
python_code += " s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n";
889
python_code += " s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)\n";
890
python_code += " s.sendto(msg, ('<broadcast>', 9))\n";
891
python_code += " s.close()\n";
893
python_code += "WakeOnLan('"+m_mac+"')\n";
894
systemEnvironment::executePythonCode( python_code );
898
const char * ifname = "eth0";
900
Q_UINT8 outpack[1000];
902
int opt_no_src_addr = 0, opt_broadcast = 0;
904
#if defined(PF_PACKET)
905
struct sockaddr_ll whereto;
907
struct sockaddr whereto; /* who to wake up */
909
struct ether_addr eaddr;
912
const int wol_passwd_size = 6;
913
Q_UINT8 wol_passwd[wol_passwd_size];
916
if (sscanf(m_mac.ascii(), "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *) &wol_passwd[0], (unsigned int *) &wol_passwd[1], (unsigned int *) &wol_passwd[2], (unsigned int *) &wol_passwd[3], (unsigned int *) &wol_passwd[4], (unsigned int *) &wol_passwd[5]) != wol_passwd_size) {
917
printf ("Invalid MAC-adress\n");
921
//printf(" The Magic packet password is %2.2x %2.2x %2.2x %2.2x (%d).\n", passwd[0], passwd[1], passwd[2], passwd[3], byte_cnt);
924
/* Note: PF_INET, SOCK_DGRAM, IPPROTO_UDP would allow SIOCGIFHWADDR to
925
work as non-root, but we need SOCK_PACKET to specify the Ethernet
926
destination address. */
928
#if defined(PF_PACKET)
929
int s = socket(PF_PACKET, SOCK_RAW, 0);
931
int s = socket(AF_INET, SOCK_PACKET, SOCK_PACKET);
935
fprintf(stderr, "ether-wake: This program must be run as root.\n");
937
perror("ether-wake: socket");
940
/* Don't revert if debugging allows a normal m_user to get the raw socket. */
943
/* We look up the station address before reporting failure so that
944
errors may be reported even when run as a normal m_user.
946
struct ether_addr * eap = ether_aton(m_mac.ascii());
949
printf ("The target station address is %s.\n", ether_ntoa(eap));
950
/* } else if (ether_hostton(m_mac.ascii(), &eaddr) == 0) {
951
fprintf(stderr, "Station address for hostname %s is %s.\n",
952
m_mac.ascii(), ether_ntoa(&eaddr));*/
954
printf ("Invalid MAC-adress\n");
960
memset (outpack+0, 0xff, 6);
962
memcpy (outpack, eaddr.ether_addr_octet, 6);
964
memcpy (outpack+6, eaddr.ether_addr_octet, 6);
965
outpack[12] = 0x08; /* Or 0x0806 for ARP, 0x8035 for RARP */
969
memset (outpack+pktsize, 0xff, 6);
972
for (int i = 0; i < 16; i++) {
973
memcpy (outpack+pktsize, eaddr.ether_addr_octet, 6);
976
// fprintf(stderr, "Packet is ");
977
// for (i = 0; i < pktsize; i++)
978
// fprintf(stderr, " %2.2x", outpack[i]);
979
// fprintf(stderr, ".\n");
981
/* Fill in the source address, if possible.
982
The code to retrieve the local station address is Linux specific. */
983
if (!opt_no_src_addr) {
984
struct ifreq if_hwaddr;
985
//unsigned char * hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
987
strcpy (if_hwaddr.ifr_name, ifname);
988
if (ioctl(s, SIOCGIFHWADDR, &if_hwaddr) < 0) {
989
fprintf (stderr, "SIOCGIFHWADDR on %s failed: %s\n", ifname, strerror(errno));
990
/* Magic packets still work if our source address is bogus, but
991
we fail just to be anal. */
994
memcpy (outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6);
996
//printf("The hardware address (SIOCGIFHWADDR) of %s is type %d %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", ifname, if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
999
memcpy (outpack+pktsize, wol_passwd, wol_passwd_size);
1000
pktsize += wol_passwd_size;
1004
#if defined(PF_PACKET)
1006
strncpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1007
if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
1008
fprintf(stderr, "SIOCGIFINDEX on %s failed: %s\n", ifname, strerror(errno));
1011
memset (&whereto, 0, sizeof(whereto));
1012
whereto.sll_family = AF_PACKET;
1013
whereto.sll_ifindex = ifr.ifr_ifindex;
1014
/* The manual page incorrectly claims the address must be filled.
1015
We do so because the code may change to match the docs. */
1016
whereto.sll_halen = ETH_ALEN;
1017
memcpy (whereto.sll_addr, outpack, ETH_ALEN);
1020
whereto.sa_family = 0;
1021
strcpy(whereto.sa_data, ifname);
1024
if (sendto(s, outpack, pktsize, 0, (struct sockaddr *)&whereto, sizeof(whereto)) < 0)
1028
if (bind(s, (struct sockaddr *)&whereto, sizeof(whereto)) < 0)
1030
else if (send(s, outpack, 100, 0) < 0)
1035
struct msghdr msghdr = { 0,};
1036
struct iovec iovector[1];
1037
msghdr.msg_name = &whereto;
1038
msghdr.msg_namelen = sizeof(whereto);
1039
msghdr.msg_iov = iovector;
1040
msghdr.msg_iovlen = 1;
1041
iovector[0].iov_base = outpack;
1042
iovector[0].iov_len = pktsize;
1043
if ((i = sendmsg(s, &msghdr, 0)) < 0)
1046
printf("sendmsg worked, %d (%d).\n", i, errno);
1057
void client::reboot( const QString & _confirm )
1059
if( userLoggedIn() )
1061
if( QMessageBox::warning( this, tr( "User logged in" ), tr( "Warning: you're trying to reboot a client at which a user "
1062
"is logged in! Continue anyway?" ), QMessageBox::Yes, QMessageBox::No )
1063
== QMessageBox::No )
1068
else if( _confirm == CONFIRM_YES || _confirm == "" )
1070
if( QMessageBox::question( this, tr( "Reboot client" ), tr( "Are you sure want to reboot selected client?" ),
1071
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
1076
execCmds( "reboot" );
1083
void client::powerOff( const QString & _confirm )
1085
if( userLoggedIn() )
1087
if( QMessageBox::warning( this, tr( "User logged in" ), tr( "Warning: you're trying to power off a client at which a "
1088
"user is logged in! Continue anyway?" ), QMessageBox::Yes, QMessageBox::No )
1089
== QMessageBox::No )
1094
else if( _confirm == CONFIRM_YES || _confirm == "" )
1096
if( QMessageBox::question( this, tr( "Power off client" ), tr( "Are you sure want to power off selected client?" ),
1097
QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
1102
execCmds( "poweroff" );
1103
// execCmds( "halt" );
1110
void client::processCmdSlot( int _cmd )
1112
processCmd( static_cast<clientCmds>( _cmd ) );
1118
void client::createActionMenu( QPopupMenu * _m )
1120
QPopupMenu * orig_root = _m;
1121
QPopupMenu * admin_submenu = new QPopupMenu( _m );
1123
for( int i = START_FULLSCREEN_DEMO; i < CMD_COUNT; ++i )
1125
if( i >= EXEC_CMDS )
1130
int id = _m->insertItem( embed::getIconPixmap( s_commands[i].m_icon ), tr(s_commands[i].m_name ), this,
1131
SLOT( processCmdSlot( int ) ) );
1132
_m->setItemParameter( id, i );
1134
if( s_commands[i].m_insertSep == TRUE )
1136
_m->insertSeparator();
1140
orig_root->insertItem( embed::getIconPixmap( "client_settings" ), tr( "Administation" ), admin_submenu );
1146
void client::setClassRoom( classRoom * _cr )
1148
delete m_classRoomItem;
1150
m_classRoomItem = new classRoomItem( this, _cr, m_name );
1156
void client::contextMenuEvent( QContextMenuEvent * )
1158
QPopupMenu context_menu( this );
1160
createActionMenu( &context_menu );
1162
context_menu.exec( QCursor::pos() );
1168
void client::resizeEvent( QResizeEvent * )
1170
m_connection->setImageSize( size() );
1171
// gives pseudo-transparency-effect, especially with Dense4Pattern -> unusable, because slow as hell!!
1172
/* QBitmap b( size(), TRUE );
1174
p.fillRect( rect(), QColor( 255, 255, 255 ) );
1175
p.fillRect( geometry(), QBrush( QColor( 0, 0, 0 ), Qt::CrossPattern ) );
1178
QBitmap b2( parentWidget()->size(), TRUE );
1180
p.fillRect( parentWidget()->rect(), QColor( 255, 255, 255 ) );
1181
p.fillRect( geometry(), QColor( 255, 255, 255 ) );
1182
p.fillRect( geometry(), QBrush( QColor( 0, 0, 0 ), Qt::CrossPattern ) );
1184
parentWidget()->setMask( b2 );*/
1191
void client::paintEvent( QPaintEvent * )
1193
QPixmap draw_pm( rect().size() );
1194
draw_pm.fill( QColor( 255, 255, 255 ) );
1196
QPainter p( &draw_pm, this );
1198
if( m_connection->connected() && m_demoRunning == FALSE )
1200
p.drawImage( 0, 0, m_connection->clientScreen() );
1204
if( m_msgImg.isNull() == FALSE )
1206
m_msgImgMutex.lock();
1207
p.drawImage( ( width()-m_msgImg.width() ) / 2, ( height()-m_msgImg.height() ) / 2, m_msgImg );
1208
m_msgImgMutex.unlock();
1211
// and blit all drawn stuff on the screen...
1212
bitBlt( this, rect().topLeft(), &draw_pm );
1218
void client::closeEvent( QCloseEvent * _ce )
1227
void client::hideEvent( QHideEvent * )
1234
if( m_classRoomItem != NULL )
1236
m_classRoomItem->setObserved( FALSE );
1243
void client::showEvent( QShowEvent * )
1245
if( m_classRoomItem != NULL )
1247
m_classRoomItem->setObserved( TRUE );
1254
void client::mouseDoubleClickEvent( QMouseEvent * )
1262
bool client::inviteForSupportingLocalUser( void )
1266
bool result = m_connection->inviteForSupport( systemEnvironment::realUserName(systemEnvironment::localUser() ) );
1268
m_syncMutex.unlock();
1276
int client::id( void ) const
1278
QMap<int, client *>::const_iterator it;
1279
for( it = s_idMap.begin(); it != s_idMap.end(); ++it )
1281
if( it.data() == this )
1292
client * client::clientFromID( int _id )
1294
if( s_idMap.contains( _id ) )
1296
return( s_idMap[_id] );
1304
int client::freeID( void )
1306
for( int i = 1; i < 32000; ++i )
1308
if( s_idMap.contains( i ) == FALSE )