; ; chmod.asm ; Written: Jan/14/87 by SDB ; Copyright (c) 1987 by Scott Ballantyne. ; ; This program may be freely distributed. Improvements are welcome, ; but any code based on this program can never become proprietary. ; You are welcome to use, improve, and distribute this program. ; You are forbidden to prevent anyone else from using, improving, ; or distributing this program. ; ; Another Contribution to the holy cause of replacing ADOS commands. ; This comes in at 588 bytes, using the manx assembler. As usual, ; using metacomposts assembler should shave about 72 bytes away. ; The BCPL version is 1092 bytes. ; This is a replacement for Protect, which is based on the Un*x ; chmod command. ; Syntax is: ; ; Chmod [operand] [permissions] file(s) ; ; Operand must be given, and is one of '+' '-' or '='. ; Permissions are optional. If given must follow immediately with ; no intervening whitespace. ; i.e. +rwed or -red or =rwed. ; files are any file names - multiple filenames may be given. Aside ; from convenience, this allows shell programs to expand wild carded ; names. You can use spaces as delimiters, or quotes - your choice. ; ; Here is how it works: ; + will add the permissions following to the file(s). No other ; permissions are affected. ; - will add remove the permissions following from the file(s). No other ; permissions are affected ; = sets permissions absolutely - only the permissions given in the ; command line will be allowed. ; ; Chmod +r file1 file2 file3 ; Will allow reading for file1 file2 file3 without changing any other ; permission. ; Chmod -rwe file1 file2 file3 ; Will disallow reading writing and executing for file1 file2 and file3 ; without affecting anyother permissions. ; Chmod =r file1 file2 file3 ; File1 file2 and file3 permissions are set absolutely to r(ead) only. ; All other permissions are disallowed. ; ; Differences from the UN*X: ; ; Only the symbolic rwed characters are accepted - no octal digits. ; Won't accept multiple permissions separated by comma's. I.E. ; under un*x you can ; Chmod a-x,g-r file(s) ; but not in this version. Didn't seem needed here, since there is ; only one owner of a file. Easily added if turns out to be a need ; for it. ; Files are pushed on the stack, and so are processed in reverse order ; of entry. ; LIBRARY_VERSION equ 31 _AbsExecBase equ 4 _LVOOpenLibrary equ -552 _LVOCloseLibrary equ -414 _LVOFreeMem equ -210 _LVOAllocMem equ -198 _LVOSetProtection equ -186 _LVOExamine equ -102 _LVOUnLock equ -90 _LVOLock equ -84 _LVOOutput equ -60 _LVOWrite equ -48 FIB_SIZE equ 260 ; size of struct fib fib_Protection equ 116 ; offset to protection var EXCLUSIVE_LOCK equ -1 entry Start rts Start: move.l sp,a5 ; save stack pointer. move.l a0,a2 ; move ptr to args move.l #20,d4 ; set error move.l _AbsExecBase,a6 move.l #FIB_SIZE,d0 ; get a fib moveq.l #0,d1 ; anywhere jsr _LVOAllocMem(a6) tst.l d0 beq.s gone move.l d0,a4 move.l #LIBRARY_VERSION,d0 lea DOSName(pc),a1 jsr _LVOOpenLibrary(a6) tst.l d0 beq.s nodos move.l d0,a6 moveq.l #0,d6 ; clear permissions sbl: move.b (a2)+,d7 ; skip blanks cmp.b #' ',d7 beq.s sbl move.l #'-+=',d5 oploop: cmp.b d5,d7 beq.s getp lsr.l #8,d5 bne.s oploop move.b #'=',d7 ; set default operator subq.l #1,a2 ; unget a character getp: move.b (a2)+,d0 cmp.b #$0a,d0 beq.s usage cmp.b #' ',d0 bne.s lab cmp.b #'=',d7 ; missing permissions only make sense with = bne.s done ; subtract nothing, add nothing move.b #$00,d6 ; After this is inverted, it will disallow bra.s files ; all permissions. lab: and.b #$5f,d0 moveq.l #0,d3 ; permission bit number moveq.l #1,d4 ; permission bit mask move.l #'RWED',d5 ; permission symbols lab1: cmp.b d5,d0 beq.s gotit addq.b #1,d3 ; up the stakes lsr.l #8,d5 ; shift next character in bne.s lab1 ; check next bra.s usage ; ah oh. gotit: asl.l d3,d4 ; calc permission or.l d4,d6 move.b (a2)+,d0 ; get another character cmp.b #$0a,d0 beq.s usage cmp.b #' ',d0 bne.s lab files: clr.l -(sp) ; push a NULL subq.l #1,a2 ; unget a character getfiles: move.b #' ',d1 skipbl: move.b (a2)+,d0 cmp.b d1,d0 beq.s skipbl cmp.b #$0a,d0 beq.s gotfiles move.l a2,-(sp) ; push pointer on the stack cmp.b #'"',d0 bne.s notq move.b d0,d1 ; stuff quote bra.s null notq: subq.l #1,(sp) ; move pointer back to start of filename null: move.b (a2)+,d0 cmp.b #$0a,d0 beq.s zap cmp.b d1,d0 bne.s null zap: clr.b -1(a2) ; zap cmp.b #$0a,d0 bne.s getfiles ; ; Got the files, now get on with the show ; gotfiles: tst.l (sp) ; Did we get a filename? beq.s usage ; no files.... cmp.b #'-',d7 ; need to flip bits? beq.s main eor.b #$0f,d6 ; + = need to be inverted. main: move.l (sp)+,a3 ; get pointer to filename cmp.l #0,a3 beq.s done cmp.b #'=',d7 ; is it absolute? bne.s longway ; go longway around move.l d6,d2 bra.s dothedeed ; ; get current permission ; longway: move.l a3,d1 ; filename move.l #EXCLUSIVE_LOCK,d2 jsr _LVOLock(a6) tst.l d0 beq.s warn ; warning, then back to main ok: move.l d0,d5 ; save lock so we can free later move.l d0,d1 move.l a4,d2 ; fib pointer jsr _LVOExamine(a6) ; file in fib move.l d0,d2 ; save return code move.l d5,d1 jsr _LVOUnLock(a6) tst.l d0 beq.s warn ; warning, then back to main okok: move.l fib_Protection(a4),d2 cmp.b #'+',d7 ; set or clear dem bits bne.s orem and.b d6,d2 bra.s dothedeed orem: or.b d6,d2 dothedeed: move.l a3,d1 ; filename jsr _LVOSetProtection(a6) tst.l d0 bne.s main ; if ok, loop, otherwise, fall through to ; ; print warning message, and loop back to main. ; warn: lea warning(pc),a0 bsr.s writeout move.l a3,a0 ; current filename to a0 bsr.s writeout ; write filename lea lf(pc),a0 bsr.s writeout ; linefeed and return to caller bra.s main ; and loop back to main ; ; Some body did something wrong, so give them a usage message. ; usage: lea usemsg(pc),a0 bsr.s writeout moveq.l #0,d4 ; set return code and fall through to done. ; ; done - enter with d4 = return code. ; Deallocate resources, and exit. ; done: ; Enter here if got FIB and Doslib ok. ; move.l a6,a1 move.l _AbsExecBase,a6 jsr _LVOCloseLibrary(a6) nodos: ; ; Enter here if FIB but no dos move.l a4,a1 move.l #FIB_SIZE,d0 jsr _LVOFreeMem(a6) ; ; Enter here if everything went wrong ; gone: move.l a5,sp ; restore stack pointer move.l d4,d0 ; set return code rts ; ; ; enter with pointer to null terminated string in A0 ; Trashes d0-d3/a0 writeout: move.l a0,d2 ; set string pointer for Write() move.l #-1,d3 cnt: addq.l #1,d3 tst.b (a0)+ bne.s cnt jsr _LVOOutput(a6) move.l d0,d1 jmp _LVOWrite(a6) usemsg: dc.b "Usage: chmod [=] [+] [-] [r][w][e][d] file(s)",10,0 warning: dc.b "Can't change permission(s) for '",0 lf: dc.b "'.",10,0 DOSName: dc.b "dos.library",0