From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 25-JUN-1991 05:41:35.48
To:	ARISIA::EVERHART
CC:	
Subj:	REMPRTSMB part 2 of 3

From:	RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP@CRDGW2
To:	Everhart@Arisia@MRGATE

Received:  by crdgw1.ge.com (5.57/GE 1.101)
	 id AA05928; Tue, 25 Jun 91 05:25:08 EDT
Message-Id:  <9106250925.AA05928@crdgw1.ge.com>
Received: From CUNYVM.CUNY.EDU by CRVAX.SRI.COM with TCP; Tue, 25 JUN 91 02:10:22 PDT
Received: from DGOGWDG1.BITNET by CUNYVM.CUNY.EDU (IBM VM SMTP R1.2.2MX) with BSMTP id 5975; Tue, 25 Jun 91 05:10:01 EDT
Received: from dnet.gwdg.de by DGOGWDG1.BITNET (Mailer R2.07) with BSMTP id
 2235; Tue, 25 Jun 91 11:07:07 MSZ
Date:    Tue, 25 Jun 1991 11:06:55 +0200
From: "GWDGV1::MOELLER" <moeller%gwdgv1.dnet.gwdg.de@CUNYVM.CUNY.EDU>
To: info-vax@sri.com, vmsnet-sources@ucbvax.berkeley.edu
Subject: REMPRTSMB part 2 of 3

+-+-+-+ Beginning of part 2 +-+-+-+
X
X`009switch(*funcp) `123
X`009  case PSM$K_OPEN:
X`009`009*argp = PSM$K_CC_INTERNAL;
X
X`009`009return init_job(ctxp,wap);`009`009/* continues via AST */
X`009`009break;
X
X`009  case PSM$K_READ:
X`009`009return RMS$_EOF;
X`009`009break;
X
X`009  case PSM$K_CLOSE:
X`009`009return SS$_NORMAL;
X`009`009break;
X
X`009  case PSM$K_CANCEL:
X`009  case PSM$K_STOP_TASK:
X`009  case PSM$K_RESET_STREAM:
X`009`009abort_job(wap);`009`009/* ggf. cancel open loop */
X`009  default:
X`009`009return PSM$_FUNNOTSUP;
X`009`009break;
X`009`125
X`125
X
X/*****`009job trailer page: close output file`009*****/
X
Xstatic unsigned remprt_job_trailer(
X`009char **ctxp,
X`009WORKAREA *wap,
X`009int *funcp,
X`009DESCR *dscp,
X`009unsigned *argp)
X`123
X`009static unsigned close_job(char **, WORKAREA *);`009/* forward */
X`009static void abort_job(WORKAREA *);`009`009/* forward */
X
X
X`009switch(*funcp) `123
X`009  case PSM$K_OPEN:
X`009`009*argp = PSM$K_CC_INTERNAL;
X
X`009`009switch(wap->wk_state) `123
X`009`009  case putting:
X`009`009  case opened:
X`009`009`009return close_job(ctxp,wap);`009/* continue via AST`009*/
X`009`009`009break;
X`009`009`125
X`009`009return SS$_NORMAL;
X`009`009break;
X
X`009  case PSM$K_READ:
X`009`009return RMS$_EOF;
X`009`009break;
X
X`009  case PSM$K_CLOSE:
X`009`009return SS$_NORMAL;
X`009`009break;
X
X`009  case PSM$K_STOP_TASK:`009`009`009/* asynch. abort`009*/
X`009`009switch(wap->wk_state) `123
X`009`009  case putting:
X`009`009  case opened:
X`009`009`009abort_job(wap);
X`009`009`009break;
X`009`009`125
X`009  default:
X`009`009return PSM$_FUNNOTSUP;
X`009`009break;
X`009`125
X`125
X
X/*****`009job startup (triggered by job_flag)`009*****/
X
Xstatic unsigned init_job(
X`009char **ctxp,
X`009WORKAREA *wap)
X`123
X`009unsigned status;
X`009int l;
X`009char /*logical*/ opt_username,opt_spool,opt_jobname,opt_rsx;
X`009char *lp, *lp1, *lp2, *optp;
X`009static unsigned short lnml;
X`009static char devlnm[32], line[256];
X`009static DESCR devlnmdsc = `1230-0,0,0,devlnm`125;
X`009static const $DESCRIPTOR(linedsc,line);
X`009static const $DESCRIPTOR(lnmtabdsc,"LNM$FILE_DEV");
X`009static struct `123
X`009`009unsigned short len;
X`009`009unsigned short code;
X`009`009void *addr;
X`009`009void *retlen;
X`009`125 itmlst[2] = `123
X`009`009`123sizeof(line)-1, LNM$_STRING, line, &lnml`125,
X`009`009`1230, 0, NULL, NULL`125
X`009`125;
X
X
X`009/*****`009link state must be =closed !!!`009****/
X
X`009if(wap->wk_state != closed) `123
X`009`009lib$stop(0x10000004,1,wap->wk_state);`009/* crash ...`009*/
X`009`125
X
X`009/***** "device name" and options *****/
X
X`009opt_username = 0;
X`009opt_jobname = 0;
X`009opt_rsx = 0;
X`009opt_spool = 0;
X
X`009devlnmdsc.dsc$w_length = sizeof(devlnm)-1;
X`009devlnm[0] = '\0';
X`009psm$read_item_dx(ctxp,&SMBMSG$K_DEVICE_NAME,&devlnmdsc);
X`009devlnm[itrmlen(&devlnmdsc)] = '\0';
X
X`009l = strlen(devlnm);
X`009if(l > 0 && devlnm[l-1] == ':') `123
X`009`009devlnm[--l] = '\0';`009/* ggf. remove trailing ':' */
X`009`125
X
X`009devlnmdsc.dsc$w_length = l;
X`009status = sys$trnlnm(NULL, &lnmtabdsc, &devlnmdsc, NULL, &itmlst);
X`009if((status & 1) == 0) return status;
X
X`009l = lnml;
X`009line[l] = '\0';
X`009for(lp=line; *lp != '\0'; lp++)
X`009`009*lp = toupper(*lp);`009/* upcase device & options */
X
X`009optp = strchr(line,'/');
X`009if(optp == NULL) optp = line + strlen(line);
X`009for(lp1 = optp; *lp1 != '\0'; lp1 = lp2) `123
X`009`009lp2 = strchr(lp1+1,'/');`009/* locate next '/' ... */
X`009`009if(lp2 == NULL) lp2 = lp1 + strlen(lp1);  /* ... or '\0' */
X
X#define opt_(o) ((lp2-lp1) == sizeof(o)-1 && strncmp(lp1,o,sizeof(o)-1) == 0)
X
X`009`009if(opt_("/USERNAME")) `123
X`009`009`009opt_username = 1;
X`009`009`125 else if(opt_("/JOBNAME")) `123
X`009`009`009opt_jobname = 1;
X`009`009`125 else if(opt_("/RSX")) `123
X`009`009`009opt_rsx = 1;
X`009`009`125 else if(opt_("/SPOOL")) `123
X`009`009`009opt_spool = 1;
X`009`009`125
X`009`125
X`009*optp = '\0';`009`009`009/* remove options now`009*/
X
X`009if(strlen(line) > (sizeof wap->wk_file)-39-1-39-1) `123
X`009`009return SS$_IVLOGNAM;`009/* make sure it's not too long */
X`009`125
X`009strcpy(wap->wk_file,line);`009/* copy "node::dev:[dir]"`009*/
X
X`009/*****`009filename`009*****/
X
X`009if(opt_jobname) `123`009`009/* have a try at JOB_NAME */
X`009`009int l1,l2;
X`009`009char c;
X
X`009`009line[0] = '\0';
X`009`009psm$read_item_dx(ctxp,&SMBMSG$K_JOB_NAME,&linedsc);
X`009`009line[itrmlen(&linedsc)] = '\0';
X
X`009`009l1 = 0; l2 = -1;
X`009`009for(lp = line; *lp; lp++) `123
X`009`009`009if(*lp == '.') `123
X`009`009`009`009if(l2 >= 0) goto job_name_failed;
X`009`009`009`009l2 = 0;
X`009`009`009`125 else if((*lp >= 'A' && *lp <= 'Z') `124`124
X`009`009`009`009  (*lp >= 'a' && *lp <= 'z') `124`124
X`009`009`009`009  (*lp >= '0' && *lp <= '9') `124`124
X`009`009`009`009  (!opt_rsx && (*lp == '_' `124`124
X`009`009`009`009`009`009*lp == '-' `124`124
X`009`009`009`009`009`009*lp == '$'))) `123
X`009`009`009`009if(l2 < 0) l1++; else l2++;
X`009`009`009`125 else goto job_name_failed;
X`009`009`125
X`009`009if(!opt_rsx) `123
X`009`009`009if(l1 == 0 `124`124 l1 > 39 `124`124
X`009`009`009   l2 == 0 `124`124 l2 > 39) goto job_name_failed;
X`009`009`125 else `123
X`009`009`009if(l1 == 0 `124`124 l1 > 9 `124`124
X`009`009`009   l2 == 0 `124`124 l2 > 3) goto job_name_failed;
X`009`009`125
X
X`009`009if(l2 < 0) strcat(line,".PRT");
X`009`009strcat(wap->wk_file,line);
X`009`009goto file_name_ok;
X`009`125
Xjob_name_failed:
X
X`009if(opt_username) `123`009`009`009/* "username.PRT" */
X`009`009line[0] = '\0';
X`009`009psm$read_item_dx(ctxp,&SMBMSG$K_USER_NAME,&linedsc);
X`009`009line[itrmlen(&linedsc)] = '\0';
X
X`009`009if(opt_rsx) `123
X`009`009`009if(strlen(line) > 9) line[9] = '\0';
X`009`009`009for(lp = line; *lp; lp++) `123
X`009`009`009`009if(!((*lp >= 'A' && *lp <= 'Z') `124`124
X`009`009`009`009     (*lp >= 'a' && *lp <= 'z') `124`124
X`009`009`009`009     (*lp >= '0' && *lp <= '9'))) `123
X`009`009`009`009`009*lp = '0';
X`009`009`009`009`125
X`009`009`009`125
X`009`009`125
X
X`009`009strcat(line,".PRT");
X`009`009strcat(wap->wk_file,line);
X`009`125 else `123`009`009`009`009/* "VAX.PRT" */
X`009`009strcat(wap->wk_file,"VAX.PRT");
X`009`125
Xfile_name_ok:
X
X`009wap->wk_fab.fab$b_fns = strlen(wap->wk_file);
X
X`009/*****`009spooling option`009*****/
X
X`009wap->wk_spool = opt_spool;
X
X`009/*****`009ready to go`009*****/
X
X`009wap->wk_scbp = *ctxp;
X`009wap->wk_state = open1;
X`009status = sys$dclast(rms_ast,&wap->wk_rab,0);
X`009if((status & 1) == 0) lib$stop(status `124 0x10000000);
X
X`009return PSM$_PENDING;
X`125
X
X/*****`009queue output`009*****/
X
Xstatic unsigned put_out(
X`009char **ctxp,
X`009WORKAREA *wap,
X`009char *bufp,
X`009unsigned short buflen)
X`123
X`009unsigned status;
X`009OUTPUTQELT *qp;
X
X
X`009qp = oq_alloc();
X`009qp->scbp = *ctxp;
X`009qp->op = bufp;
X`009qp->olen = buflen;
X`009status = lib$insqti(qp,&wap->wk_oqhead);
X`009if((status & 1) == 0) lib$stop(status `124 0x10000000);
X
X`009/* assume state=putting or =opened */
X
X`009if(wap->wk_state == opened) `123
X`009`009wap->wk_state = putting;
X`009`009status = sys$dclast(rms_ast,&wap->wk_rab,0);
X`009`009if((status & 1) == 0) lib$stop(status `124 0x10000000);
X`009`125
X
X`009return PSM$_PENDING;
X`125
X
X/*****`009abort job (asynch, no psm$report)`009*****/
X
Xstatic void abort_job(`009
X`009WORKAREA *wap)
X`123
X`009unsigned status;
X`009OUTPUTQELT *qp;
X`009static void rms_abort(WORKAREA *);`009`009/* forward */
X`009static void rms_open_cancel(WORKAREA *);`009/* forward */
X
X
X`009switch(wap->wk_state) `123
X`009  case putting:
X`009`009qp = oq_alloc();
X`009`009qp->scbp = NULL;
X`009`009qp->olen = OLEN_ABORT;
X`009`009status = lib$insqhi(qp,&wap->wk_oqhead);`009/* at HEAD */
X`009`009if((status & 1) == 0) lib$stop(status `124 0x10000000);
X`009`009break;
X
X`009  case opened:
X`009`009rms_abort(wap);
X`009`009break;
X
X`009  default:
X`009`009rms_open_cancel(wap);
X`009`009break;
X`009`125
X`125
X
X/*****`009 end of job`009*****/
X
Xstatic unsigned close_job(
X`009char **ctxp,
X`009WORKAREA *wap)
X`123
X`009unsigned status;
X`009OUTPUTQELT *qp;
X
X
X`009switch(wap->wk_state) `123
X`009  case putting:
X`009`009qp = oq_alloc();
X`009`009qp->scbp = *ctxp;
X`009`009qp->olen = OLEN_CLOSE;
X`009`009status = lib$insqti(qp,&wap->wk_oqhead);
X`009`009if((status & 1) == 0) lib$stop(status `124 0x10000000);
X`009`009break;
X
X`009  case opened:
X`009`009wap->wk_state = close1;
X`009`009wap->wk_scbp = *ctxp;
X`009`009status = sys$dclast(rms_ast,&wap->wk_rab,0);
X`009`009if((status & 1) == 0) lib$stop(status `124 0x10000000);
X`009`009break;
X`009`125
X`009return PSM$_PENDING;
X`125
X
X/*****`009initialize workarea (1st time only)`009*****/
X
Xstatic void init_wk(
X`009WORKAREA *wap)
X`123
X`009wap->wk_fab = cc$rms_fab;
X`009wap->wk_rab = cc$rms_rab;
X
X`009wap->wk_fab.fab$l_ctx = wap;
X        wap->wk_fab.fab$b_fac = FAB$M_PUT;
X#ifndef ASY_FAB
X`009wap->wk_fab.fab$l_fop = FAB$M_SQO `124 FAB$M_TEF;
X#else
X`009wap->wk_fab.fab$l_fop = FAB$M_ASY `124 FAB$M_SQO `124 FAB$M_TEF;
X#endif
X`009wap->wk_fab.fab$b_rfm = FAB$C_VAR;
X`009wap->wk_fab.fab$b_rat = 0;`009/* "none" */
X`009wap->wk_fab.fab$w_mrs = BLOCK_SIZE;
X`009wap->wk_fab.fab$l_fna = &wap->wk_file;
X`009/* b_fns to be filled in later, l_fop possibly modified */
X
X`009wap->wk_rab.rab$l_ctx = wap;
X`009wap->wk_rab.rab$l_fab = &wap->wk_fab;
X`009wap->wk_rab.rab$b_rac = RAB$C_SEQ;
X`009wap->wk_rab.rab$l_rop = RAB$M_ASY `124 RAB$M_WBH;
X`009/* l_rbf, w_rsz to be filled in later */
X
X`009wap->wk_state = closed;
X`125
X
X/*****`009cleanup OUTPUTQELTs in WORKAREA`009*****/
X
Xstatic void oq_cleanup(
X`009WORKAREA *wap)
X`123
X`009unsigned status;
X`009OUTPUTQELT *qp;
X
X
X`009/* the current qelt's scbp is NOT acknowledged !!! */
X
X`009if(wap->wk_curqp != NULL) `123`009
X`009`009oq_free(wap->wk_curqp);
X`009`009wap->wk_curqp = NULL;
X`009`125
X
X`009while((lib$remqhi(&wap->wk_oqhead, &qp) & 1) != 0) `123
X`009`009if(qp->scbp != NULL) `123
X`009`009`009psm$report(&qp->scbp,&0);`009/* fake completion */
X`009`009`125
X`009`009oq_free(qp);
X`009`125
X`125
X
X/** emergency (synch) close`009**/
X
Xstatic void rms_abort(
X`009WORKAREA *wap)
X`123
X`009unsigned fop,rop;
X
X
X`009if(wap->wk_fab.fab$w_ifi != 0) `123
X`009`009rop = wap->wk_rab.rab$l_rop;
X`009`009wap->wk_rab.rab$l_rop &= `126RAB$M_ASY;`009/* synch. $disconnect */
X`009`009fop = wap->wk_fab.fab$l_fop;
X`009`009wap->wk_fab.fab$l_fop `124= FAB$M_DLT;`009/* get rid of file */
X`009`009wap->wk_fab.fab$l_fop &= `126FAB$M_SPL;`009/* don't spool */
X#ifdef ASY_FAB
X`009`009wap->wk_fab.fab$l_fop &= `126FAB$M_ASY;`009/* synch. $close */
X#endif
X`009`009sys$close(&wap->wk_fab);`009`009/* ignore status */
X`009`009wap->wk_rab.rab$l_rop = rop;
X`009`009wap->wk_fab.fab$l_fop = fop;
X`009`125
X`009wap->wk_state=closed;
X`125
X
X/**`009AST for RMS actions, arg=pointer to RAB *or* FAB`009**/
X
Xstatic void rms_ast(
X`009struct RAB *frabp)`009/* bzw. struct FAB */
X`123
X`009unsigned status;
X`009WORKAREA *wap;
X
X
V`009wap = frabp->rab$l_ctx;`009/* same as fab$l_ctx - see old comments in .H
X */
X
X/** make sure "frabp" is used ONLY in the preceding line **/
X
Xagain:
X`009switch(wap->wk_state) `123
X
X`009/***********/
X`009  case closed:`009`009/* no-op */
X`009`009break;
X
X`009/***********/
X`009  case open1:
X`009  case open1t:
X
X`009`009if(wap->wk_spool) `123
X`009`009`009wap->wk_fab.fab$l_fop `124= FAB$M_SPL `124 FAB$M_DLT;
X`009`009`125 else `123
X`009`009`009wap->wk_fab.fab$l_fop &= `126(FAB$M_SPL `124 FAB$M_DLT);
X`009`009`125
X#ifndef ASY_FAB
X`009`009status=sys$create(&wap->wk_fab);`009/* synchronous`009*/
X`009`009if(wap->wk_spool) `123
X`009`009`009wap->wk_fab.fab$l_fop = fop;
X`009`009`125
X#else
X`009`009/* asynch. $create */
X
X`009`009wap->wk_state = open2;
X
X`009`009status = sys$create(&wap->wk_fab,rms_ast,rms_ast);
X`009`009/* AST should take care of 'status', else bad luck ... */
X
X`009`009break;
X
X`009/***********/
X`009  case open2:
X`009`009status = wap->wk_fab.fab$l_sts;
X#endif
X`009`009if((status & 1) == 0) goto set_open_timer;
X
X`009`009/* asynch $connect`009*/
X
X`009`009wap->wk_state = open3;
X`009`009status = sys$connect(&wap->wk_rab,rms_ast,rms_ast);
X`009`009if((status & 1) == 0) `123
X`009`009`009rms_abort(wap);
X`009`009`009psm$report(&wap->wk_scbp,&status);
X`009`009`009return;
X`009`009`125
X`009`009break;
X
X`009/***********/
X`009  case open3:
X`009`009status = wap->wk_rab.rab$l_sts;
X`009`009if((status & 1) == 0) `123
X`009`009`009rms_abort(wap);
X`009`009`009psm$report(&wap->wk_scbp,&status);
X`009`009`009return;
X`009`009`125
X
X`009`009wap->wk_state = opened;
X`009`009psm$report(&wap->wk_scbp);
X`009`009break;
X
X`009/***********/
X`009  case putting:
X`009`009if(wap->wk_curqp != NULL) `123`009/* $put completion`009*/
X`009`009`009psm$report(&(wap->wk_curqp->scbp),
X`009`009`009`009`009&wap->wk_rab.rab$l_sts);
X`009`009`009oq_free(wap->wk_curqp);
X`009`009`125
X
X`009`009status = lib$remqhi(&wap->wk_oqhead, &wap->wk_curqp);
X`009`009if((status & 1) == 0) `123
X`009`009`009wap->wk_curqp = NULL;
X`009`009`009wap->wk_state = opened;
X`009`009`009return;
X`009`009`125
X
X`009`009switch(wap->wk_curqp->olen) `123
X`009`009  case OLEN_CLOSE:
X`009`009`009wap->wk_scbp = wap->wk_curqp->scbp;
X`009`009`009oq_cleanup(wap);
X`009`009`009wap->wk_state = close1;
X`009`009`009goto again;`009`009/* now do "close1" action */
X
X`009`009  case OLEN_ABORT:
X`009`009`009wap->wk_scbp = wap->wk_curqp->scbp;
X`009`009`009oq_cleanup(wap);
X`009`009`009wap->wk_state = aborting;
X`009`009`009goto again;`009`009/* now do "aborting" action */
X`009`009`125
X
X`009`009wap->wk_rab.rab$l_rbf = wap->wk_curqp->op;
X`009`009wap->wk_rab.rab$w_rsz = wap->wk_curqp->olen;
X`009`009status = sys$put(&wap->wk_rab,rms_ast,rms_ast);
X`009`009if((status & 1) == 0) `123
X`009`009`009psm$report(&(wap->wk_curqp->scbp),&status);
X`009`009`009rms_abort(wap);`009`009/* state -> closed */
X`009`009`009oq_cleanup(wap);`009/* cleanup */
X`009`009`125
X`009`009break;
X
X`009/***********/
X`009  case close1:
X`009`009wap->wk_state = close2;
X`009`009status = sys$disconnect(&wap->wk_rab,rms_ast,rms_ast);
X`009`009if((status & 1) == 0) `123
X`009`009`009rms_abort(wap);
X`009`009`009psm$report(&wap->wk_scbp,&status);
X`009`009`009return;
X`009`009`125
X`009`009break;
X
X`009/***********/
X`009  case close2:
X`009`009status = wap->wk_rab.rab$l_sts;
X`009`009if((status & 1) == 0) `123
X`009`009`009rms_abort(wap);
X`009`009`009psm$report(&wap->wk_scbp,&status);
X`009`009`009return;
X`009`009`125
X
X#ifndef ASY_FAB
X`009`009status = sys$close(&wap->wk_fab);`009/* synch.`009*/
X`009`009wap->wk_state = closed;
X#else
X`009`009wap->wk_state = close3;
X`009`009status = sys$close(&wap->wk_fab,rms_ast,rms_ast);
X`009`009if((status & 1) == 0) `123
-+-+-+-+-+ End of part 2 +-+-+-+-+-

