1 ; **************************************************************************** 2 ; rm8086.s (rm0.asm) - by Erdogan Tan - 25/04/2022 3 ; ---------------------------------------------------------------------------- 4 ; Retro UNIX 8086 v1 - remove -- remove (unlink/delete) file(s) 5 ; 6 ; [ Last Modification: 28/04/2022 ] 7 ; 8 ; Derived from (original) UNIX v7 (& v7 x86) 'rm.c' source Code 9 ; Ref: 10 ; www.tuhs.org (https://minnie.tuhs.org) 11 ; v7.tar.gz 12 ; **************************************************************************** 13 ; [ v7.tar - usr/src/cmd/rm.c (archive date: 10-1-1979) ] 14 ; 15 ; Assembler: NASM v2.15 16 ; ((nasm rm8086.s -l rm8086.txt -o rm8086.bin -Z error.txt)) 17 ; 18 ; rm8086.s - 28/04/2022 - Retro UNIX 8086 v1 (16 bit 'rm0.s') 19 ; rm0.s - 27/04/2022 - Retro UNIX 386 v1 20 ; rm1.s - 27/04/2022 - Retro UNIX 386 v1.1 21 ; rm2.s - 27/04/2022 - Retro UNIX 386 v1.2 (modified unix v7 inode) 22 23 ; 12/01/2022 (Retro UNIX 386 v1.2) 24 ; 13/10/2015 25 26 ; UNIX v1 system calls 27 _rele equ 0 28 _exit equ 1 29 _fork equ 2 30 _read equ 3 31 _write equ 4 32 _open equ 5 33 _close equ 6 34 _wait equ 7 35 _creat equ 8 36 _link equ 9 37 _unlink equ 10 38 _exec equ 11 39 _chdir equ 12 40 _time equ 13 41 _mkdir equ 14 42 _chmod equ 15 43 _chown equ 16 44 _break equ 17 45 _stat equ 18 46 _seek equ 19 47 _tell equ 20 48 _mount equ 21 49 _umount equ 22 50 _setuid equ 23 51 _getuid equ 24 52 _stime equ 25 53 _quit equ 26 54 _intr equ 27 55 _fstat equ 28 56 _emt equ 29 57 _mdate equ 30 58 _stty equ 31 59 _gtty equ 32 60 _ilgins equ 33 61 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 62 _msg equ 35 ; Retro UNIX 386 v1 feature only ! 63 _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 64 ; 12/01/2022 - Retro UNIX 386 v1.2 65 ; Retro UNIX 386 v2 system calls 66 _setgid equ 37 67 _getgid equ 38 68 _sysver equ 39 ; (get) Retro Unix 386 version 69 70 ;;; 71 ESCKey equ 1Bh 72 EnterKey equ 0Dh 73 74 ;%macro sys 1-4 75 ; ; 03/09/2015 76 ; ; 13/04/2015 77 ; ; Retro UNIX 386 v1 system call. 78 ; %if %0 >= 2 79 ; mov ebx, %2 80 ; %if %0 >= 3 81 ; mov ecx, %3 82 ; ;%if %0 = 4 83 ; %if %0 >= 4 ; 11/03/2022 84 ; mov edx, %4 85 ; %endif 86 ; %endif 87 ; %endif 88 ; mov eax, %1 89 ; int 30h 90 ;%endmacro 91 92 %macro sys 1-4 93 ; Retro UNIX 8086 v1 system call. 94 %if %0 >= 2 95 mov bx, %2 96 %if %0 >= 3 97 mov cx, %3 98 %if %0 >= 4 99 mov dx, %4 100 %endif 101 %endif 102 %endif 103 mov ax, %1 104 int 20h 105 %endmacro 106 107 ;; Retro UNIX 386 v1 system call format: 108 ;; sys systemcall (eax) , , 109 110 ;; 11/03/2022 111 ;; Note: Above 'sys' macro has limitation about register positions; 112 ;; ebx, ecx, edx registers must not be used after their 113 ;; positions in sys macro. 114 ;; for example: 115 ;; 'sys _write, 1, msg, ecx' is defective, because 116 ;; ecx will be used/assigned before edx in 'sys' macro. 117 ;; correct order may be: 118 ;; 'sys _write, 1, msg, eax ; (eax = byte count) 119 120 ; Retro UNIX 8086 v1 system call format: 121 ; sys systemcall (ax) , , 122 123 ;struc stat 124 ; ; Note: This is for Retro UNIX v1.2 'sysstat' output !!! 125 ; ; (66 bytes) 126 ; .inode: resw 1 127 ; .mode: resw 1 128 ; .nlinks: resw 1 129 ; .uid: resw 1 130 ; .gid: resb 1 131 ; .size_h: resb 1 132 ; .size: resd 1 133 ; .dskptr: resd 10 134 ; .atime: resd 1 135 ; .mtime: resd 1 136 ; .ctime: resd 1 137 ; .strucsize: 138 ;endstruc 139 140 struc stat 141 ; Note: This is for Retro UNIX v1 'sysstat' output !!! 142 ; (34 bytes) 143 00000000 ???? .inode: resw 1 144 00000002 ???? .mode: resw 1 145 00000004 ?? .nlinks: resb 1 146 00000005 ?? .uid: resb 1 147 00000006 ???? .size: resw 1 148 00000008 .dskptr: resw 8 149 00000018 ???????? .ctime: resd 1 150 0000001C ???????? .mtime: resd 1 151 00000020 ???? .rsvd: resw 1 152 .strucsize: 153 endstruc 154 155 ;S_IFMT equ 0F000h ; /* type of file */ 156 ;S_IFDIR equ 04000h ; /* directory */ 157 ;S_IFCHR equ 02000h ; /* character special */ 158 ;S_IFBLK equ 06000h ; /* block special */ 159 ;S_IFREG equ 08000h ; /* regular */ 160 ;S_ISUID equ 00800h ; /* set user id on execution */ 161 ;S_ISGID equ 00400h ; /* set group id on execution */ 162 ;S_IREAD equ 00100h ; /* read permission, owner */ 163 ;S_IWRITE equ 00080h ; /* write permission, owner */ 164 ;S_IEXEC equ 00040h ; /* execute/search permission, owner */ 165 166 ; 24/04/2022 167 ; 21/04/2022 - UNIX v1 inode 168 ; byte 1 169 S_ALLOC equ 080h ; Allocated flag 170 S_IFDIR equ 040h ; Directory flag 171 S_IFMDF equ 020h ; File modified flag (always on) 172 S_IFLRG equ 010h ; Large File flag 173 ; byte 0 174 S_ISUID equ 020h ; Set User ID On Execution flag 175 S_IEXEC equ 010h ; Executable File flag 176 S_IREAD equ 008h ; Owner's Read Permission flag 177 S_IWRITE equ 004h ; Owner's Write Permission flag 178 179 ;BSIZE equ 512 180 181 ;26/04/2022 182 ; Directory entry size 183 DIRSIZ equ 10 ; Retro UNIX 386 v1 184 ;DIRSIZ equ 16 ; Retro UNIX 386 v1.1 & v1.2 185 186 ;----------------------------------------------------------------- 187 ; text - code 188 ;----------------------------------------------------------------- 189 190 ;[BITS 32] ; 32-bit intructions (for 80386 protected mode) 191 [BITS 16] ; 16-bit (x86 real mode) intructions 192 193 [ORG 0] 194 195 START_CODE: 196 ; 28/04/2022 (Real Mode, 16 bit register modification) 197 ; eax, edx, ecx, ebx -> ax, dx, cx, bx 198 ; esi, edi, ebp, esp -> si, di, bp, sp 199 ; register+4 -> register+2 200 ; dword values on stack -> word values on stack 201 ; sys _msg -> call print_msg 202 ; 203 ; 27/04/2022 204 ; 26/04/2022 205 ; 25/04/2022 206 ; main(argc, argv) 207 208 00000000 58 pop ax ; [sp] = argument count 209 ;mov [argc], ax 210 00000001 A2[3F03] mov [argc], al 211 ;dec ax 212 00000004 FEC8 dec al 213 00000006 7529 jnz short rm_0 ; [argc] = 1 214 215 ;sys _msg, program_msg, 255, 0Fh 216 ; 28/04/2022 217 00000008 B8[4303] mov ax, program_msg 218 0000000B E80B00 call print_msg 219 220 rm_usage: 221 ; "Usage: rm [–fri] file ..." 222 ;sys _msg, usage_msg, 255, 07h 223 ; 28/04/2022 224 0000000E B8[7903] mov ax, usage_msg 225 00000011 E80500 call print_msg 226 rm_exit: 227 sys _exit ; sys exit 93 <1> 94 <1> %if %0 >= 2 95 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 00000014 B80100 <1> mov ax, %1 104 00000017 CD20 <1> int 20h 228 ;hlt: 229 ; nop 230 ; nop 231 ; jmp short hlt 232 233 print_msg: 234 ; 28/04/2022 (rm8086.s) 235 ; 22/04/2022 (cp8086.s) 236 ; Modified registers: ax, bx, cx, dx 237 strlen: 238 ; ax = asciiz string address 239 00000019 89C3 mov bx, ax 240 0000001B 4B dec bx 241 nextchr: 242 0000001C 43 inc bx 243 0000001D 803F00 cmp byte [bx], 0 244 00000020 77FA ja short nextchr 245 ;cmp [bx], 0Dh 246 ;ja short nextchr 247 00000022 29C3 sub bx, ax 248 ; bx = asciiz string length 249 ;retn 250 print_str: 251 00000024 89DA mov dx, bx 252 sys _write, 1, ax 93 <1> 94 <1> %if %0 >= 2 95 00000026 BB0100 <1> mov bx, %2 96 <1> %if %0 >= 3 97 00000029 89C1 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 0000002B B80400 <1> mov ax, %1 104 0000002E CD20 <1> int 20h 253 254 00000030 C3 retn 255 256 rm_0: 257 ;if (isatty(0) == 0) 258 ; fflg++; 259 260 ; set '-f' flag if standard input is not a terminal 261 sys _fstat, 0, stbuf 93 <1> 94 <1> %if %0 >= 2 95 00000031 BB0000 <1> mov bx, %2 96 <1> %if %0 >= 3 97 00000034 B9[6604] <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 00000037 B81C00 <1> mov ax, %1 104 0000003A CD20 <1> int 20h 262 ;jc short rm_exit ; 27/04/2022 263 264 ; 25/04/2022 265 ; Retro UNIX v2 inode: 266 ; regular file flag is mode bit 15 267 ; 268 ;test [stbuf+stat.mode+1], S_IFREG 269 ;jz short rm_1 ; device file (terminal/console) 270 271 ;inc byte [fflg] 272 273 ; 25/04/2022 274 ; Retro UNIX v1 inode: 275 ; regular file inode numbers are > 41 276 ; 277 0000003C 833E[6604]29 cmp word [stbuf+stat.inode], 41 278 00000041 7604 jna short rm_1 ; device file (or root dir?) 279 280 ; (if standard input is not a terminal) 281 ; force removing (without question and 'y' answer) 282 00000043 FE06[4003] inc byte [fflg] 283 rm_1: 284 ;if(argc>1 && argv[1][0]=='-') { 285 ; arg = *++argv; 286 ; argc--; 287 ; 288 289 00000047 89E5 mov bp, sp ; 26/04/2022 290 00000049 5E pop si ; argv[0] ; executable file name (='rm') 291 ;;mov [argv], sp 292 ;mov esi, [esp] ; 26/04/2022 293 ; argv[1] ; option (if it is used) 294 ; 28/04/2022 295 0000004A 5E pop si ; == mov si, [sp] 296 0000004B 56 push si 297 0000004C AC lodsb 298 0000004D 3C2D cmp al, '-' 299 0000004F 7534 jne short rm_2 300 00000051 89E5 mov bp, sp ; 26/04/2022 301 00000053 FE0E[3F03] dec byte [argc] ; ARGC - 2 302 rm_28: 303 00000057 AC lodsb 304 00000058 A8FF test al, 0FFh 305 0000005A 7429 jz short rm_2 306 307 ;while(*++arg != '\0') 308 ; switch(*arg) { 309 ; case 'f': 310 ; fflg++; 311 ; break; 312 ; case 'i': 313 ; iflg++; 314 ; break; 315 ; case 'r': 316 ; rflg++; 317 ; break; 318 ; default: 319 ; printf("rm: unknown option %s\n", *argv); 320 ; exit(1); 321 ; } 322 323 0000005C 3C66 cmp al, 'f' 324 0000005E 7419 je short rm_1_f 325 00000060 3C69 cmp al, 'i' 326 00000062 741B je short rm_1_i 327 00000064 3C72 cmp al, 'r' 328 00000066 740B je short rm_1_r 329 rm_1_uop: 330 ; "rm: unknown option '-x'" 331 00000068 A2[AF03] mov [uop], al 332 ; 28/04/2022 333 0000006B B8[9903] mov ax, unk_op_msg 334 0000006E E8A8FF call print_msg 335 ; (exit code is not used in current Retro UNIX version) 336 ;sys _exit, 1 ; (bx = exit code = 1) 337 00000071 EBA1 jmp short rm_exit 338 rm_1_r: 339 00000073 FE06[4203] inc byte [rflg] ; rflg++; 340 ;jmp short rm_2 341 ; 27/04/2022 342 00000077 EBDE jmp short rm_28 ; get next option char 343 rm_1_f: 344 00000079 FE06[4003] inc byte [fflg] ; fflg++; 345 ;jmp short rm_2 346 ; 27/04/2022 347 0000007D EBD8 jmp short rm_28 ; get next option char 348 rm_1_i: 349 0000007F FE06[4103] inc byte [iflg] ; iflg++ 350 ; 27/04/2022 351 00000083 EBD2 jmp short rm_28 ; get next option char 352 rm_2: 353 ;while(--argc > 0) { 354 ; if(!strcmp(*++argv, "..")) { 355 ; fprintf(stderr, "rm: cannot remove `..'\n"); 356 ; continue; 357 ; } 358 ; rm(*argv, fflg, rflg, iflg, 0); 359 ;} 360 361 00000085 FE0E[3F03] dec byte [argc] 362 00000089 741C jz short rm_4 363 364 ;add word ptr [argv], 4 ; ++argv 365 ;mov si, [argv] 366 0000008B 83C502 add bp, 2 ; ++argv 367 0000008E 8B7600 mov si, [bp] 368 00000091 813C2E2E cmp word [si], '..' ; strcmp(*++argv, "..") 369 00000095 740A je short rm_3 370 ; rm(*argv, fflg, rflg, iflg, 0); 371 00000097 C606[8804]00 mov byte [level], 0 372 0000009C E81100 call remove_file 373 0000009F EBE4 jmp short rm_2 374 rm_3: 375 ; "rm: cannot remove '..'" 376 ; 28/04/2022 377 000000A1 B8[B303] mov ax, cnr_dotdot_msg 378 000000A4 E872FF call print_msg 379 rm_4: 380 ; (exit code not used in Retro UNIX 386 v1 & v1.1) 381 ;sys _exit, [errcode] 382 sys _exit 93 <1> 94 <1> %if %0 >= 2 95 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 000000A7 B80100 <1> mov ax, %1 104 000000AA CD20 <1> int 20h 383 ;hang: 384 ; jmp short hang 385 386 _return: 387 ; 27/04/2022 388 000000AC 89EC mov sp, bp ; add sp, 80 (add sp, 100) 389 000000AE 5D pop bp 390 391 000000AF C3 retn 392 393 remove_file: 394 ; rm(arg, fflg, rflg, iflg, level) 395 396 ; 28/04/2022 (16 bit registers) 397 ; 27/04/2022 398 ; 26/04/2022 399 ; modified registers: ax, bx, cx, dx, di 400 401 ; INPUT: 402 ; si = *argv ; [level] = 0 403 ; or si = namebuf ; [level] > 0 -- 404 ; byte [fflg], [rflg], [iflg] 405 ; byte [level] = sub directory level 406 407 ;if(stat(arg, &buf)) { 408 ; if (fflg==0) { 409 ; printf("rm: %s nonexistent\n", arg); 410 ; ++errcode; 411 ; } 412 ; return; 413 ;} 414 415 ; 27/04/2022 416 000000B0 55 push bp 417 000000B1 89E5 mov bp, sp 418 ;sub sp, 100 ; char name[100]; 419 000000B3 83EC50 sub sp, 80 ; Retro UNIX 8086 v1 (& 386 v1) 420 421 sys _stat, si, stbuf 93 <1> 94 <1> %if %0 >= 2 95 000000B6 89F3 <1> mov bx, %2 96 <1> %if %0 >= 3 97 000000B8 B9[6604] <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 000000BB B81200 <1> mov ax, %1 104 000000BE CD20 <1> int 20h 422 000000C0 731A jnc short rm_5 423 424 000000C2 803E[4003]00 cmp byte [fflg], 0 425 000000C7 77E3 ja short _return 426 427 ; "rm: non existent" 428 ; 28/04/2022 429 000000C9 B8[CE03] mov ax, rm_hdr_msg 430 000000CC E84AFF call print_msg 431 000000CF 89F0 mov ax, si 432 000000D1 E845FF call print_msg 433 000000D4 B8[D503] mov ax, nonex_msg 434 000000D7 E83FFF call print_msg 435 436 ;inc word [errcode] ; ++errcode; 437 438 000000DA EBD0 jmp short _return 439 rm_5: 440 ;if ((buf.st_mode&S_IFMT) == S_IFDIR) { 441 ; if(rflg) { 442 443 ; Retro UNIX 386 v2 inode 444 ;mov al, [stbuf+stat.mode+1] 445 ;and al, S_IFREG | S_IFDIR 446 ;cmp al, S_IFREG | S_IFDIR 447 ;;jne short rm_17 448 ; 27/04/2022 449 ;je short rm_24 450 ;jmp rm_17 451 452 ; Retro UNIX 386 v1 (unix v1) inode 453 000000DC F606[6904]40 test byte [stbuf+stat.mode+1], S_IFDIR 454 ;jz short rm_17 455 ; 26/04/2022 456 000000E1 7503 jnz short rm_24 457 000000E3 E9EE00 jmp rm_17 458 rm_24: 459 ; Directory ! ('-r' option is required) 460 461 ;if(rflg) { ... 462 ; .... 463 ;} 464 ;printf("rm: %s directory\n", arg); 465 ; ++errcode; 466 ; return; 467 468 000000E6 803E[4203]00 cmp byte [rflg], 0 469 000000EB 7665 jna short rm_9 ; 28/04/2022 470 ; 26/04/2022 471 ;ja short rm_25 472 ;jmp rm_9 473 474 rm_25: 475 ;if (access(arg, 02) < 0) { 476 ; if (fflg==0) 477 ; printf("%s not changed\n", arg); 478 ; errcode++; 479 ; return; 480 ;} 481 482 ; dl = permission/mode value 483 ; (dl = 2 for Retro UNIX 386 v2 inode) 484 ; (dl = 1 for Retro UNIX 386 v1 inode) 485 486 ;;mov dl, 2 487 ;mov dl, 1 488 489 000000ED E87801 call access 490 000000F0 731A jnc short rm_7 491 492 000000F2 803E[4003]00 cmp byte [fflg], 0 493 000000F7 7711 ja short rm_6 494 495 ; si = arg = *[argv] 496 497 ; " not changed" 498 ;sys _msg, nextline, 255, 07h 499 ;sys _msg, si, 255, 07h 500 ;sys _msg, nchd_msg, 255, 07h 501 ; 28/04/2022 502 000000F9 B8[9603] mov ax, nextline 503 000000FC E81AFF call print_msg 504 000000FF 89F0 mov ax, si 505 00000101 E815FF call print_msg 506 00000104 B8[E403] mov ax, nchd_msg 507 00000107 E80FFF call print_msg 508 rm_6: 509 ;inc word [errcode] ; ++errcode; 510 0000010A EBA0 jmp _return ; return; 511 rm_7: 512 ;if(iflg && level!=0) { 513 ; printf("directory %s: ", arg); 514 ; if(!yes()) 515 ; return; 516 ;} 517 518 0000010C 803E[4103]00 cmp byte [iflg], 0 519 00000111 761D jna short rm_8 520 00000113 803E[8804]00 cmp byte [level], 0 521 00000118 7616 jna short rm_8 522 523 ;"directory : ? " 524 ;sys _msg, dir_hdr_msg, 255, 07h ; message row header 525 ;sys _msg, si, 255, 07h ; directory name 526 ;sys _msg, qu_msg, 255, 07h ; question 527 ; 28/04/2022 528 0000011A B8[F303] mov ax, dir_hdr_msg 529 0000011D E8F9FE call print_msg 530 00000120 89F0 mov ax, si 531 00000122 E8F4FE call print_msg 532 00000125 B8[0004] mov ax, qu_msg 533 00000128 E8EEFE call print_msg 534 535 ; get user input (answer) 536 ; and write it (as answer) via sysmsg system call 537 0000012B E85401 call ifyes 538 0000012E 72DA jc short rm_6 ; no 539 ; yes 540 rm_8: 541 ;if((d=open(arg, 0)) < 0) { 542 ; printf("rm: %s: cannot read\n", arg); 543 ; exit(1); 544 ;} 545 546 sys _open, si, 0 ; open directory for read 93 <1> 94 <1> %if %0 >= 2 95 00000130 89F3 <1> mov bx, %2 96 <1> %if %0 >= 3 97 00000132 B90000 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 00000135 B80500 <1> mov ax, %1 104 00000138 CD20 <1> int 20h 547 0000013A 732A jnc short rm_10 ; 28/04/2022 548 ; 26/04/2022 549 ;jc short rm_26 550 ;jmp rm_10 551 rm_26: 552 ;"rm: : cannot read" 553 ;sys _msg, rm_hdr_msg, 255, 07h ; msg row header 554 ;sys _msg, si, 255, 07h ; directory name 555 ;sys _msg, cnr_msg, 255, 07h ; 'cannot read' 556 ; 28/04/2022 557 0000013C B8[CE03] mov ax, rm_hdr_msg 558 0000013F E8D7FE call print_msg 559 00000142 89F0 mov ax, si 560 00000144 E8D2FE call print_msg 561 00000147 B8[1004] mov ax, cnr_msg 562 0000014A E8CCFE call print_msg 563 564 ; (exit code not used in Retro UNIX 386 v1 & v1.1) 565 ;sys _exit, 1 ; (bx = exit code = 1) 566 sys _exit 93 <1> 94 <1> %if %0 >= 2 95 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 0000014D B80100 <1> mov ax, %1 104 00000150 CD20 <1> int 20h 567 ;here: 568 ; jmp short here 569 570 rm_9: 571 ;printf("rm: %s directory\n", arg); 572 ; ++errcode; 573 ; return; 574 575 ; "rm: directory" 576 00000152 B8[CE03] mov ax, rm_hdr_msg 577 00000155 E8C1FE call print_msg 578 00000158 89F0 mov ax, si 579 0000015A E8BCFE call print_msg 580 0000015D B8[2004] mov ax, dir_msg 581 00000160 E8B6FE call print_msg 582 583 ;inc word [errcode] ; ++errcode; 584 585 00000163 E946FF jmp _return ; return; 586 587 rm_10: 588 ;while(read(d, (char *)&direct, sizeof(direct)) == sizeof(direct)) { 589 ; if(direct.d_ino != 0 && !dotname(direct.d_name)) { 590 ; sprintf(name, "%s/%.14s", arg, direct.d_name); 591 ; rm(name, fflg, rflg, iflg, level+1); 592 ; } 593 ;} 594 ; 595 ;close(d); 596 ;errcode += rmdir(arg, iflg); 597 ;return; 598 599 ; 26/04/2022 600 00000166 A3[5A04] mov [_d_], ax ; file (directory) descriptor 601 rm_29: 602 sys _read, [_d_], direct, DIRSIZ 93 <1> 94 <1> %if %0 >= 2 95 00000169 8B1E[5A04] <1> mov bx, %2 96 <1> %if %0 >= 3 97 0000016D B9[5C04] <1> mov cx, %3 98 <1> %if %0 >= 4 99 00000170 BA0A00 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 00000173 B80300 <1> mov ax, %1 104 00000176 CD20 <1> int 20h 603 00000178 724B jc short rm_15 604 0000017A 83F80A cmp ax, DIRSIZ ; 16 (runix v1.1&v1.2) or 10 (runix v1) 605 0000017D 7246 jb short rm_15 ; (jne short rm_14) 606 607 ; 27/04/2022 608 ; if(direct.d_ino != 0 .. 609 0000017F 833E[5C04]00 cmp word [direct], 0 ; is inode number > 0 ? 610 00000184 76E3 jna short rm_29 ; no ; read next direntry ; 27/04/2022 611 ; yes 612 ; && !dotname(direct.d_name)) 613 00000186 BB[5E04] mov bx, direct+2 614 00000189 E81E01 call isdotname 615 0000018C 74DB jz short rm_29 ; '.' or '..' 616 ; read next direntry ; 27/04/2022 617 618 ; sprintf(name, "%s/%.14s", arg, direct.d_name); 619 ; 27/04/2022 620 0000018E 89E7 mov di, sp ; name ; 80 byte frame on stack 621 00000190 56 push si ; * ; save si (arg, *argv) 622 ; 28/04/2022 623 00000191 57 push di ; ** 624 rm_11: 625 00000192 AC lodsb 626 00000193 08C0 or al, al 627 00000195 7403 jz short rm_12 ; (end of the path) 628 00000197 AA stosb 629 00000198 EBF8 jmp short rm_11 630 rm_12: 631 ; add file name to the path 632 0000019A B02F mov al, '/' 633 0000019C AA stosb 634 ;mov cx, 14 ; max. 14 byte file name 635 0000019D B90800 mov cx, DIRSIZ-2 ; 8 ; 28/04/2022 636 000001A0 BE[5E04] mov si, direct+2 ; direct.d_name 637 rm_13: 638 000001A3 AC lodsb 639 000001A4 AA stosb 640 000001A5 08C0 or al, al 641 000001A7 7405 jz short rm_14 ; end of the (full) path 642 000001A9 E2F8 loop rm_13 643 ; 28/04/2022 644 000001AB C60500 mov byte [di], 0 645 rm_14: 646 ; rm(name, fflg, rflg, iflg, level+1); 647 ; 28/04/2022 (Retro UNIX 8086 v1) 648 ; 27/04/2022 649 ;lea esi, [esp+4] ; path name buffer (stack frame) 650 ; 28/04/2022 651 000001AE 5E pop si ; ** ; == lea si, [sp+2] 652 ; 653 000001AF FF36[5A04] push word [_d_] ; save file (dir) descriptor 654 000001B3 FE06[8804] inc byte [level] 655 000001B7 E8F6FE call remove_file ; ! call itself ! 656 000001BA FE0E[8804] dec byte [level] ; (this may not be necessary) 657 000001BE 8F06[5A04] pop word [_d_] ; restore file (dir) descriptor 658 000001C2 5E pop si ; * ; restore si (arg, *argv) 659 000001C3 EBA4 jmp short rm_29 660 rm_15: 661 sys _close, [_d_] ; close(d); 93 <1> 94 <1> %if %0 >= 2 95 000001C5 8B1E[5A04] <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 000001C9 B80600 <1> mov ax, %1 104 000001CC CD20 <1> int 20h 662 ; errcode += rmdir(arg, iflg); 663 ; 27/04/2022 664 000001CE E8EC00 call rmdir 665 ;jnc short rm_16 666 ;mov byte [errcode], 1 667 ;---- 668 ;NOTE: 669 ; sysexit error code ((exit(errcode);) 670 ; is not used by current Retro UNIX version 671 ;---- 672 rm_16: ; 27/04/2022 673 000001D1 E9D8FE jmp _return ; return; 674 675 rm_17: 676 ;if(iflg) { 677 ; printf("%s: ", arg); 678 ; if(!yes()) 679 ; return; 680 ;} 681 ;else if(!fflg) { 682 ; if (access(arg, 02)<0) { 683 ; printf("rm: %s %o mode ", arg, buf.st_mode&0777); 684 ; if(!yes()) 685 ; return; 686 ; } 687 ;} 688 ; 689 ;if(unlink(arg) && (fflg==0 || iflg)) { 690 ; printf("rm: %s not removed\n", arg); 691 ; ++errcode; 692 ;} 693 694 ; 26/04/2022 695 000001D4 803E[4103]00 cmp byte [iflg], 0 696 000001D9 763C jna short rm_20 ; 28/04/2022 697 ;ja short rm_27 698 ;jmp rm_20 699 rm_27: 700 ; 28/04/2022 701 000001DB B8[9603] mov ax, nextline ; next (new) line 702 000001DE E838FE call print_msg 703 000001E1 89F0 mov ax, si ; file name 704 000001E3 E833FE call print_msg 705 000001E6 B8[0004] mov ax, qu_msg ; question 706 000001E9 E82DFE call print_msg 707 000001EC E89300 call ifyes ; question 708 000001EF 72E0 jc short rm_16 ; answer = no (not 'y') 709 rm_18: 710 sys _unlink, si 93 <1> 94 <1> %if %0 >= 2 95 000001F1 89F3 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 000001F3 B80A00 <1> mov ax, %1 104 000001F6 CD20 <1> int 20h 711 000001F8 73D7 jnc short rm_16 712 ; 713 000001FA A0[4003] mov al, [fflg] 714 000001FD 0A06[4103] or al, [iflg] 715 00000201 74CE jz short rm_16 716 ; "rm: not removed" 717 ; 28/04/2022 718 00000203 B8[CE03] mov ax, rm_hdr_msg ; header 719 00000206 E810FE call print_msg 720 00000209 89F0 mov ax, si ; file name 721 0000020B E80BFE call print_msg 722 0000020E B8[2B04] mov ax, not_rmd_msg ; 'not removed' 723 00000211 E805FE call print_msg 724 ;---- 725 ;Note: Current Retro UNIX version 726 ; does not use error code return (to parent) 727 ;---- 728 ;inc byte [errcode] 729 ; 27/04/2022 730 00000214 E995FE jmp _return ; return; 731 rm_20: 732 00000217 803E[4003]00 cmp byte [fflg], 0 733 0000021C 77D3 ja short rm_18 734 ; 735 ;if (access(arg, 02)<0) { 736 ; printf("rm: %s %o mode ", arg, buf.st_mode&0777); 737 ; if(!yes()) 738 ; return; 739 ;} 740 ; 741 ;;mov dl, 2 742 ;mov dl, 1 743 0000021E E84700 call access 744 00000221 73CE jnc short rm_18 745 746 ; "rm: _octal_ mode" 747 00000223 31C0 xor ax, ax 748 00000225 31DB xor bx, bx 749 00000227 89E1 mov cx, sp 750 00000229 A1[6804] mov ax, [stbuf+stat.mode] 751 ;and ax, 1FFh ; Retro UNIX 386 v2 inode 752 0000022C 83E01F and ax, 1Fh ; Retro UNIX 386 v1 inode 753 0000022F B308 mov bl, 8 ; divisor for octal number calculation 754 00000231 BF[8904] mov di, octal 755 rm_21: 756 00000234 31D2 xor dx, dx 757 00000236 F7F3 div bx 758 00000238 52 push dx 759 00000239 09C0 or ax, ax 760 0000023B 75F7 jnz short rm_21 761 rm_22: 762 0000023D 58 pop ax 763 0000023E 0430 add al, '0' 764 00000240 AA stosb 765 00000241 39E1 cmp cx, sp 766 00000243 77F8 ja short rm_22 767 00000245 28C0 sub al, al 768 00000247 AA stosb 769 770 ;sys _msg, rm_hdr_msg, 255, 07h ; header 771 ;sys _msg, octal, 255, 07h ; octal mode 772 ;sys _msg, mode_msg, 255, 07h ; ' mode ' 773 ;sys _msg, que_msg, 255, 07h ; question 774 ; 28/04/2022 775 00000248 B8[CE03] mov ax, rm_hdr_msg 776 0000024B E8CBFD call print_msg 777 0000024E B8[8904] mov ax, octal 778 00000251 E8C5FD call print_msg 779 00000254 B8[3A04] mov ax, mode_msg 780 00000257 E8BFFD call print_msg 781 0000025A B8[0104] mov ax, que_msg 782 0000025D E8B9FD call print_msg 783 784 00000260 E81F00 call ifyes ; question 785 ;jc short rm_23 ; answer = no (not 'y') 786 ;jmp rm_18 787 ; 28/04/2022 788 00000263 738C jnc short rm_18 789 rm_23: ; 27/04/2022 790 00000265 E944FE jmp _return ; return; 791 792 access: 793 ; 28/04/2022 (16 bit registers) 794 ; 26/04/2022 795 ; INPUT: 796 ; dl = permission/mode value 797 ; (dl = 2 for Retro UNIX 386 v2 inode) 798 ; (dl = 1 for Retro UNIX 386 v1 inode) 799 ; 800 ; stbuf = status (sysstat output) buffer 801 ; 802 ; OUTPUT: 803 ; cf = 0 -> ok 804 ; cf = 1 -> error (denied) 805 806 ;mov dl, 2 ; retro unix v2 (write permit flag) 807 00000268 B201 mov dl, 1 ; unix v1 (write permit flag) 808 809 0000026A 8A0E[6804] mov cl, [stbuf+stat.mode] ; Retro UNIX 386 v1 810 ;mov cx, [stbuf+stat.mode] ; Retro UNIX 386 v2 811 812 ; Retro UNIX 386 v1.2 (v2) 813 ;sys _getuid ; get user ID of current user 814 ;mov [uid], al ; ax = real user ID (<=255) 815 ;sys _getgid ; get group ID of current user 816 ;mov [gid], al ; al = real group ID (<=255) 817 818 ; Retro UNIX 386 v1 (unix v1) 819 sys _getuid ; get user ID of current user 93 <1> 94 <1> %if %0 >= 2 95 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 0000026E B81800 <1> mov ax, %1 104 00000271 CD20 <1> int 20h 820 ;mov [uid], al ; al = user ID 821 822 ; dl = 2 -> write permission flag (retro unix v2) 823 ; dl = 1 -> write permission flag (retro unix v1) 824 825 ;mov ax, [uid] 826 ;cmp ax, [stbuf+stat.uid] ; Retro UNIX v2 inode 827 00000273 3A06[6B04] cmp al, [stbuf+stat.uid] ; unix v1 828 00000277 7503 jne short access_1 829 830 ;; Retro UNIX 386 v1.2 note: 831 ;; group permission flags will not be used for now! 832 833 ;shr cx, 6 ; Retro UNIX 386 v2 inode flags 834 ; AL bit 1 -> write permission owner 835 836 00000279 C0E902 shr cl, 2 ; Retro UNIX 386 v1 inode flags 837 ; AL bit 0 -> write permission owner 838 access_1: 839 0000027C 20D1 and cl, dl 840 0000027E 7501 jnz short access_2 841 00000280 F9 stc 842 access_2: 843 00000281 C3 retn 844 845 ifyes: 846 ; 28/04/2022 847 ; 26/04/2022 848 ; check user input as yes or no 849 ; write answer and return with carry if it is 'no' 850 sys _read, 0, chr, 1 ; read standard input 93 <1> 94 <1> %if %0 >= 2 95 00000282 BB0000 <1> mov bx, %2 96 <1> %if %0 >= 3 97 00000285 B9[8D04] <1> mov cx, %3 98 <1> %if %0 >= 4 99 00000288 BA0100 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 0000028B B80300 <1> mov ax, %1 104 0000028E CD20 <1> int 20h 851 00000290 A0[8D04] mov al, [chr] 852 00000293 3C79 cmp al, 'y' 853 00000295 740C je short ifyes_yes 854 00000297 3C59 cmp al, 'Y' 855 00000299 7408 je short ifyes_yes 856 ; another character means 'no' 857 ifyes_no: 858 ; write 'no' 859 ;sys _msg, no_msg, 255, 07h ; 'no' answer 860 0000029B B8[0B04] mov ax, no_msg 861 0000029E E878FD call print_msg 862 000002A1 F9 stc 863 000002A2 C3 retn ; return 864 ifyes_yes: 865 ; write 'yes' 866 ;sys _msg, yes_msg, 255, 07h ; 'yes' answer 867 000002A3 B8[0504] mov ax, yes_msg 868 000002A6 E870FD call print_msg 869 ;clc 870 000002A9 C3 retn 871 872 ;isdotname: 873 ; 27/04/2022 874 ; 26/04/2022 875 ; check if file name is dot ('.') or dotdot ('..') 876 ; (return: zf=1 if it is dot or dotdot) 877 ;mov ax, [direct+2] ; 1st 2 chars of file name 878 isdotname: 879 ; bx = file (or directory) name address 880 000002AA 8B07 mov ax, [bx] 881 000002AC 3C2E cmp al, '.' 882 000002AE 750C jne short isdot_retn 883 000002B0 08E4 or ah, ah ; 0 ? 884 000002B2 7408 jz short isdot_retn ; '.' 885 000002B4 38E0 cmp al, ah ; '..' ? 886 ; 27/04/2022 887 000002B6 7504 jne short isdot_retn 888 000002B8 807F0200 cmp byte [bx+2], 0 889 ; zf = 1 if it is dotdot 890 isdot_retn: 891 000002BC C3 retn 892 893 rmdir: 894 ; 28/04/2022 (16 bit registers) 895 ; 26/04/2022 896 ; INPUT: 897 ; si = directory name address (*argv) 898 ; [iflg] = interactive option 899 ; 900 ; OUTPUT: 901 ; none 902 903 ;rmdir(f, iflg) 904 ;char *f; 905 ;{ 906 ; int status, i; 907 ; 908 ; if(dotname(f)) 909 ; return(0); 910 ; if(iflg) { 911 ; printf("%s: ", f); 912 ; if(!yes()) 913 ; return(0); 914 ;} 915 916 000002BD 89F3 mov bx, si 917 000002BF E8E8FF call isdotname 918 000002C2 742C jz short rmdir_retn 919 920 000002C4 803E[4103]01 cmp byte [iflg], 1 921 000002C9 7216 jb short rmdir_1 922 923 ;sys _msg, dir_hdr_msg, 255, 07h ; message row header 924 ;sys _msg, si, 255, 07h ; directory name 925 ;sys _msg, qu_msg, 255, 07h ; question 926 ; 28/04/2022 927 000002CB B8[F303] mov ax, dir_hdr_msg 928 000002CE E848FD call print_msg 929 000002D1 89F0 mov ax, si 930 000002D3 E843FD call print_msg 931 000002D6 B8[0004] mov ax, qu_msg 932 000002D9 E83DFD call print_msg 933 934 000002DC E8A3FF call ifyes ; question 935 000002DF 720F jc short rmdir_retn ; answer = no (not 'y') 936 rmdir_1: 937 ;while((i=fork()) == -1) 938 ; sleep(3); 939 ;if(i) { 940 ; wait(&status); 941 ; return(status); 942 ;} 943 944 000002E1 BB[F102] mov bx, rmdir_2 ; ! Retro UNIX feature only ! 945 ; 'rmdir' child will continue from 946 sys _fork 93 <1> 94 <1> %if %0 >= 2 95 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 000002E4 B80200 <1> mov ax, %1 104 000002E7 CD20 <1> int 20h 947 000002E9 7205 jc short rmdir_retn 948 949 ; parent process will continue to run from here 950 ; (from 'jc' after 'sys _fork') 951 952 ; ax = child process ID 953 954 ; ---- 955 ; Note: Current Retro Unix version does not use 956 ; status return -exit code from the child- 957 ; ---- 958 959 sys _wait ; wait untill the child exits 93 <1> 94 <1> %if %0 >= 2 95 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 000002EB B80700 <1> mov ax, %1 104 000002EE CD20 <1> int 20h 960 ;jc short rmdir_retn ; 27/04/2022 961 962 ; ax = child process ID -which has been terminated- 963 ; (bx = status -may be used by retro unix later-) 964 965 ; cf = 0 ; return(0) 966 rmdir_retn: 967 ; if cf = 0 -> return(0) 968 ; else (if cf = 1) -> return(1) 969 970 000002F0 C3 retn 971 972 rmdir_2: 973 ; child process will continue to run from here 974 975 ;execl("/bin/rmdir", "rmdir", f, 0); 976 ;execl("/usr/bin/rmdir", "rmdir", f, 0); 977 ;printf("rm: can't find rmdir\n"); 978 ;exit(1); 979 980 ; run 'rmdir' utility/program 981 ; (it will/must not return here) 982 983 ; set directory address as /bin/rmdir argument 1 984 000002F1 8936[1B03] mov [binrmdira1], si 985 ;; set directory addr as /usr/bin/rmdir argument 1 986 ;mov [usrbinrmdira1], si ; ((*)) 987 988 sys _exec, binrmdir, binrmdirp 93 <1> 94 <1> %if %0 >= 2 95 000002F5 BB[2503] <1> mov bx, %2 96 <1> %if %0 >= 3 97 000002F8 B9[1903] <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 000002FB B80B00 <1> mov ax, %1 104 000002FE CD20 <1> int 20h 989 sys _exec, usrbinrmdir, usrbinrmdirp 93 <1> 94 <1> %if %0 >= 2 95 00000300 BB[3003] <1> mov bx, %2 96 <1> %if %0 >= 3 97 00000303 B9[1903] <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 00000306 B80B00 <1> mov ax, %1 104 00000309 CD20 <1> int 20h 990 991 ; ! error ! 992 ; if sysexec fails (would fail) to run 'rmdir' 993 ; cpu will return here 994 995 ; "rm: can't find rmdir" 996 ;sys _msg, cnf_rd_msg, 255, 07h 997 ; 28/04/2022 998 0000030B B8[4004] mov ax, cnf_rd_msg 999 0000030E E808FD call print_msg 1000 1001 ; bx = exit code (if there is an error, it is > 0) 1002 ;sys _exit, 1 1003 sys _exit ; Current Retro UNIX version 93 <1> 94 <1> %if %0 >= 2 95 <1> mov bx, %2 96 <1> %if %0 >= 3 97 <1> mov cx, %3 98 <1> %if %0 >= 4 99 <1> mov dx, %4 100 <1> %endif 101 <1> %endif 102 <1> %endif 103 00000311 B80100 <1> mov ax, %1 104 00000314 CD20 <1> int 20h 1004 ; does not use exit code from child 1005 hangemhigh: 1006 00000316 90 nop 1007 00000317 EBFD jmp short hangemhigh 1008 1009 ;----------------------------------------------------------------- 1010 ; data - initialized data 1011 ;----------------------------------------------------------------- 1012 1013 ; 28/04/2022 (Retro UNIX 8086 v1) 1014 ; 26/04/2022 1015 1016 binrmdirp: 1017 usrbinrmdirp: 1018 ;dw bindrmdir 1019 00000319 [1F03] dw _rmdir_ 1020 binrmdira1: 1021 usrbinrmdira1: ; ((*)) 1022 0000031B 0000 dw 0 1023 binrmdira2: 1024 usrbinrmdira2: ; ((*)) 1025 0000031D 0000 dw 0 1026 ;usrbinrmdirp: 1027 ; ;dw usrbindrmdir 1028 ; dw _rmdir_ 1029 ;usrbinrmdira1: 1030 ; dw 0 1031 ;usrbinrmdira2: 1032 ; dw 0 1033 1034 _rmdir_: 1035 0000031F 726D64697200 db 'rmdir', 0 1036 binrmdir: 1037 00000325 2F62696E2F726D6469- db '/bin/rmdir', 0 1037 0000032E 7200 1038 usrbinrmdir: 1039 00000330 2F7573722F62696E2F- db '/usr/bin/rmdir', 0 1039 00000339 726D64697200 1040 1041 ;argc: dw 0 1042 0000033F 00 argc: db 0 ; argument count 1043 00000340 00 fflg: db 0 ; -f (forced) option 1044 00000341 00 iflg: db 0 ; -i (interactive) option 1045 00000342 00 rflg: db 0 ; -r (recursive) option 1046 ;argv: dw 0 ; argument pointer (for argv[1]) 1047 ;errcode: dw 0 ; error code (will be returned by sysexit) 1048 ;uid: dw 0 ; user id 1049 ;;gid: db 0 ; group id 1050 ; 26/04/2022 1051 ;nameptr: dw namebuf 1052 1053 ; ---------------------------------------------------------------- 1054 1055 program_msg: 1056 00000343 0D0A db 0Dh, 0Ah 1057 00000345 526574726F20554E49- db "Retro UNIX 8086 v1 RM by Erdogan TAN - 28/04/2022" 1057 0000034E 582038303836207631- 1057 00000357 20524D206279204572- 1057 00000360 646F67616E2054414E- 1057 00000369 202D2032382F30342F- 1057 00000372 32303232 1058 00000376 0D0A00 db 0Dh, 0Ah, 0 1059 usage_msg: 1060 00000379 0D0A db 0Dh, 0Ah 1061 0000037B 55736167653A20726D- db "Usage: rm [ -fri ] file ..." 1061 00000384 205B202D667269205D- 1061 0000038D 2066696C65202E2E2E 1062 nextline: 1063 00000396 0D0A00 db 0Dh, 0Ah, 0 1064 1065 unk_op_msg: 1066 00000399 0D0A db 0Dh, 0Ah 1067 0000039B 726D3A20756E6B6E6F- db "rm: unknown option -" 1067 000003A4 776E206F7074696F6E- 1067 000003AD 202D 1068 000003AF 78 uop: db "x" 1069 000003B0 0D0A00 db 0Dh, 0Ah, 0 1070 1071 cnr_dotdot_msg: 1072 000003B3 0D0A db 0Dh, 0Ah 1073 000003B5 726D3A2063616E6E6F- db "rm: cannot remove '..'" 1073 000003BE 742072656D6F766520- 1073 000003C7 272E2E27 1074 000003CB 0D0A00 db 0Dh, 0Ah, 0 1075 1076 rm_hdr_msg: 1077 000003CE 0D0A db 0Dh, 0Ah 1078 000003D0 726D3A20 db "rm: " 1079 000003D4 00 db 0 1080 1081 nonex_msg: 1082 000003D5 206E6F6E6578697374- db " nonexistent" 1082 000003DE 656E74 1083 000003E1 0D0A00 db 0Dh, 0Ah, 0 1084 1085 nchd_msg: 1086 000003E4 206E6F74206368616E- db " not changed" 1086 000003ED 676564 1087 000003F0 0D0A00 db 0Dh, 0Ah, 0 1088 dir_hdr_msg: 1089 000003F3 0D0A db 0Dh, 0Ah 1090 000003F5 6469726563746F7279- db "directory " 1090 000003FE 20 1091 000003FF 00 db 0 1092 1093 qu_msg: 1094 00000400 3A db ":" 1095 00000401 203F20 que_msg: db " ? " 1096 00000404 00 db 0 1097 1098 yes_msg: 1099 00000405 796573 db "yes" 1100 00000408 0D0A00 db 0Dh, 0Ah, 0 1101 no_msg: 1102 0000040B 6E6F db "no" 1103 0000040D 0D0A00 db 0Dh, 0Ah, 0 1104 1105 cnr_msg: 1106 00000410 3A2063616E6E6F7420- db ": cannot read" 1106 00000419 72656164 1107 0000041D 0D0A00 db 0Dh, 0Ah, 0 1108 1109 dir_msg: 1110 00000420 206469726563746F72- db " directory" 1110 00000429 79 1111 0000042A 00 db 0 1112 1113 not_rmd_msg: 1114 0000042B 206E6F742072656D6F- db " not removed" 1114 00000434 766564 1115 00000437 0D0A00 db 0Dh, 0Ah, 0 1116 1117 mode_msg: 1118 0000043A 206D6F6465 db " mode" 1119 0000043F 00 db 0 1120 1121 cnf_rd_msg: 1122 00000440 0D0A db 0Dh, 0Ah 1123 00000442 726D3A2063616E2774- db "rm: can't find rmdir" 1123 0000044B 2066696E6420726D64- 1123 00000454 6972 1124 00000456 0D0A00 db 0Dh, 0Ah, 0 1125 1126 ;----------------------------------------------------------------- 1127 ; bss - uninitialized data 1128 ;----------------------------------------------------------------- 1129 1130 00000459 90 align 2 1131 1132 bss_start: 1133 1134 ABSOLUTE bss_start 1135 1136 ; 28/04/2022 (Retro UNIX 89086 v1) 1137 ; 26/04/2022 1138 0000045A ???? _d_: resw 1 ; Sub directory's file descriptor 1139 ;resw 1 1140 ;struct direct direct; 1141 0000045C direct: resb DIRSIZ ; Directory entry buffer 1142 1143 ; 25/04/2022 1144 ;;struct stat buf; 1145 ;stbuf: resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data) 1146 00000466 stbuf: resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data) 1147 1148 ; 26/04/2022 1149 00000488 ?? level: resb 1 ; (sub directory level) 1150 00000489 ???????? octal: resb 4 ; (asciiz octal mode number string) 1151 0000048D ?? chr: resb 1 ; (sysread character buffer) 1152 ; 27/04/2022 1153 ;char name[100]; 1154 ;namebuf: resb 100 1155 1156 1157 ; 25/04/2022 1158 ;----------------------------------------------------------------- 1159 ; Original UNIX v7 - rm (utility) c source code (rm.c) 1160 ;----------------------------------------------------------------- 1161 ;/* UNIX V7 source code: see www.tuhs.org for details. */; 1162 ; 1163 ;int errcode; 1164 ; 1165 ;#include 1166 ;#include 1167 ;#include 1168 ;#include 1169 ; 1170 ;char *sprintf(); 1171 ; 1172 ;main(argc, argv) 1173 ;char *argv[]; 1174 ;{ 1175 ; register char *arg; 1176 ; int fflg, iflg, rflg; 1177 ; 1178 ; fflg = 0; 1179 ; if (isatty(0) == 0) 1180 ; fflg++; 1181 ; iflg = 0; 1182 ; rflg = 0; 1183 ; if(argc>1 && argv[1][0]=='-') { 1184 ; arg = *++argv; 1185 ; argc--; 1186 ; while(*++arg != '\0') 1187 ; switch(*arg) { 1188 ; case 'f': 1189 ; fflg++; 1190 ; break; 1191 ; case 'i': 1192 ; iflg++; 1193 ; break; 1194 ; case 'r': 1195 ; rflg++; 1196 ; break; 1197 ; default: 1198 ; printf("rm: unknown option %s\n", *argv); 1199 ; exit(1); 1200 ; } 1201 ; } 1202 ; while(--argc > 0) { 1203 ; if(!strcmp(*++argv, "..")) { 1204 ; fprintf(stderr, "rm: cannot remove `..'\n"); 1205 ; continue; 1206 ; } 1207 ; rm(*argv, fflg, rflg, iflg, 0); 1208 ; } 1209 ; 1210 ; exit(errcode); 1211 ;} 1212 ; 1213 ;rm(arg, fflg, rflg, iflg, level) 1214 ;char arg[]; 1215 ;{ 1216 ; struct stat buf; 1217 ; struct direct direct; 1218 ; char name[100]; 1219 ; int d; 1220 ; 1221 ; if(stat(arg, &buf)) { 1222 ; if (fflg==0) { 1223 ; printf("rm: %s nonexistent\n", arg); 1224 ; ++errcode; 1225 ; } 1226 ; return; 1227 ; } 1228 ; if ((buf.st_mode&S_IFMT) == S_IFDIR) { 1229 ; if(rflg) { 1230 ; if (access(arg, 02) < 0) { 1231 ; if (fflg==0) 1232 ; printf("%s not changed\n", arg); 1233 ; errcode++; 1234 ; return; 1235 ; } 1236 ; if(iflg && level!=0) { 1237 ; printf("directory %s: ", arg); 1238 ; if(!yes()) 1239 ; return; 1240 ; } 1241 ; if((d=open(arg, 0)) < 0) { 1242 ; printf("rm: %s: cannot read\n", arg); 1243 ; exit(1); 1244 ; } 1245 ; while(read(d, (char *)&direct, sizeof(direct)) == sizeof(direct)) { 1246 ; if(direct.d_ino != 0 && !dotname(direct.d_name)) { 1247 ; sprintf(name, "%s/%.14s", arg, direct.d_name); 1248 ; rm(name, fflg, rflg, iflg, level+1); 1249 ; } 1250 ; } 1251 ; close(d); 1252 ; errcode += rmdir(arg, iflg); 1253 ; return; 1254 ; } 1255 ; printf("rm: %s directory\n", arg); 1256 ; ++errcode; 1257 ; return; 1258 ; } 1259 ; 1260 ; if(iflg) { 1261 ; printf("%s: ", arg); 1262 ; if(!yes()) 1263 ; return; 1264 ; } 1265 ; else if(!fflg) { 1266 ; if (access(arg, 02)<0) { 1267 ; printf("rm: %s %o mode ", arg, buf.st_mode&0777); 1268 ; if(!yes()) 1269 ; return; 1270 ; } 1271 ; } 1272 ; if(unlink(arg) && (fflg==0 || iflg)) { 1273 ; printf("rm: %s not removed\n", arg); 1274 ; ++errcode; 1275 ; } 1276 ;} 1277 ; 1278 ;dotname(s) 1279 ;char *s; 1280 ;{ 1281 ; if(s[0] == '.') 1282 ; if(s[1] == '.') 1283 ; if(s[2] == '\0') 1284 ; return(1); 1285 ; else 1286 ; return(0); 1287 ; else if(s[1] == '\0') 1288 ; return(1); 1289 ; return(0); 1290 ;} 1291 ; 1292 ;rmdir(f, iflg) 1293 ;char *f; 1294 ;{ 1295 ; int status, i; 1296 ; 1297 ; if(dotname(f)) 1298 ; return(0); 1299 ; if(iflg) { 1300 ; printf("%s: ", f); 1301 ; if(!yes()) 1302 ; return(0); 1303 ; } 1304 ; while((i=fork()) == -1) 1305 ; sleep(3); 1306 ; if(i) { 1307 ; wait(&status); 1308 ; return(status); 1309 ; } 1310 ; execl("/bin/rmdir", "rmdir", f, 0); 1311 ; execl("/usr/bin/rmdir", "rmdir", f, 0); 1312 ; printf("rm: can't find rmdir\n"); 1313 ; exit(1); 1314 ;} 1315 ; 1316 ;yes() 1317 ;{ 1318 ; int i, b; 1319 ; 1320 ; i = b = getchar(); 1321 ; while(b != '\n' && b != EOF) 1322 ; b = getchar(); 1323 ; return(i == 'y'); 1324 ;}