     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) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
   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) <arg1 (bx)>, <arg2 (cx)>, <arg3 (dx)>
   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 <res 10h>               	.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: <si> 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                                  	; "<si> 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 <si> : ? " 
   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: <si> : 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: <si> 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: <si> 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: <si> _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 <res Ah>                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 <res 22h>               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 <stdio.h>
  1166                                  ;#include <sys/types.h>
  1167                                  ;#include <sys/stat.h>
  1168                                  ;#include <sys/dir.h>
  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                                  ;}
