Category : OS/2 Files
Archive   : OS2CMAPI.ZIP
Filename : FILECSVR.C

 
Output of file : FILECSVR.C contained in archive : OS2CMAPI.ZIP
/************************************************************************/
/* */
/* MODULE NAME: FILECSVR.C */
/* */
/* DESCRIPTIVE NAME: APPC FILE SERVER C SAMPLE PROGRAM FOR */
/* OPERATING SYSTEM/2 EXTENDED EDITION */
/* */
/* COPYRIGHT: (C) COPYRIGHT IBM CORP. 1988 */
/* LICENSED MATERIAL - PROGRAM PROPERTY OF IBM */
/* ALL RIGHTS RESERVED */
/* */
/* STATUS: LPP Release 1 Modification 0 */
/* */
/* FUNCTION = Receives a request for a file from a peer */
/* requester program. This program opens the file */
/* and transfers the data (or an error indicator */
/* if the file does not exist) back to the requester. */
/* */
/* Uses the following APPC Verbs: */
/* */
/* RECEIVE_ALLOCATE */
/* MC_SEND_DATA */
/* MC_RECEIVE_AND_WAIT */
/* MC_SEND_ERROR */
/* MC_DEALLOCATE */
/* TP_ENDED */
/* */
/* Uses the following General Sevices Verbs: */
/* */
/* CONVERT */
/* LOG_MESSAGE */
/* */
/* MODULE TYPE = IBM Personal Computer C/2 Compiler Version 1.1 */
/* (Compiles with Small Memory Model) */
/* */
/* Requires message file "APX.MSG" at runtime. */
/* */
/************************************************************************/

#define LINT_ARGS

#include
#include
#include
#include
#include
#include
#include

#define TRUE 1
#define FALSE 0

/* Macro clear_vcb sets the APPC verb control block to zeros */
#define clear_vcb() memset(&vcb,(int)'\0',sizeof(vcb))

typedef unsigned int BOOL;

BOOL sys_err = FALSE; /* Fatal system error flag */
BOOL eof_flag = FALSE; /* End of File flag */
BOOL bad_filename = FALSE; /* Bad file name flag */

unsigned short dos_rc; /* Save area for return codes */
unsigned short appc_rc_p; /* APPC retcode - primary */
unsigned long appc_rc_s; /* APPC retcode - secondary */

struct { /* Data to insert in err log */
char error_vrb[5]; /* ASCII Fmt Verb */
char error_pri[5]; /* ASCII Fmt Primary RC */
char error_sec[9]; /* ASCII Fmt Secondary RC */
} log_ins_text;

char error_dos_rc[5]; /* ASCII Fmt OS/2 retcode */

char tp_id[8]; /* transaction prorgram id */
unsigned long conv_id; /* conversation id */
char ra_tp_name[64]; /* tp_name for RCV_ALLOCATE */

unsigned char far *anbptr; /* Pointer to AlphaNumeric */
/* Buffer (shared) */

unsigned short filehandle; /* Handle returned by DOSOPEN */
unsigned short bytes_read; /* Byte count from DOSREAD */

/*--------------------------------------------------------------------------*/
/* Verb Control Block - Union of Structures */
/*--------------------------------------------------------------------------*/
union {
struct receive_allocate rcv_a;
struct mc_receive_and_wait rcv_wait;
struct mc_send_data send;
struct mc_send_error senderr;
struct mc_deallocate dealloc;
struct tp_ended tpend;
struct convert cnvt; /* Genl Svcs CONVERT */
struct log_message lmg; /* Genl Svcs LOG_MESSAGE */
} vcb;

unsigned far *vcbptr; /* Pointer to the vcb */

#ifdef LINT_ARGS
/*--------------------------------------------------------------------------*/
/* Function Prototypes */
/*--------------------------------------------------------------------------*/
void main(void);
void INIT_SELF(void);
void SHOW_MSG(unsigned short);
void SHOW_ERR(void);
void SHOW_DOS_ERROR(void);

void DO_RECEIVE_ALLOCATE(void);
void DO_MC_RCV_AND_WAIT(void);
void DO_MC_SEND_DATA(void);
void DO_MC_SEND_ERROR(void);
void DO_MC_DEALLOCATE(void);
void DO_TP_ENDED(void);
void WAIT_FOR_A_REQUEST(void);
void GET_SEND_CONTROL(void);

void ALLOC_SHARED_BUFFER(void);
void OPEN_DOS_FILE(void);
void DO_DOSREAD(void);
void CLOSE_DOS_FILE(void);
#endif

/****************************************************************************/
/* Main Program Section */
/****************************************************************************/

void
main()
{
INIT_SELF(); /* Initialize */
DO_RECEIVE_ALLOCATE(); /* Get info from incoming */
/* allocate */
if (sys_err) return; /* Quit if there was a problem */
WAIT_FOR_A_REQUEST(); /* Wait for requester to */
/* send filename */
GET_SEND_CONTROL(); /* We will be next side to send */
OPEN_DOS_FILE(); /* Open requested filename */
if (bad_filename == TRUE) DO_MC_SEND_ERROR();
/* If no such file, SEND_ERROR */
while ((! eof_flag) && (! sys_err) && (! bad_filename)) {
DO_DOSREAD(); /* Read the data file */
if (sys_err) DO_MC_SEND_ERROR(); /* If error, notify requester */
else
if (! eof_flag) DO_MC_SEND_DATA(); /* Otherwise, send the data */
}

if (! bad_filename) CLOSE_DOS_FILE(); /* Close the input file */
DO_MC_DEALLOCATE(); /* Deallocate conversation */
DO_TP_ENDED(); /* Indicate TP is done */
dos_rc = DOSFREESEG(FP_SEG(anbptr)); /* Free the shared segment */
if (dos_rc != 0) {SHOW_DOS_ERROR();} /* Display an error msg. */
/* if bad return code */
}

/****************************************************************************/
/* */
/* Utility Functions */
/* */
/****************************************************************************/

void
INIT_SELF()
/* Handle initialization chores */
{
vcbptr = (unsigned far *) &vcb; /* Setup vcb pointer */
ALLOC_SHARED_BUFFER(); /* DOSALLOCSEG APPC data buffer */

/* Convert names from ASCII to EBCDIC as required by APPC */

memset (ra_tp_name, (int)' ', sizeof(ra_tp_name));
/* all blanks */
memcpy (ra_tp_name,"FILEMSVR",8); /* Set the tp_name */
clear_vcb(); /* Zero out the control block */
vcb.cnvt.opcode = SV_CONVERT; /* Do a CONVERT general service */
vcb.cnvt.direction = SV_ASCII_TO_EBCDIC; /* Cnvt ASCII to EBCDIC */
vcb.cnvt.char_set = SV_AE; /* AE conversion type */
vcb.cnvt.len = sizeof(ra_tp_name); /* Convert 64 bytes */
vcb.cnvt.source = vcb.cnvt.target = (unsigned char far *)ra_tp_name;
/* Addr.(convert in place) */
ACSSVC_C ((long) vcbptr); /* Do the convert to EBCDIC */
}

void
SHOW_MSG (msgno)
/* This function logs the requested message from message dataset APX.MSG */

unsigned short msgno;
{
clear_vcb(); /* zero the vcb, also clears */
/* last call err data */
vcb.lmg.opcode = SV_LOG_MESSAGE; /* LOG_MSG opcode */
vcb.lmg.msg_num = msgno; /* Message number in APX.MSG */
vcb.lmg.msg_file_name[0] = 'A'; /* Set "APX" as msg filename */
vcb.lmg.msg_file_name[1] = 'P';
vcb.lmg.msg_file_name[2] = 'X';
vcb.lmg.msg_act = SV_NO_INTRV; /* No intervention action type */
ACSSVC_C ((long) vcbptr); /* Go log the message */
if (vcb.lmg.primary_rc != SV_OK) /* If bad, try to display err */
{ printf("APPC Sample Program Error - Unable to log error message\n");
printf("Return code = %04d Message number = %04d\n",
vcb.lmg.primary_rc,msgno);
return; }
}

void
SHOW_ERR ()
/* This function logs the Primary and Secondary APPC return codes. */

{
sprintf (log_ins_text.error_pri,"%04X",appc_rc_p);
/* Cnvt prim. retcode to ASCII */
sprintf (log_ins_text.error_sec,"%08lX",appc_rc_s);
/* Show retcode in hex */
sprintf (log_ins_text.error_vrb,"%04X",vcb.send.opcode);
/* Cnvt verb to ASCII */
clear_vcb(); /* zero the vcb, also clears */
/* last call err data */
vcb.lmg.opcode = SV_LOG_MESSAGE; /* LOG_MSG opcode */
vcb.lmg.msg_num = 5; /* APPC err msg. # in APX.MSG */
vcb.lmg.msg_file_name[0] = 'A'; /* Set "APX" as mes. filename */
vcb.lmg.msg_file_name[1] = 'P';
vcb.lmg.msg_file_name[2] = 'X';
vcb.lmg.msg_act = SV_NO_INTRV; /* No intervention action type */
vcb.lmg.msg_ins_len = 19; /* Insertion text length */
vcb.lmg.msg_ins_ptr = (unsigned char far *) &log_ins_text;
/* Text address to insert */
/* in logged message */
ACSSVC_C ((long) vcbptr); /* Go log the message */
if (vcb.lmg.primary_rc != SV_OK) {
/* If bad, try to display err */
printf("APPC Sample Program Error - Unable to log error message\n");
printf("Return code = %04d Message number = %04d \n",
vcb.lmg.primary_rc,5);
return;
}
}

void
SHOW_DOS_ERROR ()
/* This function logs an OS/2 return code. */

{
sprintf (error_dos_rc,"%04d",dos_rc); /* Convert to ASCII */
clear_vcb(); /* zero the vcb, also clears */
/* last call err data */
vcb.lmg.opcode = SV_LOG_MESSAGE; /* LOG_MSG opcode */
vcb.lmg.msg_num = 4; /* Msg # for OS/2 err in APX.MSG*/
vcb.lmg.msg_file_name[0] = 'A'; /* Set message file name "APX" */
vcb.lmg.msg_file_name[1] = 'P';
vcb.lmg.msg_file_name[2] = 'X';
vcb.lmg.msg_act = SV_NO_INTRV; /* No intervention action type */
vcb.lmg.msg_ins_len = 5; /* Length of insertion text */
vcb.lmg.msg_ins_ptr = (unsigned char far *) error_dos_rc;
/* Text address to insert */
/* in logged message */
ACSSVC_C ((long) vcbptr); /* Go log the message */
if (vcb.lmg.primary_rc != SV_OK) {
/* If bad, try to display err */
printf("APPC Sample Program Error - Unable to log error message\n");
printf("Return code = %04d Message number = %04d \n",
vcb.lmg.primary_rc,4);
return;
}
}

/****************************************************************************/
/* */
/* APPC RELATED FUNCTIONS */
/* */
/****************************************************************************/

void
DO_RECEIVE_ALLOCATE ()
{
clear_vcb(); /* Zero out the vcb */
vcb.rcv_a.opcode = AP_RECEIVE_ALLOCATE; /* Set the APPC opcode */
memcpy (vcb.rcv_a.tp_name, ra_tp_name, sizeof(ra_tp_name));
/* Get tp_name (in EBCDIC) */
vcb.rcv_a.sync_level = AP_CONFIRM_SYNC_LEVEL;
/* Confirm sync level */
APPC_C((long) vcbptr); /* Call APPC */

appc_rc_p = vcb.rcv_a.primary_rc;
appc_rc_s = vcb.rcv_a.secondary_rc; /* Save APPC return codes */
if (appc_rc_p != AP_OK) {SHOW_ERR(); sys_err = TRUE; return;}
/* Handle any error */
conv_id = vcb.rcv_a.conv_id; /* Save the conversation_id */

memcpy (tp_id, vcb.rcv_a.tp_id, sizeof(tp_id));
/* Save the tp_id */
}

void
WAIT_FOR_A_REQUEST ()
{
DO_MC_RCV_AND_WAIT (); /* MC_RECEIVE_AND_WAIT */
if (sys_err == TRUE) return; /* Quit if there was an error */

/* Verify we received DATA_COMPLETE, display an error otherwise */

if ( (*(unsigned *)&vcb.rcv_wait.what_rcvd) != AP_DATA_COMPLETE) {
sys_err = TRUE; SHOW_MSG (16); return;
}
}

void
DO_MC_RCV_AND_WAIT ()
{
clear_vcb(); /* Zero the vcb */
vcb.rcv_wait.opcode = AP_M_RECEIVE_AND_WAIT;
/* Verb = MC_RECEIVE_AND_WAIT */
vcb.rcv_wait.opext = AP_MAPPED_CONVERSATION;
/* Set MC ext. type */
vcb.rcv_wait.conv_id = conv_id; /* Set Conversation_id */
memcpy (vcb.rcv_wait.tp_id, tp_id, sizeof(tp_id));
/* Set TP_id */
vcb.rcv_wait.max_len = 100; /* Max length of filename-100 */
vcb.rcv_wait.dptr = anbptr; /* Set data buffer pointer */

APPC_C((long) vcbptr); /* Call APPC */

appc_rc_p = vcb.rcv_wait.primary_rc;
appc_rc_s = vcb.rcv_wait.secondary_rc; /* Save APPC return codes */
if (appc_rc_p != AP_OK) {SHOW_ERR(); sys_err = TRUE; return;}
/* Handle any error */
}

void
DO_MC_DEALLOCATE ()
{
clear_vcb(); /* Zero the vcb */
vcb.dealloc.opcode = AP_M_DEALLOCATE; /* Verb-MC_DEALLOCATE */
vcb.dealloc.opext = AP_MAPPED_CONVERSATION;
/* Set MC ext. type */
vcb.dealloc.conv_id = conv_id; /* Set conversation_id */
memcpy (vcb.dealloc.tp_id, tp_id, sizeof(tp_id));
/* Set tp_id */
if ((bad_filename == TRUE) || (sys_err == TRUE))
/* Determine DEALLOC type */
vcb.dealloc.dealloc_type = AP_ABEND; /* ABEND ? or.. Normal */
else vcb.dealloc.dealloc_type = AP_SYNC_LEVEL;

APPC_C((long) vcbptr); /* Call APPC */

appc_rc_p = vcb.dealloc.primary_rc;
appc_rc_s = vcb.dealloc.secondary_rc; /* Save APPC return codes */
if (appc_rc_p != AP_OK) {SHOW_ERR(); sys_err = TRUE; return;}
/* Handle any error */
}

void
DO_TP_ENDED ()
{
clear_vcb(); /* Zero out the vcb */
vcb.tpend.opcode = AP_TP_ENDED; /* TP_ENDED opcode */
memcpy (vcb.tpend.tp_id, tp_id, sizeof(tp_id));
/* Set the tp_id */

APPC_C((long) vcbptr); /* Call APPC */

appc_rc_p = vcb.tpend.primary_rc;
appc_rc_s = vcb.tpend.secondary_rc; /* Save APPC return codes */
if (appc_rc_p != AP_OK) {SHOW_ERR(); sys_err = TRUE; return;}
/* Handle any error */
}

void
GET_SEND_CONTROL ()
{
DO_MC_RCV_AND_WAIT(); /* Wait for permission to send */
if (sys_err == TRUE) return; /* Quit if an error occured */
if ((*(unsigned *)&vcb.rcv_wait.what_rcvd) != AP_SEND) {
/* Verify WHAT_RCVD code = SEND */
sys_err = TRUE; /* Else, we had an error... */
SHOW_MSG (17); /* Permit to send not rcvd msg. */
return;
}
}

void
DO_MC_SEND_DATA ()
{
clear_vcb(); /* Zero the vcb fields */
vcb.send.opcode = AP_M_SEND_DATA; /* MC_SEND_DATA opcode */
vcb.send.opext = AP_MAPPED_CONVERSATION; /* MC type extension */
vcb.send.conv_id = conv_id; /* Set conversation_id */
memcpy (vcb.send.tp_id, tp_id, sizeof(tp_id));
/* Set tp_id */
vcb.send.dlen = bytes_read; /* Send amount read from file */
vcb.send.dptr = anbptr; /* Set pointer to data */
/* in shared segment */

APPC_C((long) vcbptr); /* Call APPC */

appc_rc_p = vcb.send.primary_rc;
appc_rc_s = vcb.send.secondary_rc; /* Save APPC return codes */
if (appc_rc_p != AP_OK) { /* Abnormal retcode ? */
if (appc_rc_p == AP_DEALLOC_ABEND) /* Requester abended */
return; /* But SERVER is still ok */
sys_err = TRUE; /* Otherwise, show error status */
SHOW_ERR();
return;
}
}

void
DO_MC_SEND_ERROR ()
{
clear_vcb(); /* Zero out the vcb */
vcb.senderr.opcode = AP_M_SEND_ERROR; /* Verb-MC_SEND_ERROR */
vcb.senderr.opext = AP_MAPPED_CONVERSATION;
/* Set MC type */
vcb.senderr.conv_id = conv_id; /* Set Conversation_id */
memcpy (vcb.senderr.tp_id, tp_id, sizeof(tp_id));
/* Set TP_id */

APPC_C ((long) vcbptr); /* Call APPC */

appc_rc_p = vcb.senderr.primary_rc;
appc_rc_s = vcb.senderr.secondary_rc; /* Save APPC return codes */
if (appc_rc_p != AP_OK) {SHOW_ERR(); sys_err = TRUE; return; }
/* Handle any error */
}

/****************************************************************************/
/* */
/* OS/2 RELATED FUNCTIONS */
/* */
/****************************************************************************/

void
ALLOC_SHARED_BUFFER()
/* APPC requires a data buffer in a shared unnamed segment */
{
unsigned short selector; /* Selector from DOSALLOCSEG */

dos_rc = DOSALLOCSEG (4096, (unsigned far *)&selector, 1);

if (dos_rc == 0) { /* If there is no error */
FP_OFF(anbptr) = 0; /* set the offset to zero */
FP_SEG(anbptr) = selector; /* address = Selector:0 */
}
else { /* Else show dos error */
SHOW_DOS_ERROR(); /* set system to true, */
sys_err = TRUE; /* zero out the pointer */
anbptr = (unsigned char far *)0;
}
}

void
OPEN_DOS_FILE()
/* Open the filename sent by the Requester. The filename is an ASCIIZ */
/* string pointed to by anbptr+1. (+1 to skip Pascal type LL length byte)*/
{
unsigned short action;

eof_flag = FALSE;
dos_rc = DOSOPEN (anbptr+1, /* addr. of file & path name */
(unsigned far *)&filehandle,
/* addr. of filehandle - */
/* returned by dos */
(unsigned far *)&action,
/* addr. of action taken by dos */
(long)0, /* file primary allocation */
0, /* file attribute */
0x0001, /* type of function to be done */
0x0020, /* Open mode of the file */
(long)0); /* Reserved double word */
/* Dos call to open the file */
if (dos_rc == 0) bad_filename = FALSE;
else { /* Show error on bad open */
if (dos_rc != 110) SHOW_DOS_ERROR(); /* RC=110 = File not found */
bad_filename = TRUE; /* Flag bad file */
}
}

void
CLOSE_DOS_FILE ()
{
dos_rc = DOSCLOSE(filehandle); /* Close the file */
if (dos_rc != 0) {SHOW_DOS_ERROR(); sys_err = TRUE; return;}
}

void
DO_DOSREAD ()
/* Read the requested file into the buffer in 4096 byte blocks */

{
dos_rc = DOSREAD (filehandle, (char far *) anbptr, 4096,
(unsigned far *)&bytes_read);
if (dos_rc != 0) {SHOW_DOS_ERROR(), sys_err = TRUE; return;}
if (bytes_read == 0) eof_flag = TRUE; /* Are we at EOF ? */
}

/* EOF FILECSVR.C */


  3 Responses to “Category : OS/2 Files
Archive   : OS2CMAPI.ZIP
Filename : FILECSVR.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/