Пример #1
0
/*
**++
**  ROUTINE:	exit_handler
**
**  FUNCTIONAL DESCRIPTION:
**
**  	Exit handler for the sp_mgr routines.  Closes down the
**  subprocesses and cleans up their SPB context blocks.
**
**  RETURNS:	cond_value, longword (unsigned), write only, by value
**
**  PROTOTYPE:
**
**  	exit_handler(unsigned int *stat, struct QUE *spq)
**
**  IMPLICIT INPUTS:	None.
**
**  IMPLICIT OUTPUTS:	None.
**
**  COMPLETION CODES:
**
**
**  SIDE EFFECTS:   	None.
**
**--
*/
static unsigned int exit_handler (unsigned int *stat, struct QUE *spq) {

    SPHANDLE ctx;

    while(queue_remove(spq->head, &ctx)) {
    	sys$delprc(&ctx->pid, 0);
    	lib$free_ef(&ctx->termefn);
    	lib$free_ef(&ctx->inefn);
    	lib$free_ef(&ctx->outefn);
    	sys$dassgn(ctx->inchn);
    	sys$dassgn(ctx->outchn);
    	lib$free_vm(&ctx->bufsiz, &ctx->bufptr);
    	lib$free_vm(&spb_size, &ctx);
    }

    return SS$_NORMAL;

} /* exit_handler */
Пример #2
0
int lib$getdvi(signed int * item_code, unsigned short int * channel, void * device_name, signed int * longword_integer_value, void * resultant_string, unsigned short * resultant_length) {
  struct _iosb iosb;
  struct item_list_3 itmlst[2];
  int retlen;
  int * retlenaddr;
  int buflen;
  void * bufaddr;
  struct dsc$descriptor * dsc;
  struct dsc$descriptor * devnam = device_name;
  struct dsc$descriptor * res = resultant_string;
  int sts;
  int efn;

  sts = lib$get_ef(&efn);
  if ((sts&1)==0)
    return sts;

  // doing some approximations since I can not now decide the return type
  
  if (longword_integer_value) {
    buflen = 4;
    bufaddr = longword_integer_value;
    retlenaddr = &retlen;
  } else {
    buflen = res->dsc$w_length;
    bufaddr = res->dsc$a_pointer;
    if (resultant_length)
      retlenaddr = resultant_length;
    else
      retlenaddr = &retlen;
  }
  
  itmlst[0].item_code=*item_code;
  itmlst[0].buflen=buflen;
  itmlst[0].retlenaddr=retlenaddr;
  itmlst[0].bufaddr=bufaddr;
  itmlst[1].item_code=0;

  int chan = 0;
  if (channel)
    chan = *channel;

  sts=sys$getdviw(efn,chan,devnam,itmlst,&iosb,0,0,0);

  if ((sts&1)==0)
    return sts;

  sts = lib$free_ef(&efn);
  if ((sts&1)==0)
    return sts;

  return sts;
}
Пример #3
0
/*
**++
**  ROUTINE:	sp_close
**
**  FUNCTIONAL DESCRIPTION:
**
**  	Close down a subprocess.
**
**  RETURNS:	cond_value, longword (unsigned), write only, by value
**
**  PROTOTYPE:
**
**  	sp_close(SPHANDLE *ctxpp)
**
**  IMPLICIT INPUTS:	None.
**
**  IMPLICIT OUTPUTS:	None.
**
**  COMPLETION CODES:
**  	    SS$_NORMAL:	    Normal successful completion.
**
**  SIDE EFFECTS:   	None.
**
**--
*/
unsigned int sp_close (SPHANDLE *ctxpp) {

    SPHANDLE ctx;
    struct SPD *spd;
    unsigned int status;

    ctx = *ctxpp;
/*
** Unlink the context block from our tracking queue
*/
    status = sys$setast(0);
    queue_remove(ctx, &ctx);
    while (queue_remove(ctx->sendque.head, &spd)) free_spd(spd);
    if (status == SS$_WASSET) sys$setast(1);

/*
** Delete the subprocess
*/
    sys$forcex(&ctx->pid, 0, SS$_NORMAL);
    sys$delprc(&ctx->pid, 0);

/*
** Wait till it actually dies
*/
    sys$waitfr(ctx->termefn);

/*
** Clean up and return
*/
    lib$free_ef(&ctx->termefn);
    lib$free_ef(&ctx->inefn);
    lib$free_ef(&ctx->outefn);
    sys$dassgn(ctx->inchn);
    sys$dassgn(ctx->outchn);
    lib$free_vm(&ctx->bufsiz, &ctx->bufptr);
    lib$free_vm(&spb_size, &ctx);
    return SS$_NORMAL;
} /* sp_close */
Пример #4
0
/* This is called at main or AST level. It is at AST level for DONTWAITFORCHILD
   and at main level otherwise. In any case it is called when a child process
   terminated. At AST level it won't get interrupted by anything except a
   inner mode level AST.
*/
int
vmsHandleChildTerm(struct child *child)
{
  int status;
  register struct child *lastc, *c;
  int child_failed;

  vms_jobsefnmask &= ~(1 << (child->efn - 32));

  lib$free_ef (&child->efn);
  if (child->comname)
    {
      if (!ISDB (DB_JOBS) && !ctrlYPressed)
        unlink (child->comname);
      free (child->comname);
    }

  (void) sigblock (fatal_signal_mask);

  child_failed = !(child->cstatus & 1 || ((child->cstatus & 7) == 0));

  /* Search for a child matching the deceased one.  */
  lastc = 0;
#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
  for (c = children; c != 0 && c != child; lastc = c, c = c->next)
    ;
#else
  c = child;
#endif

  if (child_failed && !c->noerror && !ignore_errors_flag)
    {
      /* The commands failed.  Write an error message,
         delete non-precious targets, and abort.  */
      child_error (c, c->cstatus, 0, 0, 0);
      c->file->update_status = us_failed;
      delete_child_targets (c);
    }
  else
    {
      if (child_failed)
        {
          /* The commands failed, but we don't care.  */
          child_error (c, c->cstatus, 0, 0, 1);
          child_failed = 0;
        }

#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
      /* If there are more commands to run, try to start them.  */
      start_job (c);

      switch (c->file->command_state)
        {
        case cs_running:
          /* Successfully started.  */
          break;

        case cs_finished:
          if (c->file->update_status != us_success)
            /* We failed to start the commands.  */
            delete_child_targets (c);
          break;

        default:
          OS (error, NILF,
              _("internal error: '%s' command_state"), c->file->name);
          abort ();
          break;
        }
#endif /* RECURSIVEJOBS */
    }

  /* Set the state flag to say the commands have finished.  */
  c->file->command_state = cs_finished;
  notice_finished_file (c->file);

#if defined(RECURSIVEJOBS) /* I've had problems with recursive stuff and process handling */
  /* Remove the child from the chain and free it.  */
  if (lastc == 0)
    children = c->next;
  else
    lastc->next = c->next;
  free_child (c);
#endif /* RECURSIVEJOBS */

  /* There is now another slot open.  */
  if (job_slots_used > 0)
    --job_slots_used;

  /* If the job failed, and the -k flag was not given, die.  */
  if (child_failed && !keep_going_flag)
    die (EXIT_FAILURE);

  (void) sigsetmask (sigblock (0) & ~(fatal_signal_mask));

  return 1;
}
Пример #5
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 */