From:	MERC::"uunet!WKUVX1.BITNET!FILESERV-Mgr"  3-JUN-1992 09:45:02.36
To:	galaxy::gleeve
CC:	
Subj:	GETCMD.03_OF_04

-+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+
X`09     (.pcb`5BPCB$W_STATE`5D EQLU SCH$C_COMO)))`09!... COM state
X`09THEN
X`09   IF ((.CTL$GL_PCB`5BPCB$B_PRI`5D LSSU 16) AND
X`09       (.CTL$GL_PCB`5BPCB$B_PRI`5D GTRU .pcb`5BPCB$B_PRI`5D))
X`09   THEN`09`09`09`09`09!Boost its priority
X`09`09! SCH$CHSEP is described in module RSE
X`09`09SCH$CHSEP (.CTL$GL_PCB`5BPCB$B_PRI`5D, .pcb);
X`09END
X    ELSE`09`09`09`09`09!Here, the target process was
X`09status = SS$_NONEXPR;`09`09`09!... deleted or swapped out
X
X    $SYS_UNLOCK (LOCKNAME = SCHED,`09`09!Release the SCHED spinlock
X`09`09 NEWIPL   = .old_ipl);`09`09!... and restore IPL
X
X    IF NOT(.status)`09`09`09`09!If an error occurred queueing
X    THEN`09`09`09`09`09!... the AST, then release the
X`09EXE$DEANONPAGED (.acb_addr);`09`09!... ACB back to nonpaged pool
X
X    END;
X
X  $SETIPL (NEWIPL = 0, ENVIRON=UNIPROCESSOR);`09!Lower IPL from 2 to 0
X
X  $ULWSET (INADR = wslock_range);`09`09!Unlock these pages
X
XRETURN (.status);`09`09`09`09!Return the final status
X
XEND;
X
X`0C
X%SBTTL`09'AST_CODE'
XROUTINE ast_code (pcb, acb) : NOVALUE ast_jsb =
XBEGIN
X!+
X!
X!  Routine:`09AST_CODE
X!
X!  Functional Description:
X!
X!`09This routine executes as a special Kernel-mode AST in the context
X!`09of the target process.  It copies the process's DCL command recall
X!`09buffer into the extended ACB and then queues an AST back to the
X!`09requesting process to return the buffer to it.
X!
X!`09This routine duplicates the MACRO trick of JMPing into SCH$QAST
X!`09and letting its RSB return to the ASTDEL code.  This eliminates
X!`09the problems of returning to code in memory that may have already
X!`09been deallocated to nonpaged pool.
X!
X!  Environment:
X!
X!`09Kernel-mode, IPL 2.  Called via JSB.
X!
X!  Formal parameters:
X!
X!`09R4`09- PCB address
X!`09R5`09- ACB address
X!
X!  Implicit inputs:
X!
X!`09CTL$AG_CLIDATA, PPD$L_PRC, PRC_G_COMMANDS, PRC_S_COMMANDS,
X!`09PRC_L_RECALLPTR
X!
X!  Outputs:
X!
X!`09None.
X!
X!  Returns:
X!
X!`09R0`09- Status
X!
X!  Side effects:
X!
X!`09Re-uses the ACB to queue an AST back to the requesting process.
X!
X!-
XMAP
X`09pcb`09: REF $BBLOCK,
X`09acb`09: REF $BBLOCK;
X
XBIND
X`09dcl_cliname`09= %ASCIC'DCL';
X
XREGISTER
X`09src`09: REF $BBLOCK,
X`09dst`09: REF $BBLOCK,
X`09prc`09: REF $BBLOCK;
X
XEXTERNAL
X`09CTL$AG_CLIDATA`09: G_HAT REF $BBLOCK,`09`09!Process Permanent Data
X`09CTL$GT_CLINAME`09: G_HAT $BBLOCK,`09`09!Process Permanent Data
X`09PPD$L_PRC`09: ADDRESSING_MODE (ABSOLUTE),`09!Pointer to PRC
X`09PRC_L_RECALLPTR`09: ADDRESSING_MODE (ABSOLUTE),`09!Address of last cmd
X`09PRC_G_COMMANDS`09: ADDRESSING_MODE (ABSOLUTE),`09!Address of cmd buffer
X`09PRC_S_COMMANDS`09: ADDRESSING_MODE (ABSOLUTE);`09!Size of cmd buffer
X
X  !
X  !  First, let's make sure the CLI is DCL.  The CLI name is stored as an
X  !  ASCIC string at CTL$GT_CLINAME, so we can just check to see if the
X  !  longword there matches the %ASCIC string "DCL".
X  !
X  acb`5BACB_L_AST_STATUS`5D = SS$_NORMAL;`09`09!Start off assuming all is OK
X
X  !
X  !  See if the CLI name is DCL.  Let's cheat a little bit, because we
X  !  know that the ASCIC string "DCL" is a longword in length.  Just
X  !  compare longwords.
X  !
X  !  The problem with checking the CLI name is that a manager can copy
X  !  DCL to some other filename---GETCMD would still work, but it doesn't
X  !  know that it can.
X  !
X  IF (.CTL$GT_CLINAME NEQU dcl_cliname)`09`09!Is the CLI name DCL?
X  THEN`09`09`09`09`09`09!... If it's not, then set
X      acb`5BACB_L_AST_STATUS`5D = GETCMD_NODCL;`09!... the AST status to "No
V DCL"
X
X  !
X  !  Just because DCL is the CLI doesn't mean that it's actually been mapped
X  !  in, because LOGINOUT always copies the CLI name to CTL$GT_CLINAME.
X  !  We can, however, check to make sure DCL is there by checking the
X  !  address of the CLI callback routine, which is stored in CTL$AL_CLICALBK
V.
X  !  The address initially stored there points to routine in S0 space that
X  !  just returns a "no CLI" error.  If DCL *has* been mapped, the address
X  !  will be one in P1 space.
X  !
X  IF (.CTL$AL_CLICALBK LSS 0)`09`09`09!Is the address negative?  If
X  THEN`09`09`09`09`09`09!... so, it's in S0 space, so
X      acb`5BACB_L_AST_STATUS`5D = GETCMD_NOCLI;`09!... set error status
X
X  !
X  !  If we made it here with ACB_L_AST_STATUS still true, then DCL is the
X  !  CLI and it has been mapped.  We're now ready to go get the command
X  !  recall buffer.
X  !
X  IF (.acb`5BACB_L_AST_STATUS`5D)
X  THEN
X      BEGIN
X      !
X      !  Now get the pointer to the process's PRC region.  This address
X      !  is stored in the PPD at offset PPD$L_PRC.  The global symbol
X      !  CTL$AG_CLIDATA points to the PPD.
X      !
X      prc = CTL$AG_CLIDATA;`09`09`09!Point to the PPD
X      prc = .(.prc + PPD$L_PRC);`09`09!Now point to the PRC
X      !
X      !  The command recall buffer begins at offset PRC_G_COMMANDS.  The
X      !  pointer to the end of the last command in the buffer is stored at
X      !  offset PRC_L_RECALLPTR.  We need to convert this PRC_L_RECALLPTR
X      !  address into a relative offset into the buffer.
X      !
X      acb`5BACB_L_RECALLPTR`5D = .(.prc + PRC_L_RECALLPTR) -
X`09`09`09      (.prc + PRC_G_COMMANDS);
X
X      !
X      !  Now we're ready to copy the whole command recall buffer to our
X      !  extended ACB.  A loop is used instead of CH$MOVE to keep register
X      !  usage within R0--R5.  (When CH$MOVE is used, BLISS saves R6 and
X      !  changes the JMP to SCH$QAST to a JSB.  Hence the reason for the
X      !  loop.)
X      !
X      src = .prc + PRC_G_COMMANDS;`09`09!Point to the recall buffer
X      dst = acb`5BACB_T_DCLBUFFER`5D;`09`09!Point to the buffer in the ACB
X      DECR i FROM PRC_S_COMMANDS TO 0`09`09!Copy PRC_S_COMMANDS bytes
X`09DO`09`09`09`09`09!... from the recall buffer
X`09   CH$WCHAR_A(CH$RCHAR_A(src),dst);`09!... to the buffer in the ACB
X      !
X      !  Not used for reason given above.
X      !
X      !  CH$MOVE (PRC_S_COMMANDS, .prc + PRC_G_COMMANDS, acb`5BACB_T_DCLBUFF
VER`5D);
X
X      END;
X
X  !
X  !  Now reset the ACB for queueing back to the original process.
X  !
X  acb`5BACB$L_KAST`5D = .acb`5BACB_L_2ND_KAST`5D;`09!KAST field points to 2n
Vd AST
X  acb`5BACB$L_PID`5D  = .acb`5BACB_L_PID`5D;`09`09!Move requestor's PID
X  acb`5BACB$B_RMOD`5D = .acb`5BACB$B_RMOD`5D OR ACB$M_KAST;`09!Make sure KAS
VT is set
X
X  !
X  !  Now we're ready to JMP into SCH$QAST to queue the AST back.  BLISS is
X  !  tricked into generating a JMP so that control does *not* return back
X  !  to this routine.  It is possible on SMP machines that the second AST
X  !  *could* deallocate the extended ACB before SCH$QAST returned control
X  !  to this routine, resulting in a return to memory deallacted back to
X  !  pool.  The issue is avoided by JMPing into SCH$QAST, which will then
X  !  RSB to the ASTDEL code.
X  !
X  SCH$QAST (0, .acb; pcb);`09`09!JMP into SCH$QAST and let it return
X`09`09`09`09`09!... to the caller
X
XEND;
X
X`0C
X%SBTTL`09'AST2_CODE'
XROUTINE AST2_CODE (pcb, acb) : NOVALUE ast_jsb =
XBEGIN
X!+
X!
X!  Routine:`09AST2_CODE
X!
X!  Functional Description:
X!
X!`09This routine executes as a special Kernel-mode AST in the context
X!`09of the requesting process.  It copies the target's command buffer
X!`09from the extended ACB back into this program's buffer.
X!
X!`09This routine duplicates the MACRO trick of JMPing into EXE$DEANONPAGED
X!`09and letting its RSB return to the ASTDEL code.  This eliminates
X!`09the problems of returning to code in memory that may have already
X!`09been deallocated to nonpaged pool.
X!
X!  Environment:
X!
X!`09Kernel-mode, IPL 2.  Called via JSB.
X!
X!  Formal parameters:
X!
X!`09R4`09- PCB address
X!`09R5`09- ACB address
X!
X!  Implicit inputs:
X!
X!`09Addresses stored in the extended ACB
X!
X!  Outputs:
X!
X!`09None.
X!
X!  Returns:
X!
X!`09R0`09- Status
X!
X!  Side effects:
X!
X!`09JMPs into EXE$DEANONPAGED to deallocate the extended ACB back to
X!`09nonpaged pool.
X!
X!-
XMAP
X`09pcb`09: REF $BBLOCK,
X`09acb`09: REF $BBLOCK;
X
XEXTERNAL
X`09PRC_S_COMMANDS`09: ADDRESSING_MODE (ABSOLUTE);`09!Size of command buffer
X
XREGISTER
X`09src`09: REF $BBLOCK,
X`09dst`09: REF $BBLOCK;
X
X  src = .pcb`5BPCB$L_PHD`5D;`09`09`09!Get the PHD address
X  !
X  !  If the original process is no longer running the same image that queued
X  !  the ASTs, then we don't want to do anything except deallocate the
X  !  extended ACB (otherwise, we'd copy the DCL command buffer to an address
X  !  that is no longer valid).  To ensure the same image is running, compare
X  !  the IMGCNT fields.
X  !
X  IF (.src`5BPHD$L_IMGCNT`5D EQLU .acb`5BACB_L_IMGCNT`5D)`09!If the image co
Vunt is
X  THEN`09`09`09`09`09`09`09!... the same, we're
X     BEGIN`09`09`09`09`09`09!... still running
X     IF (.acb`5BACB_L_USERSTAT`5D = .acb`5BACB_L_AST_STATUS`5D)`09!Copy stat
Vus; if OK,
X     THEN`09`09`09`09`09`09!... then copy to user
X`09BEGIN`09`09`09`09`09`09!... recall buffer
X`09.acb`5BACB_L_USERPTR`5D = .acb`5BACB_L_RECALLPTR`5D;`09!Copy the offset
X`09src = acb`5BACB_T_DCLBUFFER`5D;`09`09`09!Point to ACB buffer
X`09dst = .acb`5BACB_L_USERBUF`5D;`09`09`09!Point to user buffer
X`09DECR i FROM PRC_S_COMMANDS TO 0`09`09`09!Copy the buffer
X`09   DO`09`09`09`09`09`09!Again, a loop is used
X`09   CH$WCHAR_A(CH$RCHAR_A(src),dst);`09`09!... to avoid MOVC3
X`09END;
X     !
X     !  The process is waiting for the event flag to be set, so post it
X     !  to indicate that the recall buffer has been successfully copied.
X     !
X     SCH$POSTEF (.acb`5BACB_L_PID`5D, 0, .acb`5BACB_L_EFN`5D);
X     END;
X
X  EXE$DEANONPAGED (.acb);`09`09!JMP to deallocate the extended ACB
X
XEND;
X
X!From LOGIN
XPSECT OWN = $CODE$(NOWRITE,EXECUTE);`09! Cause this OWN to occur here
XOWN wslock_end : UNSIGNED LONG;`09`09! Used to lock down previous code pages
XPSECT OWN = $OWN$(WRITE,NOEXECUTE);`09! Restore normal own psect
X
XEND`09`09`09`09`09`09!End of module BEGIN
XELUDOM`09`09`09`09`09`09!End of module
$ CALL UNPACK [.GETCMD]GETCMD.B32;1 1695498939
$ create 'f'
X;MACRO-32 source generated by BLISS-32 compiler
X`09.TITLE  GETCMD GETCMD
X`09.IDENT  \03-001\
X`09.PSECT  $OWN$,NOEXE,2
XU.6:`09.BLKB   4
XU.7:`09.BLKB   8
XU.8:`09.WORD   8
X`09.BYTE   14, 1
X`09.ADDRESS U.7
XU.9:`09.BLKB   1025
X`09.BLKB   3
XU.10:`09.BLKB   4
XU.11:`09.BLKB   4
XU.12:`09.LONG   5, 13
X`09.ADDRESS U.6, U.9, U.11, U.10
X`09.PSECT  $PLIT$,NOWRT,NOEXE,2
XP.AAB:`09.ASCII  \_PID: \<0><0>
XP.AAA:`09.LONG   17694726
X`09.ADDRESS P.AAB
X`09.EXTRN  LIB$GET_FOREIGN, LIB$PUT_OUTPUT, OTS$CVT_TZ_L, EXE$ALONONPAGED, E
VXE$DEANONPAGED, EXE$EPID_TO_PCB
X`09.EXTRN  EXE$IPID_TO_PCB, SCH$CHSEP, SCH$CLREF, SCH$POSTEF, SCH$QAST, CTL$
VAL_CLICALBK, CTL$GL_PCB
X`09.EXTRN  CTL$GL_PHD, SCH$GL_SWPPID, GETCMD_NOCLI, GETCMD_NODCL, GETCMD_NOC
VMDS, SYS$CMKRNL, SYS$WAITFR
X`09.PSECT  $CODE$,NOWRT,2
XU.1:`09.WORD   `5EM<R2>
X`09MOVAB   W`5EU.8, R2
X`09PUSHL   R2
X`09PUSHAB  W`5EP.AAA
X`09PUSHL   R2
X`09CALLS   #3, G`5ELIB$GET_FOREIGN
X`09BLBS    R0, 3$
X`09CMPL    R0, #98938
X`09BNEQ    1$
X`09MOVL    #1, R1
X`09BRB     2$
X1$:`09MOVL    R0, R1
X2$:`09MOVL    R1, R0
X`09RET
X3$:`09PUSHAB  -12(R2)
X`09PUSHL   R2
X`09CALLS   #2, G`5EOTS$CVT_TZ_L
X`09BLBC    R0, 4$
X`09PUSHAB  1044(R2)
X`09PUSHAB  W`5EU.3
X`09CALLS   #2, G`5ESYS$CMKRNL
X`09BLBC    R0, 4$
X`09PUSHL   #13
X`09CALLS   #1, G`5ESYS$WAITFR
X`09BLBC    R0, 4$
X`09MOVL    1036(R2), R0
X`09BLBC    R0, 4$
X`09PUSHAB  1040(R2)
X`09PUSHAB  8(R2)
X`09CALLS   #2, W`5EU.2
X4$:`09RET
X`09.PSECT  $PLIT$,NOWRT,NOEXE,2
XP.AAD:`09.ASCII  \!3UB !AS\
XP.AAC:`09.LONG   17694728
X`09.ADDRESS P.AAD
XU.15=`09`09    P.AAC
X`09.EXTRN  PRC_S_COMMANDS, SYS$FAOL
X`09.PSECT  $CODE$,NOWRT,2
XU.2:`09.WORD   `5EM<R2,R3,R4,R5,R6,R7,R8,R9,R10,-
X`09`09R11>
X`09MOVAB   -564(SP), SP
X`09PUSHL   4(AP)
X`09ADDL3   #PRC_S_COMMANDS, (SP), R7
X`09MOVL    #17694976, -264(FP)
X`09MOVAB   -256(FP), -260(FP)
X`09MOVL    #17694980, 24(SP)
X`09MOVAB   32(SP), 28(SP)
X`09CLRL    16(SP)
X`09MOVAB   -264(FP), 20(SP)
X`09TSTL    @8(AP)
X`09BNEQ    1$
X`09MOVAB   G`5EGETCMD_NOCMDS, R0
X`09RET
X1$:`09ADDL3   @8(AP), (SP), 8(SP)
X`09MOVL    8(SP), R6
X`09MOVL    #1, 4(SP)
X2$:`09BLBS    4(SP), 3$
X`09BRW     13$
X3$:`09DECL    R6
X`09CMPL    R6, (SP)
X`09BGEQU   4$
X`09MOVAB   -1(R7), R6
X4$:`09MOVZBL  (R6), R11
X`09BNEQ    5$
X`09BRW     11$
X5$:`09SUBL3   R11, R6, R0
X`09CMPL    R0, (SP)
X`09BGEQU   6$
X`09SUBL3   (SP), R6, R10
X`09SUBL3   R10, R11, R8
X`09SUBL3   R8, R7, R9
X`09MOVC3   R8, (R9), -256(FP)
X`09MOVC3   R10, @0(SP), -256(FP)`5BR8`5D
X`09MOVL    R9, R6
X`09BRB     7$
X6$:`09SUBL2   R11, R6
X`09MOVC3   R11, (R6), -256(FP)
X7$:`09DECL    R6
X`09CMPL    R6, (SP)
X`09BGEQU   8$
X`09MOVAB   -1(R7), R6
X8$:`09DECL    R6
X`09CMPL    R6, (SP)
X`09BGEQU   9$
X`09MOVAB   -1(R7), R6
X9$:`09INCL    16(SP)
X`09MOVW    #260, 24(SP)
X`09MOVW    R11, -264(FP)
X`09PUSHAB  16(SP)
X`09PUSHAB  28(SP)
X`09PUSHAB  32(SP)
X`09PUSHAB  W`5EU.15
X`09CALLS   #4, G`5ESYS$FAOL
X`09BLBC    R0, 10$
X`09PUSHAB  24(SP)
X`09CALLS   #1, G`5ELIB$PUT_OUTPUT
X`09MOVL    R0, 12(SP)
X10$:`09CMPL    R6, 8(SP)
X`09BNEQ    12$
X11$:`09CLRL    4(SP)
X12$:`09BRW     2$
X13$:`09MOVL    #1, R0
X`09RET
X`09.EXTRN  SYS$LKWSET, SGN$GL_SMP_SPINWAIT, EXE$GL_TENUSEC, EXE$GL_UBDELAY,
V SMP$GL_FLAGS, SMP$TIMEOUT
X`09.EXTRN  SMP$ACQUIRE, SMP$RELEASE, SMP$RESTORE, SYS$ULWSET
XU.3:`09.WORD   `5EM<R2,R3,R4,R5,R6,R7,R8,R9,R10,-
X`09`09R11>
X`09MOVAB   G`5ESMP$GL_FLAGS, R11
X`09SUBL2   #4, SP
X`09PUSHAB  B`5EU.3
X`09MOVAB   W`5EU.16, 4(SP)
X`09CLRL    -(SP)
X`09PUSHAB  4(SP)
X`09PUSHAB  8(SP)
X`09CALLS   #3, G`5ESYS$LKWSET
X`09MOVL    R0, R9
X`09BLBS    R9, 1$
X`09BRW     17$
X1$:`09MOVL    @8(AP), R7
X`09BNEQ    2$
X`09MOVL    G`5ECTL$GL_PCB, R0
X`09MOVL    96(R0), R7
X`09BRB     8$
X2$:`09MFPR    #18, R10
X`09BLBC    (R11), 3$
X`09MOVL    #47, R0
X`09JSB     G`5ESMP$ACQUIRE
X`09BLBS    (R11), 4$
X3$:`09MTPR    #8, #18
X4$:`09MOVL    R7, R0
X`09JSB     G`5EEXE$EPID_TO_PCB
X`09MOVL    R0, R8
X`09BEQL    5$
X`09MOVL    96(R8), R7
X5$:`09BLBC    (R11), 6$
X`09MOVL    #47, R0
X`09JSB     G`5ESMP$RELEASE
X6$:`09MTPR    R10, #18
X`09TSTL    R8
X`09BNEQ    7$
X`09MOVZWL  #2280, R0
X`09RET
X7$:`09CMPL    R7, G`5ESCH$GL_SWPPID
X`09BGTRU   8$
X`09MOVAB   G`5EGETCMD_NOCLI, R0
X`09RET
+-+-+-+-+-+-+-+-  END  OF PART 3 +-+-+-+-+-+-+-+-
