Mit diesem Anwendungsbeispiel für eine UTM-Anwendung auf einem BS2000-System können Adressdaten verwaltet werden, die in einer Datei stehen. Die Anwendung stellt dazu die nachfolgenden Funktionen zur Verfügung, die durch Eintrag des jeweiligen TACs in das dafür vorgesehene Feld aufgerufen werden. Die Ein- und Ausgaben erfolgen in einem Format.
TAC | Funktion | Erklärung |
1 | Anzeige | gibt eine in der Datei vorhandene Adresse aus. Suchbegriff ist dabei der Name und die ersten zwei Buchstaben des Vornamens, welche in den zugehörigen Feldern anzugeben sind. |
2 | Neueintrag | trägt eine neue Adresse in die Datei ein. Eine Adresse mit dem gleichen Suchbegriff (s.o.) darf dort nicht schon vorhanden sein. |
3 | Ändern | ändert einen Adresseintrag. Die Adresse muss in der Datei schon vorhanden sein. |
4 | Löschen | Löscht eine in der Datei vorhandene Adresse. |
Bei Fehlbedienung erscheint in der untersten Zeile des Formats eine Fehlermeldung.
Die oben genannten Ziffern sind die Transaktionscodes (TACs), die die Anwendung steuern. Dabei rufen der Transaktionscode 1 das Teilprogramm "TPREAD" und die Transaktionscodes 2, 3 und 4 das Teilprogramm "TPUPDATE" auf. Diese Teilprogramme verzweigen dann jeweils in das Teilprogramm "TPFILE". Dieses Teilprogramm wird als START- und SHUT-Exit eingesetzt und enthält die Unterprogramme, die die Ein-/Ausgaben auf die Adressdatei durchführen.
Das Teilprogramm "BADTACS" wird vom openUTM automatisch aufgerufen, wenn ein ungültiger TAC eingegeben wird.
Die Funktion "ERRCHECK" behandelt Fehler, die in den Teilprogrammen auftreten.
Nach dem Aufbau der Verbindung mit der Anwendung und erfolgtem KDCSIGN wird sofort von openUTM das Format ausgegeben (Startformat). Die Arbeit mit dem Benutzer erfolgt dann im strengen Dialog, d.h. auf die Eingabe eines TACs und des Schlüssels reagiert die Anwendung mit der Ausgabe des Formats das die gesuchte Adresse enthält bzw. mit einer Erfolgs- oder einer Fehlermeldung in der untersten Zeile.
Die folgenden Struktogramme zeigen den Aufbau der Teilprogramme:
Bild: Struktogramm des Teilprogramms TPREAD
Bild: Struktogramm des Teilprogramms TPUPDATE
Bild: Struktogramm des Teilprogramms TPFILE
Der Vollständigkeit halber ist im Anschluss an die C-Programme die Generierung dieser Anwendung aufgeführt. Die genaue Bedeutung der einzelnen Operanden und Anweisungen entnehmen Sie bitte dem openUTM-Handbuch „Anwendungen generieren“.
Das folgende Bild zeigt das Format FORM1, das bei dieser Anwendung verwendet wurde:
******************************************************************************** A d d r e s s A d m i n i s t r a t i o n ******************************************************************************** Select function: -------------------------------------------------------------------------------- Actual function: Name: First Name: Street: No.: Postal Code: Residence: Phone: -------------------------------------------------------------------------------- Function selection 1 = Show address | 4 = Delete address 2 = Enter address | 3 = Update address | Finish with ́kdcoff ́ -------------------------------------------------------------------------------- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Im Folgenden ist die Struktur der Adressierungshilfe für dieses Format abgedruckt.
Das Feld FUNCTION ist ein geschütztes Ausgabefeld mit dem Attribut "automatische Eingabe", in das Feld POSTAL_CODE sind nur numerische Eingaben erlaubt und MSGTEXT ist ein geschütztes Ausgabefeld. Die komplette Attributliste können Sie sich ausdrucken lassen. Nähere Informationen hierzu finden Sie im Handbuch Ihres Formatierungssystems.
/* FORMAT NAME : FORM1 */ /* USER AREA LENGTH : 235 */ typedef struct { char NAME [ 14 ] ; char FIRST_NAME [ 20 ] ; char STREET [ 26 ] ; char NUMBER [ 10 ] ; char POSTAL_CODE [ 5 ] ; char RESIDENCE [ 24 ] ; char PHONE [ 21 ] ; } ADDRESS; typedef struct { char TAC [ 8 ] ; char FUNCTION [ 27 ] ; ADDRESS addr; char MSGTEXT [ 80 ] ; } FORM1 ;
#ifndef TP_H #define TP_H #include "FORM1.h" #define kcrc ca->ca_return.kcrccc #define pa spab->param struct ca_area { struct ca_hdr ca_head; struct ca_rti ca_return; }; struct work { union kc_paa param; FORM1 std_mask; /* area for addressing aid */ char progname[8]; }; void BADTACS ( struct ca_area * , struct work * ); void errcheck ( struct ca_area * , struct work * ); void TPFILE ( struct ca_area * , struct work * ); void TPREAD ( struct ca_area * , struct work * ); void TPUPDATE ( struct ca_area * , struct work * ); #endif
#include <kcmac.h> #include "tp.h" void TPREAD (struct ca_area *ca , struct work *spab ) { /* INIT-Operation */ KDCS_SET (&spab->param, &ca->ca_head, &ca->ca_return); KDCS_INIT (0,sizeof(struct work)); if (KCRCC != 0 ) { memcpy (spab->progname, "TPREAD ", 8); errcheck (ca, spab); } else memcpy (spab->std_mask.TAC, ca->ca_head.kcpr_tac, 8); /* MGET-Operation */ KDCS_MGET ( spab->std_mask.FUNCTION ,sizeof( FORM1 ) ,"*FORM1 " ); if (KCRCC != 0 ) { memcpy (spab->progname, "TPREAD", 8); errcheck (ca, spab); } /* call function "tpfile" for reading address */ TPFILE (ca, spab); /* MPUT-Operation */ KDCS_MPUTNT (&spab->std_mask,sizeof(FORM1) ,KDCS_SPACES,"*FORM1 ",KCNODF); if (KCRCC != 0 ) { memcpy (spab->progname, "TPREAD", 8); errcheck (ca, spab); } /* PEND FI-Operation */ KDCS_PENDFI(); }
#include <kcmac.h> #include "tp.h" void TPUPDATE ( struct ca_area *ca , struct work *spab ) { /* INIT-Operation */ KDCS_SET (&spab->param, &ca->ca_head, &ca->ca_return); KDCS_INIT (0,sizeof(struct work)); if (KCRCC != 0 ) { memcpy (spab->progname, "TPUPDATE", 8); errcheck (ca, spab); } else memcpy (spab->std_mask.TAC, ca->ca_head.kcpr_tac, 8); /* MGET-Operation */ KDCS_MGET ( spab->std_mask.FUNCTION ,sizeof( FORM1 ) ,"*FORM1 " ); if (KCRCC != 0 ) { memcpy (spab->progname, "TPUPDATE", 8); errcheck (ca, spab); } /* call function "tpfile" for updating address */ TPFILE (ca, spab); /* MPUT-Operation */ KDCS_MPUTNT (&spab->std_mask, sizeof(FORM1),KDCS_SPACES,"*FORM1 ",KCNODF); if (KCRCC != 0 ) { memcpy (spab->progname, "TPUPDATE", 8); errcheck (ca, spab); } /* PEND FI-Operation */ KDCS_PENDFI(); }
#include <kcmac.h> #include "tp.h" #define ERRLINE "****** Wrong TAC - Please repeat \ Input ****** " void BADTACS (struct ca_area *ca, struct work *spab ) { /* INIT-Operation */ KDCS_SET (&spab->param, &ca->ca_head, &ca->ca_return); memset (&spab->std_mask.TAC, ́ ́, 8); KDCS_INIT (0,sizeof(struct work)); if (KCRCC != 0 ) { memcpy (spab->progname, "BADTACS", 8); errcheck (ca, spab); } /* MGET-Operation */ KDCS_MGET ( spab->std_mask.FUNCTION ,sizeof( FORM1 ) ,ca->ca_return.kcrfn ); if (KCRCC != 0 ) { memcpy (spab->progname, "BADTACS", 8); errcheck (ca, spab); } /* MPUT-Operation: Replace the standard error message */ memcpy (spab->std_mask.MSGTEXT, ERRLINE, 80); memset (spab->std_mask.TAC, ́ ́, 8); KDCS_MPUTNT ( &spab->std_mask ,sizeof( FORM1 ) ,KDCS_SPACES ,"*FORM1 " ,KCNODF ); if (KCRCC != 0 ) { memcpy (spab->progname, "BADTACS", 8); errcheck (ca, spab); } /* PEND FI-Aufruf */ KDCS_PENDFI(); }
#include <kcmac.h> #include "tp.h" void errcheck ( struct ca_area * ca , struct work * spab ) { struct err_line { char ftext[35]; char progname[8]; char optext[10]; char op_code[4]; char cctext[8]; char cc[3]; char cdtext[8]; char cd[4]; } err_msg; /* ------- Making connections for the KDCS_... macros -------- */ KDCS_SET (&spab->param, &ca->ca_head, &ca->ca_return); /* making entries in the errorline */ memcpy (err_msg.ftext, "****** E R R O R in program unit ",35); memcpy (err_msg.progname, spab->progname, 8); memcpy (err_msg.optext, " Op-Code: ",10); memcpy (err_msg.op_code, pa.kcop, 4); memcpy (err_msg.cctext, " kcrccc=", 8); memcpy (err_msg.cc, KDCS_ERR , 3); memcpy (err_msg.cdtext, " kcrcdc=", 8); memcpy (err_msg.cd, KDCS_RTI->kcrcdc, 4); memset (&spab->std_mask, ́ ́, sizeof (FORM1)); memcpy (spab->std_mask.MSGTEXT, &err_msg, 80); /* MPUT-Operation */ KDCS_MPUTNE (&spab->std_mask,sizeof(FORM1),KDCS_SPACES,"*FORM1 ",KCNODF); /* PEND ER-Operation */ KDCS_PENDER(); }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <kcpa.h> #include <kcca.h> #include "tp.h" #define M spab->std_mask #define TAC ca->ca_head.kccv_tac #define JOB TAC[0] #define ADR_LENGTH ( (long) sizeof( ADDRESS ) ) #define READ ́1 ́ #define WRITE ́2 ́ #define UPDATE ́3 ́ #define DELETE ́4 ́ #ifdef __SNI_HOST_BS2000 #define FILE_NAME "link=CAPPLI" #define FILE_MODE "r+b,type=record,forg=key" #define FILE_MODE_FIRST "w+b,type=record,forg=key" #else #define FILE_NAME "cappli.address" #define FILE_MODE "r+b" #define FILE_MODE_FIRST "w+b" #endif #define PREVIOUS_POSITION -ADR_LENGTH #define SAG_NAME "FUJITSU TECHNOLOGY SOLUTIONS" #define SAG_STREET "Musterstrasse" #define SAG_NUMBER "6" #define SAG_PCODE "12345" #define SAG_RES "Musterstadt" #define SAG_PHONE "+12 34 567-89" typedef enum { FOUND = 1 ,NOT_FOUND = 2 } address_status; static address_status addr_fetch(struct work * ); static ADDRESS address; static FILE * filepointer; static fpos_t FilePosition; void TPFILE ( struct ca_area * ca , struct work *spab ) { int pr_swtch; #ifdef __SNI_HOST_BS2000 char BS2Cmd[500]; #endif if (strncmp (TAC,"STARTUP ", 8) == 0) pr_swtch = 1; else { if (strncmp (TAC,"SHUTDOWN", 8) == 0) pr_swtch = 2; else { pr_swtch = 3; memset (M.MSGTEXT, ́* ́, 80); } } switch (pr_swtch) { case 1: #ifdef __SNI_HOST_BS2000 sprintf( BS2Cmd , "SET-FILE-LINK LINK-NAME = CAPPLI ,FILE-NAME = CAPPLI.ADDRESS"\ " ,SUPPORT = *DISK( SHARED-UPDATE = *YES) ", ADR_LENGTH ); system( BS2Cmd ); #endif if ((filepointer = fopen (FILE_NAME, FILE_MODE)) == NULL) { if((filepointer = fopen( FILE_NAME , FILE_MODE_FIRST )) == NULL ) { perror("fopen:"); exit(-1); } memset( &address , ́ ́ , sizeof( address ) ); memcpy( address.NAME , SAG_NAME , sizeof( SAG_NAME )-1); memcpy( address.STREET, SAG_STREET , sizeof( SAG_STREET )-1); memcpy( address.NUMBER, SAG_NUMBER , sizeof( SAG_NUMBER )-1); memcpy( address.POSTAL_CODE , SAG_PCODE , sizeof( SAG_PCODE )-1); memcpy( address.RESIDENCE , SAG_RES , sizeof( SAG_RES )-1); memcpy( address.PHONE , SAG_PHONE , sizeof( SAG_PHONE )-1); fwrite(&address, ADR_LENGTH, 1, filepointer); fclose( filepointer ); if ((filepointer = fopen (FILE_NAME, FILE_MODE)) == NULL) { perror("fopen:"); exit(-1); } } break; case 2: fclose (filepointer); break; case 3: switch (JOB) { case READ: memcpy (M.FUNCTION, "Show address ******", 26); if (addr_fetch( spab ) == NOT_FOUND) { memcpy (M.MSGTEXT, "Address not found ", 22); break; } else { memcpy (M.addr.NAME, address.NAME, ADR_LENGTH ); break; } case WRITE: memcpy (M.FUNCTION, "Enter address ***", 26); if (addr_fetch( spab ) == FOUND) { memcpy (M.MSGTEXT, "Address already exists ", 23); break; } else { memcpy (address.NAME, M.addr.NAME, ADR_LENGTH ); fseek (filepointer, 0, 2); fwrite (&address, ADR_LENGTH, 1, filepointer); memcpy (M.MSGTEXT, "Address entered ", 24); break; } case UPDATE: memcpy (M.FUNCTION, "Update address ******", 26); if (addr_fetch( spab ) == NOT_FOUND) { memcpy (M.MSGTEXT, "Address not found ", 22); break; } else { memcpy (address.NAME, M.addr.NAME, ADR_LENGTH ); fsetpos(filepointer,&FilePosition ); fwrite (&address, ADR_LENGTH, 1, filepointer); memcpy (M.MSGTEXT, "Address changed ", 16); break; } case DELETE: memcpy (M.FUNCTION, "Delete address *****", 26); if (addr_fetch( spab ) == NOT_FOUND) { memcpy (M.MSGTEXT, "Address not found ", 22); break; } else { #ifndef __SNI_HOST_BS2000 memset (&address, ́* ́, ADR_LENGTH); fsetpos(filepointer,&FilePosition ); fwrite (&address, ADR_LENGTH, 1, filepointer); #else fdelrec(filepointer , NULL ); memcpy (M.MSGTEXT, "Address deleted ", 22); break; #endif } } } return; } /*************************************************************************/ /* Function addr_fetch */ /*************************************************************************/ static address_status addr_fetch( struct work *spab ) { address_status filestatus = NOT_FOUND; memset (&address, 0X00, ADR_LENGTH); fseek (filepointer, 0, 0); while ( fgetpos( filepointer , &FilePosition ) , (fread (&address, ADR_LENGTH, 1, filepointer)) != NULL) { if (address.NAME[0] != ́* ́) /* Address not deleted */ { if (strncmp (address.NAME, M.addr.NAME, sizeof M.addr.NAME) == 0) if (strncmp (address.FIRST_NAME , M.addr.FIRST_NAME , sizeof M.addr.FIRST_NAME) == 0) { filestatus = FOUND; break; } } memset (&address, 0X00, ADR_LENGTH); } return filestatus; }
REM ***************************************************************** REM *** D E F - S T A T E M E N T S *** REM *** *** REM *** KDCFILE = CAPPLI *** REM ***************************************************************** * OPTION GEN=ALL * ROOT CAPPLI * *+------------------------------------------------------------------+ *| MAX statements | *+------------------------------------------------------------------+ * MAX KDCFILE = kdcfile MAX APPLINAME = CAPPLI MAX APPLIMODE = S MAX TASKS = 3 MAX ASYNTASKS = 1 MAX PGPOOL = (25) MAX CACHESIZE = (100,30) MAX TRACEREC = 10000 MAX RECBUF = (5,4096) MAX LPUTBUF = 10 MAX LPUTLTH = 4096 MAX TERMWAIT = 60 MAX KB = 1024 MAX NB = 2048 MAX SPAB = 4096 MAX CLRCH = X ́FF ́ * *+------------------------------------------------------------------+ *| FORMSYS statement | *+------------------------------------------------------------------+ * FORMSYS ... * *+------------------------------------------------------------------+ *| MESSAGE statement | *+------------------------------------------------------------------+ * MESSAGE MODULE=MSGS * *+------------------------------------------------------------------+ *| PROGRAM statements | *+------------------------------------------------------------------+ REM *** Application specific TACs *** * TAC KDCMSGTC , PROGRAM=NOHACK TAC KDCBADTC , PROGRAM=BADTACS TAC 1 , PROGRAM=TPREAD , LOCK = 1 TAC 2 , PROGRAM=TPUPDATE , TACCLASS=1 , LOCK = 2 TAC 3 , PROGRAM=TPUPDATE , TACCLASS=1 , LOCK = 2 TAC 4 , PROGRAM=TPUPDATE , TACCLASS=1 , LOCK = 2 * *+------------------------------------------------------------------+ *| TACCLASS statements | *+------------------------------------------------------------------+ * TACCLASS 1,TASKS=1 * *+------------------------------------------------------------------+ *| USER statements | *+------------------------------------------------------------------+ * USER NINA ,PASS=C ́SOLO ́ ,FORMAT=*FORM1 ,KSET=BUNDLE1 (1) USER URSUS ,FORMAT=*FORM1 ,KSET=BUNDLE2 (1) USER ADMIN ,PASS=C ́ADM ́ ,KSET=MASTER,PERMIT=ADMIN * *+------------------------------------------------------------------+ *| TLS statements | *+------------------------------------------------------------------+ * TLS TLSB * *+------------------------------------------------------------------+ *| TPOOL statements | *+------------------------------------------------------------------+ * TPOOL LTERM=... , NUMBER=2 , PRONAM=*ANY, PTYPE=... , KSET = MASTER TPOOL LTERM=... , NUMBER=2 , PRONAM=*ANY, PTYPE=... , KSET = MASTER * *+-----------------------------------------------------------------+ *| PTERM / LTERM statements | *+-----------------------------------------------------------------+ * OPTION DATA=TERM ** *+------------------------------------------------------------------+ *| KSET statements | *+------------------------------------------------------------------+ * * * * OPTION DATA={ PROGRAM-STATIC | PROGRAM-SHARED-OBJ | PROGRAM-BLS | PROGRAM-OLD-DLL } * * * *+------------------------------------------------------------------+ *| EXIT statements | *+------------------------------------------------------------------+ * EXIT PROGRAM=TPFILE ,USAGE=START EXIT PROGRAM=TPFILE ,USAGE=SHUT * *+------------------------------------------------------------------+ *| TAC statements | *+------------------------------------------------------------------+ * REM *** ADMINISTRATION DIALOG *** TAC KDCTAC ,PROGRAM=KDCADM , ADMIN=Y TAC KDCLTERM ,PROGRAM=KDCADM , ADMIN=Y TAC KDCPTERM ,PROGRAM=KDCADM , ADMIN=Y TAC KDCSWTCH ,PROGRAM=KDCADM , ADMIN=Y TAC KDCSEND ,PROGRAM=KDCADM , ADMIN=Y TAC KDCAPPL ,PROGRAM=KDCADM , ADMIN=Y TAC KDCUSER ,PROGRAM=KDCADM , ADMIN=Y TAC KDCDIAG ,PROGRAM=KDCADM , ADMIN=Y TAC KDCLOG ,PROGRAM=KDCADM , ADMIN=Y TAC KDCINF ,PROGRAM=KDCADM , ADMIN=READ TAC KDCHELP ,PROGRAM=KDCADM , ADMIN=READ TAC KDCSHUT ,PROGRAM=KDCADM , ADMIN=Y TAC KDCTCL ,PROGRAM=KDCADM , ADMIN=Y * REM *** ADMINISTRATION ASYNCHRON *** TAC KDCTACA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCLTRMA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCPTRMA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCSWCHA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCUSERA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCSENDA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCAPPLA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCDIAGA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCLOGA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCINFA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=READ TAC KDCHELPA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=READ TAC KDCSHUTA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y TAC KDCTCLA ,PROGRAM=KDCADM ,TYPE=A , ADMIN=Y * KSET BUNDLE1 , KsEYS=(1,2) KSET BUNDLE2 , KEYS=(1) KSET MASTER, KEYS=MASTER
(1) BS2000-Format.
Input-Dateien für die Generierungsprozedur
PROGRAM-Anweisungen:
PROGRAM KDCADM ,COMP=C PROGRAM TPREAD ,COMP=C PROGRAM TPUPDATE ,COMP=C PROGRAM TPFILE ,COMP=C PROGRAM NOHACK ,COMP=C PROGRAM BADTACS ,COMP=C
* ------------------------------------------------------------------+ DEFAULT PROGRAM COMP = C PROGRAM KDCADM * ------------------------------------------------------------------+ MPOOL LCPOOL , SIZE = 10 - , SCOPE = GROUP - , ACCESS = READ * ------------------------------------------------------------------+ LOAD-MODULE LLMTPS , VERSION = 001 - , LIB = DYNAMIC-LOADED-LIB - , LOAD-MODE = (POOL,LCPOOL,STARTUP) * ------------------------------------------------------------------+ DEFAULT PROGRAM COMP = C , LOAD-MODULE = LLMTPS PROGRAM BADTACS PROGRAM TPUPDATE PROGRAM TPREAD PROGRAM TPFILE PROGRAM NOHACK
PTERM TERM05 ,PTYPE=T9750 ,LTERM=DST01 ,PRONAM=HOST0001 LTERM DST01 PTERM TERM10 ,PTYPE=T9750 ,LTERM=DST02 ,PRONAM=HOST0001 LTERM DST02 PTERM TERM11 ,PTYPE=T9763 ,LTERM=DST03 ,PRONAM=HOST0001 LTERM DST03 PTERM TERM12 ,PTYPE=T9763 ,LTERM=DSTADMIN ,PRONAM=HOST0001 LTERM DSTADMIN PTERM D17 ,PTYPE=T9001 ,LTERM=PRINTER1 ,PRONAM=HOST0001 LTERM PRINTER1 , USAGE = O