home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / lib / perl5 / vendor_perl / 5.8.8 / ycp.pm
Text File  |  2006-11-29  |  41KB  |  1,831 lines

  1. ########################################################################
  2. #
  3. #                                                                    #
  4. #                    __   __    ____ _____ ____                      #
  5. #                    \ \ / /_ _/ ___|_   _|___ \                     #
  6. #                     \ V / _` \___ \ | |   __) |                    #
  7. #                      | | (_| |___) || |  / __/                     #
  8. #                      |_|\__,_|____/ |_| |_____|                    #
  9. #                                                         -o)
  10. #------------------------------------------------------   /\\  --------
  11. #                                                        _\_v
  12. #
  13. #   Author:        Michael Hager <mike@suse.de>
  14. #           Martin Vidner <mvidner@suse.cz>
  15. #
  16. #   Description:   perl interface for YCP
  17. #
  18. #   Purpose:       Call a perl script within a YCP script
  19. #
  20. #----------------------------------------------------------------------
  21. # $Id: ycp.pm 32969 2006-09-19 12:21:30Z mvidner $
  22.  
  23. package ycp;
  24.  
  25. =head1 NAME
  26.  
  27. ycp - a Perl module for parsing and writing the YaST2 Communication Protocol
  28.  
  29. =head1 SYNOPSIS
  30.  
  31. C<($symbol, @config) = ycp::ParseTerm ('MyAgentConfig ("/etc/file", false, true, $["a":1, "b":2])');>
  32.  
  33. C<($command, $path, $arg) = ycp::ParseCommand ('Write (.magic.path, "abacadabra")');>
  34.  
  35. C<ycp::Return (["arbitrarily", "complex", "data"]);>
  36.  
  37. =head1 DATA
  38.  
  39. =head2 PerlYCPValue
  40.  
  41. PerlYCPValue is a convention for storing a YCP value in a Perl variable.
  42. L</ParseYcp> parses YCP string representation into PerlYCPValues.
  43.  
  44. A PerlYCPValue cannot represent a term but only a term is allowed
  45. to initialize an agent in a .scr file. Therefore L</ParseTerm> is provided.
  46.  
  47. =over 4
  48.  
  49. =item string, integer, boolean
  50.  
  51. Stored as a scalar.
  52.  
  53. =item list
  54.  
  55. Stored as a reference to a list of PerlYCPValues.
  56.  
  57. =item map
  58.  
  59. Stored as a reference to a map  of PerlYCPValues.
  60.  
  61. =item path
  62.  
  63. Stored as a reference to a string (starting with a "." as expected).
  64.  
  65. =item nil (void)
  66.  
  67. Stored as an undef.
  68.  
  69. =back
  70.  
  71. =head1 PARSING
  72.  
  73. =cut
  74.  
  75. use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
  76. use Exporter;
  77. use diagnostics;
  78. use strict;
  79. use Time::localtime;
  80. use Sys::Hostname;
  81.  
  82. @ISA     = qw(Exporter);
  83.  
  84.  
  85. my @e_io = qw(
  86.            ParseTerm
  87.            ParseCommand
  88.            PathComponents
  89.            Return
  90.            );
  91.  
  92. @EXPORT_OK = @e_io;
  93.  
  94. my @e_logging = qw(y2debug y2milestone y2warning y2error y2security y2internal);
  95. my @e_obsolete  = qw(
  96.            ycpDoVerboseLog
  97.            ycpInit
  98.            ycpArgIsMap
  99.            ycpArgIsList
  100.            ycpArgIsInteger
  101.            ycpArgIsString
  102.            ycpArgIsNil
  103.            ycpArgIsNone
  104.            ycpGetArgMap
  105.            ycpGetArgList
  106.            ycpGetArgString
  107.            ycpGetArgInteger
  108.            ycpReturnSkalarAsInt
  109.            ycpReturnArrayAsList
  110.            ycpReturnSkalarAsBoolean
  111.            ycpReturnHashAsMap
  112.            ycpReturnSkalarAsString
  113.            ycpCommandIsDir
  114.            ycpCommandIsRead
  115.            ycpCommandIsWrite
  116.            ycpCommandIsExecute
  117.            ycpCommandIsResult
  118.            ycpGetCommand
  119.            ycpGetPath
  120.            ycpGetArgType
  121.            ycpReturn );
  122.  
  123. @EXPORT = (@e_logging, @e_obsolete);
  124.  
  125. our %EXPORT_TAGS = (IO => [@e_io],
  126.             LOGGING => [@e_logging],
  127.             OBSOLETE => [@e_obsolete]);
  128.  
  129. my $ycpcommand    = "";
  130. my $ycppath       = "";
  131.  
  132. my $type          = "unknown";
  133. my $ismap         = 0;
  134. my $islist        = 0;
  135. my $isinteger     = 0;
  136. my $isstring      = 0;
  137. my $isknown       = 0;
  138. my $isnil         = 0;
  139. my $isnone        = 0;
  140.  
  141. my %arghash;
  142. my @argarray;
  143. my $argskalar;
  144.  
  145. my $verbose = 0;
  146. my $againstcompileerror = 1;
  147.  
  148. my $hostname = hostname();
  149.  
  150.  
  151. ################################################################################
  152. # Parsing
  153. ################################################################################
  154.  
  155. =head2 ParseCommand
  156.  
  157. ParseComand $line
  158.  
  159. C<($command, $path, $arg) = ParseCommand ('Write (.moria.gate, "mellon")');>
  160.  
  161. Parse a SCR command of the form Command (.some.path, optional_argument)
  162.  
  163. Returns a three element list ("Command", ".some.path", $argument)
  164. where the argument is a L</PerlYCPValue> and will be undef
  165. if it was not specified.
  166. Note that the path is converted to a string.
  167.  
  168. If there was a parse error, the command or path will be the empty string.
  169.  
  170. =cut
  171.  
  172. sub ParseCommand ($)
  173. {
  174.     my @term = ParseTerm (shift);
  175.  
  176.     my $command = shift @term || "";
  177.  
  178.     my $path = "";
  179.     my $pathref = shift @term;
  180.     if (defined $pathref)
  181.     {
  182.     if (ref($pathref) eq "SCALAR" && $$pathref =~ /^\./)
  183.     {
  184.         $path = $$pathref;
  185.     }
  186.     # 'result (nil)' is a standard command
  187.     elsif ($command ne "result")
  188.     {
  189.         y2error ("The first argument is not a path. ('$pathref')");
  190.     }
  191.     }
  192.  
  193.     my $argument = shift @term;
  194.     y2warning ("Superfluous command arguments ignored") if (@term > 0);
  195.  
  196.     return ($command, $path, $argument);
  197. }
  198.  
  199. =head2 ParseTerm
  200.  
  201. ParseTerm $line
  202.  
  203. C<($symbol, @config) = ParseTerm ('MyAgentConfig ("/etc/file", false, true, $["a":1, "b":2])');>
  204.  
  205. Parse a YCP term. Note that there can be no other term inside.
  206.  
  207. Returns a list whose first element is the term symbol as a string
  208. (or C<""> in case of an error) and the remaining elements are the term
  209. arguments (L</PerlYCPValue>)
  210.  
  211. =cut
  212.  
  213. sub ParseTerm ($)
  214. {
  215.     my $input = shift;
  216.  
  217.     my $symbol;
  218.     my @ret;
  219.  
  220.     $input =~ s/^\s*`?(\w*)\s*//; # allow both Term and `Term (for the NI)
  221.     $symbol = $1;
  222.     if (! $symbol)
  223.     {
  224.     y2error ("No term symbol");
  225.     }
  226.     push @ret, $symbol;
  227.  
  228.     if ($input !~ m/^\(/)
  229.     {
  230.     y2error ("No term parentheses");
  231.     }
  232.  
  233.     my ($argref, $err, $rest) = ParseYcpTermBody ($input);
  234.     if ($err)
  235.     {
  236.     y2error ("$err ('$rest')");
  237.     }
  238.     else
  239.     {
  240.     push @ret, @$argref;
  241.     }
  242.  
  243.     return @ret;
  244. }
  245.  
  246. # ------------------------------------------------------------
  247. # Internal parsing functions start here.
  248.  
  249. # PerlYCPParserResult is a triple:
  250. # ($result, $error, $rest_of_input)
  251. # where
  252. #   $result is a PerlYCPValue.
  253. #   $error is either "" or an error description.
  254. #        In that case, $result is not specfied.
  255. #   $rest_of_input is the unmatched part of the input.
  256. #        On success, parsing can go on, on error, the ofending input is there.
  257.  
  258. # this is how it looks like in lex:
  259. # PATHSEGMENT [[:alnum:]_-]+|\"([^\\"]*(\\.)*)+\"
  260. my $lex_pathsegment = qr{
  261.         (?:                # outer group
  262.         [[:alnum:]_-]+            # ordinary segment
  263.         |
  264.         "
  265.         (?:
  266.         [^\\"]*                # any-except-bkls-quot
  267.         (?: \\ . )*            # bksl, any
  268.         )+
  269.         "
  270.         )
  271.         }x;        # enable whitespace and comments in regex
  272.  
  273. # Internal
  274. # Parses a YCP value. See PerlYCPValue. Notably terms are not supported.
  275. # Returns PerlYCPParserResult.
  276. sub ParseYcp ($)
  277. {
  278.     my $ycp_value = shift;
  279.  
  280.     #remove leading whitespace;
  281.     $ycp_value =~ s/^\s+//;
  282.  
  283.  
  284.     if ($ycp_value =~ /^nil(.*)/)
  285.     {
  286.     return (undef, "", $1);
  287.     }
  288.     elsif ($ycp_value =~ /^false(.*)/)
  289.     {
  290.     return (0, "", $1);
  291.     }
  292.     elsif ($ycp_value =~ /^true(.*)/)
  293.     {
  294.     return (1, "", $1);
  295.     }
  296.     # numbers. TODO not only integers: floats
  297.     elsif ($ycp_value =~ /^(-?\d+)(.*)/)
  298.     {
  299.     my $num = $1;
  300.     my $rest = $2;
  301.     $num = oct ($num) if $num =~ /^0/;
  302.     return ($num, "", $rest);
  303.     }
  304.     elsif ($ycp_value =~ /^\"/) #"
  305.     {
  306.     return ParseYcpString ($ycp_value);
  307.     }
  308.     elsif ($ycp_value =~ /^((?:\.${lex_pathsegment})+|\.)(.*)/)
  309.     {
  310.     my $path = $1; # must be a "my" variable, not \$1.
  311.     return (\$path, "", $2);
  312.     }
  313.     elsif ($ycp_value =~ /^\[/)
  314.     {
  315.     return ParseYcpList ($ycp_value);
  316.     }
  317.     elsif ($ycp_value =~ /^\$\[/)
  318.     {
  319.     return ParseYcpMap ($ycp_value);
  320.     }
  321.     elsif ($ycp_value =~ /^\#\[/)
  322.     {
  323.     return ParseYcpByteblock ($ycp_value);
  324.     }
  325.     elsif ($ycp_value =~ /^$/)
  326.     {
  327.     return ("", "Unexpected end of input.", $ycp_value);
  328.     }
  329.     else
  330.     {
  331.     return ("", "Construct not supported.", $ycp_value);
  332.     }
  333. }
  334.  
  335. # Internal
  336. # Parses a YCP string. The input must start with a double quote.
  337. # Returns PerlYCPParserResult.
  338.  
  339. # we limit ourselves to parsing the output of YCPStringRep::toString()
  340. # (see YCPString.cc in libycp)
  341. sub ParseYcpString ($)
  342. {
  343.     my $ycp_value = shift;
  344.     my $ret = "";
  345.  
  346.     #remove the leading quote
  347.     $ycp_value =~ s/^"//; #";
  348.  
  349.     while (1)
  350.     {
  351.     # ordinary characters
  352.     if ($ycp_value =~ s/^([^\"\\]+)//) #" #newline?
  353.     {
  354.         $ret .= $1;
  355.     }
  356.     # octal escapes
  357.     elsif ($ycp_value =~ s/^\\([0-7]{3})//)
  358.     {
  359.         $ret .= chr (oct ($1));
  360.     }
  361.     # weird behavior for 1 or 2 digits
  362.     elsif ($ycp_value =~ s/^\\([0-7]{1,2})//)
  363.     {
  364.         $ret .= $1;
  365.     }
  366.     # other escapes
  367.     elsif ($ycp_value =~ s/^\\([^0-7])//)
  368.     {
  369.         if ($1 eq "n")
  370.         {
  371.         $ret .= "\n";
  372.         }
  373.         elsif ($1 eq "t")
  374.         {
  375.         $ret .= "\t";
  376.         }
  377.         elsif ($1 eq "r")
  378.         {
  379.         $ret .= "\r";
  380.         }
  381.         elsif ($1 eq "f")
  382.         {
  383.         $ret .= "\f";
  384.         }
  385.         elsif ($1 eq "b")
  386.         {
  387.         $ret .= "\b";
  388.         }
  389.         elsif ($1 eq "\\")
  390.         {
  391.         $ret .= "\\";
  392.         }
  393.         elsif ($1 eq "\"")
  394.         {
  395.         $ret .= "\"";
  396.         }
  397.         else
  398.         {
  399.         $ret .= $1;
  400.         }
  401.     }
  402.     elsif ($ycp_value =~ /^"(.*)/) #");
  403.     {
  404.         return ($ret, "", $1);
  405.     }
  406.     elsif ($ycp_value =~ /^$/)
  407.     {
  408.         return ("", "Unexpected end of input.", $ycp_value);
  409.     }
  410.     else
  411.     {
  412.         #can't happen
  413.         return ("", "Can't happen in ParseYcpString", $ycp_value);
  414.     }
  415.     }
  416. }
  417.  
  418. =head2 PathComponents
  419.  
  420. PathComponents $path_ref
  421.  
  422.  ($cmd, $path) = ParseCommand ('`Read (.foo."%gconf.d"."gernel")'
  423.  @c = PathComponents (\$path);
  424.  if ($c[0] eq '%gconf.d' && $c[1] eq "gernel") {...}
  425.  
  426. Converts a path (a string reference, L</PerlYCPValue>) to a list
  427. of its components. It deals with the nontrivial parts of path syntax.
  428. On error it returns undef.
  429.  
  430.  .            -> ()
  431.  .foo.bar        -> ('foo', 'bar')
  432.  ."foo"            -> ('foo')
  433.  ."double\"quote"    -> ('double"quote')
  434.  ."a.dot"        -> ('a.dot')
  435.  
  436. =cut
  437.  
  438. sub PathComponents ($)
  439. {
  440.     my $path_ref = shift;
  441.     if (ref ($path_ref) ne "SCALAR") {
  442.     y2error ("Expecting a reference to a scalar");
  443.     return undef;
  444.     }
  445.     my $path = $$path_ref;
  446.  
  447.     return undef if $path eq "";
  448.     return () if $path eq ".";
  449.  
  450.     my @result = ();
  451.  
  452.     while ($path =~ s/^\.(${lex_pathsegment})(.*)/$2/o) {
  453.     my $segment = $1;
  454.     if ($segment =~ /^"/) {
  455.         # FIXME check whether paths are like strings, unify
  456.         my ($parsed, $err, $rest) = ParseYcpString ($segment);
  457.         if ($err ne "") {
  458.         y2error ("Bad complex path component: '$err'");
  459.         return undef;
  460.         }
  461.         elsif ($rest ne "") {
  462.         y2error ("Extra characters in path component: '$rest'");
  463.         return undef;
  464.         }
  465.         $segment = $parsed;
  466.     }
  467.     push @result, $segment;
  468.     }
  469.     if ($path ne "") {
  470.     y2error ("Extra characters in path: '$path'");
  471.     return undef;
  472.     }
  473.     return @result;
  474. }
  475.  
  476. # Internal
  477. # Parses a YCP list. The input must start with "["
  478. # A comma after the last element is permitted.
  479. # Returns PerlYCPParserResult.
  480. sub ParseYcpList ($)
  481. {
  482.     return ParseYcpGenericList (shift, "list", qr/\[/, qr/\]/);
  483. }
  484.  
  485. # Internal
  486. # Parses a term argument list. The input must start with "("
  487. # A comma after the last element is permitted.
  488. # Returns PerlYCPParserResult.
  489. sub ParseYcpTermBody ($)
  490. {
  491.     return ParseYcpGenericList (shift, "term", qr/\(/, qr/\)/);
  492. }
  493.  
  494. # Internal
  495. # Parses a comma delimited list introduced by $open and terminated by $close.
  496. # A comma after the last element is permitted.
  497. # Returns PerlYCPParserResult.
  498. sub ParseYcpGenericList ($$$$)
  499. {
  500.     my ($ycp_value, $description, $open, $close) = @_;
  501.     my $ret = [];
  502.     my $elem;
  503.     my $err;
  504.  
  505.     #remove leading bracket and whitespace;
  506.     if ($ycp_value !~ s/^$open\s*//)
  507.     {
  508.     return ("", "Expecting /$open/ in a $description",$ycp_value);
  509.     }
  510.  
  511.     my $seen_comma = 0;
  512.     my $seen_elem = 0;
  513.  
  514.     # if there's a bracket, eat it and return
  515.     until ($ycp_value =~ s/^$close\s*//)
  516.     {
  517.     if ($seen_elem && ! $seen_comma)
  518.     {
  519.         return ("", "Expecting /$close/ or a comma in a $description",$ycp_value);
  520.     }
  521.  
  522.     ($elem, $err, $ycp_value) = ParseYcp ($ycp_value);
  523.     return ("", $err, $ycp_value) if $err;
  524.     push @{$ret}, $elem;
  525.     $seen_elem = 1;
  526.  
  527.     # skip spaces and comma
  528.     $ycp_value =~ s/^\s*(,)?\s*//;
  529.     $seen_comma = defined $1;
  530.     }
  531.     return ($ret, "", $ycp_value);
  532. }
  533.  
  534. # Internal
  535. # Parses a YCP map. The input must start with "$["
  536. # A comma after the last element is permitted.
  537. # Returns PerlYCPParserResult.
  538. sub ParseYcpMap ($)
  539. {
  540.     my $ycp_value = shift;
  541.     my $ret = {};
  542.     my $key;
  543.     my $value;
  544.     my $err;
  545.  
  546.     #remove leading dollar-bracket and whitespace;
  547.     $ycp_value =~ s/^\$\[\s*//;
  548.  
  549.     my $seen_comma = 0;
  550.     my $seen_elem = 0;
  551.  
  552.     # if there's a bracket, eat it and return
  553.     until ($ycp_value =~ s/^\]\s*//)
  554.     {
  555.     if ($seen_elem && ! $seen_comma)
  556.     {
  557.         return ("", "Expecting a bracket or a comma in a map",$ycp_value);
  558.     }
  559.  
  560.     ($key, $err, $ycp_value) = ParseYcp ($ycp_value);
  561.     return ("", $err, $ycp_value) if $err;
  562.  
  563.     # skip spaces, match a colon
  564.     if ($ycp_value !~ s/^\s*:\s*//)
  565.     {
  566.         return ("", "Expecting a colon in a map", $ycp_value);
  567.     }
  568.  
  569.     ($value, $err, $ycp_value) = ParseYcp ($ycp_value);
  570.     return ("", $err, $ycp_value) if $err;
  571.  
  572.     $ret->{$key} = $value;
  573.     $seen_elem = 1;
  574.  
  575.     # skip spaces and comma
  576.     $ycp_value =~ s/^\s*(,)?\s*//;
  577.     $seen_comma = defined $1;
  578.     }
  579.     return ($ret, "", $ycp_value);
  580. }
  581.  
  582. # Internal
  583. # Parses a YCP byteblock. The input must start with "#["
  584. # Returns PerlYCPParserResult.
  585. sub ParseYcpByteblock ($)
  586. {
  587.     my $ycp_value = shift;
  588.     my $ret = "";
  589.     my $err;
  590.  
  591.     #remove leading hash-bracket and whitespace;
  592.     $ycp_value =~ s/^\#\[\s*//;
  593.  
  594.     # if there's a bracket, eat it and return
  595.     until ($ycp_value =~ s/^\]\s*//)
  596.     {
  597.     if ($ycp_value =~ s/^(([[:xdigit:]][[:xdigit:]])+)(\s|\n)*//)
  598.     {
  599.         $ret .= pack ('H*', $1);
  600.     }
  601.     else
  602.     {
  603.         return ("", "Unexpected characters in byteblock",$ycp_value);
  604.     }
  605.     }
  606.     return ($ret, "", $ycp_value);
  607. }
  608.  
  609.  
  610. ################################################################################
  611. #                         R E T U R N                                          #
  612. ################################################################################
  613. # Function which return a ycp value to the calling YCP-Server
  614.  
  615. =head1 WRITING
  616.  
  617. =cut
  618.  
  619. # Autoflush output, otherwise the caller would not get the answer.
  620. $| = 1;
  621.  
  622. =head2 Return
  623.  
  624. C<Return (["arbitrarily", "complex", "data"]);>
  625.  
  626. Sends a L</PerlYCPValue> to the partner YCP component.
  627.  
  628. If there's just one argment, scalars are interpreted this way:
  629. "true" or "false" are sent as
  630. booleans, integers or strings of digits are sent as integers, otherwise as
  631. strings.
  632. If a second argument exists and is true, all scalars are written as strings.
  633. If a second argument exists and is false, all scalars are written as byteblocks.
  634.  
  635. To send a list, call Return(\@list), not Return(@list).
  636. Similarly for a map. You can use references to anonymous lists [] and hashes {}.
  637.  
  638. The difference from L</ycpReturn> is that Return can return scalars directly,
  639. strings are properly escaped if needeed and paths can be returned.
  640.  
  641. =cut
  642.  
  643. sub Return ($;$);
  644. sub Return ($;$)
  645. {
  646.     my ($val, $quote_everything) = @_;
  647.  
  648.     my $reftype = ref ($val);
  649.     if (! defined ($val))
  650.     {
  651.     print "(nil)";
  652.     }
  653.     elsif (! $reftype)
  654.     {
  655.     if (! defined $quote_everything)
  656.     {
  657.         if ($val =~ /^(true|false|\s*-?\d+\s*)$/)
  658.         {
  659.         print "($val)";
  660.         }
  661.         else
  662.         {
  663.         print WriteYcpString($val);
  664.         }
  665.     }
  666.     elsif ($quote_everything)
  667.     {
  668.         print WriteYcpString($val);
  669.     }
  670.     else
  671.     {
  672.         print WriteYcpByteblock($val);
  673.     }
  674.     }
  675.     elsif ($reftype eq "SCALAR")
  676.     {
  677.     # a path
  678.     print "($$val)";
  679.     }
  680.     elsif ($reftype eq "ARRAY")
  681.     {
  682.     print "[";
  683.     foreach my $elem (@$val)
  684.     {
  685.         Return ($elem, $quote_everything);
  686.         print ","; # trailing comma is allowed
  687.     }
  688.     print "] "; # no "]:"
  689.     }
  690.     elsif ($reftype eq "HASH")
  691.     {
  692.     print "\$[";
  693.     while (my ($key, $value) = each %$val)
  694.     {
  695.         Return ($key, $quote_everything);
  696.         print ":";
  697.         Return ($value, $quote_everything);
  698.         print ","; # trailing comma is allowed
  699.     }
  700.     print "] "; # no "]:"
  701.     }
  702.     else
  703.     {
  704.     y2error ("Cannot pass $reftype to YCP");
  705.     print "(nil)";
  706.     }
  707. }
  708.  
  709. # Internal
  710. # Returns a properly escaped string.
  711. # (Double quotes, backslashes and control characters are handled)
  712. #
  713. # 'qux'                -> '"qux"'
  714. # 'with "quotes"'        -> '"with \"quotes\""'
  715. sub WriteYcpString ($)
  716. {
  717.     my $string = shift;
  718.     my @substrings = split /\\/, $string, -1;
  719.     foreach my $substring (@substrings)
  720.     {
  721.     $substring =~ s/"/\\"/g;# escape quotes
  722.     # escape control chars except newline (easier to debug a parse error)
  723.     $substring =~ s/([\000-\011\013-\027])/sprintf "\\%03o",ord($1)/eg;
  724.     }
  725.     return '"'. join ("\\\\", @substrings) .'"';
  726. }
  727.  
  728. # Internal
  729. # Returns a byteblock.
  730. sub WriteYcpByteblock ($)
  731. {
  732.     my $bb = shift;
  733.     return "#[". unpack ("H*", $bb) ."] ";
  734. }
  735.  
  736.  
  737. ################################################################################
  738. #                         L O G G I N G                                        #
  739. ################################################################################
  740.  
  741. =head1 LOGGING
  742.  
  743. If you are running in the main yast process and thus can afford to import
  744. YaST::YCP, it is better to use its logging functions because they use log.conf
  745. and logging just works. In such case, you should not need to use ycp.pm at all.
  746. Instead, C<use YaST::YCP (":LOGGING")>.
  747.  
  748. The log output can now be redirected, which will be useful for test suites.
  749. If the first command-line option is "-l", the second argument is taken as
  750. the log file. A hyphen "-" designates standard output.
  751.  
  752. Otherwise, F</var/log/YaST2/y2log> and F<$HOME/.y2log> are tried, in that order.
  753.  
  754. =cut
  755.  
  756. my $Y2DEBUG;
  757. my $log_good;
  758.  
  759. # Constructor: open the log and set the two above variables
  760. # so that y2logger has small overhead.
  761. sub BEGIN
  762. {
  763.     $Y2DEBUG = $ENV{"Y2DEBUG"};
  764.  
  765.     my @names = ( "/var/log/YaST2/y2log", "$ENV{HOME}/.y2log" );
  766.     if (defined ($ARGV[0]) && $ARGV[0] =~ /^(-l|--log)$/)
  767.     {
  768.     @names = ( $ARGV[1] );
  769.     }
  770.  
  771.     foreach my $name (@names)
  772.     {
  773.     $log_good = open (LOG, ">>$name");
  774.     if ($log_good)
  775.     {
  776.         my $old_handle = select (LOG);
  777.         $| = 1;        # autoflush
  778.         select ($old_handle);
  779.         return;
  780.     }
  781.     }
  782.  
  783.     # no log?! cry to STDERR.
  784.     print STDERR "Could not open log file: '", join("' nor '", @names), "'.\n";
  785. }
  786.  
  787. sub END
  788. {
  789.     close LOG;
  790. }
  791.  
  792. ##--------------------------------------
  793. # @perlapi y2debug
  794. # Logs debug messages to /var/log/YaST2/y2log.
  795. # Other then ycp-y2debug the output is <b>always</b> logt
  796. # to /var/log/YaST2/y2log
  797. # and usually you <b>have to root</b> to do this
  798. # @example ..;  y2debug( "In the script: param1:", myarray, " param2: ", hash2 );
  799. ##--------------------------------------
  800.  
  801. =head2 y2debug
  802.  
  803. y2debug,
  804. y2milestone,
  805. y2warning,
  806. y2error,
  807. y2security,
  808. y2internal
  809.  
  810. Logs debug messages to F</var/log/YaST2/y2log> or F<$HOME/.y2log>
  811.  
  812. Note a B<semantic change> in y2debug: now the environment variable
  813. Y2DEBUG is honored so y2debug will not produce output unless this
  814. variable is set. This is for compatibility with the logging system in libycp.
  815.  
  816. =cut
  817.  
  818. my $log_component = $0;        # use program name as the log component
  819. $log_component =~ s:.*/::;    # strip path part
  820.  
  821. sub y2debug    { y2logger (0, @_); }
  822. sub y2milestone    { y2logger (1, @_); }
  823. sub y2warning    { y2logger (2, @_); }
  824. sub y2error    { y2logger (3, @_); }
  825. sub y2security    { y2logger (4, @_); }
  826. sub y2internal    { y2logger (5, @_); }
  827.  
  828. # Internal
  829. sub y2logger ($@)
  830. {
  831.     my $level = shift;
  832.     if (!$log_good || ($level == 0 && ! defined ($Y2DEBUG)))
  833.     {
  834.     return;
  835.     }
  836.  
  837.     my $tm = localtime;
  838.     my $datestr = sprintf( "%04d-%02d-%02d %02d:%02d:%02d <%d> %s(%d) [%s]",
  839.                $tm->year+1900, $tm->mon+1, $tm->mday,
  840.                $tm->hour, $tm->min, $tm->sec,
  841.                $level, $hostname, $$, $log_component);
  842.  
  843.     print LOG "$datestr ", join(" ", @_), "\n";
  844. }
  845.  
  846. ##--------------------------------------
  847. # @perlapi ycpDoVerboseLog
  848. # Turns on verbose logging of this the perl interface lib
  849. # Logging output is ALWAYS send to /var/log/YaST2/y2log
  850. # and usually you <b>have to be root</b> to do this
  851. # @example ..;  ycpDoVerboseLog;
  852. ##--------------------------------------
  853.  
  854. =head2 ycpDoVerboseLog
  855.  
  856. Enables output of y2verbose which is used in some of the obsolete functions.
  857.  
  858. =cut
  859.  
  860. sub ycpDoVerboseLog
  861. {
  862.    $verbose = 1;
  863. }
  864.  
  865. # Internal
  866. sub y2verbose
  867. {
  868.     if ( $verbose )
  869.     {
  870.     y2debug( @_ );
  871.     }
  872. }
  873.  
  874.  
  875. ################################################################################
  876. # Old functions
  877. ################################################################################
  878.  
  879. =head1 OBSOLETE FUNCTIONS
  880.  
  881. =cut
  882.  
  883. #########################################
  884. ## Check type of the given Argument
  885. #########################################
  886. #
  887.  
  888. ##--------------------------------------
  889. # @perlapi ycpArgIsMap -> 0 or 1
  890. # Checks, if the given argument is a map.
  891. # requirements: a call of  ycpInit()
  892. # @example if ( ycpArgIsMap ) \n { my %arg_hash =  ycpGetArgMap;  }
  893. ##--------------------------------------
  894.  
  895. =head2 ycpArgIsMap
  896.  
  897. Obsolete. Use (ref($arg) eq "HASH") instead.
  898.  
  899. =cut
  900.  
  901. sub ycpArgIsMap
  902. {
  903.    return( $ismap );
  904. }
  905.  
  906.  
  907. ##--------------------------------------
  908. # @perlapi ycpArgIsList -> 0 or 1
  909. # Checks, if the given argument is a list.
  910. # requirements: a call of  ycpInit()
  911. # @example if ( ycpArgIsList ) \n { my @arg_array = ycpGetArgList;  }
  912. ##--------------------------------------
  913.  
  914. =head2 ycpArgIsList
  915.  
  916. Obsolete. Use (ref($arg) eq "ARRAY") instead.
  917.  
  918. =cut
  919.  
  920. sub ycpArgIsList
  921. {
  922.    return( $islist );
  923. }
  924.  
  925. ##--------------------------------------
  926. # @perlapi ycpArgIsInteger -> 0 or 1
  927. # Checks, if the given argument is a Integer.
  928. # requirements: a call of  ycpInit()
  929. # @example if ( ycpArgIsInteger ) \n { my $arg_int =  ycpGetArgInteger; }
  930. ##--------------------------------------
  931.  
  932. =head2 ycpArgIsInteger
  933.  
  934. Not really obsolete because the new parser simply treats
  935. integers, booleans and strings as scalars. But who cares,
  936. nobody used this anyway.
  937.  
  938. =cut
  939.  
  940. sub ycpArgIsInteger
  941. {
  942.    return( $isinteger );
  943. }
  944.  
  945. ##--------------------------------------
  946. # @perlapi ycpArgIsString -> 0 or 1
  947. # Checks, if the given argument is a String.
  948. # requirements: a call of  ycpInit()
  949. # @example if ( ycpArgIsString ) \n { my $new_string =  ycpGetArgString; }
  950. ##--------------------------------------
  951.  
  952. =head2 ycpArgIsString
  953.  
  954. Not really obsolete because the new parser simply treats
  955. integers, booleans and strings as scalars. But who cares,
  956. nobody used this anyway.
  957.  
  958. =cut
  959.  
  960. sub ycpArgIsString
  961. {
  962.    return( $isstring );
  963. }
  964.  
  965. ##--------------------------------------
  966. # @perlapi ycpArgIsNil -> 0 or 1
  967. # Checks, if the given argument is a nil.
  968. # requirements: a call of  ycpInit()
  969. # @example if ( ycpArgIsNil ) \n { ... }
  970. ##--------------------------------------
  971.  
  972. =head2 ycpArgIsNil
  973.  
  974. Obsolete. Use (ref($arg) eq "SCALAR" && $$arg eq "nil") instead.
  975.  
  976. =cut
  977.  
  978. sub ycpArgIsNil
  979. {
  980.    return( $isnil );
  981. }
  982.  
  983. ##--------------------------------------
  984. # @perlapi ycpArgIsNone -> 0 or 1
  985. # Checks, if the given argument is a None.
  986. # requirements: a call of  ycpInit()
  987. # @example if ( ycpArgIsNone ) \n { ... }
  988. ##--------------------------------------
  989.  
  990. =head2 ycpArgIsNone
  991.  
  992. Obsolete. Use (defined ($arg)) instead.
  993.  
  994. =cut
  995.  
  996. sub ycpArgIsNone
  997. {
  998.    return( $isnone );
  999. }
  1000.  
  1001. ##--------------------------------------
  1002. # @perlapi ycpCommandIsDir -> 0 or 1
  1003. # Checks, if the given command is a <tt>Dir</tt>.
  1004. # requirements: a call of  ycpInit()
  1005. # @example if ( ycpCommandIsDir ) \n { ... }
  1006. ##--------------------------------------
  1007.  
  1008. =head2 ycpCommandIsDir
  1009.  
  1010. Obsolete. Use ($command eq "Dir")
  1011.  
  1012. =cut
  1013.  
  1014. sub ycpCommandIsDir
  1015. {
  1016.    return( $ycpcommand =~ /Dir/i );
  1017. }
  1018.  
  1019. ##--------------------------------------
  1020. # @perlapi ycpCommandIsRead -> 0 or 1
  1021. # Checks, if the given command is a <tt>Read</tt>.
  1022. # requirements: a call of  ycpInit()
  1023. # @example if ( ycpCommandIsRead ) \n { ... }
  1024. ##--------------------------------------
  1025.  
  1026. =head2 ycpCommandIsRead
  1027.  
  1028. Obsolete. Use ($command eq "Read")
  1029.  
  1030. =cut
  1031.  
  1032. sub ycpCommandIsRead
  1033. {
  1034.    return( $ycpcommand =~ /Read/i );
  1035. }
  1036.  
  1037. ##--------------------------------------
  1038. # @perlapi ycpCommandIsWrite -> 0 or 1
  1039. # Checks, if the given command is a <tt>Write</tt>.
  1040. # requirements: a call of  ycpInit()
  1041. # @example if ( ycpCommandIsWrite ) \n { ... }
  1042. ##--------------------------------------
  1043.  
  1044. =head2 ycpCommandIsWrite
  1045.  
  1046. Obsolete. Use ($command eq "Write")
  1047.  
  1048. =cut
  1049.  
  1050. sub ycpCommandIsWrite
  1051. {
  1052.    return( $ycpcommand =~ /Write/i );
  1053. }
  1054.  
  1055. ##--------------------------------------
  1056. # @perlapi ycpCommandIsExecute -> 0 or 1
  1057. # Checks, if the given command is a <tt>Execute</tt>.
  1058. # requirements: a call of  ycpInit()
  1059. # @example if ( ycpCommandIsExecute ) \n { ... }
  1060. ##--------------------------------------
  1061.  
  1062. =head2 ycpCommandIsExecute
  1063.  
  1064. Obsolete. Use ($command eq "Execute")
  1065.  
  1066. =cut
  1067.  
  1068. sub ycpCommandIsExecute
  1069. {
  1070.    return( $ycpcommand =~ /Execute/i );
  1071. }
  1072.  
  1073. ##--------------------------------------
  1074. # @perlapi ycpCommandIsResult -> 0 or 1
  1075. # Checks, if the given command is a <tt>result</tt>.
  1076. # requirements: a call of  ycpInit()
  1077. # @example if ( ycpCommandIsResult ) \n { ... }
  1078. ##--------------------------------------
  1079.  
  1080. =head2 ycpCommandIsResult
  1081.  
  1082. Obsolete. Use ($command eq "result"), note the lowercase 'r'.
  1083.  
  1084. =cut
  1085.  
  1086. sub ycpCommandIsResult
  1087. {
  1088.    return( $ycpcommand =~ /result/i );
  1089. }
  1090.  
  1091.  
  1092. ########################################
  1093. # Return the argument, converted to perl
  1094. # datatype
  1095. ########################################
  1096.  
  1097.  
  1098. ##--------------------------------------
  1099. # @perlapi ycpGetCommand -> "Read" or "Write" or "Execute" or "Dir"
  1100. # Returns the current command.
  1101. # requirements: a call of  ycpInit()
  1102. ##--------------------------------------
  1103.  
  1104. =head2 ycpGetCommand
  1105.  
  1106. Obsolete. Use the return value of L</ParseCommand>.
  1107.  
  1108. =cut
  1109.  
  1110. sub ycpGetCommand
  1111. {
  1112.    return( $ycpcommand );
  1113. }
  1114.  
  1115. ##--------------------------------------
  1116. # @perlapi ycpGetPath -> <string>
  1117. # Returns the current <b>sub</b>path of the current call.
  1118. # If the script is mounted on <tt>.ping</tt> and the agent is called
  1119. # with <tt>.ping.suse</tt> the subpath is <tt>.suse</tt>
  1120. # requirements: a call of  ycpInit()
  1121. ##--------------------------------------
  1122.  
  1123. =head2 ycpGetPath
  1124.  
  1125. Obsolete. Use the return value of L</ParseCommand>.
  1126.  
  1127. =cut
  1128.  
  1129. sub ycpGetPath
  1130. {
  1131.    return( $ycppath );
  1132. }
  1133.  
  1134. ##--------------------------------------
  1135. # @perlapi ycpGetArgType -> <string>
  1136. # Returns the type of the current argument.
  1137. # At the moment "string", "integer", "list" and "map" are supported.
  1138. # requirements: a call of  ycpInit()
  1139. ##--------------------------------------
  1140.  
  1141. =head2 ycpGetArgType
  1142.  
  1143. Obsolete. Use ref on a return value of L</ParseCommand>.
  1144.  
  1145. Umm, string/integer/boolean?
  1146.  
  1147. =cut
  1148.  
  1149. sub ycpGetArgType
  1150. {
  1151.    return( $type );
  1152. }
  1153.  
  1154. ##--------------------------------------
  1155. # @perlapi ycpGetArgMap -> <hash>
  1156. # Returns the curren argument as a hash, if the argument was a map.
  1157. # Otherwise the return value is not defined.
  1158. # requirements: a call of  ycpInit()
  1159. # @example if ( ycpArgIsMap ) \n { my %arg_hash =  ycpGetArgMap;  }
  1160. ##--------------------------------------
  1161.  
  1162. =head2 ycpGetArgMap
  1163.  
  1164. Obsolete. See L</PerlYCPValue>.
  1165.  
  1166. =cut
  1167.  
  1168. sub ycpGetArgMap
  1169. {
  1170.    return( %arghash );
  1171. }
  1172.  
  1173. ##--------------------------------------
  1174. # @perlapi ycpGetArgList -> <array>
  1175. # Returns the current argument as an arry, if the argument was a list.
  1176. # Otherwise the return value is not defined.
  1177. # requirements: a call of  ycpInit()
  1178. # @example if ( ycpArgIsList ) \n { my @arg_array =  ycpGetArgList;  }
  1179. ##--------------------------------------
  1180.  
  1181. =head2 ycpGetArgList
  1182.  
  1183. Obsolete. See L</PerlYCPValue>.
  1184.  
  1185. =cut
  1186.  
  1187. sub ycpGetArgList
  1188. {
  1189.    return( @argarray );
  1190. }
  1191.  
  1192. ##--------------------------------------
  1193. # @perlapi ycpGetArgString -> <string>
  1194. # Returns the current argument as a string, if the argument was a string
  1195. # Otherwise the return value is not defined.
  1196. # requirements: a call of  ycpInit()
  1197. # @example if ( ycpArgIsString ) \n { my $arg_string =  ycpGetArgString;  }
  1198. ##--------------------------------------
  1199.  
  1200. =head2 ycpGetArgString
  1201.  
  1202. Obsolete. See L</PerlYCPValue>.
  1203.  
  1204. =cut
  1205.  
  1206. sub ycpGetArgString
  1207. {
  1208.    return( $argskalar );
  1209. }
  1210.  
  1211. ##--------------------------------------
  1212. # @perlapi ycpGetArgInteger -> <integer>
  1213. # Returns the current argument as an integer, if the argument was an integer
  1214. # Otherwise the return value is not defined.
  1215. # requirements: a call of  ycpInit()
  1216. # @example if ( ycpArgIsInteger ) \n { my $arg_string =  ycpGetArgInteger;  }
  1217. ##--------------------------------------
  1218.  
  1219. =head2 ycpGetArgInteger
  1220.  
  1221. Obsolete. See PerlYCPValue.
  1222.  
  1223. Umm, string/integer/boolean?
  1224.  
  1225. =cut
  1226.  
  1227. sub ycpGetArgInteger
  1228. {
  1229.    return( $argskalar );
  1230. }
  1231.  
  1232.  
  1233. # OBSOLETE WRITING
  1234.  
  1235.  
  1236. ##--------------------------------------
  1237. # @perlapi ycpReturnSkalarAsInt
  1238. # Sends a scalar as a YCP-Integer to the calling server, the SCR
  1239. # Attention: It is very important to send in <b>ANY</b> case
  1240. # exactly one YCP value to the server. So you must take care, that
  1241. # for every call of the server, your script calls exactly one ycpReturn<..>
  1242. # function-
  1243. # @example ycpReturnSkalarAsInt( 17 ) -> Returns a
  1244. ##--------------------------------------
  1245.  
  1246. =head2 ycpReturnSkalarAsInt
  1247.  
  1248. Obsolete. Use L</Return>.
  1249.  
  1250. =cut
  1251.  
  1252. sub ycpReturnSkalarAsInt( $ )
  1253. {
  1254.     my ( $entry ) = @_;
  1255.  
  1256.     printf( "(%d)", $entry );
  1257. }
  1258.  
  1259. ##--------------------------------------
  1260. # @perlapi ycpReturnSkalarAsBoolean
  1261. # Sends a scalar as a YCP-Boolean to the calling server, the SCR
  1262. # Attention: It is very important to send in <b>ANY</b> case
  1263. # exactly one YCP value to the server. So you must take care, that
  1264. # for every call of the server, your script calls exactly one ycpReturn<..>
  1265. # function-
  1266. # @example ycpReturnSkalarAsBoolean( 1 ) -> Returns a true
  1267. # @example ycpReturnSkalarAsBoolean( 0 ) -> Returns a false
  1268. ##--------------------------------------
  1269.  
  1270. =head2 ycpReturnSkalarAsBoolean
  1271.  
  1272. Obsolete. Use L</Return>("true" or "false")
  1273.  
  1274. =cut
  1275.  
  1276. sub ycpReturnSkalarAsBoolean( $ )
  1277. {
  1278.     my ( $entry ) = @_;
  1279.  
  1280.     printf( "(%s)", $entry ? "true" : "false");
  1281. }
  1282.  
  1283. ##--------------------------------------
  1284. # @perlapi ycpReturnSkalarAsString
  1285. # Sends a scalar as a YCP-String to the calling server, the SCR
  1286. # Attention: It is very important to send in <b>ANY</b> case
  1287. # exactly one YCP value to the server. So you must take care, that
  1288. # for every call of the server, your script calls exactly one ycpReturn<..>
  1289. # function
  1290. # @example ycpReturnSkalarAsString( "ok" )
  1291. ##--------------------------------------
  1292.  
  1293. =head2 ycpReturnSkalarAsString
  1294.  
  1295. Obsolete. Works only on strings not containing backslashes and quotes
  1296. that would need escaping.
  1297.  
  1298. Use L</Return>.
  1299.  
  1300. =cut
  1301.  
  1302. sub ycpReturnSkalarAsString( $ )
  1303. {
  1304.     my ( $entry ) = @_;
  1305.     y2verbose( "assk: ", $entry );
  1306.     printf( "(\"%s\")", $entry );
  1307. }
  1308.  
  1309. ##--------------------------------------
  1310. # @perlapi ycpReturnArrayAsList
  1311. # Sends a array as a YCP-List to the calling server, the SCR
  1312. # Attention: It is very important to send in <b>ANY</b> case
  1313. # exactly one YCP value to the server. So you must take care, that
  1314. # for every call of the server, your script calls exactly one ycpReturn<..>
  1315. # function
  1316. # @example my @array = ( 1,2,3); ycpReturnSkalarAsString( array )
  1317. ##--------------------------------------
  1318.  
  1319. =head2 ycpReturnArrayAsList
  1320.  
  1321. Obsolete. Works only on list of strings not containing backslashes and quotes
  1322. that would need escaping.
  1323.  
  1324. Use L</Return>.
  1325.  
  1326. =cut
  1327.  
  1328. sub ycpReturnArrayAsList( @ )
  1329. {
  1330.     my ( @entry ) = @_;
  1331.  
  1332.     # starting the List
  1333.     printf ( "[ " );
  1334.  
  1335.     if ( @entry > 0 )
  1336.     {
  1337.     printf( "\"%s\"", shift( @entry ));
  1338.  
  1339.     foreach my $elem ( @entry )
  1340.     {
  1341.        printf( ", \"%s\"", $elem);
  1342.     }
  1343.     }
  1344.  
  1345.     # end of list
  1346.     printf ( " ] " ); # no "]:"
  1347. }
  1348.  
  1349.  
  1350. ##--------------------------------------
  1351. # @perlapi ycpReturnHashAsMap
  1352. # Sends a hash as a YCP-List to the calling server, the SCR
  1353. # Attention: It is very important to send in <b>ANY</b> case
  1354. # exactly one YCP value to the server. So you must take care, that
  1355. # for every call of the server, your script calls exactly one ycpReturn<..>
  1356. # function
  1357. # @example my %myhash; ...; ycpReturnSkalarAsString( myhash );
  1358. ##--------------------------------------
  1359.  
  1360. =head2 ycpReturnHashAsMap
  1361.  
  1362. Obsolete. Works only on maps of strings not containing backslashes and quotes
  1363. that would need escaping.
  1364.  
  1365. Use L</Return>.
  1366.  
  1367. =cut
  1368.  
  1369. sub ycpReturnHashAsMap
  1370. {
  1371.     my ( %entry ) = @_;
  1372.  
  1373.     my $first = 1;
  1374.  
  1375.     # starting the Map
  1376.     printf ( " \$\[ " );
  1377.  
  1378.  
  1379.     foreach my $key (keys (%entry))
  1380.     {
  1381.     if ( $first )
  1382.     {
  1383.         $first = 0;
  1384.     }
  1385.     else
  1386.     {
  1387.         printf( ", " );
  1388.     }
  1389.  
  1390.     printf( "\"%s\":\"%s\"", $key, $entry{$key});
  1391.     }
  1392.  
  1393.     printf ( " ] " ); # no "]:"
  1394. }
  1395.  
  1396.  
  1397. ##--------------------------------------
  1398. # @perlapi ycpReturnSkalarAsIntSub
  1399. # Private function to return a ycp-formatted int.
  1400. ##--------------------------------------
  1401.  
  1402. sub ycpReturnSkalarAsIntSub( $ )
  1403. {
  1404.     my ( $entry ) = @_;
  1405.  
  1406.     return sprintf( "(%d)", $entry );
  1407. }
  1408.  
  1409. ##--------------------------------------
  1410. # @perlapi ycpReturnSkalarAsBooleanSub
  1411. # Private function to return a ycp-formatted boolean.
  1412. ##--------------------------------------
  1413.  
  1414. sub ycpReturnSkalarAsBooleanSub( $ )
  1415. {
  1416.     my ( $entry ) = @_;
  1417.  
  1418.     return sprintf( "(%s)", $entry ? "true" : "false");
  1419. }
  1420.  
  1421.  
  1422.  
  1423. ##--------------------------------------
  1424. # @perlapi ycpReturnSkalarAsStringSub
  1425. # Private function to return a ycp-formatted string.
  1426. ##--------------------------------------
  1427.  
  1428. sub ycpReturnSkalarAsStringSub( $ )
  1429. {
  1430.     my ( $entry ) = @_;
  1431.     y2verbose( "assk: ", $entry );
  1432.     return sprintf( "(\"%s\")", $entry );
  1433. }
  1434.  
  1435.  
  1436. ##--------------------------------------
  1437. # @perlapi ycpReturnArrayAsListSub
  1438. # Sends a array as a YCP-List to the calling server, the SCR
  1439. # Attention: It is very important to send in <b>ANY</b> case
  1440. # exactly one YCP value to the server. So you must take care, that
  1441. # for every call of the server, your script calls exactly one ycpReturn<..>
  1442. # function
  1443. # @example my @array = ( 1,2,3); ycpReturnSkalarAsString( array )
  1444. ##--------------------------------------
  1445.  
  1446. sub ycpReturnArrayAsListSub( @ )
  1447. {
  1448.     my ( @entry ) = @_;
  1449.     my $ret;
  1450.  
  1451.     # starting the List
  1452.     $ret =  "[ ";
  1453.  
  1454.     if ( @entry > 0 )
  1455.     {
  1456.     $ret .= sprintf( "\"%s\"", shift( @entry ));
  1457.  
  1458.     foreach my $elem ( @entry )
  1459.     {
  1460.        $ret .= sprintf( ", \"%s\"", $elem);
  1461.     }
  1462.     }
  1463.  
  1464.     # end of list
  1465.     $ret .= " ] "; # no "]:"
  1466.     return $ret;
  1467. }
  1468.  
  1469. ##--------------------------------------
  1470. # @perlapi ycpReturn
  1471. # sends a complex data structure to the calling server, the SCR.
  1472. # Attention: It is very important to send in <b>ANY</b> case
  1473. # exactly one YCP value to the server. So you must take care, that
  1474. # for every call of the server, your script calls exactly one ycpReturn<..>
  1475. # function
  1476. # The complex data structure is build in perl using references. A perl array
  1477. # is transformed to a ycp list, a perl hash will become a ycp map and a scalar
  1478. # will be a simple string, integer or boolean.
  1479. # This function takes one refernce to one of the mentioned data
  1480. # types. It easily can be a refernce to a tree of refernces to all valid data types.
  1481. # For example: To build a map, containing a list, in perl, you do:
  1482. #
  1483. # @example my @list_of_values = ( 'l1', 'l2', 'l3', 'l4' );
  1484. # @example my %maphash = { "key1" => "value1", "key2" => \@list_of_values };
  1485. # @example ycpReturn( \%maphash );
  1486. ##--------------------------------------
  1487.  
  1488. =head2 ycpReturn
  1489.  
  1490. Obsolete. Use L</Return>
  1491.  
  1492. =cut
  1493.  
  1494. sub ycpReturn
  1495. {
  1496.     print ycpReturnSub(@_);
  1497. }
  1498.  
  1499. ##--------------------------------------
  1500. # @perlapi ycpReturnSub
  1501. # private function to provide the functionality for ycpReturn
  1502. ##--------------------------------------
  1503. sub ycpReturnSub
  1504. {
  1505.     my ($itemref) = @_;
  1506.     my $ret = "";
  1507.     unless( ref($itemref) ) {
  1508.     # Error: Not a reference at all !
  1509.     # Was tun ?
  1510.     return "[] "; # no "]:"
  1511.     }
  1512.  
  1513.     if( ref( $itemref ) eq "SCALAR" )
  1514.     {
  1515.     $ret = formatItem( $$itemref );
  1516.     }
  1517.     elsif( ref( $itemref ) eq "ARRAY" )
  1518.     {
  1519.     my $docomma = 0;
  1520.     my $list = "[ ";
  1521.     foreach my $item ( @$itemref )
  1522.     {
  1523.         my $append = "";
  1524.         if( $docomma ) {
  1525.         $append .= ", ";
  1526.         } else {
  1527.         $docomma = 1;
  1528.         }
  1529.  
  1530.         if( ref( $item ) )
  1531.         {
  1532.         $append .= &ycpReturnSub( $item );
  1533.         }
  1534.         else
  1535.         {
  1536.         $append .= formatItem( $item );
  1537.         }
  1538.         $list .= $append;
  1539.     }
  1540.     $list .= " ] "; # no "]:"
  1541.     $ret = $list;
  1542.     }
  1543.     elsif( ref( $itemref ) eq "HASH" )
  1544.     {
  1545.     my $docomma = 0;
  1546.     $ret = "\$\[ ";
  1547.     my $oneMapItem;
  1548.     while ( my ($key, $value) = each %$itemref )
  1549.     {
  1550.         if( ref( $key ) )
  1551.         {
  1552.         # Error - darf keine referenz sein, oder ?
  1553.         }
  1554.         else
  1555.         {
  1556.         if( $docomma )
  1557.         {
  1558.             $ret .= ", ";
  1559.         }
  1560.         else
  1561.         {
  1562.             $docomma = 1;
  1563.         }
  1564.  
  1565.         $oneMapItem = formatItem( $key ) . ":";
  1566.         my $expanded = "";
  1567.         if( ref( $value ) )
  1568.         {
  1569.             $expanded = &ycpReturnSub( $value );
  1570.         }
  1571.         else
  1572.         {
  1573.             $expanded = formatItem( $value );
  1574.         }
  1575.         $oneMapItem .= $expanded;
  1576.         }
  1577.         $ret .= $oneMapItem;
  1578.     }
  1579.     $ret .= " \] "; # no "]:"
  1580.     }
  1581.     return $ret;
  1582. }
  1583.  
  1584. ##--------------------------------------
  1585. # @perlapi formatItem
  1586. # private function that formats exactly one item according to it's type.
  1587. # It handles boolean, integers and Strings.
  1588. # needed by ycpReturn, this function is not exported.
  1589. ##--------------------------------------
  1590. sub formatItem( $ )
  1591. {
  1592.     my ($item) = @_;
  1593.  
  1594.     # Format boolean, must be true or false literally.
  1595.     if( $item =~ /true|false/i )
  1596.     {
  1597.     return sprintf( "%s", lc $item );
  1598.     }
  1599.  
  1600.     # Format integers
  1601.     if( $item =~ /^\s*\d+\s*$/ )
  1602.     {
  1603.     return( sprintf( "%d", $item ) );
  1604.     }
  1605.  
  1606.     # Format strings
  1607.     return( sprintf( "\"%s\"", $item ));
  1608. }
  1609.  
  1610.  
  1611. # OBSOLETE PARSING
  1612.  
  1613. ##############################
  1614. # String or Integer or Boolean to Skalar
  1615. ##############################
  1616.  
  1617. sub ycpSIBtoSkalar
  1618. {
  1619.     my ( $entry ) = @_;
  1620.     if( $entry =~ /^\s*\$\[.*\]\s*$/ )
  1621.     {
  1622.     # It is unintentional a map -> not handled yet -> TODO
  1623.     $entry = "Unhandled";
  1624.     }
  1625.     elsif ( $entry =~ /^\s*\"(.*)\"\s*$/ )
  1626.     {
  1627.     # "
  1628.     $entry = $1;
  1629.     }
  1630.     else
  1631.     {
  1632.     if ( $entry =~ /^\s+(.*)$/ )
  1633.     {
  1634.         $entry = $1;
  1635.     }
  1636.     if ( $entry =~ /^(.*?)\s+$/ )
  1637.     {
  1638.         $entry = $1;
  1639.     }
  1640.  
  1641.     }
  1642.  
  1643.     return( $entry );
  1644. }
  1645.  
  1646. sub ycpmap
  1647. {
  1648.     my @input = @_;
  1649.  
  1650.     chop @input if( $input[0] =~ /\n$/ );
  1651.  
  1652.     my $wholeline = join( "", @input );
  1653.  
  1654.     my %result;
  1655.  
  1656.     if( $wholeline =~ /^\s*\$\[(.+)\]\s*$/ )
  1657.     {
  1658.     my $mapcont = $1;
  1659.     # Killing all lists etc inside the map. TODO !!!!
  1660.     $mapcont =~ s/\$\[.+\]//g;
  1661.  
  1662.     my @mapentries = split( /\s*,\s*/, $mapcont );
  1663.  
  1664.     foreach my $mentry ( @mapentries )
  1665.     {
  1666.         if( $mentry =~ /(.+?):(.+)$/ )
  1667.         {
  1668.         # " fill the hash
  1669.         my $key = ycpSIBtoSkalar($1);
  1670.         my $val = ycpSIBtoSkalar($2);
  1671.         $result{$key} = $val;
  1672.  
  1673.         y2verbose( "new hashentry key:-$key- Value:-$val- ");
  1674.         }
  1675.     }
  1676.     }
  1677.     return( %result );
  1678. }
  1679.  
  1680. sub ycplist
  1681. {
  1682.     my @input = @_;
  1683.  
  1684.     chop @input if( $input[0] =~ /\n$/ );
  1685.     my $wholeline = join( "", @input );
  1686.  
  1687.     my @result;
  1688.  
  1689.     if( $wholeline =~ /^\s*\[(.+)\]\s*$/ )
  1690.     {
  1691.     my $mapcont = $1;
  1692.  
  1693.     my @mapentries = split( /\s*,\s*/, $mapcont );
  1694.  
  1695.     foreach my $mentry ( @mapentries )
  1696.     {
  1697.         $mentry = ycpSIBtoSkalar( $mentry );
  1698.  
  1699.         push( @result, $mentry );
  1700.         y2verbose( "listentry: -$mentry-");
  1701.     }
  1702.  
  1703.     @result = @mapentries;
  1704.     }
  1705.     return( @result );
  1706. }
  1707.  
  1708. ##--------------------------------------
  1709. # @perlapi ycpInit
  1710. # Initializes a call of the server. Therefor this function reads a YCP Value
  1711. # from <tt>stdin</tt>. To use this value, call the convenice functions:
  1712. # ycpArgIs<..>, ycpGetArg<..>, ycpCommandIs<..>, ycpGetCommand, ycpGetPath
  1713. # As parameter, you have to insert $_
  1714. # @example ycpInit( $_ );
  1715. ##--------------------------------------
  1716.  
  1717. =head2 ycpInit
  1718.  
  1719. Obsolete. Use L</ParseCommand>.
  1720.  
  1721. =cut
  1722.  
  1723. sub ycpInit
  1724. {
  1725.     my @input = @_;
  1726.  
  1727.     chop @input if( $input[0] =~ /\n$/ );
  1728.  
  1729.     my $wholeline = join( "", @input );
  1730.  
  1731.     y2verbose( "call: <", $wholeline, ">" );
  1732.  
  1733.     my %result;
  1734.  
  1735.     if( $wholeline =~ /^(.*)\((.*?),(.*)\)\s*$/)
  1736.     {
  1737.     y2verbose( "work: <", $wholeline, ">" );
  1738.  
  1739.     $ycpcommand    = $1;
  1740.     $ycppath       = $2;
  1741.     my $parameter  = $3;
  1742.  
  1743.     y2verbose( "com:", $ycpcommand, " path:", $ycppath, " param:", $parameter);
  1744.  
  1745.     $type     = "unknown";
  1746.  
  1747.     $ismap     = 0;
  1748.     $islist    = 0;
  1749.     $isinteger = 0;
  1750.     $isstring  = 0;
  1751.     $isknown   = 0;
  1752.     $isnil     = 0;
  1753.     $isnone    = 0;
  1754.  
  1755.  
  1756.     # is a map?
  1757.     if( $parameter =~ /^\s*\$\[.*\]\s*$/ )
  1758.     {
  1759.         y2verbose( "Is a map", $parameter );
  1760.         %arghash  = ycpmap(  $parameter );
  1761.         $ismap    = 1;
  1762.         $type     = "map";
  1763.     }
  1764.  
  1765.     # is a list?
  1766.     elsif( $parameter =~ /^\s*\[.*\]\s*$/ )
  1767.     {
  1768.         y2verbose(   "Is a list", $parameter);
  1769.         @argarray  = ycplist( $parameter );
  1770.         $islist    = 1;
  1771.         $type      = "list";
  1772.     }
  1773.  
  1774.     # is a integer?
  1775.     elsif( $parameter =~ /^\s*([0-9]+)\s*$/ )
  1776.     {
  1777.         y2verbose(   "Is a integer", $parameter);
  1778.         $argskalar = $1;
  1779.         $isinteger = 1;
  1780.         $type      = "integer";
  1781.     }
  1782.  
  1783.     # is a string?
  1784.     elsif( $parameter =~ /^\s*\"(.*)\"\s*$/ )
  1785.     {
  1786.         y2verbose(   "Is a string", $parameter);
  1787.         $argskalar = $1;
  1788.         $isstring  = 1;
  1789.         $type      = "string";
  1790.     }
  1791.  
  1792.     # is a string?
  1793.     elsif( $parameter =~ /^\s*nil\s*$/ )
  1794.     {
  1795.         y2verbose(   "Is a nil", $parameter);
  1796.         $isnil     = 1;
  1797.         $type      = "nil";
  1798.     }
  1799.     else
  1800.     {
  1801.         $isknown = 1;
  1802.         $type    = "unknown";
  1803.     }
  1804.     }
  1805.     elsif ($wholeline =~ /^(.*)\((.*?)\)\s*$/) {
  1806.  
  1807.     y2verbose( "work: <", $wholeline, ">" );
  1808.  
  1809.     $ycpcommand    = $1;
  1810.     $ycppath       = $2;
  1811.  
  1812.     y2verbose( "com:", $ycpcommand, " path:", $ycppath, " param: none" );
  1813.  
  1814.     $type     = "unknown";
  1815.  
  1816.     $ismap     = 0;
  1817.     $islist    = 0;
  1818.     $isinteger = 0;
  1819.     $isstring  = 0;
  1820.     $isknown   = 0;
  1821.     $isnil     = 0;
  1822.     $isnone    = 1;
  1823.  
  1824.     }
  1825.     return( %result );
  1826. }
  1827.  
  1828. 1;
  1829.  
  1830. ################################## EOF ########################################
  1831.