This file is indexed.

/usr/share/picolisp/src64/net.l is in picolisp 15.11-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# 30oct15abu
# (c) Software Lab. Alexander Burger

# (port ['T] 'cnt|(cnt . cnt) ['var]) -> cnt
(code 'doPort 2)
   push X
   push Y
   push Z
   ld X E
   ld Y (E CDR)  # Y on args
   ld Z SOCK_STREAM  # Type defaults to TCP
   ld E (Y)  # Eval first arg
   eval
   cmp E TSym  # 'T'?
   if eq  # Yes
      ld Z SOCK_DGRAM  # Type UDP
      ld Y (Y CDR)  # Eval next arg
      ld E (Y)
      eval
   end
   cc socket(AF_INET6 Z 0)  # Create socket
   nul4  # OK?
   js ipSocketErrX  # No
   ld C A  # Keep socket in C
   call closeOnExecAX
   ld A 0  # Socket option "off"
   st4 (Buf)  # Store into 'optval'
   cc setsockopt(C IPPROTO_IPV6 IPV6_V6ONLY Buf 4)  # "Not only IPv6" option
   nul4  # OK?
   js ipV6onlyErrX  # No
   ld B 0  # Clear socket structure
   mset (Addr) SOCKADDR_IN6
   ld A AF_INET6
   st2 (Addr SIN6_FAMILY)
   ld B 0  # Clear sin6_addr
   mset (Addr SIN6_ADDR) 16  # "::" (16 null-bytes)
   cnt E  # Single port-argument?
   if nz  # Yes
      shr E 4  # Port zero?
      if nz  # No
         ld A 1  # Socket option "on"
         st4 (Buf)  # Store into 'optval'
         cc setsockopt(C SOL_SOCKET SO_REUSEADDR Buf 4)  # "Reuse socket" option
         nul4  # OK?
         js ipReuseaddrErrX  # No
      end
      push 0  # <S> No range limit
   else
      atom E  # Port range?
      jnz argErrEX  # No
      ld A (E CDR)  # Get second port
      ld E (E)  # First port
      shr E 4  # Range start
      shr A 4  # Normalize second port
      push A  # <S> Range limit
   end
   do
      cc htons(E)  # Convert port to network order
      st2 (Addr SIN6_PORT)  # Store as port
      cc bind(C Addr SOCKADDR_IN6)  # Try to bind socket
      nul4  # OK?
   while s  # No
      inc E  # Next port in range
      cmp E (S)  # Exceeded limit?
      if gt  # Yes
         cc close(C)  # Close socket
         jmp ipBindErrX
      end
   loop
   add S I  # Drop range limit
   cmp Z SOCK_STREAM  # TCP socket?
   if eq  # Yes
      cc listen(C 5)  # Mark as server socket
      nul4  # OK?
      if s  # No
         cc close(C)  # Close socket
         jmp ipListenErrX
      end
   end
   ld Z C  # Keep socket in Z
   ld Y (Y CDR)  # Eval 'var'
   ld E (Y)
   eval
   cmp E Nil  # Any?
   if ne  # Yes
      ld A SOCKADDR_IN6  # Structure size
      st4 (Buf)  # Store into 'namelen'
      cc getsockname(Z Addr Buf)  # Get socket name
      nul4  # OK?
      if s  # No
         cc close(Z)  # Close socket
         jmp ipGetsocknameErrX
      end
      call needVarEX  # Need variable
      ld2 (Addr SIN6_PORT)  # Get port
      cc ntohs(A)  # Convert to host byte order
      shl A 4  # Make short number
      or A CNT
      ld (E) A  # Store in variable
   end
   ld E Z  # Get socket
   shl E 4  # Make short number
   or E CNT
   pop Z
   pop Y
   pop X
   ret

(code 'tcpAcceptA_FE)
   ld E A  # Save socket in E
   call nonblockingA_A  # Set socket to non-blocking
   push A  # <S> Old socket status flags
   ld C 200  # Maximally 20 seconds
   do
      ld A SOCKADDR_IN6  # Structure size
      st4 (Buf)  # Store into 'addrlen'
      cc accept(E Addr Buf)  # Accept connection
      nul4  # OK?
      if ns  # Yes
         xchg A (S)  # Save new socket, retrieve flags
         cc fcntl(E F_SETFL A)  # Restore socket status flags
         ? (<> *TargetOS "Linux")  # Non-Linux (BSD sockets)?
            cc fcntl((S) F_SETFL 0)  # Yes: Set new socket to non-blocking
         =
         sub S (%% INET6_ADDRSTRLEN)  # Allocate name buffer
         cc inet_ntop(AF_INET6 &(Addr SIN6_ADDR) S INET6_ADDRSTRLEN)
         ld E S
         call mkStrE_E  # Make transient symbol
         ld (Adr) E  # Store in '*Adr'
         add S (%% INET6_ADDRSTRLEN)  # Drop buffer
         ld A (S)  # Get socket
         call initInFileA_A  # Init input file
         ld A (S)
         call initOutFileA_A  # and output file
         pop E  # Get new socket
         shl E 4  # Make short number
         or E CNT  # Return 'nz'
         ret
      end
      cc usleep(100000)  # Sleep 100 milliseconds
      dec C  # Done?
   until z  # Yes
   cc fcntl(E F_SETFL pop)  # Restore socket status flags
   eq  # Return 'z'
   ret

# (accept 'cnt) -> cnt | NIL
(code 'doAccept 2)
   push X
   ld X E
   ld E ((E CDR))  # Eval socket descriptor
   call evCntEX_FE
   ld A E  # Accept connection
   call tcpAcceptA_FE  # OK?
   ldz E Nil  # No
   pop X
   ret

# (listen 'cnt1 ['cnt2]) -> cnt | NIL
(code 'doListen 2)
   push X
   push Y
   push Z
   ld X E
   ld Y (E CDR)  # Y on args
   call evCntXY_FE  # Eval 'cnt1'
   ld Z E  # Keep socket descriptor in Z
   ld Y (Y CDR)  # Next arg
   ld E (Y)
   eval  # Eval 'cnt2'
   cmp E Nil  # Given?
   ldz Y -1  # No timeout
   if ne  # Yes
      call xCntEX_FE  # Milliseconds
      ld Y E
   end
   do
      ld C Z  # Socket descriptor
      ld E Y  # Milliseconds
      call waitFdCEX_A  # Wait for events
      ld E Nil  # Preload NIL
      null A  # Timeout?
   while nz  # No
      ld A Z  # Accept connection
      call tcpAcceptA_FE  # OK?
   until nz  # Yes
   pop Z
   pop Y
   pop X
   ret

# (host 'any) -> sym
(code 'doHost 2)
   push Z
   ld E ((E CDR))  # Eval IP address
   call evSymE_E
   sub S I  # 'lst' buffer
   call bufStringE_SZ  # Write to stack buffer
   cc getaddrinfo(S 0 0 Z)  # Get address info
   ld S Z  # Drop buffer
   pop Z  # Get 'lst' into Z
   ld E Nil  # Preset return value
   nul4  # Address valid?
   if z  # Yes
      sub S (%% NI_MAXHOST)  # <S> Hostname buffer
      ld C Z  # Get 'lst'
      do
         nulp C  # Any?
      while nz  # Yes
         ld4 (C AI_ADDRLEN)
         cc getnameinfo((C AI_ADDR) A S NI_MAXHOST 0 0 NI_NAMEREQD)
         nul4  # OK?
         if z  # Yes
            ld E S
            call mkStrE_E  # Make transient symbol
            break T
         end
         ld C (C AI_NEXT)  # Try next
      loop
      add S (%% NI_MAXHOST)  # Drop buffer
      cc freeaddrinfo(Z)
   end
   pop Z
   ret

# (connect 'any1 'any2) -> cnt | NIL
(code 'doConnect 2)
   push X
   push Y
   push Z
   ld X E
   ld Y (E CDR)  # Y on args
   call evSymY_E  # Eval host
   ld Y (Y CDR)  # Next arg
   ld C SOCK_STREAM
   call serverCEY_FE  # Found server?
   if z  # Yes
      ld Z E  # Keep list in Z
      do
         nulp E  # Any?
      while nz  # Yes
         ld4 (E AI_SOCKTYPE)  # Create socket
         ld C A
         ld4 (E AI_FAMILY)
         cc socket(A C 0)
         nul4  # OK?
         if ns  # Yes
            ld Y A  # Keep socket in Y
            ld4 (E AI_ADDRLEN)
            cc connect(Y (E AI_ADDR) A)  # Try to connect
            nul4  # OK?
            if z  # Yes
               ld A Y
               call closeOnExecAX
               ld A Y  # Get socket
               call initInFileA_A  # Init input file
               ld A Y
               call initOutFileA_A  # and output file
               ld E Y  # Return socket
               shl E 4  # Make short number
               or E CNT
               jmp 80
            end
            cc close(Y)  # Close socket
         end
         ld E (E AI_NEXT)  # Try next
      loop
      ld E Nil  # Return NIL
80    cc freeaddrinfo(Z)
   end
   pop Z
   pop Y
   pop X
   ret

(code 'serverCEY_FE)
   link
   push E  # <L I> Host
   link
   sub S (%% ADDRINFO)  # <S> Hints
   ld B 0  # Clear hints
   mset (S) ADDRINFO
   ld A AF_UNSPEC  # Accept IPv4 and IPv6
   st4 (S AI_FAMILY)  # Store into 'ai_family'
   ld A C  # Get type
   st4 (S AI_SOCKTYPE)  # Store into 'ai_socktype'
   call evSymY_E  # Eval service
   call bufStringE_SZ  # Write to stack buffer
   push Z  # Save pointer to hints
   ld E (L I)  # Get host
   call bufStringE_SZ  # Write to stack buffer
   sub S I  # 'lst' buffer
   cc getaddrinfo(&(S I) &(Z I) (Z) S)  # Get address info
   pop E  # Into 'lst'
   ld S (Z)  # Clean up
   add S (%% ADDRINFO)
   nul4  # Address valid -> 'z'
   ldnz E Nil
   drop
   ret

# (udp 'any1 'any2 'any3) -> any
# (udp 'cnt) -> any
(code 'doUdp 2)
   push X
   push Y
   push Z
   sub S UDPMAX  # Allocate udp buffer
   ld X E
   ld Y (E CDR)  # Y on args
   ld E (Y)  # Eval first
   eval  # 'any1' or 'cnt'
   ld Y (Y CDR)  # Next arg?
   atom Y
   if nz  # No
      call xCntEX_FE  # 'cnt'
      cc recv(E S UDPMAX 0)  # Receive message
      null A  # OK?
      js 10  # No
      ld Z S  # Buffer pointer
      lea (BufEnd) (Z UDPMAX)  # Calculate buffer end
      ld (GetBinZ_FB) getUdpZ_FB  # Set binary read function
      ld (Extn) (ExtN)  # Set external symbol offset
      call binReadZ_FE  # Read item?
      if lt  # No
10       ld E Nil  # Return NIL
      end
   else
      call xSymE_E  # Host
      ld C SOCK_DGRAM
      call serverCEY_FE  # Found server?
      if z  # Yes
         ld X E  # Keep list in X
         ld Y (Y CDR)  # Next arg
         ld E (Y)  # Eval 'any2'
         eval
         ld Y E  # Keep return value in Y
         ld Z S  # Buffer pointer
         lea (BufEnd) (Z UDPMAX)  # Calculate buffer end
         ld (PutBinBZ) putUdpBZ  # Set binary print function
         ld (Extn) (ExtN)  # Set external symbol offset
         call binPrintEZ  # Print item
         ld E X  # Get list
         do
            nulp E  # Any?
         while nz  # Yes
            ld4 (E AI_SOCKTYPE)  # Create socket
            ld C A
            ld4 (E AI_FAMILY)
            cc socket(A C 0)
            nul4  # OK?
            if ns  # Yes
               ld C A  # Keep socket in C
               sub Z S  # Data length
               ld4 (E AI_ADDRLEN)
               cc sendto(C S Z 0 (E AI_ADDR) A)  # Transmit message
               cc close(C)  # Close socket
               ld E Y  # Get return value
               jmp 80
            end
            ld E (E AI_NEXT)  # Try next
         loop
         ld E Nil  # Return NIL
80       cc freeaddrinfo(X)
      end
   end
   add S UDPMAX  # Drop buffer
   pop Z
   pop Y
   pop X
   ret

(code 'getUdpZ_FB 0)
   cmp Z (BufEnd)  # End of buffer data?
   jeq retLt  # Yes: Return 'lt'
   ld B (Z)  # Next byte
   add Z 1  # (gt)
   ret

(code 'putUdpBZ 0)
   cmp Z (BufEnd)  # End of buffer data?
   jeq udpOvflErr  # Yes
   ld (Z) B  # Store byte
   inc Z  # Increment pointer
   ret

# vi:et:ts=3:sw=3