Tivoli Service Desk 6.0 Developer's Toolkit - Guia do Criador de Interface

Capítulo 7: Como Utilizar o CPIC

Retornar ao Índice


Introdução

Visão Geral

O Common Programming Interface for Communications (CPIC) fornece uma API consistente para aplicativos que requerem comunicação de aplicativo-para-aplicativo. A interface do CPIC utiliza a LU 6.2 do SNA para criar um conjunto de serviços de interaplicativos, incluindo:

Os comandos do CPIC são construídos na linguagem do TSD Script para estender estes serviços ao programador do TSD Script. O CPIC foi escolhido sobre as macros de APPC base para garantir a consistência através de plataformas.

Esta seção do manual pretende ser um guia para programadores do TSD Script que utilizam o CPIC para construir TPs. Para obter informações detalhadas sobre a programação do CPIC SAA, consulte o manual da IBM, Systems Application Architecture Common Programming Interface for Communications Reference, SC26-4399.

O CPIC deve ser instalado para que qualquer comando do CPIC funcione. Se o CPIC não for instalado corretamente, a utilização de comandos do CPIC fará com que o Tivoli Service Desk (TSD) Developer's Toolkit exiba uma mensagem de erro indicando que o CPIC não pôde ser carregado.

Termos & Conceitos

APPC

APPC é advanced peer-to-peer communication (comunicação avançada ponto a ponto).

Conversação básica

Conversação básica é um tipo de conversação no qual os aplicativos trocam dados em um formato de fluxo de byte padrão. Este formato contém campos de comprimento de dois bytes (chamados LLs) que especificam o comprimento do buffer a seguir. Cada agrupamento de dados LL é chamado de um registro lógico.

Conversação

Uma conversação é a conexão lógica entre dois aplicativos que utilizam CPIC ou APPC para trocar dados. Há dois tipos de conversação, mapeada e básica. Uma conversação conecta aplicativos utilizando uma sessão. Um aplicativo do CPIC pode conversar com um aplicativo do APPC da mesma maneira que conversa com outro aplicativo do CPIC.

DDF

Um DDF (Arquivo de Descrição de Dados) é um arquivo utilizado para mapear a relação entre estruturas de registro do TSD Script e buffers de bytes transmitidos.

LU

Uma LU (Unidade Lógica) é, efetivamente, uma máquina virtual. Embora você possa designar cada máquina física como uma LU, é possível, também, configurar múltiplas LUs em uma máquina física. Note que o CPIC utiliza apenas nós da LU Tipo 6.2.

Conversação mapeada

Uma conversação mapeada é um tipo de conversação que permite que os parceiros troquem registros de dados arbitrários em formatos pré-determinados.

Nome do modo

Um nome do modo é utilizado pelo APPC para designar as propriedades para a sessão entre as LUs durante uma conversação. Estas propriedades incluem a classe de serviço.

Serviço do nó

Um serviço do nó é um aplicativo (ou conjunto de aplicativos) que fornece funções de utilitário básicas para uma LU. Os serviços fornecidos incluem manipulação de informações secundárias, processamento de inicialização de aplicativo e processamento de encerramento de aplicativo. Os serviços de nó do OS/2 são fornecidos pelo Communications Manager (CM) ou pelo Communications Manager/2 (CM/2).

Parceiros

Parceiros são dois aplicativos do CPIC que trocam dados através de conversações do CPIC.

As conversações do CPIC podem ser duplex. Isto significa que em qualquer período determinado durante uma conversação do CPIC, um parceiro tem permissão para enviar e o outro parceiro está no estado de recepção (o que significa que está pronto para receber os dados). Um aplicativo que está no estado de recepção pode emitir um pedido para enviar quando precisa enviar dados. O parceiro é notificado deste pedido e o aplicativo que está solicitando recebe a notificação no parâmetro StatusReceived.

SDN

SDN (Nome de Destino Simbólico) é o nome de uma configuração do CPIC no Communications Manager/2 que permite que um aplicativo indique um conjunto de atributos a ser utilizado para um pedido de alocação de conversação.

Sessão

Uma sessão é uma conexão lógica entre duas LUs. As LUs comunicam-se através de sessões.

Informações secundárias

Informações de inicialização utilizadas pelo CPIC durante uma tentativa para estabelecer uma conversação. As informações secundárias incluem o nome da LU parceira, o nome do modo e o nome do TP. Estas informações são configuradas antes da conversação.

Nota: Informações secundárias são mencionadas por um SDN.

Rede SNA

Uma rede SNA é uma rede lógica de LUs.

Nível de sincronização

O nível de sincronização indica o grau de sincronização que uma conversação do CPIC utiliza. O nível de sincronização pode ser um dos seguintes:

SYNC_POINT

SYNC_POINT indica que o seu aplicativo suporta operações completas de Recuperação de Recursos SAA, como notificações Take Commit e Take Backout.

Nota: SYNC_POINT não é suportado no OS/2.

TP

TP (Programa de Transação) é um aplicativo que utiliza comandos do CPIC ou do APPC para participar em uma conversação.

nome do TP

O nome do TP é o nome de um aplicativo de transação. Este nome é especificado nas informações secundárias. Dependendo do sistema operacional, o nome do TP pode especificar uma entrada de tabela para o aplicativo de serviços de nó da LU de destino. Esta tabela é utilizada para procurar as informações necessárias para iniciar o TP.

Como Iniciar uma Conversação com Outro Programa

Exemplo de uma conversação simples

A seguir, está um breve exemplo do método utilizado quando um aplicativo inicia uma conversação com outro aplicativo.

  1. O Programa A emite um comando CPICInitialize para preparar o início da conversação. Ele dá um SDN para designar o Programa C como o destino da conversação. O Programa A recebe um identificador exclusivo para a conversação.
  2. O Programa A emite um comando CPICAllocate utilizando o identificador de conversação.
  3. Através dos serviços de nós, o CPIC instrui a LU parceira (especificada nas informações secundárias utilizadas na etapa 1) de que o Programa C deve ser iniciado para aceitar a nova conversação.
    Resultado: O Programa C inicia e emite o comando CPICAccept. Ele recebe um identificador de conversação para ser utilizado em comandos do CPIC posteriores que são trocados durante a conversação.

Arquivos de Descrição de Dados do TSD Script

Visão Geral

O TSD Script não permite controle direto do tamanho alocado de estruturas de memória, o que faz com que os programadores não tenham que se preocupar com o tamanho dos registros que eles declaram.

Embora isto seja considerado um atributo atrativo de uma linguagem de quarta geração, pode apresentar dificuldades no trabalho com aplicativos do CPIC. Os aplicativos do CPIC enviam e recebem buffers de bytes de um tamanho e formato específicos. Um aplicativo do parceiro pode utilizar formatos de armazenamento diferentes do aplicativo local, incluindo inteiros não-Intel e cadeias de caracteres EBCDIC.

Os arquivos de descrição de dados (ou DDFs) endereçam as possibilidades de tamanhos de buffer diferentes. Um DDF define a forma exata de um buffer de byte transmitido e especifica a conversão do formato. O TSD Developer's Toolkit utiliza estes DDFs como "filtros" para buffers de entrada e de saída para um aplicativo do CPIC.

A estrutura básica de um DDF é:

-- Traços duplos são comentários até o final da linha.
-- A primeira seção é a seção parceiro.
*PARTNER
-- tipos de conversões de caracteres
EBCDIC=TRUE
-- ordem de byte inteiro
NON_INTEL=TRUE
-- tabela de conversão de caracteres. Se não for especificada, o TSD Developer's
Toolkit irá
-- utilizar a tabela AE do CM/2. Esta tabela padrão
-- pode ser insuficiente para sua utilização (por exemplo, ela
-- traduz espaços incorporados em x'00'). Se você desejar uma
-- tabela de conversão mais normal, defina o nome do arquivo de tabelas de conversão do CM/2
-- para ACSGTAB.DAT, que é fornecido com o
-- CM/2. Em seguida, defina CUSTOM_CONVERT para TRUE.
CUSTOM_CONVERT=TRUE
-- Esta seção é a seção campo. Ela é utilizada
-- para descrever cada campo do registro e o seu
-- mapeamento e conversão de bytes. Essencialmente, esta seção
-- mostra como o buffer de dados deve parecer exatamente após
-- ser recebido (antes da conversão) ou exatamente antes de um
-- envio (após a conversão).
*FIELDS
-- Fieldname Type ByteWidth SendUnknowns? Default
   name CHAR 20 FALSE
   street CHAR 20 TRUE
   age INTEGER 20 TRUE
   birthDate CCYYMMDD 8 FALSE

Neste exemplo, o aplicativo do parceiro é executado em uma máquina EBCDIC com inteiros de estilo não-Intel (como um Sistema IBM 370). O registro que é enviado é declarado no TSD Script como a seguir:

SomeRecordName IS RECORD
   name :STRING;
   street :STRING;
   age :INTEGER;
   birthDate :DATE;
   description:STRING;
      END;

O campo de descrição não é incluído no DDF, o que significa que o campo de descrição não é transferido durante comunicações do CPIC.

A seção Parceiro

Esta seção de um DDF descreve o tipo de máquina do aplicativo do parceiro. O início desta seção é marcado pelo texto *PARTNER. A seção parceiro indica os tipos de conversões de dados que o TSD Developer's Toolkit executa. Por exemplo, definir EBCDIC=TRUE significa que o TSD Developer's Toolkit traduz todas as cadeias de caracteres para e do EBCDIC quando se comunica com o aplicativo do parceiro.

Atributos do parceiro

Na seção Parceiro, os seguintes atributos devem ser definidos. Todos os atributos que você não define tomam o valor padrão indicado.

A seção Campos

Esta seção do DDF especifica campos e os tipos de campos a serem compactados ou descompactados nos buffers de dados do CPIC. Esta seção no DDF começa com a linha contendo "*FIELDS". Cada linha na seção Campos aplica-se a um campo de registro transferido do TSD Script. O formato de tal linha é o seguinte:

{fieldname} {fieldtype} {bytewidth} {sendunknowns?} {default}

O espaço em branco divide cada coluna; as definições de colunas são listadas aqui:

O comando $INCLUDE

O comando $INCLUDE simplifica a organização de um DDF. Este comando fornece a capacidade para "ligar" outros arquivos dinamicamente. Quando o TSD Developer's Toolkit encontra o comando $INCLUDE, ele carrega o DDF especificado e coloca suas definições de campo no DDF atual.

O comando $INCLUDE pode ser incluído em qualquer lugar na seção Campos. O formato do comando $INCLUDE é:

$INCLUDE({DDFname})

Se o arquivo não estiver no diretório atual, o TSD Developer's Toolkit pesquisará o DPATH para o arquivo. Se não for encontrado, o TSD Developer's Toolkit retornará um erro.

O comando $SIZEOF

O comando $SIZEOF recalcula automaticamente o tamanho dos arquivos incluídos. Os arquivos incluídos não terão que ser recontados manualmente se outro campo for incluído neles.

Os comandos $SIZEOF e $INCLUDE são utilizados em casos especiais, como na configuração de um buffer vetorizado. Eles podem ser utilizados em uma combinação como a que segue:

*PARTNER
   EBCDIC =TRUE
   NON_INTEL =TRUE
   CUSTOM_CONVERT =TRUE
*FIELDS
GDS1310 INT 2 TRUE 4880
GDS1311LEN INT 2 TRUE
   $SIZEOF(1311.DDF) + 2 $INCLUDE(1311.DDF)
GDS1549LEN INT 2 TRUE
   $SIZEOF(1549.DDF) + 2 $INCLUDE(1549.DDF)
DataLen INT 2 TRUE
   $SIZEOF(RTRNDATA.DDF) + 2 $INCLUDE(RTRNDATA.DDF)

Tipos de campos do DDF

Os tipos reconhecidos para processamento do DDF são:

Como Utilizar o CPIC com o Communications Manager/2

Visão Geral

Há vários detalhes que você deve conhecer antes de tentar gravar um aplicativo do CPIC do OS/2. Alguns deles podem ser reunidos pelo tipo de serviços de nós que você tem no seu sistema.

Alocações de entrada

Por causa da forma que os serviços de nós definem um TP para receber uma alocação de entrada, um aplicativo do CPIC do OS/2 não pode ser um TP de Serviço do SNA. Reveja as etapas a seguir que resumem como uma alocação de entrada é identificada:

  1. Os serviços de nós iniciam um processo e definem uma variável de ambiente denominada APPCTPN para que seja igual ao nome do TP.
  2. Quando o aplicativo emite um comando Accept, os serviços de nós verificam o APPCTPN do ambiente do aplicativo de aceitação.
  3. Os serviços de nós varrem a lista de alocações de entrada de espera para uma com o mesmo nome de TP.
  4. Se o nome for encontrado, os serviços de nós concluem a chamada. Devido ao fato dos nomes do TP de serviço do SNA iniciarem com um número hexadecimal, eles não podem ser definidos em uma variável de ambiente do OS/2.

Múltiplos aplicativos do TSD Script com TPs

Se tiver mais que um aplicativo do TSD Script para o qual deseja configurar um TP, você terá que fazer uma configuração especial. O Communications Manager/2 permite apenas que você especifique kml.exe como o arquivo e CAMINHO do aplicativo do OS/2 para uma definição do TP. Para o outro, crie um arquivo de comandos do OS/2 que contenha os seguintes comandos:

SET APPCTPN={o nome do seu TP}
START /C KML /U{o caminho para o seu KB} {o nome do seu KB}
EXIT

Communications Manager/2 Versão 1.1 (CM/2)

O Communications Manager/2 permite que um único processo do CPIC aceite múltiplas conversações. Além disso, um aplicativo do CPIC pode emitir um comando Initialize, uma vez que nenhum comando Accept anterior foi emitido.

Estudo de Caso do CPIC do TSD Script

Visão Geral

Esta seção é um estudo de caso breve do processo de criação de um aplicativo simples do CPIC. O aplicativo é projetado para concluir uma transferência de arquivo.

Para ilustrar os benefícios do CPIC, o estudo de caso tem dois módulos de exemplo. O aplicativo é criado no primeiro módulo de exemplo. No segundo módulo de exemplo, foram feitas algumas alterações menores no aplicativo para melhorar o desempenho.

Suposições

Este estudo de caso faz várias suposições sobre a sua familiaridade com o CPIC, com o Communications Manager/2 e com o processamento de comunicações no geral. Por exemplo, pressupõe-se que você esteja familiarizado com o utilitário CMSETUP do Communications Manager/2.

O aplicativo do parceiro (RCV.CMD)

Para começar, reveja o aplicativo do parceiro que está gravado em REXX.

O aplicativo do parceiro de REXX é denominado RCV.CMD. Essencialmente, este aplicativo recebe dados (armazenando-os em uma variável de função) até que o parâmetro recebido de status indique que o aplicativo pode, agora, enviar dados.

Seguindo este exemplo de código, estão explicações que fornecem detalhes adicionais sobre o aplicativo.

/* RCV.CMD */ 
/* Receives data strings, building a buffer of all data. /*Upon completion of*/
/* receiving, sends back the buffer. */ 
/* CPIC commands used: CMACCP */ 
/*                     CMCFMD */
/*                     CMDEAL */
/*                     CMRCV */
/*                     CMSEND */ 
/* a few useful constants */ 
CM_OK               = 0
/* status received */ 
CM_SEND_RECEIVED    = 1
CM_CONFIRM_RECEIVED = 2
/* data received */ 
CM_NO_DATA_RECEIVED = 0
MaxLength           = 257;
BufferLen           = 0;
FileBuffer.0        = 0; 
'CPICREXX' 
address cpicomm 
'CMACCP Conv_ID RetC'; 
if \(RetC = CM_OK) then do 
     SAY 'ACCP = 'Retc
   end; 
   'CMRCV Conv_ID Data MaxLength DataReceived 
    ReceivedLength StatusRecvd ReqToSendRecvd Retc'; 
if \(RetC = CM_OK) then do 
      SAY 'RCV = 'Retc 
   end; 
do while (RetC = CM_OK) & 
  (StatusRecvd \= CM_SEND_RECEIVED) 
  if (DataReceived \= CM_NO_DATA_RECEIVED) then do 
/*    SAY Data */ 
      FileBuffer.0 = FileBuffer.0 + 1; 
      i = FileBuffer.0; 
      FileBuffer.i = Data; 
   end; 
   if (StatusRecvd = CM_CONFIRM_RECEIVED) then do 
      'CMCFMD Conv_ID RetC'; 
   end; 
   'CMRCV Conv_ID Data MaxLength DataReceived 
    ReceivedLength StatusRecvd ReqToSendRecvd Retc'; 
   if (RetC \= CM_OK) then do 
      SAY 'RCV = 'Retc 
end; 
   end; 
SAY 'Re-transmitting file' 
DO i = 1 TO FileBuffer.0 
   BufferLen = LENGTH(FileBuffer.i); 
   Data = FileBuffer.i; 
   'CMSEND Conv_ID Data BufferLen ReqToSendRecvd RetC'; 
   if (RetC \= CM_OK) then do 
      SAY 'SND = 'Retc 
   end; 
      END; 
'CMDEAL Conv_ID RetC'; 
address cmd 
'EXIT'

Módulo de exemplo 1 - FILESND.KB

O objetivo deste aplicativo é ler um arquivo de texto e transmitir cada linha a um aplicativo do parceiro. Após o aplicativo concluir a transferência de arquivo, ele começa a receber de volta o mesmo arquivo e exibe cada linha em uma janela de exibição.

  1. Analise o arquivo com o comando KP FILESND.
  2. Inicie o aplicativo CMSETUP a partir da pasta do CM/2.
    Resultado: A caixa de diálogo Utilitário de Configuração do CPI Communications Manager aparece.
  3. Digite o nome FILESND na caixa.
  4. No menu CPI Communications, escolha Recursos do SNA.
    Resultado: A caixa de diálogo Definição de Configuração do CM/2 aparece.
  5. Configure a entrada das informações secundárias.
  6. Na caixa de diálogo Recursos do SNA, escolha o item Informações Secundárias do CPI Communications.
  7. Escolha Criar.
  8. Digite o seguinte na caixa de diálogo:
    SDN = FILESND
    Target LU = {nome da máquina de destino aqui}
    TP Name = FILERCV
    Security = NONE
    Mode = #INTER
  9. Escolha OK.
  10. Selecione o item Definições do Programa de Transação
  11. Escolha Criar.
  12. Digite esses valores na caixa de diálogo:
    Service TP = deselected
    TP Name = FILERCV
    OS/2 Program PATH and Filename = CMD.EXE
    Conversation security required = deselected
    Program Parameters = /C {PATH to tutorial code}RCV.CMD
  13. Escolha Continuar.
  14. Digite o seguinte:
    Presentation Type = Background
    Operation Type = Queued, Attach Manager started

Rever o procedimento de configuração

Começando com a Etapa 3, você configura uma entrada na Tabela de Informações Secundárias do Communication Manager/2. A Tabela de Informações Secundárias é utilizada durante a inicialização de uma conversação. A inicialização ocorre da seguinte maneira:

  1. Um aplicativo chama CPICInitialize, transmitindo um SDN como um parâmetro. Um SDN age como uma tecla para a Tabela de Informações Secundárias.
  2. O CPIC utiliza o SDN para definir atributos para a nova conversação. Os atributos podem representar a máquina de destino e o TP.

Utilizando este método, podem ser gravados aplicativos do CPIC que não têm informações com código permanente, específicas do site. Ele também fornece um método padrão para todos os aplicativos do CPIC acessarem esse tipo de informação.

Começando com a Etapa 8, uma definição de TP é criada. Esta entrada instrui os serviços de nós sobre como iniciar um determinado TP.

Quando uma conversação é alocada, a LU que solicitou a alocação envia o nome do TP desejado ao sistema de serviços de nós da LU de destino. O sistema de serviços de nós verifica se o nome desse TP está definido no sistema. Se estiver, os serviços de nós seguem as instruções sobre como iniciar o TP. Se ele puder iniciar com êxito o aplicativo, ele iniciará (quando Attach Manager iniciado for definido para o TP). O TP, então, emite um CPICAccept. A LU que está solicitando obtém uma indicação bem-sucedida e a conversação é iniciada.

Para este aplicativo REXX, é iniciado um processador de comandos do OS/2 (CMD.EXE). A cadeia de parâmetros instrui o CMD.EXE a sair quando o comando é concluído (/C) e instrui sobre qual comando executar (RCV.CMD).

Como iniciar o arquivo RCV.CMD a partir da linha de comandos

A próxima parte do estudo de caso inicia o arquivo RCV.CMD a partir da linha de comandos do OS/2.

  1. Defina um indicador para instruir o CM/2 sobre qual TP está aguardando uma conversação de entrada. Isto é feito definindo-se uma variável de ambiente para a sessão do comando:

    SET APPCTPN=FILERCV

    (Opcional) Para evitar uma espera muito longa por uma alocação de entrada, você pode editar o seu Arquivo de Definição de Nó (NDF) no diretório CMLIB. Este arquivo tem o mesmo nome que o arquivo de configuração do Communications Manager/2.
  2. Procure a seção que define os atributos para o TP FILERCV (pesquisar FILERCV).
  3. Altere o INCOMING_ALLOCATE_TIMEOUT e o RECEIVE_ALLOCATE_TIMEOUT para inteiros positivos (as unidades são em segundos-180 para cada é um bom padrão).
  4. Salve o arquivo.
  5. Para fazer estas alterações entrarem em vigor, inicie o utilitário CM Setup e faça alterações suficientes nos campos de dados para fazer com que o CM Setup verifique novamente e aplique as alterações dinamicamente.
  6. Execute o aplicativo REXX digitando RCV e pressionando ENTER.
    Resultado: O aplicativo pára até que uma alocação chegue ou até que o tempo limite para RECEIVE_ALLOCATE_TIMEOUT seja excedido. Na conclusão, este aplicativo encerra o processo de comando atual.
    Nota: Não inicie o aplicativo REXX até que você esteja pronto para iniciar FILESND.KB.

Executar FILESND.KB

Isto transmite o arquivo fonte de um lado para o outro entre os dois aplicativos e, em seguida, exibe os resultados em uma janela.

Pode demorar um pouco para a transferência dupla terminar. Abaixo da listagem de arquivos na janela, você vê os resultados da sincronização.

Além disso, observe o número da linha para cada linha do arquivo. Estes números foram transmitidos de um lado para o outro com cada linha do arquivo de texto.

Listagem de linhas do FILESND.KB

Seguindo esta seção de linhas numeradas, está uma discussão sobre o arquivo.

1
2      KNOWLEDGEBASE FILESND;
3
4      ROUTINES 
5      PROCEDURE DoConversation(VAL Args:List of String);
6                              (* sdn, infile *) 
7
8
9      PRIVATE 
10
11     CONSTANTS 
12        CPIC_SUCCESS IS 1; 
13
14     TYPES 
15        FileRec IS RECORD 
16           LineNbr:Integer; 
17           Buff:String; 
18        END; 
19
20     ROUTINES 
21
22     FUNCTION RcvData(REF w:WINDOW, VAL 
                        Conv:Conversation) 
                        :INTEGER IS 
23     VARIABLES 
24        totalBuff :FileRec; 
25        dataRcvd  :integer; 
26        statRcvd  :integer; 
27        reqTSRcvd :integer; 
28        rc        :integer; 
29     ACTIONS 
30        IF (not(Known(w))) THEN 
31        WinCreateScrollWindow($DESKTOP,w, 
32                              $NullHandler, 
                                1,1,67,7, 
                                'FileSnd','', 0, 
                                  $WinBorder+ 
                                  $WinTitle+ 
                                  $WinHScroll+ 
                                  $WinVScroll+ 
                                $WinSysMenu+ 
                                  $WinResize); 
      END; 
33       REPEAT 
34       rc := CPICReceive(Conv,'FILEREC.DDF', 
                              totalBuff,DataRcvd, 
                              StatRcvd,ReqTSRcvd); 
35          IF (rc > 0) THEN 
36          IF ((StatRcvd = $CPICConfirmReceived) or 
37             (StatRcvd = $CPICConfirmSend 
                Received)) THEN 
38              rc := CPICConfirmed(Conv); 
39       END; 
40            totalBuff.buff := StrTrim 
                (totalBuff.buff); 
41             WinWriteLn(w,totalBuff.lineNbr:5&' 
                         :'&totalBuff.buff); 
42        END; 
43       UNTIL ((rc <> 1) OR ((StatRcvd = 
                         $CPICSendReceived) OR 
44                  (StatRcvd = $CPICConfirmSend 
                     Received))); 
45       Exit(rc); 
46    END; -- RcvData
47
48
49 --------------------------------------------- 
50 -- Descrição: Lê no arquivo especificado,
         transmitindo cada linha através do CPIC 
51 -- ao parceiro especificado através do
      SDN determinado.
52 --------------------------------------------- 
53 PROCEDURE DoConversation(VAL Args:List of 
                            String) IS 
54 VARIABLES 
55    Conv     :Conversation; 
56    fRec     :FileRec; 
57    ReqTSRcvd:INTEGER; 
58    rc       :INTEGER; 
59    inf      :FILE; 
60    w        :WINDOW; 
61    t1,t2    :TIME; 
62 ACTIONS 
63    t1       := $NOW; 
64    SE (ListLength(Args) <2) ENTÃO WinMessageBox($DESKTOP,Ò