     1                                  ; ****************************************************************************
     2                                  ; ln8086.s (ln0.s) - by Erdogan Tan - 18/05/2022
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; Retro UNIX 8086 v1 - ln -- link file (to file)
     5                                  ;
     6                                  ; [ Last Modification: 21/05/2022 ]
     7                                  ;
     8                                  ; Derived from (original) UNIX v2 (ln.s) and v5 'ln.c' source Code
     9                                  ; Ref:
    10                                  ; www.tuhs.org (https://minnie.tuhs.org)
    11                                  ; ****************************************************************************
    12                                  ; [ v5root.tar - usr/source/s1/ln.c (archive date: 27-11-1974) ]
    13                                  ;
    14                                  ; Assembler: NASM v2.15
    15                                  ; ((nasm ln0.s -l ln0.txt -o ln0 -Z error.txt))
    16                                  
    17                                  ; ln0.s - 21/05/2022 - Retro UNIX 8086 v1 (16 bit 'ln1.s')
    18                                  ; ln1.s - 18/05/2022 - Retro UNIX 386 v1 & v1.1 & v1.2
    19                                  
    20                                  ; 12/01/2022 (Retro UNIX 386 v1.2)
    21                                  ; 13/10/2015
    22                                  
    23                                  ; UNIX v1 system calls
    24                                  _rele 	equ 0
    25                                  _exit 	equ 1
    26                                  _fork 	equ 2
    27                                  _read 	equ 3
    28                                  _write	equ 4
    29                                  _open	equ 5
    30                                  _close 	equ 6
    31                                  _wait 	equ 7
    32                                  _creat 	equ 8
    33                                  _link 	equ 9
    34                                  _unlink	equ 10
    35                                  _exec	equ 11
    36                                  _chdir	equ 12
    37                                  _time 	equ 13
    38                                  _mkdir 	equ 14
    39                                  _chmod	equ 15
    40                                  _chown	equ 16
    41                                  _break	equ 17
    42                                  _stat	equ 18
    43                                  _seek	equ 19
    44                                  _tell 	equ 20
    45                                  _mount	equ 21
    46                                  _umount	equ 22
    47                                  _setuid	equ 23
    48                                  _getuid	equ 24
    49                                  _stime	equ 25
    50                                  _quit	equ 26	
    51                                  _intr	equ 27
    52                                  _fstat	equ 28
    53                                  _emt 	equ 29
    54                                  _mdate 	equ 30
    55                                  _stty 	equ 31
    56                                  _gtty	equ 32
    57                                  _ilgins	equ 33
    58                                  _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
    59                                  _msg    equ 35 ; Retro UNIX 386 v1 feature only !
    60                                  _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
    61                                  ; 12/01/2022 - Retro UNIX 386 v1.2
    62                                  ; Retro UNIX 386 v2 system calls
    63                                  _setgid	equ 37
    64                                  _getgid	equ 38
    65                                  _sysver	equ 39 ; (get) Retro Unix 386 version
    66                                  
    67                                  ;;;
    68                                  ESCKey equ 1Bh
    69                                  EnterKey equ 0Dh
    70                                  
    71                                  ;%macro sys 1-4
    72                                  ;   ; 03/09/2015
    73                                  ;   ; 13/04/2015
    74                                  ;   ; Retro UNIX 386 v1 system call.
    75                                  ;   %if %0 >= 2   
    76                                  ;       mov ebx, %2
    77                                  ;       %if %0 >= 3    
    78                                  ;           mov ecx, %3
    79                                  ;           ;%if %0 = 4
    80                                  ;           %if	%0 >= 4 ; 11/03/2022
    81                                  ;		mov edx, %4
    82                                  ;           %endif
    83                                  ;       %endif
    84                                  ;   %endif
    85                                  ;   mov eax, %1
    86                                  ;   int 30h
    87                                  ;%endmacro
    88                                  
    89                                  %macro sys 1-4
    90                                      ; Retro UNIX 8086 v1 system call.
    91                                      %if %0 >= 2   
    92                                          mov bx, %2
    93                                          %if %0 >= 3
    94                                              mov cx, %3
    95                                              %if %0 >= 4
    96                                                 mov dx, %4
    97                                              %endif
    98                                          %endif
    99                                      %endif
   100                                      mov ax, %1
   101                                      int 20h
   102                                  %endmacro
   103                                  
   104                                  ;; Retro UNIX 386 v1 system call format:
   105                                  ;; sys systemcall (eax) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
   106                                  
   107                                  ;; 11/03/2022
   108                                  ;; Note: Above 'sys' macro has limitation about register positions;
   109                                  ;;	ebx, ecx, edx registers must not be used after their
   110                                  ;;	positions in sys macro.
   111                                  ;; for example:
   112                                  ;;	'sys _write, 1, msg, ecx' is defective, because
   113                                  ;;	 ecx will be used/assigned before edx in 'sys' macro.
   114                                  ;; correct order may be:
   115                                  ;;	'sys _write, 1, msg, eax ; (eax = byte count)
   116                                  
   117                                  ; Retro UNIX 8086 v1 system call format:
   118                                  ; sys systemcall (ax) <arg1 (bx)>, <arg2 (cx)>, <arg3 (dx)>
   119                                  
   120                                  ;struc stat
   121                                  ;	; Note: This is for Retro UNIX v1.2 'sysstat' output !!!
   122                                  ;	; (66 bytes)
   123                                  ;	.inode:  resw 1	
   124                                  ;	.mode:	 resw 1
   125                                  ;	.nlinks: resw 1 
   126                                  ;	.uid:	 resw 1
   127                                  ;	.gid:	 resb 1
   128                                  ;	.size_h: resb 1
   129                                  ;	.size:	 resd 1
   130                                  ;	.dskptr: resd 10
   131                                  ;	.atime:	 resd 1
   132                                  ;	.mtime:	 resd 1
   133                                  ;	.ctime:  resd 1
   134                                  ;	.strucsize:
   135                                  ;endstruc   
   136                                  
   137                                  ;;struc stat
   138                                  ;;	; Note: Retro UNIX v2 'sysstat' output DRAFT !!!
   139                                  ;;	; (72 bytes)
   140                                  ;;	.idev:	 resb 1
   141                                  ;;	.rsvd:	 resb 3
   142                                  ;;	.inum:   resd 1	
   143                                  ;;	.mode:	 resw 1
   144                                  ;;	.nlinks: resw 1 
   145                                  ;;	.uid:	 resw 1
   146                                  ;;	.gid:	 resb 1
   147                                  ;;	.size_h: resb 1
   148                                  ;;	.size:	 resd 1
   149                                  ;;	.dskptr: resd 10
   150                                  ;;	.atime:	 resd 1
   151                                  ;;	.mtime:	 resd 1
   152                                  ;;	.ctime:  resd 1
   153                                  ;;	.strucsize:
   154                                  ;;endstruc
   155                                  
   156                                  ;;S_IFMT   equ 0F000h ; /* type of file */
   157                                  ;;S_IFDIR  equ 04000h ; /* directory */
   158                                  ;;S_IFCHR  equ 02000h ; /* character special */
   159                                  ;;S_IFBLK  equ 06000h ; /* block special */
   160                                  ;;S_IFREG  equ 08000h ; /* regular */
   161                                  ;;S_ISUID  equ 00800h ; /* set user id on execution */
   162                                  ;;S_ISGID  equ 00400h ; /* set group id on execution */
   163                                  ;;S_IREAD  equ 00100h ; /* read permission, owner */
   164                                  ;;S_IWRITE equ 00080h ; /* write permission, owner */
   165                                  ;;S_IEXEC  equ 00040h ; /* execute/search permission, owner */
   166                                  ;
   167                                  ;S_IFMT   equ 0F0h ; /* type of file */
   168                                  ;S_IFDIR  equ 040h ; /* directory */
   169                                  ;S_IFCHR  equ 020h ; /* character special */
   170                                  ;S_IFBLK  equ 060h ; /* block special */
   171                                  ;S_IFREG  equ 080h ; /* regular */
   172                                  ;S_ISUID  equ 008h ; /* set user id on execution */
   173                                  ;S_ISGID  equ 004h ; /* set group id on execution */
   174                                  ;S_IREAD  equ 001h ; /* read permission, owner */
   175                                  ;S_IWRITE equ 080h ; /* write permission, owner */
   176                                  ;S_IEXEC  equ 040h ; /* execute/search permission, owner */
   177                                  
   178                                  struc stat
   179                                  	; Note: This is for Retro UNIX v1 'sysstat' output !!!
   180                                  	; (34 bytes)
   181 00000000 ????                    	.inode:  resw 1	
   182 00000002 ????                    	.mode:	 resw 1
   183 00000004 ??                      	.nlinks: resb 1
   184 00000005 ??                      	.uid:	 resb 1
   185 00000006 ????                    	.size:	 resw 1
   186 00000008 <res 10h>               	.dskptr: resw 8
   187 00000018 ????????                	.ctime:	 resd 1
   188 0000001C ????????                	.mtime:	 resd 1
   189 00000020 ????                    	.rsvd:   resw 1
   190                                  	.strucsize:
   191                                  endstruc  
   192                                  
   193                                  ; UNIX v1 inode
   194                                  ; byte 1
   195                                  S_ALLOC  equ 080h ; Allocated flag
   196                                  S_IFDIR  equ 040h ; Directory flag
   197                                  S_IFMDF  equ 020h ; File modified flag (always on)
   198                                  S_IFLRG  equ 010h ; Large File flag
   199                                  ; byte 0
   200                                  S_ISUID  equ 020h ; Set User ID On Execution flag
   201                                  S_IEXEC  equ 010h ; Executable File flag
   202                                  S_IREAD  equ 008h ; Owner's Read Permission flag
   203                                  S_IWRITE equ 004h ; Owner's Write Permission flag
   204                                  
   205                                  ; ----------------------------------------------------------------------------
   206                                  
   207                                  [BITS 16] ; 16-bit intructions (for 8086/x86 real mode)
   208                                  
   209                                  [ORG 0] 
   210                                  
   211                                  START_CODE:
   212                                  	; 21/05/2022
   213                                  	; 18/05/2022
   214                                  	; 17/05/2022
   215 00000000 89E6                    	mov	si, sp		
   216 00000002 58                      	pop	ax ; number of arguments
   217 00000003 5A                      	pop	dx  ; argv[0]	
   218                                  	;;mov	[argc], ax
   219                                  	;mov	[argc], al
   220                                  
   221                                  	;cmp	ax, 2
   222 00000004 3C02                    	cmp	al, 2
   223 00000006 730F                    	jnb	short ln_0
   224 00000008 FEC8                    	dec	al
   225 0000000A 7506                    	jnz	short ln_usage
   226                                  	; 21/05/2022
   227 0000000C B8[9D00]                	mov	ax, program_msg
   228 0000000F E87300                  	call	print_msg
   229                                  ln_usage:
   230 00000012 B8[D400]                	mov	ax, usage_msg
   231                                  	;call	print_msg
   232 00000015 EB57                    	jmp	short ln_5	
   233                                  ;ln_exit:
   234                                  ;	sys	_exit	; sys exit
   235                                  ;;hlt:
   236                                  ;;	nop
   237                                  ;;	nop
   238                                  ;;	jmp	short hlt
   239                                  
   240                                  ln_0:
   241                                  	; 21/05/2022
   242 00000017 5F                      	pop	di ; argv[1]
   243 00000018 7719                    	ja	short ln_3 ; al > 2
   244                                  
   245                                  	; same file name (different directories)
   246                                  	; (new file is in current directory)
   247 0000001A 89FE                    	mov	si, di
   248 0000001C 89F2                    	mov	dx, si
   249                                  ln_1:
   250 0000001E AC                      	lodsb
   251 0000001F 08C0                    	or	al, al
   252 00000021 7408                    	jz	short ln_2
   253 00000023 3C2F                    	cmp	al, '/'
   254 00000025 75F7                    	jne	short ln_1
   255 00000027 89F2                    	mov	dx, si ; last '/' + 1
   256 00000029 EBF3                    	jmp	short ln_1
   257                                  ln_2:
   258 0000002B 4A                      	dec	dx  ; last '/'
   259 0000002C 39FA                    	cmp	dx, di
   260 0000002E 762C                    	jna	short err
   261 00000030 42                      	inc	dx  ; last '/' + 1 ; = argv[2]
   262 00000031 EB01                    	jmp	short ln_4
   263                                  ln_3:
   264                                  	; different file name
   265 00000033 5A                      	pop	dx ; argv[2]
   266                                  ln_4:
   267                                  	sys	_stat, di, stbuf
    90                              <1> 
    91                              <1>  %if %0 >= 2
    92 00000034 89FB                <1>  mov bx, %2
    93                              <1>  %if %0 >= 3
    94 00000036 B9[4601]            <1>  mov cx, %3
    95                              <1>  %if %0 >= 4
    96                              <1>  mov dx, %4
    97                              <1>  %endif
    98                              <1>  %endif
    99                              <1>  %endif
   100 00000039 B81200              <1>  mov ax, %1
   101 0000003C CD20                <1>  int 20h
   268 0000003E 723B                    	jc	short ln_not_exists
   269                                  
   270                                  	; check if it is a directory..
   271 00000040 A0[4901]                	mov	al, [stbuf+stat.mode+1]
   272                                  	; 21/05/2022
   273                                  	;and	al, S_IFDIR|S_ALLOC ; (S_ALLOC = S_IFREG)
   274                                  	;cmp	al, S_IFDIR|S_ALLOC ; directory ?
   275                                  	;je	short ln_is_dir ; yes
   276 00000043 2440                    	and	al, S_IFDIR
   277 00000045 7539                    	jnz	short ln_is_dir ; yes		
   278                                  
   279                                  	sys	_link, di, dx
    90                              <1> 
    91                              <1>  %if %0 >= 2
    92 00000047 89FB                <1>  mov bx, %2
    93                              <1>  %if %0 >= 3
    94 00000049 89D1                <1>  mov cx, %3
    95                              <1>  %if %0 >= 4
    96                              <1>  mov dx, %4
    97                              <1>  %endif
    98                              <1>  %endif
    99                              <1>  %endif
   100 0000004B B80900              <1>  mov ax, %1
   101 0000004E CD20                <1>  int 20h
   280 00000050 7324                    	jnc	short ln_6
   281                                  	
   282                                  	; 21/05/2022
   283 00000052 B8[2201]                	mov	ax, cant_link_msg
   284 00000055 E82D00                  	call	print_msg
   285 00000058 89F8                    	mov	ax, di
   286 0000005A EB12                    	jmp	short ln_5
   287                                  
   288                                  err:
   289 0000005C B8[3201]                	mov	ax, err_msg
   290 0000005F EB0D                    	jmp	short ln_5
   291                                  
   292                                  ln_p_error:
   293 00000061 B8[F500]                	mov	ax, ln_header
   294 00000064 E81E00                  	call	print_msg
   295 00000067 89F8                    	mov	ax, di
   296 00000069 E81900                  	call	print_msg
   297 0000006C 89E8                    	mov	ax, bp
   298                                  ln_5:	 
   299 0000006E E81400                  	call	print_msg
   300                                  ln_exit:
   301                                  	sys	_exit	; sys exit
    90                              <1> 
    91                              <1>  %if %0 >= 2
    92                              <1>  mov bx, %2
    93                              <1>  %if %0 >= 3
    94                              <1>  mov cx, %3
    95                              <1>  %if %0 >= 4
    96                              <1>  mov dx, %4
    97                              <1>  %endif
    98                              <1>  %endif
    99                              <1>  %endif
   100 00000071 B80100              <1>  mov ax, %1
   101 00000074 CD20                <1>  int 20h
   302                                  ;hlt:
   303                                  ;	nop
   304                                  ;	nop
   305                                  ;	jmp	short hlt
   306                                  
   307                                  ln_6:
   308 00000076 B8[3E01]                	mov	ax, ok_msg
   309 00000079 EBF3                    	jmp	short ln_5
   310                                  
   311                                  ln_not_exists:
   312 0000007B BD[FC00]                	mov	bp, not_exists_msg
   313 0000007E EBE1                    	jmp	short ln_p_error
   314                                  
   315                                  ln_is_dir:
   316 00000080 BD[0F01]                	mov	bp, is_dir_msg
   317 00000083 EBDC                    	jmp	short ln_p_error
   318                                  
   319                                  ;-----------------------------------------------------------------
   320                                  
   321                                  print_msg:
   322                                  	; ax = asciiz string address
   323 00000085 89C6                    	mov	si, ax
   324 00000087 4E                      	dec	si
   325                                  nextchr:
   326 00000088 46                      	inc	si
   327 00000089 803C00                  	cmp	byte [si], 0
   328 0000008C 77FA                    	ja	short nextchr
   329                                  	;cmp	[si], 0Dh
   330                                  	;ja	short nextchr
   331 0000008E 29C6                    	sub	si, ax
   332                                  	; si = asciiz string length
   333                                  	;
   334                                  	sys	_write, 1, ax, si
    90                              <1> 
    91                              <1>  %if %0 >= 2
    92 00000090 BB0100              <1>  mov bx, %2
    93                              <1>  %if %0 >= 3
    94 00000093 89C1                <1>  mov cx, %3
    95                              <1>  %if %0 >= 4
    96 00000095 89F2                <1>  mov dx, %4
    97                              <1>  %endif
    98                              <1>  %endif
    99                              <1>  %endif
   100 00000097 B80400              <1>  mov ax, %1
   101 0000009A CD20                <1>  int 20h
   335                                  	;
   336 0000009C C3                      	retn
   337                                  
   338                                  ;-----------------------------------------------------------------
   339                                  ;  data - initialized data
   340                                  ;-----------------------------------------------------------------
   341                                  
   342                                  ;;argc:	dd 0
   343                                  ;argc:	db 0
   344                                  
   345                                  ; ----------------------------------------------------------------
   346                                  
   347                                  program_msg:
   348 0000009D 0D0A                    	db  0Dh, 0Ah
   349 0000009F 526574726F20554E49-     	db  'Retro UNIX 386 v1 LINK by Erdogan TAN - 21/05/2022'
   349 000000A8 582033383620763120-
   349 000000B1 4C494E4B2062792045-
   349 000000BA 72646F67616E205441-
   349 000000C3 4E202D2032312F3035-
   349 000000CC 2F32303232         
   350 000000D1 0D0A00                  	db  0Dh, 0Ah, 0
   351                                  
   352                                  usage_msg:
   353 000000D4 0D0A                    	db  0Dh, 0Ah
   354 000000D6 55736167653A206C6E-     	db  'Usage: ln target [ newname ]'
   354 000000DF 20746172676574205B-
   354 000000E8 206E65776E616D6520-
   354 000000F1 5D                 
   355                                  nextline:
   356 000000F2 0D0A00                  	db  0Dh, 0Ah, 0
   357                                  ln_header:
   358 000000F5 0D0A                    	db 0Dh, 0Ah
   359 000000F7 6C6E3A20                	db 'ln: '
   360 000000FB 00                      	db 0
   361                                  not_exists_msg:
   362                                  	;db 0Dh, 0Ah
   363 000000FC 20646F6573206E6F74-     	db ' does not exist '
   363 00000105 20657869737420     
   364 0000010C 0D0A00                  	db 0Dh, 0Ah, 0
   365                                  
   366                                  is_dir_msg:
   367 0000010F 206973206120646972-     	db ' is a directory '
   367 00000118 6563746F727920     
   368 0000011F 0D0A00                  	db 0Dh, 0Ah, 0
   369                                  
   370                                  cant_link_msg:
   371 00000122 0D0A                    	db 0Dh, 0Ah
   372 00000124 43616E206E6F74206C-     	db 'Can not link '
   372 0000012D 696E6B20           
   373                                  	;db 0Dh, 0Ah, 0
   374 00000131 00                      	db 0 ; 21/05/2022
   375                                  
   376                                  err_msg:
   377 00000132 0D0A                    	db 0Dh, 0Ah
   378 00000134 4572726F722120          	db 'Error! '
   379 0000013B 0D0A00                  	db 0Dh, 0Ah, 0
   380                                  
   381                                  ok_msg:
   382 0000013E 0D0A                    	db  0Dh, 0Ah
   383 00000140 4F4B2E                  	db  'OK.'
   384 00000143 0D0A00                  	db  0Dh, 0Ah, 0
   385                                  
   386                                  ;-----------------------------------------------------------------
   387                                  ;  bss - uninitialized data
   388                                  ;-----------------------------------------------------------------
   389                                  
   390                                  align 2
   391                                  
   392                                  bss_start:
   393                                  
   394                                  ABSOLUTE bss_start
   395                                  
   396 00000146 <res 22h>               stbuf:	resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data)
   397                                  ;stbuf:	resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data)
   398                                  
   399                                  ; 17/05/2022
   400                                  ;-----------------------------------------------------------------
   401                                  ; Original UNIX v2 - ln (utility) pdp-11 asm source code (ln.s)
   402                                  ;-----------------------------------------------------------------
   403                                  ;/* UNIX V2 source code: see www.tuhs.org for details. */;
   404                                  ;
   405                                  ;/*
   406                                  ; * ln target [ new name ]
   407                                  ; */
   408                                  ; ----------------------------------------------------------------
   409                                  ;/  link command
   410                                  ;
   411                                  ;ln:
   412                                  ;	mov	sp,r5
   413                                  ;	cmp	(r5)+,$2
   414                                  ;	bhis	1f
   415                                  ;	sys	exit
   416                                  ;1:
   417                                  ;	beq	1f
   418                                  ;	tst	(r5)+
   419                                  ;	mov	(r5)+,0f
   420                                  ;	mov	(r5),0f+2
   421                                  ;	br	2f
   422                                  ;1:
   423                                  ;	tst	(r5)+
   424                                  ;	mov	(r5),0f
   425                                  ;	mov	(r5),r4
   426                                  ;1:
   427                                  ;	tstb	(r4)+
   428                                  ;	bne	1b
   429                                  ;1:
   430                                  ;	cmpb	-(r4),$'/
   431                                  ;	beq	1f
   432                                  ;	cmp	(r5),r4
   433                                  ;	bne	1b
   434                                  ;	br	err
   435                                  ;1:
   436                                  ;	inc	r4
   437                                  ;	mov	r4,0f+2
   438                                  ;2:
   439                                  ;	mov	0f,2f
   440                                  ;	sys	stat; 2:..; stbuf
   441                                  ;	bes	err
   442                                  ;	bit	$40000,stbuf+2
   443                                  ;	bne	err
   444                                  ;	sys	link; 0:..; ..
   445                                  ;	bes	err
   446                                  ;	sys	exit
   447                                  ;
   448                                  ;err:
   449                                  ;	mov	$1,r0
   450                                  ;	sys write; quest; 2
   451                                  ;	sys	exit
   452                                  ;
   453                                  ;quest:
   454                                  ;	<?\n>
   455                                  ;
   456                                  ;.bss
   457                                  ;stbuf:	.=.+40.
   458                                  
   459                                  ;-----------------------------------------------------------------
   460                                  ; Original UNIX v5 - ln (utility) c source code (ln.c)
   461                                  ;-----------------------------------------------------------------
   462                                  ;/* UNIX V5 source code: see www.tuhs.org for details. */;
   463                                  ;
   464                                  ;/*
   465                                  ; * ln target [ new name ]
   466                                  ; */
   467                                  ;
   468                                  ;struct ibuf {
   469                                  ;	int	inum;
   470                                  ;	int	iflags;
   471                                  ;	char	inl;
   472                                  ;	char	iuid;
   473                                  ;	int	isize;
   474                                  ;	int	iaddr[8];
   475                                  ;	char	*ictime[2];
   476                                  ;	char	*imtime[2];
   477                                  ;	int	fill;
   478                                  ;};
   479                                  ;
   480                                  ;#define DIR	040000
   481                                  ;#define FMT	060000
   482                                  ;
   483                                  ;main(argc, argv)
   484                                  ;char **argv;
   485                                  ;{
   486                                  ;	static struct ibuf statb;
   487                                  ;	register char *np;
   488                                  ;
   489                                  ;	if (argc<2) {
   490                                  ;		write(1, "Usage: ln target [ newname ]\n", 29);
   491                                  ;		exit(1);
   492                                  ;	}
   493                                  ;	if (argc==2) {
   494                                  ;		np = argv[1];
   495                                  ;		while(*np++);
   496                                  ;		while (*--np!='/' && np>argv[1]);
   497                                  ;		np++;
   498                                  ;		argv[2] = np;
   499                                  ;	}
   500                                  ;	stat(argv[1], &statb);
   501                                  ;	if ((statb.iflags&FMT) == DIR) {
   502                                  ;		write(1, "No directory link\n", 18);
   503                                  ;		exit(1);
   504                                  ;	}
   505                                  ;	if (link(argv[1], argv[2])<0) {
   506                                  ;		write(1, "Can't link\n", 11);
   507                                  ;		exit(1);
   508                                  ;	}
   509                                  ;	exit(0);
   510                                  ;}
   511                                  
   512                                  ;-----------------------------------------------------------------
   513                                  ; Original UNIX v7 - ln (utility) c source code (ln.c)
   514                                  ;-----------------------------------------------------------------
   515                                  ;/* UNIX V7 source code: see www.tuhs.org for details. */;
   516                                  ;
   517                                  ;/*
   518                                  ; * ln [ -f ] target [ new name ]
   519                                  ; */
   520                                  ;
   521                                  ;#include <sys/types.h>
   522                                  ;#include <sys/stat.h>
   523                                  ;#include "stdio.h"
   524                                  ;char	*rindex();
   525                                  ;
   526                                  ;main(argc, argv)
   527                                  ;char **argv;
   528                                  ;{
   529                                  ;	struct stat statb;
   530                                  ;	register char *np;
   531                                  ;	int fflag = 0;
   532                                  ;	char nb[100], *name=nb, *arg2;
   533                                  ;	int statres;
   534                                  ;
   535                                  ;	if (argc >1 && strcmp(argv[1], "-f")==0) {
   536                                  ;		argc--;
   537                                  ;		argv++;
   538                                  ;		fflag++;
   539                                  ;	}
   540                                  ;	if (argc<2 || argc>3) {
   541                                  ;		printf("Usage: ln target [ newname ]\n");
   542                                  ;		exit(1);
   543                                  ;	}
   544                                  ;	np = rindex(argv[1], '/');
   545                                  ;	if (np==0)
   546                                  ;		np = argv[1];
   547                                  ;	else
   548                                  ;		np++;
   549                                  ;	if (argc==2)
   550                                  ;		arg2 = np;
   551                                  ;	else
   552                                  ;		arg2 = argv[2];
   553                                  ;	statres = stat(argv[1], &statb);
   554                                  ;	if (statres<0) {
   555                                  ;		printf ("ln: %s does not exist\n", argv[1]);
   556                                  ;		exit(1);
   557                                  ;	}
   558                                  ;	if (fflag==0 && (statb.st_mode&S_IFMT) == S_IFDIR) {
   559                                  ;		printf("ln: %s is a directory\n", argv[1]);
   560                                  ;		exit(1);
   561                                  ;	}
   562                                  ;	statres = stat(arg2, &statb);
   563                                  ;	if (statres>=0 && (statb.st_mode&S_IFMT) == S_IFDIR)
   564                                  ;		sprintf(name, "%s/%s", arg2, np);
   565                                  ;	else
   566                                  ;		name = arg2;
   567                                  ;	if (link(argv[1], name)<0) {
   568                                  ;		perror("ln");
   569                                  ;		exit(1);
   570                                  ;	}
   571                                  ;	exit(0);
   572                                  ;}
