1 | /***************************************************************** |
2 | ksmserver - the KDE session management server |
3 | |
4 | Copyright 2000 Matthias Ettrich <ettrich@kde.org> |
5 | Copyright 2005 Lubos Lunak <l.lunak@kde.org> |
6 | |
7 | relatively small extensions by Oswald Buddenhagen <ob6@inf.tu-dresden.de> |
8 | |
9 | some code taken from the dcopserver (part of the KDE libraries), which is |
10 | Copyright 1999 Matthias Ettrich <ettrich@kde.org> |
11 | Copyright 1999 Preston Brown <pbrown@kde.org> |
12 | |
13 | Permission is hereby granted, free of charge, to any person obtaining a copy |
14 | of this software and associated documentation files (the "Software"), to deal |
15 | in the Software without restriction, including without limitation the rights |
16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
17 | copies of the Software, and to permit persons to whom the Software is |
18 | furnished to do so, subject to the following conditions: |
19 | |
20 | The above copyright notice and this permission notice shall be included in |
21 | all copies or substantial portions of the Software. |
22 | |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
26 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
27 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
28 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
29 | |
30 | ******************************************************************/ |
31 | |
32 | #include <config-workspace.h> |
33 | |
34 | #include "client.h" |
35 | |
36 | #include <stdlib.h> |
37 | #include <unistd.h> |
38 | #ifdef HAVE_SYS_TIME_H |
39 | #include <sys/time.h> |
40 | #endif |
41 | #include <time.h> |
42 | |
43 | #include <kglobal.h> |
44 | #include <krandom.h> |
45 | #include "server.h" |
46 | |
47 | extern KSMServer* the_server; |
48 | |
49 | KSMClient::KSMClient( SmsConn conn) |
50 | { |
51 | smsConn = conn; |
52 | id = 0; |
53 | resetState(); |
54 | } |
55 | |
56 | KSMClient::~KSMClient() |
57 | { |
58 | foreach( SmProp *prop, properties ) |
59 | SmFreeProperty( prop ); |
60 | if (id) free((void*)id); |
61 | } |
62 | |
63 | SmProp* KSMClient::property( const char* name ) const |
64 | { |
65 | foreach ( SmProp *prop, properties ) { |
66 | if ( !qstrcmp( prop->name, name ) ) |
67 | return prop; |
68 | } |
69 | return 0; |
70 | } |
71 | |
72 | void KSMClient::resetState() |
73 | { |
74 | saveYourselfDone = false; |
75 | pendingInteraction = false; |
76 | waitForPhase2 = false; |
77 | wasPhase2 = false; |
78 | } |
79 | |
80 | /* |
81 | * This fakes SmsGenerateClientID() in case we can't read our own hostname. |
82 | * In this case SmsGenerateClientID() returns NULL, but we really want a |
83 | * client ID, so we fake one. |
84 | */ |
85 | K_GLOBAL_STATIC(QString, my_addr) |
86 | char * safeSmsGenerateClientID( SmsConn /*c*/ ) |
87 | { |
88 | // Causes delays with misconfigured network :-/. |
89 | // char *ret = SmsGenerateClientID(c); |
90 | char* ret = NULL; |
91 | if (!ret) { |
92 | if (my_addr->isEmpty()) { |
93 | // qWarning("Can't get own host name. Your system is severely misconfigured\n"); |
94 | |
95 | /* Faking our IP address, the 0 below is "unknown" address format |
96 | (1 would be IP, 2 would be DEC-NET format) */ |
97 | char hostname[ 256 ]; |
98 | if( gethostname( hostname, 255 ) != 0 ) |
99 | my_addr->sprintf("0%.8x" , KRandom::random()); |
100 | else { |
101 | // create some kind of hash for the hostname |
102 | int addr[ 4 ] = { 0, 0, 0, 0 }; |
103 | int pos = 0; |
104 | for( unsigned int i = 0; |
105 | i < strlen( hostname ); |
106 | ++i, ++pos ) |
107 | addr[ pos % 4 ] += hostname[ i ]; |
108 | *my_addr = "0" ; |
109 | for( int i = 0; |
110 | i < 4; |
111 | ++i ) |
112 | *my_addr += QString::number( addr[ i ], 16 ); |
113 | } |
114 | } |
115 | /* Needs to be malloc(), to look the same as libSM */ |
116 | ret = (char *)malloc(1+my_addr->length()+13+10+4+1 + /*safeness*/ 10); |
117 | static int sequence = 0; |
118 | |
119 | if (ret == NULL) |
120 | return NULL; |
121 | |
122 | sprintf(ret, "1%s%.13ld%.10d%.4d" , my_addr->toLatin1().constData(), (long)time(NULL), |
123 | getpid(), sequence); |
124 | sequence = (sequence + 1) % 10000; |
125 | } |
126 | return ret; |
127 | } |
128 | |
129 | void KSMClient::registerClient( const char* previousId ) |
130 | { |
131 | id = previousId; |
132 | if ( !id ) |
133 | id = safeSmsGenerateClientID( smsConn ); |
134 | SmsRegisterClientReply( smsConn, (char*) id ); |
135 | SmsSaveYourself( smsConn, SmSaveLocal, false, SmInteractStyleNone, false ); |
136 | SmsSaveComplete( smsConn ); |
137 | the_server->clientRegistered( previousId ); |
138 | } |
139 | |
140 | |
141 | QString KSMClient::program() const |
142 | { |
143 | SmProp* p = property( SmProgram ); |
144 | if ( !p || qstrcmp( p->type, SmARRAY8) || p->num_vals < 1) |
145 | return QString(); |
146 | return QLatin1String( (const char*) p->vals[0].value ); |
147 | } |
148 | |
149 | QStringList KSMClient::restartCommand() const |
150 | { |
151 | QStringList result; |
152 | SmProp* p = property( SmRestartCommand ); |
153 | if ( !p || qstrcmp( p->type, SmLISTofARRAY8) || p->num_vals < 1) |
154 | return result; |
155 | for ( int i = 0; i < p->num_vals; i++ ) |
156 | result +=QLatin1String( (const char*) p->vals[i].value ); |
157 | return result; |
158 | } |
159 | |
160 | QStringList KSMClient::discardCommand() const |
161 | { |
162 | QStringList result; |
163 | SmProp* p = property( SmDiscardCommand ); |
164 | if ( !p || qstrcmp( p->type, SmLISTofARRAY8) || p->num_vals < 1) |
165 | return result; |
166 | for ( int i = 0; i < p->num_vals; i++ ) |
167 | result +=QLatin1String( (const char*) p->vals[i].value ); |
168 | return result; |
169 | } |
170 | |
171 | int KSMClient::restartStyleHint() const |
172 | { |
173 | SmProp* p = property( SmRestartStyleHint ); |
174 | if ( !p || qstrcmp( p->type, SmCARD8) || p->num_vals < 1) |
175 | return SmRestartIfRunning; |
176 | return *((unsigned char*)p->vals[0].value); |
177 | } |
178 | |
179 | QString KSMClient::userId() const |
180 | { |
181 | SmProp* p = property( SmUserID ); |
182 | if ( !p || qstrcmp( p->type, SmARRAY8) || p->num_vals < 1) |
183 | return QString(); |
184 | return QLatin1String( (const char*) p->vals[0].value ); |
185 | } |
186 | |