     1                                  ; ****************************************************************************
     2                                  ; ln386.s (ln1.s) - by Erdogan Tan - 18/05/2022
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; Retro UNIX 386 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 ln1.s -l ln1.txt -o ln1 -Z error.txt))
    16                                  
    17                                  ; ln1.s - 18/05/2022 - Retro UNIX 386 v1 & v1.1 & v1.2
    18                                  ; ln0.s - 21/05/2022 - Retro UNIX 8086 v1 (16 bit 'ln1.s')
    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                                  ; Retro UNIX 386 v1 system call format:
    90                                  ; sys systemcall (eax) <arg1 (ebx)>, <arg2 (ecx)>, <arg3 (edx)>
    91                                  
    92                                  ; 11/03/2022
    93                                  ; Note: Above 'sys' macro has limitation about register positions;
    94                                  ;	ebx, ecx, edx registers must not be used after their
    95                                  ;	positions in sys macro.
    96                                  ; for example:
    97                                  ;	'sys _write, 1, msg, ecx' is defective, because
    98                                  ;	 ecx will be used/assigned before edx in 'sys' macro.
    99                                  ; correct order may be:
   100                                  ;	'sys _write, 1, msg, eax ; (eax = byte count)
   101                                  
   102                                  struc stat
   103                                  	; Note: This is for Retro UNIX v1.2 'sysstat' output !!!
   104                                  	; (66 bytes)
   105 00000000 ????                    	.inode:  resw 1	
   106 00000002 ????                    	.mode:	 resw 1
   107 00000004 ????                    	.nlinks: resw 1 
   108 00000006 ????                    	.uid:	 resw 1
   109 00000008 ??                      	.gid:	 resb 1
   110 00000009 ??                      	.size_h: resb 1
   111 0000000A ????????                	.size:	 resd 1
   112 0000000E <res 28h>               	.dskptr: resd 10
   113 00000036 ????????                	.atime:	 resd 1
   114 0000003A ????????                	.mtime:	 resd 1
   115 0000003E ????????                	.ctime:  resd 1
   116                                  	.strucsize:
   117                                  endstruc   
   118                                  
   119                                  ;struc stat
   120                                  ;	; Note: Retro UNIX v2 'sysstat' output DRAFT !!!
   121                                  ;	; (72 bytes)
   122                                  ;	.idev:	 resb 1
   123                                  ;	.rsvd:	 resb 3
   124                                  ;	.inum:   resd 1	
   125                                  ;	.mode:	 resw 1
   126                                  ;	.nlinks: resw 1 
   127                                  ;	.uid:	 resw 1
   128                                  ;	.gid:	 resb 1
   129                                  ;	.size_h: resb 1
   130                                  ;	.size:	 resd 1
   131                                  ;	.dskptr: resd 10
   132                                  ;	.atime:	 resd 1
   133                                  ;	.mtime:	 resd 1
   134                                  ;	.ctime:  resd 1
   135                                  ;	.strucsize:
   136                                  ;endstruc 
   137                                  
   138                                  ;S_IFMT   equ 0F000h ; /* type of file */
   139                                  ;S_IFDIR  equ 04000h ; /* directory */
   140                                  ;S_IFCHR  equ 02000h ; /* character special */
   141                                  ;S_IFBLK  equ 06000h ; /* block special */
   142                                  ;S_IFREG  equ 08000h ; /* regular */
   143                                  ;S_ISUID  equ 00800h ; /* set user id on execution */
   144                                  ;S_ISGID  equ 00400h ; /* set group id on execution */
   145                                  ;S_IREAD  equ 00100h ; /* read permission, owner */
   146                                  ;S_IWRITE equ 00080h ; /* write permission, owner */
   147                                  ;S_IEXEC  equ 00040h ; /* execute/search permission, owner */
   148                                  
   149                                  S_IFMT   equ 0F0h ; /* type of file */
   150                                  S_IFDIR  equ 040h ; /* directory */
   151                                  S_IFCHR  equ 020h ; /* character special */
   152                                  S_IFBLK  equ 060h ; /* block special */
   153                                  S_IFREG  equ 080h ; /* regular */
   154                                  S_ISUID  equ 008h ; /* set user id on execution */
   155                                  S_ISGID  equ 004h ; /* set group id on execution */
   156                                  S_IREAD  equ 001h ; /* read permission, owner */
   157                                  S_IWRITE equ 080h ; /* write permission, owner */
   158                                  S_IEXEC  equ 040h ; /* execute/search permission, owner */
   159                                  
   160                                  ;; UNIX v1 inode
   161                                  ;; byte 1
   162                                  ;S_ALLOC  equ 080h ; Allocated flag
   163                                  ;S_IFDIR  equ 040h ; Directory flag
   164                                  ;S_IFMDF  equ 020h ; File modified flag (always on)
   165                                  ;S_IFLRG  equ 010h ; Large File flag
   166                                  ;; byte 0
   167                                  ;S_ISUID  equ 020h ; Set User ID On Execution flag
   168                                  ;S_IEXEC  equ 010h ; Executable File flag
   169                                  ;S_IREAD  equ 008h ; Owner's Read Permission flag
   170                                  ;S_IWRITE equ 004h ; Owner's Write Permission flag
   171                                  
   172                                  ;-----------------------------------------------------------------
   173                                  ;  text - code
   174                                  ;-----------------------------------------------------------------
   175                                  
   176                                  [BITS 32] ; 32-bit intructions (for 80386 protected mode)
   177                                  
   178                                  [ORG 0] 
   179                                  
   180                                  START_CODE:
   181                                  	; 21/05/2022
   182                                  	; 18/05/2022
   183                                  	; 17/05/2022
   184 00000000 89E6                    	mov	esi, esp		
   185 00000002 58                      	pop	eax ; number of arguments
   186 00000003 5A                      	pop	edx  ; argv[0]	
   187                                  	;;mov	[argc], eax
   188                                  	;mov	[argc], al
   189                                  
   190                                  	;cmp	eax, 2
   191 00000004 3C02                    	cmp	al, 2
   192 00000006 7321                    	jnb	short ln_0
   193 00000008 FEC8                    	dec	al
   194 0000000A 7516                    	jnz	short ln_usage
   195                                  	sys	_msg, program_msg, 255, 0Fh
    72                              <1> 
    73                              <1> 
    74                              <1> 
    75                              <1>  %if %0 >= 2
    76 0000000C BB[D3000000]        <1>  mov ebx, %2
    77                              <1>  %if %0 >= 3
    78 00000011 B9FF000000          <1>  mov ecx, %3
    79                              <1> 
    80                              <1>  %if %0 >= 4
    81 00000016 BA0F000000          <1>  mov edx, %4
    82                              <1>  %endif
    83                              <1>  %endif
    84                              <1>  %endif
    85 0000001B B823000000          <1>  mov eax, %1
    86 00000020 CD30                <1>  int 30h
   196                                  ln_usage:
   197                                  	;sys	_msg, usage_msg, 255, 07h
   198 00000022 B8[0A010000]            	mov	eax, usage_msg
   199                                  	;call	print_msg
   200 00000027 EB6D                    	jmp	short ln_5	
   201                                  ;ln_exit:
   202                                  ;	sys	_exit	; sys exit
   203                                  ;;hlt:
   204                                  ;;	nop
   205                                  ;;	nop
   206                                  ;;	jmp	short hlt
   207                                  
   208                                  ln_0:
   209                                  	; 21/05/2022
   210 00000029 5F                      	pop	edi ; argv[1]
   211 0000002A 7719                    	ja	short ln_3 ; al > 2
   212                                  
   213                                  	; same file name (different directories)
   214                                  	; (new file is in current directory)
   215 0000002C 89FE                    	mov	esi, edi
   216 0000002E 89F2                    	mov	edx, esi
   217                                  ln_1:
   218 00000030 AC                      	lodsb
   219 00000031 08C0                    	or	al, al
   220 00000033 7408                    	jz	short ln_2
   221 00000035 3C2F                    	cmp	al, '/'
   222 00000037 75F7                    	jne	short ln_1
   223 00000039 89F2                    	mov	edx, esi ; last '/' + 1
   224 0000003B EBF3                    	jmp	short ln_1
   225                                  ln_2:
   226 0000003D 4A                      	dec	edx  ; last '/'
   227 0000003E 39FA                    	cmp	edx, edi
   228 00000040 763A                    	jna	short err
   229 00000042 42                      	inc	edx  ; last '/' + 1 ; = argv[2]
   230 00000043 EB01                    	jmp	short ln_4
   231                                  ln_3:
   232                                  	; different file name
   233 00000045 5A                      	pop	edx ; argv[2]
   234                                  ln_4:
   235                                  	sys	_stat, edi, stbuf
    72                              <1> 
    73                              <1> 
    74                              <1> 
    75                              <1>  %if %0 >= 2
    76 00000046 89FB                <1>  mov ebx, %2
    77                              <1>  %if %0 >= 3
    78 00000048 B9[7C010000]        <1>  mov ecx, %3
    79                              <1> 
    80                              <1>  %if %0 >= 4
    81                              <1>  mov edx, %4
    82                              <1>  %endif
    83                              <1>  %endif
    84                              <1>  %endif
    85 0000004D B812000000          <1>  mov eax, %1
    86 00000052 CD30                <1>  int 30h
   236 00000054 7253                    	jc	short ln_not_exists
   237                                  
   238                                  	; check retro unix v2 inode flags
   239                                  	;	(a bit different than unix v7 inode flags)
   240                                  	; if it is a directory..
   241                                  	;	regular file flag and dir flag must be 1
   242 00000056 A0[7F010000]            	mov	al, [stbuf+stat.mode+1]
   243 0000005B 24C0                    	and	al, S_IFDIR|S_IFREG ; S_IFREG = S_ALLOC
   244 0000005D 3CC0                    	cmp	al, S_IFDIR|S_IFREG ; directory ?
   245 0000005F 744F                    	je	short ln_is_dir ; yes
   246                                  	
   247                                  	sys	_link, edi, edx
    72                              <1> 
    73                              <1> 
    74                              <1> 
    75                              <1>  %if %0 >= 2
    76 00000061 89FB                <1>  mov ebx, %2
    77                              <1>  %if %0 >= 3
    78 00000063 89D1                <1>  mov ecx, %3
    79                              <1> 
    80                              <1>  %if %0 >= 4
    81                              <1>  mov edx, %4
    82                              <1>  %endif
    83                              <1>  %endif
    84                              <1>  %endif
    85 00000065 B809000000          <1>  mov eax, %1
    86 0000006A CD30                <1>  int 30h
   248 0000006C 7334                    	jnc	short ln_6
   249                                  	
   250                                  	; 21/05/2022
   251 0000006E B8[58010000]            	mov	eax, cant_link_msg
   252 00000073 E83F000000              	call	print_msg
   253 00000078 89F8                    	mov	eax, edi
   254 0000007A EB1A                    	jmp	short ln_5
   255                                  
   256                                  err:
   257 0000007C B8[68010000]            	mov	eax, err_msg
   258 00000081 EB13                    	jmp	short ln_5
   259                                  
   260                                  ln_p_error:
   261 00000083 B8[2B010000]            	mov	eax, ln_header
   262 00000088 E82A000000              	call	print_msg
   263 0000008D 89F8                    	mov	eax, edi
   264 0000008F E823000000              	call	print_msg
   265 00000094 89E8                    	mov	eax, ebp
   266                                  ln_5:	 
   267 00000096 E81C000000              	call	print_msg
   268                                  ln_exit:
   269                                  	sys	_exit	; sys exit
    72                              <1> 
    73                              <1> 
    74                              <1> 
    75                              <1>  %if %0 >= 2
    76                              <1>  mov ebx, %2
    77                              <1>  %if %0 >= 3
    78                              <1>  mov ecx, %3
    79                              <1> 
    80                              <1>  %if %0 >= 4
    81                              <1>  mov edx, %4
    82                              <1>  %endif
    83                              <1>  %endif
    84                              <1>  %endif
    85 0000009B B801000000          <1>  mov eax, %1
    86 000000A0 CD30                <1>  int 30h
   270                                  ;hlt:
   271                                  ;	nop
   272                                  ;	nop
   273                                  ;	jmp	short hlt
   274                                  
   275                                  ln_6:
   276 000000A2 B8[74010000]            	mov	eax, ok_msg
   277 000000A7 EBED                    	jmp	short ln_5
   278                                  
   279                                  ln_not_exists:
   280 000000A9 BD[32010000]            	mov	ebp, not_exists_msg
   281 000000AE EBD3                    	jmp	short ln_p_error
   282                                  
   283                                  ln_is_dir:
   284 000000B0 BD[45010000]            	mov	ebp, is_dir_msg
   285 000000B5 EBCC                    	jmp	short ln_p_error
   286                                  
   287                                  ;-----------------------------------------------------------------
   288                                  
   289                                  print_msg:
   290                                  	; eax = asciiz string address
   291 000000B7 89C6                    	mov	esi, eax
   292 000000B9 4E                      	dec	esi
   293                                  nextchr:
   294 000000BA 46                      	inc	esi
   295 000000BB 803E00                  	cmp	byte [esi], 0
   296 000000BE 77FA                    	ja	short nextchr
   297                                  	;cmp	[esi], 0Dh
   298                                  	;ja	short nextchr
   299 000000C0 29C6                    	sub	esi, eax
   300                                  	; esi = asciiz string length
   301                                  	;
   302                                  	sys	_write, 1, eax, esi
    72                              <1> 
    73                              <1> 
    74                              <1> 
    75                              <1>  %if %0 >= 2
    76 000000C2 BB01000000          <1>  mov ebx, %2
    77                              <1>  %if %0 >= 3
    78 000000C7 89C1                <1>  mov ecx, %3
    79                              <1> 
    80                              <1>  %if %0 >= 4
    81 000000C9 89F2                <1>  mov edx, %4
    82                              <1>  %endif
    83                              <1>  %endif
    84                              <1>  %endif
    85 000000CB B804000000          <1>  mov eax, %1
    86 000000D0 CD30                <1>  int 30h
   303                                  	;
   304 000000D2 C3                      	retn
   305                                  
   306                                  ;-----------------------------------------------------------------
   307                                  ;  data - initialized data
   308                                  ;-----------------------------------------------------------------
   309                                  
   310                                  ;;argc:	dd 0
   311                                  ;argc:	db 0
   312                                  
   313                                  ; ----------------------------------------------------------------
   314                                  
   315                                  program_msg:
   316 000000D3 0D0A                    	db  0Dh, 0Ah
   317 000000D5 526574726F20554E49-     	db  'Retro UNIX 386 v1 LINK by Erdogan TAN - 21/05/2022'
   317 000000DE 582033383620763120-
   317 000000E7 4C494E4B2062792045-
   317 000000F0 72646F67616E205441-
   317 000000F9 4E202D2032312F3035-
   317 00000102 2F32303232         
   318 00000107 0D0A00                  	db  0Dh, 0Ah, 0
   319                                  
   320                                  usage_msg:
   321 0000010A 0D0A                    	db  0Dh, 0Ah
   322 0000010C 55736167653A206C6E-     	db  'Usage: ln target [ newname ]'
   322 00000115 20746172676574205B-
   322 0000011E 206E65776E616D6520-
   322 00000127 5D                 
   323                                  nextline:
   324 00000128 0D0A00                  	db  0Dh, 0Ah, 0
   325                                  ln_header:
   326 0000012B 0D0A                    	db 0Dh, 0Ah
   327 0000012D 6C6E3A20                	db 'ln: '
   328 00000131 00                      	db 0
   329                                  not_exists_msg:
   330                                  	;db 0Dh, 0Ah
   331 00000132 20646F6573206E6F74-     	db ' does not exist '
   331 0000013B 20657869737420     
   332 00000142 0D0A00                  	db 0Dh, 0Ah, 0
   333                                  
   334                                  is_dir_msg:
   335 00000145 206973206120646972-     	db ' is a directory '
   335 0000014E 6563746F727920     
   336 00000155 0D0A00                  	db 0Dh, 0Ah, 0
   337                                  
   338                                  cant_link_msg:
   339 00000158 0D0A                    	db 0Dh, 0Ah
   340 0000015A 43616E206E6F74206C-     	db 'Can not link '
   340 00000163 696E6B20           
   341                                  	;db 0Dh, 0Ah, 0
   342 00000167 00                      	db 0 ; 21/05/2022
   343                                  
   344                                  err_msg:
   345 00000168 0D0A                    	db 0Dh, 0Ah
   346 0000016A 4572726F722120          	db 'Error! '
   347 00000171 0D0A00                  	db 0Dh, 0Ah, 0
   348                                  
   349                                  ok_msg:
   350 00000174 0D0A                    	db  0Dh, 0Ah
   351 00000176 4F4B2E                  	db  'OK.'
   352 00000179 0D0A00                  	db  0Dh, 0Ah, 0
   353                                  
   354                                  ;-----------------------------------------------------------------
   355                                  ;  bss - uninitialized data
   356                                  ;-----------------------------------------------------------------
   357                                  
   358                                  align 2
   359                                  
   360                                  bss_start:
   361                                  
   362                                  ABSOLUTE bss_start
   363                                  
   364                                  ;stbuf:	resb 34 ; for Retro UNIX 386 v1.1 (34 byte sysstat data)
   365 0000017C <res 42h>               stbuf:	resb 66 ; for Retro UNIX 386 v1.2 (66 byte sysstat data)
   366                                  
   367                                  ; 17/05/2022
   368                                  ;-----------------------------------------------------------------
   369                                  ; Original UNIX v2 - ln (utility) pdp-11 asm source code (ln.s)
   370                                  ;-----------------------------------------------------------------
   371                                  ;/* UNIX V2 source code: see www.tuhs.org for details. */;
   372                                  ;
   373                                  ;/*
   374                                  ; * ln target [ new name ]
   375                                  ; */
   376                                  ; ----------------------------------------------------------------
   377                                  ;/  link command
   378                                  ;
   379                                  ;ln:
   380                                  ;	mov	sp,r5
   381                                  ;	cmp	(r5)+,$2
   382                                  ;	bhis	1f
   383                                  ;	sys	exit
   384                                  ;1:
   385                                  ;	beq	1f
   386                                  ;	tst	(r5)+
   387                                  ;	mov	(r5)+,0f
   388                                  ;	mov	(r5),0f+2
   389                                  ;	br	2f
   390                                  ;1:
   391                                  ;	tst	(r5)+
   392                                  ;	mov	(r5),0f
   393                                  ;	mov	(r5),r4
   394                                  ;1:
   395                                  ;	tstb	(r4)+
   396                                  ;	bne	1b
   397                                  ;1:
   398                                  ;	cmpb	-(r4),$'/
   399                                  ;	beq	1f
   400                                  ;	cmp	(r5),r4
   401                                  ;	bne	1b
   402                                  ;	br	err
   403                                  ;1:
   404                                  ;	inc	r4
   405                                  ;	mov	r4,0f+2
   406                                  ;2:
   407                                  ;	mov	0f,2f
   408                                  ;	sys	stat; 2:..; stbuf
   409                                  ;	bes	err
   410                                  ;	bit	$40000,stbuf+2
   411                                  ;	bne	err
   412                                  ;	sys	link; 0:..; ..
   413                                  ;	bes	err
   414                                  ;	sys	exit
   415                                  ;
   416                                  ;err:
   417                                  ;	mov	$1,r0
   418                                  ;	sys write; quest; 2
   419                                  ;	sys	exit
   420                                  ;
   421                                  ;quest:
   422                                  ;	<?\n>
   423                                  ;
   424                                  ;.bss
   425                                  ;stbuf:	.=.+40.
   426                                  
   427                                  ;-----------------------------------------------------------------
   428                                  ; Original UNIX v5 - ln (utility) c source code (ln.c)
   429                                  ;-----------------------------------------------------------------
   430                                  ;/* UNIX V5 source code: see www.tuhs.org for details. */;
   431                                  ;
   432                                  ;/*
   433                                  ; * ln target [ new name ]
   434                                  ; */
   435                                  ;
   436                                  ;struct ibuf {
   437                                  ;	int	inum;
   438                                  ;	int	iflags;
   439                                  ;	char	inl;
   440                                  ;	char	iuid;
   441                                  ;	int	isize;
   442                                  ;	int	iaddr[8];
   443                                  ;	char	*ictime[2];
   444                                  ;	char	*imtime[2];
   445                                  ;	int	fill;
   446                                  ;};
   447                                  ;
   448                                  ;#define DIR	040000
   449                                  ;#define FMT	060000
   450                                  ;
   451                                  ;main(argc, argv)
   452                                  ;char **argv;
   453                                  ;{
   454                                  ;	static struct ibuf statb;
   455                                  ;	register char *np;
   456                                  ;
   457                                  ;	if (argc<2) {
   458                                  ;		write(1, "Usage: ln target [ newname ]\n", 29);
   459                                  ;		exit(1);
   460                                  ;	}
   461                                  ;	if (argc==2) {
   462                                  ;		np = argv[1];
   463                                  ;		while(*np++);
   464                                  ;		while (*--np!='/' && np>argv[1]);
   465                                  ;		np++;
   466                                  ;		argv[2] = np;
   467                                  ;	}
   468                                  ;	stat(argv[1], &statb);
   469                                  ;	if ((statb.iflags&FMT) == DIR) {
   470                                  ;		write(1, "No directory link\n", 18);
   471                                  ;		exit(1);
   472                                  ;	}
   473                                  ;	if (link(argv[1], argv[2])<0) {
   474                                  ;		write(1, "Can't link\n", 11);
   475                                  ;		exit(1);
   476                                  ;	}
   477                                  ;	exit(0);
   478                                  ;}
   479                                  
   480                                  ;-----------------------------------------------------------------
   481                                  ; Original UNIX v7 - ln (utility) c source code (ln.c)
   482                                  ;-----------------------------------------------------------------
   483                                  ;/* UNIX V7 source code: see www.tuhs.org for details. */;
   484                                  ;
   485                                  ;/*
   486                                  ; * ln [ -f ] target [ new name ]
   487                                  ; */
   488                                  ;
   489                                  ;#include <sys/types.h>
   490                                  ;#include <sys/stat.h>
   491                                  ;#include "stdio.h"
   492                                  ;char	*rindex();
   493                                  ;
   494                                  ;main(argc, argv)
   495                                  ;char **argv;
   496                                  ;{
   497                                  ;	struct stat statb;
   498                                  ;	register char *np;
   499                                  ;	int fflag = 0;
   500                                  ;	char nb[100], *name=nb, *arg2;
   501                                  ;	int statres;
   502                                  ;
   503                                  ;	if (argc >1 && strcmp(argv[1], "-f")==0) {
   504                                  ;		argc--;
   505                                  ;		argv++;
   506                                  ;		fflag++;
   507                                  ;	}
   508                                  ;	if (argc<2 || argc>3) {
   509                                  ;		printf("Usage: ln target [ newname ]\n");
   510                                  ;		exit(1);
   511                                  ;	}
   512                                  ;	np = rindex(argv[1], '/');
   513                                  ;	if (np==0)
   514                                  ;		np = argv[1];
   515                                  ;	else
   516                                  ;		np++;
   517                                  ;	if (argc==2)
   518                                  ;		arg2 = np;
   519                                  ;	else
   520                                  ;		arg2 = argv[2];
   521                                  ;	statres = stat(argv[1], &statb);
   522                                  ;	if (statres<0) {
   523                                  ;		printf ("ln: %s does not exist\n", argv[1]);
   524                                  ;		exit(1);
   525                                  ;	}
   526                                  ;	if (fflag==0 && (statb.st_mode&S_IFMT) == S_IFDIR) {
   527                                  ;		printf("ln: %s is a directory\n", argv[1]);
   528                                  ;		exit(1);
   529                                  ;	}
   530                                  ;	statres = stat(arg2, &statb);
   531                                  ;	if (statres>=0 && (statb.st_mode&S_IFMT) == S_IFDIR)
   532                                  ;		sprintf(name, "%s/%s", arg2, np);
   533                                  ;	else
   534                                  ;		name = arg2;
   535                                  ;	if (link(argv[1], name)<0) {
   536                                  ;		perror("ln");
   537                                  ;		exit(1);
   538                                  ;	}
   539                                  ;	exit(0);
   540                                  ;}
