| 567 | */ |
| 568 | |
| 569 | static long raw_command_length( char const * command ) |
| 570 | { |
| 571 | char const * p; |
| 572 | char const * escape = 0; |
| 573 | char inquote = 0; |
| 574 | char const * newline = 0; |
| 575 | |
| 576 | /* Skip leading whitespace. */ |
| 577 | while ( isspace( *command ) ) |
| 578 | ++command; |
| 579 | |
| 580 | p = command; |
| 581 | |
| 582 | /* Look for newlines and unquoted I/O redirection. */ |
| 583 | do |
| 584 | { |
| 585 | p += strcspn( p, "\n\"'<>|\\" ); |
| 586 | switch ( *p ) |
| 587 | { |
| 588 | case '\n': |
| 589 | /* If our command contains non-whitespace content split over |
| 590 | * multiple lines we can not execute it directly. |
| 591 | */ |
| 592 | newline = p; |
| 593 | while ( isspace( *++p ) ); |
| 594 | if ( *p ) return -1; |
| 595 | break; |
| 596 | |
| 597 | case '\\': |
| 598 | escape = escape && escape == p - 1 ? 0 : p; |
| 599 | ++p; |
| 600 | break; |
| 601 | |
| 602 | case '"': |
| 603 | case '\'': |
| 604 | if ( escape && escape == p - 1 ) |
| 605 | escape = 0; |
| 606 | else if ( inquote == *p ) |
| 607 | inquote = 0; |
| 608 | else if ( !inquote ) |
| 609 | inquote = *p; |
| 610 | ++p; |
| 611 | break; |
| 612 | |
| 613 | case '<': |
| 614 | case '>': |
| 615 | case '|': |
| 616 | if ( !inquote ) |
| 617 | return -1; |
| 618 | ++p; |
| 619 | break; |
| 620 | } |
| 621 | } |
| 622 | while ( *p ); |
| 623 | |
| 624 | /* Return the number of characters the command will occupy. */ |
| 625 | return ( newline ? newline : p ) - command; |
| 626 | } |
no test coverage detected