Exemplo n.º 1
0
/*
** Name: CS_cp_mbx_create	- mailbox creation and initialization
**
** Description:
**	This subroutine is called from CSinitiate().
**
**	It does the following:
**	    a) establishes a mailbox, with the name II_CPRES_xx_pid, where
**		xx is the (optional) installation code, and pid is the
**		process ID in hex.
**	    b) queues a read on the mailbox, with completion routine set to
**		CS_cp_mbx_complete
**	    c) deletes the mailbox, so it'll go away when the process dies.
**
** Inputs:
**	num_sessions    - Number of sessions for the process.
**
** Outputs:
**	sys_err		- reason for error
**
** Returns:
**	OK, !OK
**
** Side Effects:
**	Sets cpres_mbx_chan to the mailbox's channel
**	Defines the system-wide logical name II_CPRES_xx_pid
**
** History:
**	Summer, 1992 (bryanp)
**	    Working on the new portable logging and locking system.
**	08-Nov-2007 (jonj)
**	    Use of "num_sessions" is totally bogus. CS_cp_mbx_create() is called
**	    before the startup parms are determined from config.dat (where we'd
**	    find "connect_limit"), so SCD hard-codes num_sessions = 32, resulting
**	    in CS_CP_MIN_MSGS == 5 always being used, which is way too small.
**	    Instead, default to the (configurable) VMS sysgen parameter
**	    DEFMBXBUFQUO.
**	    Also, create mailbox as read-only. Writers will assign write-only
**	    channels.
*/
STATUS
CS_cp_mbx_create(i4 num_sessions, CL_ERR_DESC	*sys_err)
{
    struct	dsc$descriptor_s    name_desc;
    i4		vms_status;
    char	mbx_name[100];
    char	*inst_id;
    PID		pid;

    CL_CLEAR_ERR(sys_err);
    /*
    ** Build the mailbox logical name:
    */
    PCpid(&pid);
    NMgtAt("II_INSTALLATION", &inst_id);
    if (inst_id && *inst_id)
	STprintf(mbx_name, "II_CPRES_%s_%x", inst_id, (i4)pid);
    else
	STprintf(mbx_name, "II_CPRES_%x", (i4)pid);

    name_desc.dsc$a_pointer = mbx_name;
    name_desc.dsc$w_length = STlength(mbx_name);
    name_desc.dsc$b_dtype = DSC$K_DTYPE_T;
    name_desc.dsc$b_class = DSC$K_CLASS_S;

    vms_status = sys$crembx(
		1,		    /* Mailbox is "permanent" */
		&cpres_mbx_chan,    /* where to put channel */
		(i4)sizeof(CS_CP_WAKEUP_MSG),
				    /* maximum message size */
		0,		    /* buffer quota (DEFMBXBUFQUO) */
		0,		    /* prot mask = all priv */
		PSL$C_USER,	    /* acmode */
		&name_desc,	    /* logical name descriptor */
		CMB$M_READONLY,	    /* flags */
		0);		    /* nullarg */

    if ( vms_status != SS$_NORMAL )
    {
	sys_err->error = vms_status;
	if (vms_status == SS$_NOPRIV)
	    return (E_CS00F8_CSMBXCRE_NOPRIV);
	else
	    return (E_CS00F7_CSMBXCRE_ERROR);
    }

    /* Hang a read */
    cpres_q_read_io();

    /* Mark for deletion, so it disappears when we exit. */

    sys$delmbx(cpres_mbx_chan);

    cpres_channels_sem = 0;

    cpres_num_channels_assigned = 0;

    return (OK);
}
Exemplo n.º 2
0
NamedEventImpl::NamedEventImpl(const std::string& name):
	_name(name)
{
	struct dsc$descriptor_s mbxDesc;
	mbxDesc.dsc$w_length  = _name.length();
	mbxDesc.dsc$b_dtype   = DSC$K_DTYPE_T;
	mbxDesc.dsc$b_class   = DSC$K_CLASS_S;
	mbxDesc.dsc$a_pointer = _name.c_str();
	if (sys$crembx(0, &_mbxChan, 0, 0, 0, 0, &mbxDesc, 0, 0) != 1)
		throw SystemException("cannot create named event", _name);
}
Exemplo n.º 3
0
int job_control(void *unused)
{
  int sts;
  struct _pcb *tsk = ctl$gl_pcb;
  strcpy(tsk->pcb$t_lname, "JOB_CONTROL");
  sts=exe$crembx(1,&mailbox_channel,512,512,0,0,0,0);
  sys$ar_jobctlmb=ctl$gl_ccbbase[mailbox_channel].ccb$l_ucb;
  do_mbx_read();
  sys$hiber();
  printk("job control should not get past sys$hiber\n");
}
Exemplo n.º 4
0
/*
**++
**  ROUTINE:	sp_open
**
**  FUNCTIONAL DESCRIPTION:
**
**  	Spawns a subprocess, possibly passing it an initial command.
**
**  RETURNS:	cond_value, longword (unsigned), write only, by value
**
**  PROTOTYPE:
**
**  	sp_open(SPHANDLE *ctxpp, struct dsc$descriptor *inicmd,
**  	    	    unsigned int (*rcvast)(void *), void *rcvastprm);
**
**  IMPLICIT INPUTS:	None.
**
**  IMPLICIT OUTPUTS:	None.
**
**  COMPLETION CODES:
**  	    SS$_NORMAL:	    Normal successful completion.
**
**  SIDE EFFECTS:   	None.
**
**--
*/
unsigned int sp_open (SPHANDLE *ctxpp, void *inicmd, unsigned int (*rcvast)(void *), void *rcvastprm) {

    SPHANDLE ctx;
    unsigned int dvi_devnam = DVI$_DEVNAM, dvi_devbufsiz = DVI$_DEVBUFSIZ;
    unsigned int spawn_flags = CLI$M_NOWAIT|CLI$M_NOKEYPAD;
    unsigned int status;
    struct dsc$descriptor inbox, outbox;

    status = lib$get_vm(&spb_size, &ctx);
    if (!OK(status)) return status;

/*
** Assign the SPHANDLE address for the caller immediately to avoid timing issues with
** WRTATTN AST that passes the ctx as rcvastprm (which sp_once does).
*/
    *ctxpp = ctx;
    ctx->sendque.head = ctx->sendque.tail = &ctx->sendque;
    ctx->ok_to_send = 0;

/*
** Create the mailboxes we'll be using for I/O with the subprocess
*/
    status = sys$crembx(0, &ctx->inchn, 1024, 1024, 0xff00, 0, 0, 0);
    if (!OK(status)) {
    	lib$free_vm(&spb_size, &ctx);
    	return status;
    }
    status = sys$crembx(0, &ctx->outchn, 1024, 1024, 0xff00, 0, 0, 0);
    if (!OK(status)) {
    	sys$dassgn(ctx->inchn);
    	lib$free_vm(&spb_size, &ctx);
    	return status;
    }

/*
** Now that they're created, let's find out what they're called so we
** can tell LIB$SPAWN
*/
    INIT_DYNDESC(inbox);
    INIT_DYNDESC(outbox);
    lib$getdvi(&dvi_devnam, &ctx->inchn, 0, 0, &inbox);
    lib$getdvi(&dvi_devnam, &ctx->outchn, 0, 0, &outbox);
    lib$getdvi(&dvi_devbufsiz, &ctx->outchn, 0, &ctx->bufsiz);

/*
** Create the output buffer for the subprocess.
*/
    status = lib$get_vm(&ctx->bufsiz, &ctx->bufptr);
    if (!OK(status)) {
    	sys$dassgn(ctx->outchn);
    	sys$dassgn(ctx->inchn);
    	str$free1_dx(&inbox);
    	str$free1_dx(&outbox);
    	lib$free_vm(&spb_size, &ctx);
    	return status;
    }

/*
** Set the "receive AST" routine to be invoked by SP_WRTATTN_AST
*/
    ctx->rcvast = rcvast;
    ctx->astprm = rcvastprm;
    sys$qiow(0, ctx->outchn, IO$_SETMODE|IO$M_WRTATTN, 0, 0, 0,
    	sp_wrtattn_ast, ctx, 0, 0, 0, 0);
    sys$qiow(0, ctx->inchn, IO$_SETMODE|IO$M_READATTN, 0, 0, 0,
    	sp_readattn_ast, ctx, 0, 0, 0, 0);

/*
** Get us a termination event flag
*/
    status = lib$get_ef(&ctx->termefn);
    if (OK(status)) lib$get_ef(&ctx->inefn);
    if (OK(status)) lib$get_ef(&ctx->outefn);
    if (!OK(status)) {
    	sys$dassgn(ctx->outchn);
    	sys$dassgn(ctx->inchn);
    	str$free1_dx(&inbox);
    	str$free1_dx(&outbox);
    	lib$free_vm(&ctx->bufsiz, &ctx->bufptr);
    	lib$free_vm(&spb_size, &ctx);
    	return status;
    }

/*
** Now create the subprocess
*/
    status = lib$spawn(inicmd, &inbox, &outbox, &spawn_flags, 0, &ctx->pid,
    	    0, &ctx->termefn);
    if (!OK(status)) {
    	lib$free_ef(&ctx->termefn);
    	lib$free_ef(&ctx->outefn);
    	lib$free_ef(&ctx->inefn);
    	sys$dassgn(ctx->outchn);
    	sys$dassgn(ctx->inchn);
    	str$free1_dx(&inbox);
    	str$free1_dx(&outbox);
    	lib$free_vm(&ctx->bufsiz, &ctx->bufptr);
    	lib$free_vm(&spb_size, &ctx);
    	return status;
    }

/*
** Set up the exit handler, if we haven't done so already
*/
    status = sys$setast(0);
    if (!exh_declared) {
    	sys$dclexh(&exhblk);
    	exh_declared = 1;
    }
    if (status == SS$_WASSET) sys$setast(1);

/*
** Save the SPB in our private queue
*/
    queue_insert(ctx, spque.tail);

/*
** Clean up and return
*/
    str$free1_dx(&inbox);
    str$free1_dx(&outbox);

    return SS$_NORMAL;

} /* sp_open */
Exemplo n.º 5
0
void cce_dbdump(void)
{
	uint4	channel, status, flags, pid, real_size, req_size, size, addrs[2], sec_addrs[2];
	int		i, j, k, l;
	gds_file_id	file;
	m_iosb		stat_blk;
	sgmnt_data	*sd;
	unsigned char	mbuff[512], *c, *cptr, *ctop;
	$DESCRIPTOR(d_sec,mbuff);
	static readonly $DESCRIPTOR(d_cmd,"install lis/glo");
	static readonly $DESCRIPTOR(d_mnam,"CCE$DBDUMPMBX");
	static readonly $DESCRIPTOR(d_pnam,"CCE$DBDUMPPRC");
	char		filename[]="SYS$LOGIN:CCE_DBDUMP.DMP", buff[RECORD_SIZE], id_lab[]=" FILE ID:";
	struct FAB	fab;
	struct RAB	rab;
	error_def(ERR_CCEDBDUMP);
	error_def(ERR_CCEDBNODUMP);


	util_out_open(0);
	status = sys$crembx(0, &channel, 512, 0, 0, PSL$C_USER, &d_mnam);
	if (status != SS$_NORMAL)
		sys$exit(status);
	flags = CLI$M_NOWAIT | CLI$M_NOLOGNAM;
	status = lib$spawn(&d_cmd, 0, &d_mnam, &flags, &d_pnam, &pid);
	if (status != SS$_NORMAL)
	{	if (status == SS$_DUPLNAM)
		{	util_out_print("Spawned process CCE$DBDUMPPRC already exists, cannot continue rundown",TRUE);
		}
		sys$exit(status);
	}
	/* the following guess at the dump file size is modeled on the calculation for a section */
	size = DIVIDE_ROUND_UP((SIZEOF(sgmnt_data) + (WC_MAX_BUFFS + getprime(WC_MAX_BUFFS) + 1) * SIZEOF(bt_rec)
				+ (DEF_LOCK_SIZE / OS_PAGELET_SIZE)
				 + (WC_MAX_BUFFS + getprime(WC_MAX_BUFFS)) * SIZEOF(cache_rec) + SIZEOF(cache_que_heads)),
				OS_PAGELET_SIZE);
	size += EXTRA_SPACE;

	fab = cc$rms_fab;
	fab.fab$b_fac = FAB$M_PUT;
	fab.fab$l_fop = FAB$M_CBT | FAB$M_MXV | FAB$M_TEF;
	fab.fab$l_fna = filename;
	fab.fab$b_fns = SIZEOF(filename);
	fab.fab$b_rfm = FAB$C_FIX;
	fab.fab$w_mrs = RECORD_SIZE;
	fab.fab$w_deq = size;
	fab.fab$l_alq = size;
	switch (status = sys$create(&fab))
	{
	case RMS$_NORMAL:
	case RMS$_CREATED:
	case RMS$_SUPERSEDE:
	case RMS$_FILEPURGED:
		break;
	default:
		util_out_print("Error: Cannot create dump file !AD.",TRUE,fab.fab$b_fns,fab.fab$l_fna);
		sys$exit(status);
	}

	rab = cc$rms_rab;
	rab.rab$l_fab = &fab;
	status = sys$connect(&rab);
	if (status != RMS$_NORMAL)
	{	util_out_print("Error: Cannot connect to dump file !AD.",TRUE,fab.fab$b_fns,fab.fab$l_fna);
		sys$exit(status);
	}
	rab.rab$w_rsz = SIZEOF(buff);

	for (; ;)
	{	status = sys$qiow (0, channel,IO$_READVBLK ,&stat_blk, 0, 0, mbuff, 512,0,0,0,0);
		if (status != SS$_NORMAL)
		{	sys$exit(status);
			break;
		}
		if (stat_blk.status == SS$_ENDOFFILE)
			break;
		if (stat_blk.status != SS$_NORMAL)
		{	sys$exit(stat_blk.status);
			break;
		}
		if (!memcmp("GT$S",mbuff,4))
		{	for ( c = mbuff; *c > 32 ; c++)
				;
			d_sec.dsc$w_length = c - mbuff;
			flags = SEC$M_GBL | SEC$M_WRT | SEC$M_SYSGBL | SEC$M_PAGFIL | SEC$M_DZRO | SEC$M_PERM;
			addrs[0] = addrs[1] = 0;
			fid_from_sec(&d_sec,&file);

			real_size = cce_sec_size(&file);
			if (real_size == 0)
				real_size = size;
			real_size += 1;

			assert(OS_PAGE_SIZE % OS_PAGELET_SIZE == 0);

			/* Request enough pagelets to ensure enough contiguous pages to contain desired number of pagelets. */
			req_size = ROUND_UP(real_size, OS_PAGE_SIZE);
			lib$get_vm_page(&req_size, &addrs[0]);

			/* addrs will hold addresses of start and end of contiguous block of pagelets for use by $deltva. */
			assert((addrs[0] + (req_size * OS_PAGELET_SIZE) - 1) == addrs[1]);

			/* $get_vm_page returns pagelets; we must align to integral page boundary. */
			/* sec_addrs will contain the starting and ending addresses of the mapped section. */
			sec_addrs[0] = ROUND_UP(addrs[0], OS_PAGE_SIZE);	/* align to first integral page boundary */
			sec_addrs[1] = addrs[0] + (real_size * OS_PAGELET_SIZE);
			sec_addrs[1] = ROUND_UP(addrs[1], OS_PAGE_SIZE) - 1;  /* A(last byte of last page) */

			status = init_sec(sec_addrs, &d_sec, 0, real_size, flags);
			if (status & 1)
			{
				sd = sec_addrs[0];
				memset(buff, 0, RECORD_SIZE);
				memcpy(buff, d_sec.dsc$a_pointer, d_sec.dsc$w_length);
				cptr = &buff[0] + d_sec.dsc$w_length;
				memcpy(cptr,id_lab,SIZEOF(id_lab));
				cptr += SIZEOF(id_lab);
				memcpy(cptr,&file,SIZEOF(file));
				rab.rab$l_rbf = buff;
				status = sys$put(&rab);
				if (status != RMS$_NORMAL)
				{	util_out_print("Error writing to dump file !AD.",TRUE,fab.fab$b_fns,fab.fab$l_fna);
					util_out_print("Status code is !UL.",TRUE,status);
					break;
				}
				for (c = sd, i = 0; (real_size + EXTRA_SPACE) >= i;
					c += RECORD_SIZE, i += (RECORD_SIZE / DISK_BLOCK_SIZE))
				{
					rab.rab$l_rbf = c;
					status = sys$put(&rab);
					if (status != RMS$_NORMAL)
					{	util_out_print("Error writing to dump file !AD.",TRUE,fab.fab$b_fns,fab.fab$l_fna);
						util_out_print("Status code is !UL.",TRUE,status);
						break;
					}
				}
				lib$signal(ERR_CCEDBDUMP,2,d_sec.dsc$w_length,d_sec.dsc$a_pointer);
			}else
			{	lib$signal(ERR_CCEDBNODUMP,2,d_sec.dsc$w_length,d_sec.dsc$a_pointer,status,0);
			}
			gtm_deltva(&addrs[0],0,0);
			lib$free_vm_page(&real_size,&addrs[0]);
		}
	}
	sys$exit(SS$_NORMAL);
}
Exemplo n.º 6
0
rlMailbox::rlMailbox(const char *mbxname)
{
#ifdef RLUNIX
FILE  *fp;
key_t key;

  status = OK;
  buffer = NULL;
  buffer_size = 0;
  name = new char[strlen(mbxname)+1];
  strcpy(name,mbxname);
  // create file
  fp = fopen(name,"r");
  if(fp == NULL)
  {
    fp = fopen(name,"w");
    if(fp == NULL)
    {
      int ret;
      char buf[1024];
      sprintf(buf,"could not write mailbox=%s\n",mbxname);
      ret = ::write(1,buf,strlen(buf));
      if(ret < 0) exit(-1);
      sprintf(buf,"you have to run this program as root !!!\n");
      ret = ::write(1,buf,strlen(buf));
      if(ret < 0) exit(-1);
      exit(-1);
    }
    fchmod(fileno(fp),0x0fff);
    if(fp == NULL) { status=COULD_NOT_CREATE_MAILBOX; return; }
  }
  fclose(fp);
  // getkey

  // old stuff, without suggestions from Stefan Lievens 
  // key = ftok(name, 'R');

  key = ftok(name, 'b');
  if(key == ((key_t) (-1))) { status=COULD_NOT_GET_KEY; return; }
  // get chanid

  // old stuff, without suggestions from Stefan Lievens 
  // chanid = msgget(key,IPC_CREAT);
  chanid = msgget(key, 0600 | IPC_CREAT);
  if(chanid == -1) { status=COULD_NOT_GET_CHAN_ID; return; }
#endif

#ifdef __VMS
  long   ret;
  short  chan_id;
  struct dsc$descriptor_s dmbxname;

  chanid = -1;
  status = OK;
  name = new char[strlen(mbxname)+1];
  strcpy(name,mbxname);
  dmbxname.dsc$w_length  = strlen(name);
  dmbxname.dsc$a_pointer = name;
  dmbxname.dsc$b_dtype   = DSC$K_DTYPE_T;
  dmbxname.dsc$b_class   = DSC$K_CLASS_S;
  ret = sys$crembx((char)1,                     // 0 temp 1 permanence flag
                   &chan_id,                    // i/o channel
                   MAX_MAILBOX,                 // max msg length
                   MAX_MAILBOX*4,               // max buffer size
                   (long)0,
                   (long)0,
                   &dmbxname);                   // mailbox name
  if(ret == SS$_NORMAL) { chanid = chan_id; return; }
  else                  { status = COULD_NOT_CREATE_MAILBOX; return; }
#endif

#ifdef RLWIN32
  chanid = -1;
  status = OK;
  name = new char[strlen(mbxname)+1];
  strcpy(name,mbxname);
#endif
}
Exemplo n.º 7
0
		}

		break;
	    }

	    default:
		break;
	}
    }

	/*
	** create mailbox for passing commands to the new process.
	** Get the device name of the mailbox to to be used as input
	** stream for new process.
	*/
    status = sys$crembx( 0, &chan, 0, 0, 0, PSL$C_USER, NULL );
    if ( !(status & 1) )
    {
	log_errmsg( "SYS$CREMBX(1) failed", status, 1 );
	return ( status );
    }

    dviitem = DVI$_DEVNAM;
    $DESCFILL( input, sizeof( inbuf ), inbuf );
    status = lib$getdvi( &dviitem, &chan, NULL, NULL, &input, &input );
    if ( !(status & 1) )
    {
	log_errmsg( "LIB$GETDVI(1) failed", status, 1 );
	return ( status );
    }
Exemplo n.º 8
0
Arquivo: mbx.c Projeto: Rick33/freevms
main(){
  struct _iosb myiosb;

  char mybuf1[MBXBUFSIZ]="test1";
  char mybuf2[MBXBUFSIZ]="test2";
  char mybuf3[MBXBUFSIZ]="test3";

  char * out1="hello";
  char * out2="world";
  char * out3="hi";

  void *p1, mbxast();
  char mbuffer[MBXBUFSIZ];
  unsigned short mbxchan1, mbxchan2, mbxchan3, mbxiosb;
  unsigned int status, outlen;
  unsigned int mbuflen=MBXBUFSIZ, bufquo=MBXBUFQUO, promsk=0;
  $DESCRIPTOR(mblognam1,"MAILBOX1");
  $DESCRIPTOR(mblognam2,"MAILBOX2");
  $DESCRIPTOR(mblognam3,"MAILBOX3");

  printf("this was originally in 1: %s\n",mybuf1);
  printf("this was originally in 2: %s\n",mybuf2);
  printf("this was originally in 3: %s\n",mybuf3);

  status = sys$crembx(0,&mbxchan1,mbuflen,bufquo,promsk,0,&mblognam1,0);
  printf("status %x mbxchan %x \n", status,mbxchan1);
  if ((status&1)==0) signal(status);
  status = sys$crembx(0,&mbxchan2,mbuflen,bufquo,promsk,0,&mblognam2,0);
  printf("status %x mbxchan %x \n", status,mbxchan2);
  if ((status&1)==0) signal(status);
  status = sys$crembx(0,&mbxchan3,mbuflen,bufquo,promsk,0,&mblognam3,0);
  printf("status %x mbxchan %x \n", status,mbxchan3);
  if ((status&1)==0) signal(status);

  printf("before qio %x\n",time(0));

  status=sys$qio(0,mbxchan1,IO$_READVBLK,0,0,0,mybuf1,512,0,0,0,0);

  printf("after qio %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);

  printf("before qiow %x\n",time(0));
  status=sys$qio(0,mbxchan1,IO$_WRITEVBLK,0,0,0,out1,strlen(out1),0,0,0,0);
  printf("after qiow %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);
  printf("before qiow %x\n",time(0));
  status=sys$qio(0,mbxchan1,IO$_WRITEVBLK,0,0,0,out2,strlen(out2),0,0,0,0);
  printf("after qiow %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);

  printf("this was read from 1: %s\n",mybuf1);

  printf("Pausing...\n");
  sleep(2);





  printf("before qio %x\n",time(0));

  status=sys$qio(0,mbxchan2,IO$_READVBLK|IO$M_STREAM,0,0,0,mybuf2,512,0,0,0,0);

  printf("after qio %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);

  printf("before qiow %x\n",time(0));
  status=sys$qio(0,mbxchan2,IO$_WRITEVBLK,0,0,0,out1,strlen(out1),0,0,0,0);
  printf("after qiow %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);
  printf("before qiow %x\n",time(0));
  status=sys$qio(0,mbxchan2,IO$_WRITEVBLK,0,0,0,out2,strlen(out2),0,0,0,0);
  printf("after qiow %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);

  printf("this was read from 2: %s\n",mybuf2);

  printf("Pausing...\n");
  sleep(2);




  printf("before qio %x\n",time(0));

  printf("before qiow %x\n",time(0));
  status=sys$qio(0,mbxchan3,IO$_WRITEVBLK,0,0,0,out1,strlen(out1),0,0,0,0);
  printf("after qiow %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);
  printf("before qiow %x\n",time(0));
  status=sys$qio(0,mbxchan3,IO$_WRITEVBLK,0,0,0,out2,strlen(out2),0,0,0,0);
  printf("after qiow %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);

  status=sys$qiow(0,mbxchan3,IO$_READVBLK|IO$M_STREAM,0,0,0,mybuf3,512,0,0,0,0);

  printf("after qio %x\n",time(0));
  printf("status %x done %x \n", status,done);
  if ((status&1)==0) signal(status);

  printf("this was read from 3: %s\n",mybuf3);

  sleep(2);


  {

    struct item_list_3 { short buflen, item_code;
			 void *bufaddr;
			 void *retlenaddr;
		       } itmlist[2];

    char buf[50];
    int retlen;

    itmlist[0].item_code=LNM$_STRING;
    itmlist[0].bufaddr=buf;
    itmlist[0].buflen=50;
    itmlist[0].retlenaddr=&retlen;
    itmlist[1].item_code=0;
    itmlist[1].buflen=0;
    itmlist[1].bufaddr=0;

    $DESCRIPTOR(tab,"LNM$TEMPORARY_MAILBOX");

    status = sys$trnlnm(0,
		    &tab,
		    &mblognam1, 0,
		    itmlist);
    if ((status&1)==0) signal(status);
    printf("mailbox1 translates to %s\n",buf);
  }
  return SS$_NORMAL;
}