The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

ClearCase::ClearPrompt - Handle clearprompt in a portable, convenient way

SYNOPSIS

 use ClearCase::ClearPrompt qw(clearprompt);

 # Boolean usage
 my $rc = clearprompt(qw(yes_no -mask y,n -type ok -prompt), 'Well?');

 # Returns text into specified variable (context sensitive).
 my $txt = clearprompt(qw(text -pref -pro), 'Enter text data here: ');

 # Asynchronous usage - show dialog box and continue
 clearprompt(qw(proceed -mask p -type ok -prompt), "You said: $txt");

 # Trigger series (record/replay responses for multiple elements)
 use ClearCase::ClearPrompt qw(clearprompt /TRIGGERSERIES);
 my $txt = clearprompt(qw(text -pref -pro), 'Response for all elems: ');

 # Clean up environment on Windows to use /-style paths:
 use ClearCase::ClearPrompt qw(/ENV);

 # Cause the program to run in the debugger, even in a GUI environment:
 use ClearCase::ClearPrompt qw(/DEBUG);

 # Automatically divert trigger error msgs to clearprompt dialogs
 use ClearCase::ClearPrompt qw(+ERRORS);

 # As above but send error msgs via email instead to user1 and user2
 use ClearCase::ClearPrompt qw(+ERRORS=user1,user2);

 # As above but send msgs to the current user
 use ClearCase::ClearPrompt '+ERRORS=' . ($ENV{LOGNAME} || $ENV{USERNAME});

 # Prompt for a directory (not supported natively by clearprompt cmd)
 use ClearCase::ClearPrompt qw(clearprompt_dir);
 my $dir = clearprompt_dir('/tmp', "Please choose a directory");

DESCRIPTION

This module provides various areas of functionality, each based on clearprompt in some way but otherwise orthogonal. These are:

  • Clearprompt Abstraction

    Provides a simplified interface to the clearprompt program, taking care of creating and removing temp files as required.

  • Trigger Series Support

    Records and replays responses across multiple trigger firings.

  • Message Capture

    Catches output to stdout or stderr which would otherwise be lost in a GUI environment and pops them up as dialog boxes using clearprompt.

  • GUI trigger debugging support

    Can be told to run the trigger in a perl debugger session in a separate window. Useful for debugging trigger problems that come up only in the GUI.

  • InterOp Environment Normalization

    Modifies %ENV on Windows such that all CLEARCASE_* values use forward (/) slashes instead of backslashes. Generally useful in triggers where many path values such as $ENV{CLEARCASE_PN} are provided in the environment.

  • Directory Chooser

    Allows clearprompt to be used for selecting directories (aka folders).

Many of these are of particular value within trigger scripts. All are discussed in more detail below, but first the import/export scenario needs some detail. Most modules are intended to be used like this

        use Some::Module qw(X Y Z);

where X, Y, and Z are symbols (variables, functions, etc) you want exported (or imported, depending where you stand) from the module into the current namespace. ClearPrompt extends this: X, Y, and Z may be imports as above, or they may be commands, or they may represent captures. Command names start with /, capture names start with +, and all others are assumed to be traditional symbols for import/export. All may be intermingled. Thus,

        # These are all the currently-recognized commands
        use ClearCase::ClearPrompt qw(/ENV /TRIGGERSERIES);

        # This shows a sample of the captures available.
        use ClearCase::ClearPrompt qw(+DIE +ERRORS=vobadm);

        # This shows how to import a couple of useful symbols
        use ClearCase::ClearPrompt qw($CT clearprompt);

        # And this specifies some of each
        use ClearCase::ClearPrompt qw($CT /ENV +ERRORS=vobadm);

CLEARPROMPT ABSTRACTION

Native ClearCase provides a utility (clearprompt) for collecting user input or displaying messages within triggers. However, use of this tool is awkward and error prone, especially in multi-platform environments. Often you must create temp files, invoke clearprompt to write into them, open them and read the data, then unlink them. In many cases this code must run seamlessly on both Unix and Windows systems and is replicated throughout many scripts. ClearCase::ClearPrompt abstracts this dirty work without changing the interface to clearprompt.

The clearprompt() function takes the exact same set of flags as the eponymous ClearCase command except that the -outfile flag is unnecessary since creation, reading, and removal of this temp file is managed internally. Thus the single function call:

    my $response = clearprompt('text', '-def', '0', '-pro', 'So nu? ');

can replace the entire code sequence:

    my $outfile = "/tmp/clearprompt.$$";
    system('clearprompt', '-outfile', $outfile, 'text', '-def', '0', '-pro', 'So nu? ');
    open(OF, $outfile);
    my $response = <OF>;
    close(OF);
    unlink $outfile;

With the further caveat that the code sequence would need a few more lines to be portable to Windows and to check for error conditions.

In a void context, clearprompt() behaves asynchronously; i.e. it displays the dialog box and returns so that execution can continue. This allows it to be used for informational displays. In any other context it waits for the dialog's button to be pushed and returns the appropriate data type.

The clearprompt() function always leaves the return code of the clearprompt command in $? just as system('clearprompt ...') would. If the prompt was interrupted via a signal, the function returns the undefined value.

TRIGGER SERIES

Since clearprompt is often used in triggers, special support is provided in ClearCase::ClearPrompt for multiple trigger firings deriving from a single CC operation upon multiple objects.

If the boolean $ClearCase::ClearPrompt::TriggerSeries has a true value, clearprompt will 'stash' its responses through multiple trigger firings. For instance, assuming a checkin trigger which prompts the user for a bugfix number and a command "cleartool ci *.c", the TriggerSeries flag would cause all response(s) to clearprompts for the first file to be recorded and replayed for the 2nd through nth trigger firings. The user gets prompted only once.

Trigger series behavior can be requested at import time via:

    use ClearCase::ClearPrompt qw(/TRIGGERSERIES);

This feature is only available on CC versions which support the CLEARCASE_SERIES_ID environment variable (3.2.1 and up) but attempts to use it are harmless in older versions. The module will just drop back to prompting per-file in that case.

MESSAGE CAPTURE

In a ClearCase GUI environment, output to stdout or stderr (typically from a trigger) has no console to go to and thus disappears without a trace. This applies to both Unix and Windows GUI's and - especially on Windows where the GUI is used almost exclusively - can cause trigger bugs to go undetected for long periods. Trigger scripts sometimes exec clearprompt manually to display error messages but this is laborious and will not catch unanticipated errors such as those emanating from included modules or child processes.

ClearCase::ClearPrompt can be told to fix this problem by capturing all stderr/stdout and displaying it automatically using clearprompt. There's also a facility for forwarding error messages to a specified list of users via email.

ClearPrompt can capture messages to 4 "channels": the stdout and stderr I/O streams and the Perl warn() and die() functions. Now, since warn() and die() send their output to stderr they could be subsumed by the STDERR channel, but they have different semantics and are thus treated separately. Messages thrown by warn/die are anticipated errors from within the current (perl) process, whereas other messages arriving on stderr will typically be unexpected messages not under the control of the running script (for instance those from a backquoted cleartool command). This distinction is quite important in triggers, where the former may represent a policy decision and the latter a plain old programming bug or system error such as a locked VOB. Warn/die captures are also displayed with the appropriate GUI icons and the title Warning or Error.

The 4 channels are known to ClearPrompt as WARN, DIE, STDOUT, and STDERR. To capture any of them to clearprompt just specify them with a leading + at use time:

        use ClearCase::ClearPrompt qw(+STDERR +WARN +DIE);

These 3 "error channels" can also be requested via the meta-command

        use ClearCase::ClearPrompt qw(+ERRORS);

while all 4 can be captured with

        use ClearCase::ClearPrompt qw(+CAPTURE);

Messages may be automatically mailed to a list of users by attaching the comma-separated list to the name of the channel using '=' in the import method, e.g.

    use ClearCase::ClearPrompt '+ERRORS=vobadm';
    use ClearCase::ClearPrompt qw(+STDOUT=vobadm +STDERR=tom,dick,harry);

An additional pseudo-channel can be specified for email representing interactions with the user via the clearprompt program itself. I.e. the following

    use ClearCase::ClearPrompt qw(+PROMPT=vobadm);

will take all prompt strings and the user's responses and mail them to the specified user(s).

MESSAGE CAPTURE NOTES

  • The capture-to-dialog-box feature appears to be largely obsoleted by ClearCase v4.2 which implements similar functionality. In 4.2, messages to stdout/stderr are placed in the "trigger failed" dialog box. Of course this doesn't help if the trigger generated warnings but didn't fail but it solves the main problem.

  • As of ClearPrompt 1.25, the capture-to-dialog and capture-to-email lists are discrete. This means that +WARN will capture warnings to a dialog box, while +WARN=vobadm will send warnings via email but NOT to a dialog box. To get both you must request both, e.g. +WARN +WARN=vobadm. This change was made as a result of the CC fix mentioned above.

  • The email feature first attempts to use the Net::SMTP module. If this is uninstalled or reports failure, the notify utility which first shipped in CC 4.0 is used. Thus you must have either Net::SMTP or CC 4.0 (or both) for email to succeed.

  • When using message capture for triggers, it may be preferable to handle it as a property of the trigger type rather than as part of the script. For instance, here's one of my triggers:

        % ct lstype -l trtype:uncheckout_post@/vobs_test
        trigger type "uncheckout_post"
         17-Dec-01.17:09:55 by [VOB Admin] (vobadm.ccusers@u10)
          owner: vobadm
          group: ccusers
          all element trigger 
          post-operation uncheckout
          action: -execunix /opt/perl/bin/perl -MClearCase::ClearPrompt=+CAPTURE=dsb /data/ccase/triggers/uncheckout_post.tgr
          action: -execwin //u10/perl5/bin/perl -MClearCase::ClearPrompt=+CAPTURE=dsb //data/ccase/triggers/uncheckout_post.tgr

    The -MClearCase::ClearPrompt=+CAPTURE=dsb on the cmdline for both Unix and Windows tells the trigger to email error messages to dsb. The advantage, of course, is that the scripts aren't polluted by use statements which aren't critical to their functionality, and the mailing list or capture options can be maintained in one place (the trigger-install script) rather than in each trigger script.

SAMPLE CAPTURE USAGE

Try setting ATRIA_FORCE_GUI=1 by hand and running the following little script which generates a warning via warn() and a hard error from a child process:

   BEGIN { $ENV{ATRIA_FORCE_GUI} = 1 }
   use ClearCase::ClearPrompt qw(+CAPTURE);
   warn qq(This is a warning\n);
   system q(perl nosuchscript);

You should see a couple of error msgs in dialog boxes, and none on stderr. Removing the +CAPTURE would leave the messages on text-mode stderr. Changing it to +WARN would put the warning in a dialog box but let the error msg come to text stderr, while +STDERR would put both messages in the same dialog since warn() would no longer be treated specially. Appending "=<username>" would cause mail to be sent to <username>. See also ./examples/capture.pl.

TRIGGER DEBUGGING SUPPORT

If /DEBUG is specified, e.g.:

    use ClearCase::ClearPrompt '/DEBUG';

Then the trigger script will run in a Perl debugger session. If the trigger was fired from a GUI environment (Unix or Windows), the debugger session will run in a separate text window. This same feature is available by setting the environment variable

    export CLEARCASE_CLEARPROMPT_DEBUG=1

Or, an interactive shell can be automatically invoked at trigger firing time if the use statement includes /SHELL or the CLEARCASE_CLEARPROMPT_DEBUG_SHELL EV is set. This is also valuable for developing and debugging trigger scripts because it lets the user explore the script's runtime environment (the CLEARCASE_* env vars, the current working directory, etc.). Thus either of

    use ClearCase::ClearPrompt '/SHELL';
    export CLEARCASE_CLEARPROMPT_DEBUG_SHELL=1

causes an interactive shell (/bin/sh or cmd.exe) to be started just before the script executes. In a GUI environment the shell will be started in a separate window. The script waits for the shell to finish before continuing and will exit immediately if the shell returns a nonzero exit status.

INTEROP ENVIRONMENT NORMALIZATION

If /ENV is specified:

    use ClearCase::ClearPrompt '/ENV';

Any environment variables whose names match CLEARCASE_* and whose value contains back \ slashes will be modified to use forward (/) slashes instead. This is a no-op except on Windows.

DIRECTORY PROMPTING

The clearprompt command has no builtin directory chooser, so this module provides a separate clearprompt_dir() function which implements it with "clearprompt list" and opendir/readdir/closedir. Usage is

    use ClearCase::ClearPrompt qw(clearprompt_dir);
    $dir = clearprompt_dir($starting_dir, $prompt_string);

This is pretty awkward to use since it doesn't employ a standard directory-chooser interface but it works. The only way to make your selection final is to select "." or hit the Abort button. And there's no way to create a directory via this interface. You would not use this feature unless you had to, typically.

MORE EXAMPLES

Examples of advanced usage can be found in the test.pl script. There is also a ./examples subdir with some sample scripts.

ENVIRONMENT VARIABLES

There are a few other EV's which can affect this module's behavior. Those not mentioned above are advanced debugging features and are documented only in the code. They are all in the CLEARCASE_CLEARPROMPT_* namespace.

NOTES

An apparent undocumented "feature" of clearprompt(1) is that it catches SIGINT (Ctrl-C) and provides a status of 4 rather than returning the signal number in $? according to normal (UNIX) signal semantics. We fix that up here so it looks like a normal signal 2. Thus, if clearprompt() returns undef the signal number is reliably in $? as it's documented to be.

Also, there is a bug in ClearCase 4.0 for Win32. The list option doesn't display the prompt text correctly. This is a bug in CC itself, not the module, and is fixed in CC 4.1.

PORTING

This package has been known to work fine on Solaris2.5.1/perl5.004_04, Solaris7/perl5.6, Solaris8/perl5.6.1, WindowsNT4.0SP3/perl5.005_02, and Win2KSP2/perl5.6.1. As these platforms are cover a wide range they should take care of any significant portability issues but please send reports of tweaks needed for other platforms to the address below. Note also that I no longer test on the older platforms so the may inadvertently have done something to break them.

It will work in a degraded form with ccperl (the 5.001 version supplied with ClearCase through at least CC5.0). Most features seem to work with ccperl (in limited testing); the trigger series code is an exception because it uses Data::Dumper which in turn requires Perl5.004. However, though I've made some effort to port this to ccperl, I still strongly recommend you use a modern Win32 Perl configured for network use, as described at http://www.cleartool.com/.

AUTHOR

David Boyce <dsbperl@cleartool.com>

Copyright (c) 1999-2002 David Boyce. All rights reserved. This Perl program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

clearprompt(1), perl(1)