~ubuntu-branches/ubuntu/gutsy/kdebase-workspace/gutsy

« back to all changes in this revision

Viewing changes to kdm/backend/process.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2007-09-05 20:45:14 UTC
  • Revision ID: james.westby@ubuntu.com-20070905204514-632hhspl0nvrc84i
Tags: upstream-3.93.0
ImportĀ upstreamĀ versionĀ 3.93.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright 1988, 1998  The Open Group
 
4
Copyright 2001-2004 Oswald Buddenhagen <ossi@kde.org>
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included
 
13
in all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
21
OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
Except as contained in this notice, the name of a copyright holder shall
 
24
not be used in advertising or otherwise to promote the sale, use or
 
25
other dealings in this Software without prior written authorization
 
26
from the copyright holder.
 
27
 
 
28
*/
 
29
 
 
30
/*
 
31
 * xdm - display manager daemon
 
32
 * Author: Keith Packard, MIT X Consortium
 
33
 *
 
34
 * subdaemon and external process management and communication
 
35
 */
 
36
 
 
37
#include "dm.h"
 
38
#include "dm_error.h"
 
39
#if defined(SINGLE_PIPE) && !defined(__FreeBSD__)
 
40
# include "dm_socket.h"
 
41
#endif
 
42
 
 
43
#include <ctype.h>
 
44
#include <stdio.h>
 
45
#include <stdarg.h>
 
46
#include <signal.h>
 
47
#include <unistd.h>
 
48
#ifdef _POSIX_PRIORITY_SCHEDULING
 
49
# include <sched.h>
 
50
#endif
 
51
 
 
52
extern char **environ;
 
53
 
 
54
 
 
55
SIGFUNC Signal( int sig, SIGFUNC handler )
 
56
{
 
57
#ifndef __EMX__
 
58
        struct sigaction sigact, osigact;
 
59
        sigact.sa_handler = handler;
 
60
        sigemptyset( &sigact.sa_mask );
 
61
# ifdef SA_RESTART
 
62
        sigact.sa_flags = SA_RESTART;
 
63
# else
 
64
        sigact.sa_flags = 0;
 
65
# endif
 
66
        sigaction( sig, &sigact, &osigact );
 
67
        return osigact.sa_handler;
 
68
#else
 
69
        return signal( sig, handler );
 
70
#endif
 
71
}
 
72
 
 
73
 
 
74
void
 
75
terminateProcess( int pid, int sig )
 
76
{
 
77
        kill( pid, sig );
 
78
#ifdef SIGCONT
 
79
        kill( pid, SIGCONT );
 
80
#endif
 
81
}
 
82
 
 
83
 
 
84
static fd_set closeMask;
 
85
static int max = -1;
 
86
 
 
87
void
 
88
registerCloseOnFork( int fd )
 
89
{
 
90
        FD_SET( fd, &closeMask );
 
91
        if (fd > max)
 
92
                max = fd;
 
93
}
 
94
 
 
95
void
 
96
clearCloseOnFork( int fd )
 
97
{
 
98
        FD_CLR( fd, &closeMask );
 
99
}
 
100
 
 
101
void
 
102
closeNclearCloseOnFork( int fd )
 
103
{
 
104
        close( fd );
 
105
        FD_CLR( fd, &closeMask );
 
106
}
 
107
 
 
108
static void
 
109
closeOnFork( void )
 
110
{
 
111
        int fd;
 
112
 
 
113
        for (fd = 0; fd <= max; fd++)
 
114
                if (FD_ISSET( fd, &closeMask ))
 
115
                        close( fd );
 
116
        FD_ZERO( &closeMask );
 
117
        max = -1;
 
118
}
 
119
 
 
120
int
 
121
Fork( volatile int *pidr )
 
122
{
 
123
        int pid;
 
124
 
 
125
        sigset_t ss, oss;
 
126
        sigfillset( &ss );
 
127
        sigprocmask( SIG_SETMASK, &ss, &oss );
 
128
 
 
129
        if (!(pid = fork())) {
 
130
#ifdef SIGCHLD
 
131
                (void)Signal( SIGCHLD, SIG_DFL );
 
132
#endif
 
133
                (void)Signal( SIGTERM, SIG_DFL );
 
134
                (void)Signal( SIGINT, SIG_IGN ); /* for -nodaemon */
 
135
                (void)Signal( SIGPIPE, SIG_DFL );
 
136
                (void)Signal( SIGALRM, SIG_DFL );
 
137
                (void)Signal( SIGHUP, SIG_DFL );
 
138
                sigemptyset( &ss );
 
139
                sigprocmask( SIG_SETMASK, &ss, NULL );
 
140
                closeOnFork();
 
141
                return 0;
 
142
        }
 
143
        *pidr = pid;
 
144
 
 
145
        sigprocmask( SIG_SETMASK, &oss, 0 );
 
146
 
 
147
        return pid;
 
148
}
 
149
 
 
150
static void
 
151
cldCatcher( int n ATTR_UNUSED )
 
152
{
 
153
}
 
154
 
 
155
int
 
156
Wait4( volatile int *pid )
 
157
{
 
158
        int result;
 
159
        sigset_t ss, oss;
 
160
        struct sigaction osa;
 
161
 
 
162
        sigfillset( &ss );
 
163
        sigprocmask( SIG_SETMASK, &ss, &oss );
 
164
        sigaction( SIGCHLD, 0, &osa );
 
165
        if (osa.sa_handler == SIG_DFL)
 
166
                Signal( SIGCHLD, cldCatcher );
 
167
        for (;;) {
 
168
                switch (waitpid( *pid, &result, WNOHANG )) {
 
169
                case 0:
 
170
                        sigsuspend( &oss );
 
171
                        break;
 
172
                case -1:
 
173
                        debug( "Wait4(%d) failed: %m\n", *pid );
 
174
                        result = 0;
 
175
                        /* fallthrough */
 
176
                default:
 
177
                        *pid = 0;
 
178
                        if (osa.sa_handler == SIG_DFL)
 
179
                                Signal( SIGCHLD, SIG_DFL );
 
180
                        sigprocmask( SIG_SETMASK, &oss, 0 );
 
181
                        return wcFromWait( result );
 
182
                }
 
183
        }
 
184
}
 
185
 
 
186
 
 
187
void
 
188
execute( char **argv, char **env )
 
189
{
 
190
        debug( "execute: %[s ; %[s\n", argv, env );
 
191
        execve( argv[0], argv, env );
 
192
        /*
 
193
         * In case this is a shell script which hasn't been
 
194
         * made executable (or this is a SYSV box), do
 
195
         * a reasonable thing
 
196
         */
 
197
        if (errno != ENOENT) {
 
198
                char **newargv;
 
199
                FILE *f;
 
200
                int nu;
 
201
                char program[1024];
 
202
 
 
203
                /*
 
204
                 * emulate BSD kernel behaviour -- read
 
205
                 * the first line; check if it starts
 
206
                 * with "#!", in which case it uses
 
207
                 * the rest of the line as the name of
 
208
                 * program to run.      Else use "/bin/sh".
 
209
                 */
 
210
                if (!(f = fopen( argv[0], "r" )))
 
211
                        return;
 
212
                if (!fGets( program, sizeof(program), f )) {
 
213
                        fclose( f );
 
214
                        return;
 
215
                }
 
216
                fclose( f );
 
217
                if (!strncmp( program, "#!", 2 ))
 
218
                        newargv = parseArgs( 0, program + 2 );
 
219
                else
 
220
                        newargv = addStrArr( 0, "/bin/sh", 7 );
 
221
                if (!newargv)
 
222
                        return;
 
223
                nu = arrLen( newargv );
 
224
                if (!(argv = xCopyStrArr( nu, argv )))
 
225
                        return;
 
226
                memcpy( argv, newargv, sizeof(char *) * nu );
 
227
                debug( "shell script execution: %[s\n", argv );
 
228
                execve( argv[0], argv, env );
 
229
        }
 
230
}
 
231
 
 
232
int
 
233
runAndWait( char **args, char **env )
 
234
{
 
235
        int pid, ret;
 
236
 
 
237
        switch (Fork( &pid )) {
 
238
        case 0:
 
239
                execute( args, env );
 
240
                logError( "Can't execute %\"s: %m\n", args[0] );
 
241
                exit( 127 );
 
242
        case -1:
 
243
                logError( "Can't fork to execute %\"s: %m\n", args[0] );
 
244
                return wcCompose( 0, 0, 127 );
 
245
        }
 
246
        ret = Wait4( &pid );
 
247
        return wcFromWait( ret );
 
248
}
 
249
 
 
250
FILE *
 
251
pOpen( char **what, char m, volatile int *pid )
 
252
{
 
253
        int dp[2];
 
254
 
 
255
        if (pipe( dp ))
 
256
                return 0;
 
257
        switch (Fork( pid )) {
 
258
        case 0:
 
259
                if (m == 'r')
 
260
                        dup2( dp[1], 1 );
 
261
                else
 
262
                        dup2( dp[0], 0 );
 
263
                close( dp[0] );
 
264
                close( dp[1] );
 
265
                execute( what, environ );
 
266
                logError( "Can't execute %\"s: %m\n", what[0] );
 
267
                exit( 127 );
 
268
        case -1:
 
269
                close( dp[0] );
 
270
                close( dp[1] );
 
271
                logError( "Can't fork to execute %\"s: %m\n", what[0] );
 
272
                return 0;
 
273
        }
 
274
        if (m == 'r') {
 
275
                close( dp[1] );
 
276
                return fdopen( dp[0], "r" );
 
277
        } else {
 
278
                close( dp[0] );
 
279
                return fdopen( dp[1], "w" );
 
280
        }
 
281
}
 
282
 
 
283
int
 
284
pClose( FILE *f, volatile int *pid )
 
285
{
 
286
        fclose( f );
 
287
        return Wait4( pid );
 
288
}
 
289
 
 
290
char *
 
291
locate( const char *exe )
 
292
{
 
293
        int len;
 
294
        char *path, *pathe, *name, *thenam, nambuf[PATH_MAX+1];
 
295
 
 
296
        if (!(path = getenv( "PATH" ))) {
 
297
                logError( "Can't execute %'s: $PATH not set.\n", exe );
 
298
                return 0;
 
299
        }
 
300
        len = strlen( exe );
 
301
        name = nambuf + PATH_MAX - len;
 
302
        memcpy( name, exe, len + 1 );
 
303
        *--name = '/';
 
304
        do {
 
305
                if (!(pathe = strchr( path, ':' )))
 
306
                        pathe = path + strlen( path );
 
307
                len = pathe - path;
 
308
                if (len && !(len == 1 && *path == '.')) {
 
309
                        thenam = name - len;
 
310
                        if (thenam >= nambuf) {
 
311
                                memcpy( thenam, path, len );
 
312
                                if (!access( thenam, X_OK )) {
 
313
                                        strDup( &name, thenam );
 
314
                                        return name;
 
315
                                }
 
316
                        }
 
317
                }
 
318
                path = pathe;
 
319
        } while (*path++ != '\0');
 
320
        logError( "Can't execute %'s: not in $PATH.\n", exe );
 
321
        return 0;
 
322
}
 
323
 
 
324
 
 
325
static GTalk *curtalk;
 
326
 
 
327
void
 
328
gSet( GTalk *tlk )
 
329
{
 
330
        curtalk = tlk;
 
331
}
 
332
 
 
333
void
 
334
gCloseOnExec( GPipe *pajp )
 
335
{
 
336
        fcntl( pajp->fd.r, F_SETFD, FD_CLOEXEC );
 
337
#ifndef SINGLE_PIPE
 
338
        fcntl( pajp->fd.w, F_SETFD, FD_CLOEXEC );
 
339
#endif
 
340
}
 
341
 
 
342
#if !defined(SINGLE_PIPE) || defined(__FreeBSD__)
 
343
# define make_pipe(h) pipe( h )
 
344
#else
 
345
# define make_pipe(h) socketpair( AF_UNIX, SOCK_STREAM, 0, h )
 
346
#endif
 
347
 
 
348
int
 
349
gFork( GPipe *pajp, const char *pname, char *cname,
 
350
       GPipe *ogp, char *cgname,
 
351
       GPipe *gp,
 
352
       volatile int *pidr )
 
353
{
 
354
        int opipe[2], ogpipe[2];
 
355
#ifndef SINGLE_PIPE
 
356
        int ipipe[2], igpipe[2];
 
357
#endif
 
358
        int pid;
 
359
 
 
360
        if (make_pipe( opipe ))
 
361
                goto badp1;
 
362
#ifndef SINGLE_PIPE
 
363
        if (pipe( ipipe ))
 
364
                goto badp2;
 
365
#endif
 
366
        if (ogp) {
 
367
                if (make_pipe( ogpipe ))
 
368
#ifdef SINGLE_PIPE
 
369
                {
 
370
#else
 
371
                        goto badp3;
 
372
                if (pipe( igpipe ))
 
373
                {
 
374
                        close( ogpipe[0] );
 
375
                        close( ogpipe[1] );
 
376
                  badp3:
 
377
                        close( ipipe[0] );
 
378
                        close( ipipe[1] );
 
379
                  badp2:
 
380
#endif
 
381
                        close( opipe[0] );
 
382
                        close( opipe[1] );
 
383
                  badp1:
 
384
                        logError( "Cannot start %s, pipe() failed", cname );
 
385
                        if (cname)
 
386
                                free( cname );
 
387
                        return -1;
 
388
                }
 
389
        }
 
390
        registerCloseOnFork( opipe[1] );
 
391
#ifndef SINGLE_PIPE
 
392
        registerCloseOnFork( ipipe[0] );
 
393
#endif
 
394
        if (ogp) {
 
395
                registerCloseOnFork( ogpipe[1] );
 
396
#ifndef SINGLE_PIPE
 
397
                registerCloseOnFork( igpipe[0] );
 
398
#endif
 
399
        }
 
400
        if (gp) {
 
401
                clearCloseOnFork( gp->fd.r );
 
402
#ifndef SINGLE_PIPE
 
403
                clearCloseOnFork( gp->fd.w );
 
404
#endif
 
405
        }
 
406
        if ((pid = Fork( pidr ))) {
 
407
                if (gp) {
 
408
                        registerCloseOnFork( gp->fd.r );
 
409
#ifndef SINGLE_PIPE
 
410
                        registerCloseOnFork( gp->fd.w );
 
411
#endif
 
412
                }
 
413
                if (ogp) {
 
414
                        close( ogpipe[0] );
 
415
#ifndef SINGLE_PIPE
 
416
                        close( igpipe[1] );
 
417
#endif
 
418
                }
 
419
                close( opipe[0] );
 
420
#ifndef SINGLE_PIPE
 
421
                close( ipipe[1] );
 
422
#endif
 
423
        }
 
424
        switch (pid) {
 
425
        case -1:
 
426
                closeNclearCloseOnFork( opipe[1] );
 
427
#ifndef SINGLE_PIPE
 
428
                closeNclearCloseOnFork( ipipe[0] );
 
429
#endif
 
430
                if (ogp) {
 
431
                        closeNclearCloseOnFork( ogpipe[1] );
 
432
#ifndef SINGLE_PIPE
 
433
                        closeNclearCloseOnFork( igpipe[0] );
 
434
#endif
 
435
                }
 
436
                logError( "Cannot start %s, fork() failed\n", cname );
 
437
                if (cname)
 
438
                         free( cname );
 
439
                return -1;
 
440
        case 0:
 
441
#ifndef SINGLE_PIPE
 
442
                pajp->fd.w = ipipe[1];
 
443
                registerCloseOnFork( ipipe[1] );
 
444
#endif
 
445
                pajp->fd.r = opipe[0];
 
446
                registerCloseOnFork( opipe[0] );
 
447
                pajp->who = (char *)pname;
 
448
                if (ogp) {
 
449
#ifndef SINGLE_PIPE
 
450
                        ogp->fd.w = igpipe[1];
 
451
                        registerCloseOnFork( igpipe[1] );
 
452
#endif
 
453
                        ogp->fd.r = ogpipe[0];
 
454
                        registerCloseOnFork( ogpipe[0] );
 
455
                        ogp->who = (char *)pname;
 
456
                }
 
457
                if (cname)
 
458
                         free( cname );
 
459
                return 0;
 
460
        default:
 
461
                pajp->fd.w = opipe[1];
 
462
#ifndef SINGLE_PIPE
 
463
                pajp->fd.r = ipipe[0];
 
464
#endif
 
465
                pajp->who = cname;
 
466
                if (ogp) {
 
467
                        ogp->fd.w = ogpipe[1];
 
468
#ifndef SINGLE_PIPE
 
469
                        ogp->fd.r = igpipe[0];
 
470
#endif
 
471
                        ogp->who = cgname;
 
472
                }
 
473
                return pid;
 
474
        }
 
475
}
 
476
 
 
477
int
 
478
gOpen( GProc *proc, char **argv, const char *what, char **env, char *cname,
 
479
       GPipe *gp )
 
480
{
 
481
        char **margv;
 
482
        int pip[2];
 
483
        char coninfo[32];
 
484
 
 
485
        if (proc->pid > 0) {
 
486
                logError( "%s already running\n", cname );
 
487
                if (cname)
 
488
                        free( cname );
 
489
                return -1;
 
490
        }
 
491
        if (!(margv = xCopyStrArr( 1, argv ))) {
 
492
                if (cname)
 
493
                        free( cname );
 
494
                return -1;
 
495
        }
 
496
        if (!strApp( margv, progpath, what, (char *)0 )) {
 
497
                free( margv );
 
498
                if (cname)
 
499
                        free( cname );
 
500
                return -1;
 
501
        }
 
502
        if (pipe( pip )) {
 
503
                logError( "Cannot start %s, pipe() failed\n", cname );
 
504
                if (cname)
 
505
                        free( cname );
 
506
                goto fail;
 
507
        }
 
508
        switch (gFork( &proc->pipe, 0, cname, 0, 0, gp, &proc->pid )) {
 
509
        case -1:
 
510
                close( pip[1] );
 
511
          fail1:
 
512
                close( pip[0] );
 
513
          fail:
 
514
                free( margv[0] );
 
515
                free( margv );
 
516
                return -1;
 
517
        case 0:
 
518
                (void)Signal( SIGPIPE, SIG_IGN );
 
519
                close( pip[0] );
 
520
                fcntl( pip[1], F_SETFD, FD_CLOEXEC );
 
521
                if (gp)
 
522
                        sprintf( coninfo, "CONINFO=%d %d %d %d",
 
523
                                 proc->pipe.fd.r, proc->pipe.fd.w, gp->fd.r, gp->fd.w );
 
524
                else
 
525
                        sprintf( coninfo, "CONINFO=%d %d",
 
526
                                 proc->pipe.fd.r, proc->pipe.fd.w );
 
527
                env = putEnv( coninfo, env );
 
528
                if (debugLevel & DEBUG_VALGRIND) {
 
529
                        char **nmargv = xCopyStrArr( 1, margv );
 
530
                        nmargv[0] = locate( "valgrind" );
 
531
                        execute( nmargv, env );
 
532
                } else if (debugLevel & DEBUG_STRACE) {
 
533
                        char **nmargv = xCopyStrArr( 1, margv );
 
534
                        nmargv[0] = locate( "strace" );
 
535
                        execute( nmargv, env );
 
536
                } else
 
537
                        execute( margv, env );
 
538
                write( pip[1], "", 1 );
 
539
                exit( 1 );
 
540
        default:
 
541
                (void)Signal( SIGPIPE, SIG_IGN );
 
542
                close( pip[1] );
 
543
                if (reader( pip[0], coninfo, 1 )) {
 
544
                        Wait4( &proc->pid );
 
545
                        logError( "Cannot execute %\"s (%s)\n", margv[0], cname );
 
546
                        gClosen( &proc->pipe );
 
547
                        goto fail1;
 
548
                }
 
549
                close( pip[0] );
 
550
                debug( "started %s (%\"s), pid %d\n", cname, margv[0], proc->pid );
 
551
                free( margv[0] );
 
552
                free( margv );
 
553
                gSendInt( debugLevel );
 
554
                return 0;
 
555
        }
 
556
}
 
557
 
 
558
static void
 
559
_gClosen( GPipe *pajp )
 
560
{
 
561
        closeNclearCloseOnFork( pajp->fd.r );
 
562
#ifndef SINGLE_PIPE
 
563
        closeNclearCloseOnFork( pajp->fd.w );
 
564
        pajp->fd.w =
 
565
#endif
 
566
        pajp->fd.r = -1;
 
567
}
 
568
 
 
569
void
 
570
gClosen( GPipe *pajp )
 
571
{
 
572
        _gClosen( pajp );
 
573
        if (pajp->who)
 
574
                free( pajp->who );
 
575
        pajp->who = 0;
 
576
}
 
577
 
 
578
int
 
579
gClose( GProc *proc, GPipe *gp, int force )
 
580
{
 
581
        int ret;
 
582
 
 
583
        if (proc->pid <= 0) {
 
584
                debug( "whoops, gClose while helper not running\n" );
 
585
                return 0;
 
586
        }
 
587
        _gClosen( &proc->pipe );
 
588
        if (gp)
 
589
                gClosen( gp );
 
590
        if (force)
 
591
                terminateProcess( proc->pid, SIGTERM );
 
592
        ret = Wait4( &proc->pid );
 
593
        if (wcSig( ret ) ? wcSig( ret ) != SIGTERM :
 
594
            (wcCode( ret ) < EX_NORMAL || wcCode( ret ) > EX_MAX))
 
595
                logError( "Abnormal termination of %s, code %d, signal %d\n",
 
596
                          proc->pipe.who, wcCode( ret ), wcSig( ret ) );
 
597
        debug( "closed %s\n", proc->pipe.who );
 
598
        if (proc->pipe.who)
 
599
                free( proc->pipe.who );
 
600
        proc->pipe.who = 0;
 
601
        return ret;
 
602
}
 
603
 
 
604
static void ATTR_NORETURN
 
605
gErr( void )
 
606
{
 
607
        Longjmp( curtalk->errjmp, 1 );
 
608
}
 
609
 
 
610
static void
 
611
gRead( void *buf, int len )
 
612
{
 
613
        if (reader( curtalk->pipe->fd.r, buf, len ) != len) {
 
614
                logError( "Cannot read from %s\n", curtalk->pipe->who );
 
615
                gErr();
 
616
        }
 
617
}
 
618
 
 
619
static void
 
620
gWrite( const void *buf, int len )
 
621
{
 
622
        if (writer( curtalk->pipe->fd.w, buf, len ) != len) {
 
623
                logError( "Cannot write to %s\n", curtalk->pipe->who );
 
624
                gErr();
 
625
        }
 
626
#ifdef _POSIX_PRIORITY_SCHEDULING
 
627
        if ((debugLevel & DEBUG_HLPCON))
 
628
                sched_yield();
 
629
#endif
 
630
}
 
631
 
 
632
void
 
633
gSendInt( int val )
 
634
{
 
635
        gDebug( "sending int %d (%#x) to %s\n", val, val, curtalk->pipe->who );
 
636
        gWrite( &val, sizeof(val) );
 
637
}
 
638
 
 
639
int
 
640
gRecvInt()
 
641
{
 
642
        int val;
 
643
 
 
644
        gDebug( "receiving int from %s ...\n", curtalk->pipe->who );
 
645
        gRead( &val, sizeof(val) );
 
646
        gDebug( " -> %d (%#x)\n", val, val );
 
647
        return val;
 
648
}
 
649
 
 
650
int
 
651
gRecvCmd( int *cmd )
 
652
{
 
653
        gDebug( "receiving command from %s ...\n", curtalk->pipe->who );
 
654
        if (reader( curtalk->pipe->fd.r, cmd, sizeof(*cmd) ) == sizeof(*cmd)) {
 
655
                gDebug( " -> %d\n", *cmd );
 
656
                return 1;
 
657
        }
 
658
        gDebug( " -> no data\n" );
 
659
        return 0;
 
660
}
 
661
 
 
662
void
 
663
gSendArr( int len, const char *data )
 
664
{
 
665
        gDebug( "sending array[%d] %02[*{hhx to %s\n",
 
666
                len, len, data, curtalk->pipe->who );
 
667
        gWrite( &len, sizeof(len) );
 
668
        gWrite( data, len );
 
669
}
 
670
 
 
671
static char *
 
672
_gRecvArr( int *rlen )
 
673
{
 
674
        unsigned len;
 
675
        char *buf;
 
676
 
 
677
        gRead( &len, sizeof(len) );
 
678
        *rlen = len;
 
679
        gDebug( " -> %d bytes\n", len );
 
680
        if (!len || len > 0x10000)
 
681
                return (char *)0;
 
682
        if (!(buf = Malloc( len )))
 
683
                gErr();
 
684
        gRead( buf, len );
 
685
        return buf;
 
686
}
 
687
 
 
688
char *
 
689
gRecvArr( int *rlen )
 
690
{
 
691
        char *buf;
 
692
 
 
693
        gDebug( "receiving array from %s ...\n", curtalk->pipe->who );
 
694
        buf = _gRecvArr( rlen );
 
695
        gDebug( " -> %02[*{hhx\n", *rlen, buf );
 
696
        return buf;
 
697
}
 
698
 
 
699
static int
 
700
_gRecvArrBuf( char *buf )
 
701
{
 
702
        unsigned len;
 
703
 
 
704
        gRead( &len, sizeof(len) );
 
705
        gDebug( " -> %d bytes\n", len );
 
706
        if (len && len < 0x10000)
 
707
                gRead( buf, len );
 
708
        return len;
 
709
}
 
710
 
 
711
int
 
712
gRecvArrBuf( char *buf )
 
713
{
 
714
        int len;
 
715
 
 
716
        gDebug( "receiving already allocated array from %s ...\n",
 
717
                curtalk->pipe->who );
 
718
        len = _gRecvArrBuf( buf );
 
719
        gDebug( " -> %02[*{hhx\n", len, buf );
 
720
        return len;
 
721
}
 
722
 
 
723
int
 
724
gRecvStrBuf( char *buf )
 
725
{
 
726
        int len;
 
727
 
 
728
        gDebug( "receiving already allocated string from %s ...\n",
 
729
                curtalk->pipe->who );
 
730
        len = _gRecvArrBuf( buf );
 
731
        gDebug( " -> %\".*s\n", len, buf );
 
732
        return len;
 
733
}
 
734
 
 
735
void
 
736
gSendStr( const char *buf )
 
737
{
 
738
        int len;
 
739
 
 
740
        gDebug( "sending string %\"s to %s\n", buf, curtalk->pipe->who );
 
741
        if (buf) {
 
742
                len = strlen( buf ) + 1;
 
743
                gWrite( &len, sizeof(len) );
 
744
                gWrite( buf, len );
 
745
        } else
 
746
                gWrite( &buf, sizeof(int) );
 
747
}
 
748
 
 
749
void
 
750
gSendNStr( const char *buf, int len )
 
751
{
 
752
        int tlen = len + 1;
 
753
        gDebug( "sending string %\".*s to %s\n", len, buf, curtalk->pipe->who );
 
754
        gWrite( &tlen, sizeof(tlen) );
 
755
        gWrite( buf, len );
 
756
        gWrite( "", 1 );
 
757
}
 
758
 
 
759
void
 
760
gSendStrN( const char *buf, int len )
 
761
{
 
762
        if (buf)
 
763
                gSendNStr( buf, strnlen( buf, len ) );
 
764
        else
 
765
                gSendStr( buf );
 
766
}
 
767
 
 
768
char *
 
769
gRecvStr()
 
770
{
 
771
        int len;
 
772
        char *buf;
 
773
 
 
774
        gDebug( "receiving string from %s ...\n", curtalk->pipe->who );
 
775
        buf = _gRecvArr( &len );
 
776
        gDebug( " -> %\".*s\n", len, buf );
 
777
        return buf;
 
778
}
 
779
 
 
780
static void
 
781
_gSendStrArr( int num, char **data )
 
782
{
 
783
        char **cdata;
 
784
 
 
785
        gWrite( &num, sizeof(num) );
 
786
        for (cdata = data; --num >= 0; cdata++)
 
787
                gSendStr( *cdata );
 
788
}
 
789
 
 
790
/*
 
791
void
 
792
gSendStrArr (int num, char **data)
 
793
{
 
794
        gDebug( "sending string array[%d] to %s\n", num, curtalk->pipe->who );
 
795
        _gSendStrArr( num, data );
 
796
}
 
797
*/
 
798
 
 
799
char **
 
800
gRecvStrArr( int *rnum )
 
801
{
 
802
        int num;
 
803
        char **argv, **cargv;
 
804
 
 
805
        gDebug( "receiving string array from %s ...\n", curtalk->pipe->who );
 
806
        gRead( &num, sizeof(num) );
 
807
        gDebug( " -> %d strings\n", num );
 
808
        *rnum = num;
 
809
        if (!num)
 
810
                return (char **)0;
 
811
        if (!(argv = Malloc( num * sizeof(char *) )))
 
812
                gErr();
 
813
        for (cargv = argv; --num >= 0; cargv++)
 
814
                *cargv = gRecvStr();
 
815
        return argv;
 
816
}
 
817
 
 
818
void
 
819
gSendArgv( char **argv )
 
820
{
 
821
        int num;
 
822
 
 
823
        if (argv) {
 
824
                for (num = 0; argv[num]; num++);
 
825
                gDebug( "sending argv[%d] to %s ...\n", num, curtalk->pipe->who );
 
826
                _gSendStrArr( num + 1, argv );
 
827
        } else {
 
828
                gDebug( "sending NULL argv to %s\n", curtalk->pipe->who );
 
829
                gWrite( &argv, sizeof(int) );
 
830
        }
 
831
}
 
832
 
 
833
char **
 
834
gRecvArgv()
 
835
{
 
836
        int num;
 
837
 
 
838
        return gRecvStrArr( &num );
 
839
}
 
840