; ; $Id: last.asm 1.7 1994/12/12 17:13:55 rthomas Exp rthomas $ ; ; The Press-Enterprise Co. ; 3512 Fourteenth Street ; Riverside, California 92501-3878 ; (c) Copyright 1994 ; ; Author: Randolph Thomas ; rthomas@pe.com ; ; LICENCE INFORMATION ; This program is free software; you may redistribute it and/or ; modify it under the terms of the GNU General Public Licence ; as published by the Free Software Foundation; either version 1 ; or (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; with even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public Licence for more details. ; ; You should have received a copy of the GNU General Public Licence ; along with this program; if not, write to the Free Software ; Foundation, Inc., 675 Mass Ave., Cambridge, MA 02139, USA. ; ; $Log: last.asm $ ; Revision 1.7 1994/12/12 17:13:55 rthomas ; Added the -w option. Fixed a bug associated with EOF. ; ; Revision 1.6 1994/12/10 00:39:57 rthomas ; Corrected the FileError reporting. ; ; Revision 1.5 1994/12/10 00:15:19 rthomas ; Added the -f option and the SkipWord() usage. ; ; Revision 1.4 1994/12/01 18:48:00 rthomas ; Recovered the source. ; ; Revision 1.3 1992/09/04 23:19:07 rthomas ; Added the -h option. ; ; Revision 1.2 1992/09/04 23:07:23 rthomas ; Added ReadToEnd on reading the end of file. ; ; Revision 1.1 1992/04/01 19:50:29 rthomas ; Initial revision ; .MODEL small include ascii.inc include filei.inc LoginNote struct Net dd ? NodeH dd ? NodeL dw ? LoginNote ends LogoutNote struct Net dd ? NodeH dd ? NodeL dw ? LogoutNote ends E3h36h_GetBindObjName_req struct dw 5 db 036h ObjectID dd ? E3h36h_GetBindObjName_req ends E3h36h_GetBindObjName_rep struct dw 4+2+48 ObjectID dd ? ObjectType dw ? ObjectName db 48 dup(?) E3h36h_GetBindObjName_rep ends .STACK .DATA RcsId db "$Id: last.asm 1.7 1994/12/12 17:13:55 rthomas Exp rthomas $" Warranty db "last - a Unix-like last program for the Novell Network",10,13 db "Copyright (C) 1994 Press-Enterprise Co.",10,13 db 10,13 db "This program is free software; you can redistribute it and/or modify",10,13 db "it under the terms of the GNU General Public License as published by",10,13 db "the Free Software Foundation; either version 1, or (at your option)",10,13 db "any later version.",10,13 db 10,13 db "This program is distributed in the hope that it will be useful,",10,13 db "but WITHOUT ANY WARRANTY; without even the implied warranty of",10,13 db "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",10,13 db "GNU General Public License for more details.",10,13 db 10,13 db "You should have received a copy of the GNU General Public License",10,13 db "along with this program; if not, write to the Free Software",10,13 db "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",10,13,"$" NoteRecord dw ? ServerID dd ? TimeStamp db 6 dup(?) RecordType db ? db ? ServiceType dw ? ClientID dd ? CommentType dw ? CommentField db 300 dup(?) ClientIDtoMatch dd ? ;these are used when looking for NetToMatch dd ? ;the matching logout record NodeHtoMatch dd ? NodeLtoMatch dw ? NameToMatchLength dw 0 NameToMatch db 47 dup(0),0 ;yes, login names can be 47 long GetName_req E3h36h_GetBindObjName_req <> GetName_rep E3h36h_GetBindObjName_rep <> FileError db "last: Error opening " FileName db "SYS:SYSTEM/NET$ACCT.DAT",256 dup(0) HexTable db "0123456789ABCDEF" Months db "Jan","Feb","Mar","Apr","May","Jun" db "Jul","Aug","Sep","Oct","Nov","Dec" LineOut db 80 dup(0) IllegalOption db "last: bad option",10,13 ErrorWithObject db "last: error in GetBinderyObjectName",10,13 Usage db "Usage:",10,13,9,"last [-f file] [-h] [-v] [-w] [name]" .CODE .STARTUP mov ax,seg DGROUP mov es,ax call CheckCmdLine lea si,FileName call OpenFile jnc ALoop mov ax,seg DGROUP mov es,ax mov ds,ax mov ah,40h mov bx,1 mov cx,LENGTHOF FileError lea si,FileName @@: lodsb cmp al,0 je @F inc cx jmp @B @@: lea dx,FileError int 21h .EXIT 1 ALoop: call ReadRecord jc DoneH cmp [RecordType],02h jne @F cmp [CommentType],0300h ;remember, Motorola format jne @F call ObjectID2Name mov cx,[NameToMatchLength] jcxz NoCheck lea si,GetName_rep.ObjectName lea di,NameToMatch repe cmpsb jne @F cmp cx,0 jne @F NoCheck: call PrintRecord @@: jmp ALoop DoneH: call CloseFile .EXIT 0 ;----------------------------------------------------------------------- ;Given: ;Returns: ; Carry Set - End of File (or perhaps an error) ;----------------------------------------------------------------------- ReadRecord proc USES ax bx cx di call ReadNextByte cmp ax,-1 je ReadToEnd mov bh,al call ReadNextByte cmp ax,-1 je ReadToEnd mov ah,bh mov [NoteRecord],ax cmp ax,01Eh ; is it the right length? je @F call SkipWord mov [RecordType],0 clc jmp OuttaHere @@: lea di,ServerID mov cx,ax @@: call ReadNextByte cmp ax,-1 je ReadToEnd stosb loop @B clc jmp OuttaHere ReadToEnd: stc OuttaHere: ret ReadRecord endp ;----------------------------------------------------------------------- ;Given: ;Returns: ;----------------------------------------------------------------------- PrintRecord proc lea si,GetName_rep.ObjectName lea di,LineOut xor cx,cx @@: lodsb cmp al,0 je @F inc cx stosb jmp @B @@: cmp cx,11 jnb @F neg cx add cx,11 mov al,' ' rep stosb @@: lea si,CommentField lodsw xchg ah,al call Bin2Hex lodsw xchg ah,al call Bin2Hex mov al,':' stosb lodsw xchg ah,al call Bin2Hex lodsw xchg ah,al call Bin2Hex lodsw xchg ah,al call Bin2Hex mov al,' ' stosb lea si,TimeStamp lodsb ;get year mov ah,al cmp al,99 ja @F mov al,'1' stosb mov al,'9' stosb jmp Not19 @@: mov al,'2' stosb mov al,'0' stosb Not19: mov al,ah xor ah,ah aam or ax,03030h xchg al,ah stosw mov al,' ' stosb lodsb ;get month dec al xor ah,ah lea si,Months add si,ax shl ax,1 add si,ax lodsb stosb lodsb stosb lodsb stosb mov al,' ' stosb mov si,offset TimeStamp + 2 lodsb ;get day cmp al,27 jne ToHere nop ToHere: aam or ax,03030h xchg al,ah stosw mov al,' ' stosb lodsb ;get hour aam or ax,03030h xchg al,ah stosw mov al,':' stosb lodsb ;get minute aam or ax,03030h xchg al,ah stosw call FindLogout mov al,Ascii_CR stosb mov al,Ascii_LF stosb mov cx,di sub cx,offset LineOut mov ah,040h mov bx,1 lea dx,LineOut int 21h ret PrintRecord endp ;----------------------------------------------------------------------- ;Given: ;Returns: ; Carry set - no logout found ; Carry clear - logout found ;----------------------------------------------------------------------- FindLogout proc USES ax si LOCAL DoneHere:word mov DoneHere,0 mov ax,word ptr [ClientID] ; store the ID we'll look for mov word ptr [ClientIDtoMatch],ax mov ax,word ptr [ClientID+2] mov word ptr [ClientIDtoMatch+2],ax lea si,CommentField mov ax,word ptr [si.LogoutNote.NodeH] ; store the Host too mov word ptr [NodeHtoMatch],ax mov ax,word ptr [si.LogoutNote.NodeH+2] mov word ptr [NodeHtoMatch+2],ax mov ax,word ptr [si.LogoutNote.NodeL] mov [NodeLtoMatch],ax call FileSetMark BLoop: call ReadRecord jnc @F mov DoneHere,1 @@: cmp [RecordType],02h jne @F cmp [CommentType],0300h ;login note? je CmpID cmp [CommentType],0400h ;logout note? jne @F CmpID: mov ax,word ptr [ClientIDtoMatch] cmp ax,word ptr [ClientID] jne @F mov ax,word ptr [ClientIDtoMatch+2] cmp ax,word ptr [ClientID+2] jne @F lea si,CommentField ; good, it matched the ID mov ax,word ptr [NodeHtoMatch] ; now check the Host cmp ax,word ptr [si.LogoutNote.NodeH] jne @F mov ax,word ptr [NodeHtoMatch+2] cmp ax,word ptr [si.LogoutNote.NodeH+2] jne @F mov ax,word ptr [NodeLtoMatch] cmp ax,word ptr [si.LogoutNote.NodeL] jne @F cmp [CommentType],0400h ;logout note? je FoundLogout mov DoneHere,1 jmp @F FoundLogout: mov al,' ' stosb mov al,'-' stosb mov al,' ' stosb lea si,TimeStamp lodsb ;get year mov ah,al cmp al,99 ja Is20 mov al,'1' stosb mov al,'9' stosb jmp Not19 Is20: mov al,'2' stosb mov al,'0' stosb Not19: mov al,ah xor ah,ah aam or ax,03030h xchg al,ah stosw mov al,' ' stosb lodsb ;get month dec al xor ah,ah lea si,Months add si,ax shl ax,1 add si,ax lodsb stosb lodsb stosb lodsb stosb mov al,' ' stosb mov si,offset TimeStamp + 2 lodsb ;get day aam or ax,03030h xchg al,ah stosw mov al,' ' stosb lodsb ;get hour aam or ax,03030h xchg al,ah stosw mov al,':' stosb lodsb ;get minute aam or ax,03030h xchg al,ah stosw call FileGotoMark clc jmp OuttaHere @@: cmp DoneHere,1 jne BLoop call FileGotoMark stc OuttaHere: ret FindLogout endp ;----------------------------------------------------------------------- ;Given: ; ES:DI =place to put it ;Returns: ;----------------------------------------------------------------------- Bin2Hex proc USES bx cx dx mov dx,ax mov cx,4 xchg al,ah lea bx,HexTable shr al,cl xlat stosb mov ax,dx xchg al,ah and al,0Fh xlat stosb mov ax,dx clc shr al,cl xlat stosb mov ax,dx and al,0Fh xlat stosb ret Bin2Hex endp ;----------------------------------------------------------------------- ;Given: ;Returns: ;----------------------------------------------------------------------- CheckCmdLine proc USES ds mov ah,062h ;Get PSP int 21h mov ds,bx mov si,80h lodsb ;get the # of characters in cmdline mov cl,al xor ch,ch jcxz OuttaHere1 jmp CLoop OuttaHere1: jmp OuttaHere CLoop: lodsb cmp al,0Dh ;end of line? je OuttaHere1 cmp al,' ' jne @F ;skip over spaces loop CLoop jmp OuttaHere @@: cmp al,'-' ;check if a dash option jne NoDash dec cx jcxz ShowUsage lodsb cmp al,'h' jne @F jmp ShowUsage @@: cmp al,'f' ; file option ? jne @F jmp FileOption @@: cmp al,'v' ; version option? jne @F jmp VersionOption @@: cmp al,'w' ; warranty option? jne @F jmp WarrantyOption @@: mov ax,seg DGROUP mov ds,ax mov ah,40h mov bx,1 mov cx,LENGTHOF IllegalOption lea dx,IllegalOption int 21h ShowUsage: mov ax,seg DGROUP mov ds,ax mov ah,40h mov bx,1 mov cx,LENGTHOF Usage lea dx,Usage int 21h .EXIT 2 WarrantyOption: mov ax,seg DGROUP mov ds,ax mov ah,9 lea dx,Warranty int 21h .EXIT 0 VersionOption: mov ax,seg DGROUP mov ds,ax mov ah,40h mov bx,1 mov cx,LENGTHOF RcsId lea dx,RcsId int 21h .EXIT 0 FileOption: lea di,FileName @@: dec cx ;check to make sure there are more characters jcxz ShowUsage lodsb cmp al,' ' je @B @@: call CapAL stosb lodsb dec cx cmp al,' ' je @F cmp al,Ascii_CR je @F jcxz OuttaHere jmp @B @@: mov al,0 stosb jcxz OuttaHere jmp CLoop NoDash: lea di,NameToMatch @@: inc es:[NameToMatchLength] call CapAL stosb lodsb cmp al,' ' je @F cmp al,Ascii_CR je @F loop @B @@: mov al,0 stosb OuttaHere: ret CheckCmdLine endp ;----------------------------------------------------------------------- ;Given: ;Returns: ;----------------------------------------------------------------------- ObjectID2Name proc USES ax si di mov ax,word ptr [ClientID] mov word ptr [GetName_req.ObjectID],ax mov ax,word ptr [ClientID+2] mov word ptr [GetName_req.ObjectID+2],ax mov ah,0E3h xor al,al lea si,GetName_req lea di,GetName_rep int 21h cmp al,0 je OuttaHere cmp al,0FCh ; no such object? jne @F lea di,GetName_rep.ObjectName mov al,'0' stosb mov al,'x' stosb mov ax,word ptr [ClientID+2] call Bin2Hex mov ax,word ptr [ClientID] call Bin2Hex jmp OuttaHere @@: mov ah,40h mov bx,1 mov cx,LENGTHOF ErrorWithObject lea dx,ErrorWithObject int 21h .EXIT 4 OuttaHere: ret ObjectID2Name endp CapAL proc cmp al,'a' jb @F cmp al,'z' ja @F and al,0DFh ;capitalize it @@: ret CapAL endp END