~ubuntu-branches/ubuntu/oneiric/psi/oneiric

« back to all changes in this revision

Viewing changes to src/tools/openpgp/gpgproc/gpgproc.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2006-01-20 00:20:36 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060120002036-7nw6yo6totip0ee5
Tags: 0.10-2
* Added upstream changelog (Closes: Bug#327748)
* Mention --no-gpg and --no-gpg-agent in manpage (Closes: Bug#204416)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  TODO:
 
3
    maybe have a queue for aux/command ??
 
4
*/
 
5
 
 
6
#include"gpgproc.h"
 
7
 
 
8
#include<qsocketnotifier.h>
 
9
#include<qtimer.h>
 
10
#include"safedelete.h"
 
11
#include"qpipe.h"
 
12
 
 
13
#ifdef Q_WS_WIN
 
14
#include<qprocess.h>
 
15
#include<windows.h>
 
16
#else
 
17
#include<unistd.h>
 
18
#include"sprocess.h"
 
19
#endif
 
20
 
 
21
//----------------------------------------------------------------------------
 
22
// GPGProc
 
23
//----------------------------------------------------------------------------
 
24
class GPGProc::Private
 
25
{
 
26
public:
 
27
        Private() {}
 
28
 
 
29
        QByteArray statusbuf;
 
30
        SafeDelete sd;
 
31
 
 
32
#ifdef Q_WS_WIN
 
33
        QProcess *proc;
 
34
#else
 
35
        SProcess *proc;
 
36
#endif
 
37
        QPipe pipeAux, pipeCommand, pipeStatus;
 
38
 
 
39
        QTimer *t;
 
40
        QSocketNotifier *snStatus;
 
41
};
 
42
 
 
43
GPGProc::GPGProc()
 
44
:QObject(0)
 
45
{
 
46
        d = new Private;
 
47
        d->proc = 0;
 
48
 
 
49
        d->snStatus = 0;
 
50
        d->t = 0;
 
51
}
 
52
 
 
53
GPGProc::~GPGProc()
 
54
{
 
55
        closePipes();
 
56
 
 
57
        if(d->proc) {
 
58
                d->proc->disconnect(this);
 
59
                if(d->proc->isRunning())
 
60
                        d->proc->kill();
 
61
                d->sd.deleteLater(d->proc);
 
62
        }
 
63
 
 
64
        delete d;
 
65
}
 
66
 
 
67
void GPGProc::closePipes()
 
68
{
 
69
        d->pipeAux.close();
 
70
        d->pipeCommand.close();
 
71
        d->pipeStatus.close();
 
72
 
 
73
        delete d->snStatus;
 
74
        d->snStatus = 0;
 
75
        delete d->t;
 
76
        d->t = 0;
 
77
}
 
78
 
 
79
bool GPGProc::isRunning() const
 
80
{
 
81
        return d->proc->isRunning();
 
82
}
 
83
 
 
84
bool GPGProc::normalExit() const
 
85
{
 
86
        return d->proc->normalExit();
 
87
}
 
88
 
 
89
int GPGProc::exitStatus() const
 
90
{
 
91
        return d->proc->exitStatus();
 
92
}
 
93
 
 
94
bool GPGProc::start(const QString &bin, const QStringList &args, bool useExtra)
 
95
{
 
96
        if(d->proc) {
 
97
                closePipes();
 
98
                d->proc->disconnect(this);
 
99
                d->sd.deleteLater(d->proc);
 
100
                d->proc = 0;
 
101
        }
 
102
        d->statusbuf.resize(0);
 
103
 
 
104
        if(!d->pipeAux.open()) {
 
105
#ifdef GPG_DEBUG
 
106
                printf("Error creating pipeAux\n");
 
107
#endif
 
108
                closePipes();
 
109
                return false;
 
110
        }
 
111
        if(!d->pipeCommand.open()) {
 
112
#ifdef GPG_DEBUG
 
113
                printf("Error creating pipeCommand\n");
 
114
#endif
 
115
                closePipes();
 
116
                return false;
 
117
        }
 
118
        if(!d->pipeStatus.open()) {
 
119
#ifdef GPG_DEBUG
 
120
                printf("Error creating pipeStatus\n");
 
121
#endif
 
122
                closePipes();
 
123
                return false;
 
124
        }
 
125
 
 
126
 
 
127
#ifdef Q_WS_WIN
 
128
        if(!d->pipeAux.writeEnd().winDupHandle()) {
 
129
#ifdef GPG_DEBUG
 
130
                printf("Error dup'ing pipeAux\n");
 
131
#endif
 
132
                closePipes();
 
133
                return false;
 
134
        }
 
135
        if(!d->pipeCommand.writeEnd().winDupHandle()) {
 
136
#ifdef GPG_DEBUG
 
137
                printf("Error dup'ing pipeCommand\n");
 
138
#endif
 
139
                closePipes();
 
140
                return false;
 
141
        }
 
142
        if(!d->pipeStatus.readEnd().winDupHandle()) {
 
143
#ifdef GPG_DEBUG
 
144
                printf("Error dup'ing pipeStatus\n");
 
145
#endif
 
146
                closePipes();
 
147
                return false;
 
148
        }
 
149
 
 
150
        // timer
 
151
        d->t = new QTimer;
 
152
        connect(d->t, SIGNAL(timeout()), SLOT(timeout()));
 
153
        d->t->start(100);
 
154
#else
 
155
        // status socket notifier
 
156
        d->pipeStatus.readEnd().setBlock(false);
 
157
        d->snStatus = new QSocketNotifier(d->pipeStatus.readEnd().id(), QSocketNotifier::Read);
 
158
        connect(d->snStatus, SIGNAL(activated(int)), SLOT(sn_activated(int)));
 
159
#endif
 
160
 
 
161
        /*{
 
162
                // test: write some data into the pipe
 
163
                QCString cs = "Foobar";
 
164
                d->pipeStatus.write(cs);
 
165
                QByteArray buf = d->pipeStatus.readAll();
 
166
                QCString cs2 = buf.data();
 
167
                if(cs != cs2)
 
168
                        printf("Pipe test failed.\n");
 
169
                else
 
170
                        printf("Pipe test succeeded.\n");
 
171
        }*/
 
172
 
 
173
#ifdef Q_WS_WIN
 
174
        d->proc = new QProcess;
 
175
#else
 
176
        d->proc = new SProcess;
 
177
#endif
 
178
 
 
179
#ifdef GPG_DEBUG
 
180
        printf("Pipe setup complete.\n");
 
181
#endif
 
182
 
 
183
        QStringList fullargs;
 
184
        fullargs += bin;
 
185
        fullargs += "--no-tty";
 
186
 
 
187
        if(useExtra) {
 
188
                fullargs += "--enable-special-filenames";
 
189
 
 
190
                fullargs += "--status-fd";
 
191
                fullargs += d->pipeStatus.writeEnd().toString();
 
192
 
 
193
                fullargs += "--command-fd";
 
194
                fullargs += d->pipeCommand.readEnd().toString();
 
195
        }
 
196
 
 
197
        for(QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) {
 
198
                const QString &a = (*it);
 
199
                if(a == "-&?")
 
200
                        fullargs += (QString("-&") + d->pipeAux.readEnd().toString());
 
201
                else
 
202
                        fullargs += a;
 
203
        }
 
204
 
 
205
        // show full command
 
206
#ifdef GPG_DEBUG
 
207
        printf("GPGProc: ");
 
208
        for(QStringList::ConstIterator it2 = fullargs.begin(); it2 != fullargs.end(); ++it2) {
 
209
                printf("%s ", (*it2).latin1());
 
210
        }
 
211
        printf("\n");
 
212
#endif
 
213
 
 
214
        d->proc->setArguments(fullargs);
 
215
 
 
216
#ifndef Q_WS_WIN
 
217
        QValueList<int> plist;
 
218
        plist += d->pipeAux.writeEnd().id();
 
219
        plist += d->pipeCommand.writeEnd().id();
 
220
        plist += d->pipeStatus.readEnd().id();
 
221
        d->proc->setClosePipeList(plist);
 
222
#endif
 
223
 
 
224
        connect(d->proc, SIGNAL(readyReadStdout()), SLOT(proc_readyReadStdout()));
 
225
        connect(d->proc, SIGNAL(readyReadStderr()), SLOT(proc_readyReadStderr()));
 
226
        connect(d->proc, SIGNAL(wroteToStdin()), SLOT(proc_wroteToStdin()));
 
227
        connect(d->proc, SIGNAL(processExited()), SLOT(proc_processExited()));
 
228
 
 
229
        bool ok = d->proc->start();
 
230
 
 
231
        // we don't care about these
 
232
        d->pipeAux.closeReadEnd();
 
233
        d->pipeCommand.closeReadEnd();
 
234
        d->pipeStatus.closeWriteEnd();
 
235
 
 
236
        if(!ok) {
 
237
                closePipes();
 
238
                d->proc->disconnect(this);
 
239
                d->sd.deleteLater(d->proc);
 
240
                d->proc = 0;
 
241
                return false;
 
242
        }
 
243
 
 
244
        return true;
 
245
}
 
246
 
 
247
void GPGProc::writeToStdin(const QByteArray &buf)
 
248
{
 
249
        d->proc->writeToStdin(buf);
 
250
}
 
251
 
 
252
void GPGProc::writeToAux(const QByteArray &buf)
 
253
{
 
254
        d->pipeAux.write(buf);
 
255
        wroteToAux();
 
256
}
 
257
 
 
258
void GPGProc::writeToCommand(const QByteArray &buf)
 
259
{
 
260
        d->pipeCommand.write(buf);
 
261
        wroteToCommand();
 
262
}
 
263
 
 
264
void GPGProc::closeStdin()
 
265
{
 
266
        d->proc->closeStdin();
 
267
}
 
268
 
 
269
void GPGProc::closeAux()
 
270
{
 
271
        d->pipeAux.close();
 
272
}
 
273
 
 
274
void GPGProc::closeCommand()
 
275
{
 
276
        d->pipeCommand.close();
 
277
}
 
278
 
 
279
QByteArray GPGProc::readStdout()
 
280
{
 
281
        return d->proc->readStdout();
 
282
}
 
283
 
 
284
QByteArray GPGProc::readStderr()
 
285
{
 
286
        return d->proc->readStderr();
 
287
}
 
288
 
 
289
void GPGProc::proc_readyReadStdout()
 
290
{
 
291
        SafeDeleteLock s(&d->sd);
 
292
        readyReadStdout();
 
293
}
 
294
 
 
295
void GPGProc::proc_readyReadStderr()
 
296
{
 
297
        SafeDeleteLock s(&d->sd);
 
298
        readyReadStderr();
 
299
}
 
300
 
 
301
void GPGProc::proc_wroteToStdin()
 
302
{
 
303
        SafeDeleteLock s(&d->sd);
 
304
        wroteToStdin();
 
305
}
 
306
 
 
307
void GPGProc::proc_processExited()
 
308
{
 
309
        SafeDeleteLock s(&d->sd);
 
310
 
 
311
#ifdef Q_WS_WIN
 
312
        timeout();
 
313
        delete d->t;
 
314
        d->t = 0;
 
315
#else
 
316
        // maybe there is some status left??
 
317
        QByteArray buf = d->pipeStatus.readAll();
 
318
        if(!buf.isEmpty())
 
319
                processStatusData(buf);
 
320
#endif
 
321
        processExited();
 
322
}
 
323
 
 
324
#ifdef Q_WS_WIN
 
325
void GPGProc::timeout()
 
326
{
 
327
        QByteArray buf = d->pipeStatus.readAll();
 
328
        if(!buf.isEmpty())
 
329
                processStatusData(buf);
 
330
}
 
331
 
 
332
void GPGProc::sn_activated(int)
 
333
{
 
334
}
 
335
#else
 
336
void GPGProc::timeout()
 
337
{
 
338
}
 
339
 
 
340
void GPGProc::sn_activated(int)
 
341
{
 
342
        bool done;
 
343
        QByteArray buf = d->pipeStatus.readAll(&done);
 
344
        if(done) {
 
345
                d->pipeStatus.close();
 
346
                delete d->snStatus;
 
347
                d->snStatus = 0;
 
348
        }
 
349
        if(!buf.isEmpty())
 
350
                processStatusData(buf);
 
351
}
 
352
#endif
 
353
 
 
354
void GPGProc::processStatusData(const QByteArray &buf)
 
355
{
 
356
        // append to the statusbuf
 
357
        int oldsize = d->statusbuf.size();
 
358
        d->statusbuf.resize(oldsize + buf.size());
 
359
        memcpy(d->statusbuf.data() + oldsize, buf.data(), buf.size());
 
360
 
 
361
        // extract all lines
 
362
        QStringList list;
 
363
        while(1) {
 
364
                int n = 0;
 
365
                int len = d->statusbuf.size();
 
366
                char *p = (char *)d->statusbuf.data();
 
367
                for(; n < len; ++n) {
 
368
                        if(p[n] == '\n')
 
369
                                break;
 
370
                }
 
371
                // no full line
 
372
                if(n >= len)
 
373
                        break;
 
374
                // extract the string from statusbuf
 
375
                ++n;
 
376
                QCString cs;
 
377
                cs.resize(n+1);
 
378
                memcpy(cs.data(), p, n);
 
379
                int newsize = len - n;
 
380
                memmove(p, p + n, newsize);
 
381
                d->statusbuf.resize(newsize);
 
382
 
 
383
                // convert to string without newline
 
384
                QString str = QString::fromUtf8(cs);
 
385
                str.truncate(str.length()-1);
 
386
                // ensure it has a proper header
 
387
                if(str.left(9) != "[GNUPG:] ")
 
388
                        continue;
 
389
                // take it off
 
390
                str = str.mid(9);
 
391
                // add to the list
 
392
                list += str;
 
393
        }
 
394
 
 
395
        for(QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
 
396
                statusLine(*it);
 
397
}