~zulcss/ubuntu/lucid/likewise-open/likewise-open-sru

« back to all changes in this revision

Viewing changes to centutils/libcentutils/ctshell.c

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-08-27 08:56:20 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080827085620-5q0f58b9qtog9myq
Tags: 4.1.0.2956-0ubuntu1
* missing-likewise-logo.diff: removed
* fixed copyright notice
* updated Standards-Version to 3.8.0
* removed path from command in prerm
* removed stop in S runlevel

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include "ctarray.h"
27
27
#include <sys/types.h>
28
28
#include <sys/wait.h>
 
29
#include "config/config.h"
29
30
 
30
31
#define SIGIL '%'
31
32
 
 
33
#ifndef HAVE__NSGETENVIRON
 
34
extern char **environ;
 
35
#endif
 
36
 
32
37
typedef struct
33
38
{
34
39
    int fds[2];
84
89
    return result;
85
90
}
86
91
 
 
92
struct CTShellVar __CTVarZero(const char* name)
 
93
{
 
94
    CTShellVar result;
 
95
    result.type = SVAR_ZERO;
 
96
    result.name = name;
 
97
 
 
98
    return result;
 
99
}
 
100
 
87
101
static unsigned int
88
102
VarLength(const char* format, unsigned int offset)
89
103
{
225
239
}
226
240
 
227
241
static BOOLEAN
228
 
NeedsEscape(char c)
 
242
NeedsEscape(char c, BOOLEAN inDouble)
229
243
{
230
 
    switch (c)
231
 
    {
232
 
    case '\\':
233
 
    case '"':
234
 
    case '$':
235
 
    case '\'':
236
 
    case ' ':
237
 
    case '\t':
238
 
    case '(':
239
 
    case ')':
240
 
    case '&':
241
 
    case ';':
242
 
    case '|':
243
 
    // Solaris treats ^ like |
244
 
    case '^':
245
 
    case '>':
246
 
    case '<':
247
 
    case '{':
248
 
    case '}':
249
 
        return TRUE;
250
 
    default:
251
 
        return FALSE;
 
244
    if (inDouble)
 
245
    {
 
246
        switch(c)
 
247
        {
 
248
        case '\"':
 
249
            return TRUE;
 
250
        default:
 
251
            return FALSE;
 
252
        }
 
253
    }
 
254
    else
 
255
    {
 
256
        switch (c)
 
257
        {
 
258
        case '\\':
 
259
        case '"':
 
260
        case '$':
 
261
        case '\'':
 
262
        case ' ':
 
263
        case '\t':
 
264
        case '(':
 
265
        case ')':
 
266
        case '&':
 
267
        case ';':
 
268
        case '|':
 
269
            // Solaris treats ^ like |
 
270
        case '^':
 
271
        case '>':
 
272
        case '<':
 
273
        case '{':
 
274
        case '}':
 
275
            return TRUE;
 
276
        default:
 
277
            return FALSE;
 
278
        }
252
279
    }
253
280
}
254
281
 
255
282
static CENTERROR
256
 
AppendStringEscaped(StringBuffer* buffer, const char* str, int length)
 
283
AppendStringEscaped(StringBuffer* buffer, const char* str, int length, BOOLEAN inDouble)
257
284
{
258
285
    CENTERROR ceError = CENTERROR_SUCCESS;
259
286
    unsigned int i;
260
287
 
 
288
    if (inDouble)
 
289
    {
 
290
        BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\"'));
 
291
    }
 
292
 
 
293
    BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\''));
 
294
    
261
295
    for (i = 0; str[i] && (length == -1 || i < (unsigned int) length); i++)
262
296
    {
263
 
        if (NeedsEscape(str[i]))
264
 
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\\'));
265
 
        BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, str[i]));
 
297
        if (str[i] == '\'')
 
298
        {
 
299
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\''));
 
300
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\\'));
 
301
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\''));
 
302
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\''));
 
303
        }
 
304
        else
 
305
        {
 
306
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, str[i]));
 
307
        }
 
308
    }
 
309
    
 
310
    BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\''));
 
311
 
 
312
    if (inDouble)
 
313
    {
 
314
        BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\"'));
266
315
    }
267
316
 
268
317
error:
282
331
}
283
332
 
284
333
static CENTERROR
285
 
AppendVariable(Command* result, struct CTShellVar* var)
 
334
AppendVariable(Command* result, struct CTShellVar* var, BOOLEAN inDouble)
286
335
{
287
336
    CENTERROR ceError = CENTERROR_SUCCESS;
288
337
    char* str = NULL;
299
348
        BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppend(&result->buffer, str));
300
349
        break;
301
350
    case SVAR_STR:
302
 
        BAIL_ON_CENTERIS_ERROR(ceError = AppendStringEscaped(&result->buffer, var->value.string, -1));
 
351
        BAIL_ON_CENTERIS_ERROR(ceError = AppendStringEscaped(&result->buffer, var->value.string, -1, inDouble));
303
352
        break;
304
353
    case SVAR_ARR:
305
354
        for (ptr = var->value.array; *ptr; ptr++)
308
357
                BAIL_ON_CENTERIS_ERROR(ceError = 
309
358
                                       CTStringBufferAppendChar(&result->buffer, ' '));
310
359
            
311
 
            BAIL_ON_CENTERIS_ERROR(ceError = AppendStringEscaped(&result->buffer, *ptr, -1));
 
360
            BAIL_ON_CENTERIS_ERROR(ceError = AppendStringEscaped(&result->buffer, *ptr, -1, inDouble));
312
361
        }
313
362
        break;
314
363
    case SVAR_OUT:
324
373
        BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppend(&result->buffer, str));
325
374
 
326
375
        ppipe = NULL;
 
376
        break;
 
377
    case SVAR_ZERO:
 
378
        break;
327
379
    default:
328
380
        break;
329
381
    }
384
436
    unsigned int i, length;
385
437
    char* variable = NULL;
386
438
    StringBuffer* buffer = &result->buffer;
 
439
    BOOLEAN inDouble = FALSE;
387
440
 
388
441
    for (i = 0; format[i]; i++)
389
442
    {
390
443
        switch (format[i])
391
444
        {
 
445
        case '\"':
 
446
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, format[i]));
 
447
            inDouble = !inDouble;
 
448
            break;
392
449
        case '\'':
393
450
            length = QuoteLength(format, i);        
394
 
            BAIL_ON_CENTERIS_ERROR(ceError = AppendStringEscaped(buffer, format+i+1, length-2));
 
451
            BAIL_ON_CENTERIS_ERROR(ceError = AppendStringEscaped(buffer, format+i+1, length-2, inDouble));
395
452
            i += length-1;
396
453
            break;
397
454
        case '\\':
398
455
            i++;
399
 
            if (NeedsEscape(format[i]))
 
456
            if (NeedsEscape(format[i], inDouble))
400
457
                BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\\'));
401
458
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, format[i]));
402
459
            break;
406
463
            BAIL_ON_CENTERIS_ERROR(ceError = 
407
464
                                   AppendVariable(result, 
408
465
                                                  lwg_hash_table_lookup(result->variables, 
409
 
                                                                      (void*) (variable+1))));
 
466
                                                                        (void*) (variable+1)),
 
467
                                                  inDouble));
410
468
            i += length-1;
 
469
            CT_SAFE_FREE_STRING(variable);
411
470
            variable = NULL;
412
471
            break;
413
472
        // Characters to pass through unmodified to the shell
415
474
        case '|':
416
475
        case ';':
417
476
        case '$':
418
 
        case '\"':
419
477
        case '(':
420
478
        case ')':
421
479
        case '{':
427
485
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, format[i]));
428
486
            break;
429
487
        default:
430
 
            if (NeedsEscape(format[i]))
 
488
            if (NeedsEscape(format[i], inDouble))
431
489
                BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, '\\'));
432
490
            BAIL_ON_CENTERIS_ERROR(ceError = CTStringBufferAppendChar(buffer, format[i]));
433
491
            break;
439
497
}
440
498
 
441
499
CENTERROR
442
 
ExecuteShellCommand(Command* command)
 
500
ExecuteShellCommand(char * const envp[], Command* command)
443
501
{
444
502
    CENTERROR ceError = CENTERROR_SUCCESS;
445
 
    pid_t pid;
446
 
 
447
 
//    fprintf(stderr, "CTShell: %s\n", command->buffer.data);
 
503
    pid_t pid, wpid;
448
504
 
449
505
    pid = fork();
450
506
    if (pid < 0)
467
523
                    abort();
468
524
            }
469
525
        }
470
 
        execl("/bin/sh", (const char*) "sh", (const char*) "-c", (const char*) command->buffer.data, (const char*) NULL);
471
 
        // If we are still here, die horribly
472
 
        abort();
 
526
        if (envp)
 
527
            execle("/bin/sh", (const char*) "sh", (const char*) "-c", (const char*) command->buffer.data, (const char*) NULL, envp);
 
528
        else
 
529
            execl("/bin/sh", (const char*) "sh", (const char*) "-c", (const char*) command->buffer.data, (const char*) NULL);
 
530
        exit(1);
473
531
    }
474
532
    else
475
533
    {
524
582
                    {
525
583
                        char buffer[1024];
526
584
                        int amount;
527
 
 
 
585
                        
528
586
                        while ((amount = read(pipes[i]->fds[0], buffer, sizeof(buffer)-1)) < 0)
529
587
                        {
530
588
                            if (errno != EAGAIN)
552
610
                }
553
611
            }
554
612
        }
555
 
        if (waitpid(pid, &status, 0) != pid || status)
556
 
        {
557
 
            if (status)
558
 
                BAIL_ON_CENTERIS_ERROR(ceError = CENTERROR_COMMAND_FAILED);
559
 
            else
560
 
                BAIL_ON_CENTERIS_ERROR(ceError = CTMapSystemError(errno));
561
 
        }
 
613
        
 
614
        do
 
615
        {
 
616
            wpid = waitpid(pid, &status, 0);
 
617
        } while (wpid != pid && errno == EINTR);
 
618
        if (wpid != pid)
 
619
            BAIL_ON_CENTERIS_ERROR(ceError = CTMapSystemError(errno));
 
620
        else if (status)
 
621
            BAIL_ON_CENTERIS_ERROR(ceError = CENTERROR_COMMAND_FAILED);
562
622
    }
563
623
 
564
624
error:
566
626
}
567
627
 
568
628
CENTERROR
 
629
CTShellEx(char * const envp[], const char* format, ...)
 
630
{
 
631
    CENTERROR ceError = CENTERROR_SUCCESS;
 
632
    unsigned int numvars = 0;
 
633
    va_list ap;
 
634
    Command command;
 
635
 
 
636
    va_start(ap, format);
 
637
 
 
638
    BAIL_ON_CENTERIS_ERROR(ceError = CommandConstruct(&command));
 
639
    BAIL_ON_CENTERIS_ERROR(ceError = CountVariables(format, &numvars));
 
640
    BAIL_ON_CENTERIS_ERROR(ceError = BuildVariableTable(numvars, ap, &command.variables));
 
641
    BAIL_ON_CENTERIS_ERROR(ceError = ConstructShellCommand(format, &command));
 
642
    BAIL_ON_CENTERIS_ERROR(ceError = ExecuteShellCommand(envp, &command));
 
643
 
 
644
error:
 
645
    va_end (ap);
 
646
 
 
647
    CommandDestroy(&command);
 
648
 
 
649
    return ceError;
 
650
}
 
651
 
 
652
CENTERROR
569
653
CTShell(const char* format, ...)
570
654
{
571
655
    CENTERROR ceError = CENTERROR_SUCCESS;
577
661
 
578
662
    BAIL_ON_CENTERIS_ERROR(ceError = CommandConstruct(&command));
579
663
    BAIL_ON_CENTERIS_ERROR(ceError = CountVariables(format, &numvars));
580
 
    BAIL_ON_CENTERIS_ERROR(ceError = BuildVariableTable(numvars, ap, &command.variables));
 
664
    BAIL_ON_CENTERIS_ERROR(ceError = BuildVariableTable(numvars, ap,
 
665
                &command.variables));
581
666
    BAIL_ON_CENTERIS_ERROR(ceError = ConstructShellCommand(format, &command));
582
 
    BAIL_ON_CENTERIS_ERROR(ceError = ExecuteShellCommand(&command));
 
667
    BAIL_ON_CENTERIS_ERROR(ceError = ExecuteShellCommand(NULL, &command));
583
668
 
584
669
error:
585
670
    va_end (ap);