Consolidate license copies
[its.git] / sysdoc / job.100
1 Copyright (c) 1999 Massachusetts Institute of Technology
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 3 of the License, or (at
6 your option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 ------------------------------
17
18 PROGRAMMING TECHNOLOGY DIVISION DOCUMENT                     SYS.xx.yy
19
20
21 IDENTIFICATIONî______________
22
23      The JOB/BOJ Device:  A Mechanism for Implementing
24                           Non-standard Devices
25
26      Marc S. Seriff, Jack Haverty, Richard Stallman (MIT-AI)
27
28      September 18, 1974
29
30
31 INTRODUCTIONî____________
32
33      It is occasionally desirable to extend the ITS system to allow
34
35 for the use of non-standard I/O devices.  A very desirable feature
36
37 would be to allow user-level programs to make use of the newly defined
38
39 devices with out modification of the user-level programs.  For this
40
41 reason the JOB/BOJ device was implemented.
42
43      When a job (call it the user) attempts an OPEN for a file whose
44
45 name is "JOB: <\b-dir>\b-; <\b-fn1>\b- <\b-fn2>\b-", the system creates a
46
47 new job, called the BOJ device handler, or BDH (this is a terrible
48
49 name; it USES the BOJ device and HANDLES the JOB device), and attempts
50
51 to load the file "DSK: <\b-dir>\b-; <\b-fn1>\b- <\b-fn2>\b-" into that job.
52
53 If the load fails, the OPEN will fail.  If this load succeeds, the
54
55 OPEN, as well as all further I/O operations on the user's JOB channel
56
57 will be referred to the BDH for execution.  At that point, it will be
58
59 up to the BDH to decide whether or not the open should fail.  In order
60
61 to get a handle on information about the user's open, The BDH opens
62
63 one or more channels to the "BOJ" device.  The system will insure that
64
65 the BDH's BOJ channel is logically linked to the user's JOB channel.
66
67 The following diagram illustrates what happens:
68 \fPTDD                                2                        SYS.xx.yy
69
70
71
72         __________                    _________
73        |          |                  |         |
74        |   User   |------\bv\b\b__________\b\b\b------>|   BDH   |
75        |__________| | | ---X\bO---  | | |_________|
76                     | |  Sys\b|tem  | |
77                 ____| |_____\b|_____| |____
78                |\bv           |            |\bv
79         The JOB channel    |     The BOJ channel
80                            |
81                            |\bv
82                      System mediates
83
84
85      Once the BDH has successfully opened the BOJ channel, it will be
86
87 notified (via an I/O channel interrupt) every time the user attempts
88
89 an I/O operation on the JOB channel.  The BDH may then examine the
90
91 data that is made available to it about the I/O operation and may
92
93 simulate the operation for the user.  In this way, BDHs can be written
94
95 to give anything the appearance of a disk, tape or other specific type
96
97 of I/O device.
98
99 USING THE JOB DEVICEî_____ ___ ___ ______
100
101      Programs that use the JOB device should not be required to make
102
103 special provisions.  A BDH should, in general, be written so that the
104
105 non-standard device will behave exactly like some standard device.  In
106
107 other words, a user program may open a JOB device using a standard
108
109 open and may then execute any legal I/O operation.
110
111      A file name with something other than "JOB" for a device code can
112
113 be made to act like a JOB device in one of two ways.  The first way
114
115 should be used for devices that are not generally applicable or are
116
117 expected to be used only for a short time.  To use this method simply
118
119 use translates (using MONIT, DDT or directly via system calls) to
120
121 inform the system which file should be used as a BDH.  For instance,
122
123 if we translate all file names of the form "XXX:" into the file name
124 \fPTDD                                3                        SYS.xx.yy
125
126
127 "JOB:ABC;TS RUNXXX", then the system will use the file "DSK:ABC;TS
128
129 RUNXXX" as the BDH for any file name whose device code is "XXX".
130
131      The other method is much simpler and is designed for non-standard
132
133 devices that are to be made available to the entire user community.
134
135 When an OPEN is attempted on a device whose name the system does not
136
137 recognize, the system will examine the "DEVICE;" directory for a file
138
139 whose first name is "JOBDEV" and whose second name is the unrecognized
140
141 device name.  If such a file exists, then the contents of that file
142
143 will be loaded by the system and used as the BDH for the user's OPEN.
144
145 USING THE BOJ DEVICE - THE BOJ DEVICE HANDLERî_____ ___ ___ ______ _ ___ ___ ______ _______
146
147      The BDH is the workhorse in the JOB/BOJ device scheme.  It is
148
149 required to interpret all of the user's I/O operations.  It must do
150
151 everything to make the non-standard device that it represents appear
152
153 standard.  The system provides five .CALLs to give the BDH some of the
154
155 required communcation with the user.
156
157      The first thing that the BDH should do when he is loaded and
158
159 started by the system is to execute an OPEN on the BOJ device.  This
160
161 establishs a logical link between the user and the BDH.  The BDH may
162
163 enable a channel interrupt on the BOJ channel, in order to be informed
164
165 whenever the user attempts an I/O operation.
166
167      It should be noted that the ITS system allows for the possibility
168
169 of a full duplex connection between the user and the BDH (i.e. a
170
171 channel in each direction).  If a user attempts an open for reading
172
173 and an open for writing on the same device, then the system will
174
175 present both opens to the same activation of the BDH.  Should this be
176
177 undesirable for a particular BDH, that BDH should use an open mode
178
179 with the 3.4 bit set (10 in the left half) each time it attempts to
180
181 open the BOJ device.
182 \fPTDD                                4                        SYS.xx.yy
183
184
185 JOBCAL SYSTEM CALLî______ ______ ____
186
187      The first .CALL that will be discussed is the JOBCAL.  This call
188
189 enables the BDH to find out what I/O operation the user has attempted
190
191 to execute.  It has the following calling sequence:
192
193         .CALL   JOBCAL
194         ...             ; Error return
195         ...             ; Success return
196
197 JOBCAL: SETZ
198         SIXBIT/JOBCAL/
199         [<\b-BOJ channel number>\b-]
200         2000,,<\b-opcode>\b-
201         SETZ [-<\b-n>\b-,,<\b-data>\b-]
202
203
204 This .CALL, as well as the other three discussed below, will fail to
205
206 skip if any of the following conditions hold:
207
208         1.  <\b-BOJ channel number>\b- is an illegal channel number.
209
210         2.  <\b-BOJ channel number>\b- is not open on the BOJ device.
211
212         3.  the user job does not exist or as has closed his channel.
213
214         4.  the user job is no longer attempting to execute the I/O
215             operation.
216
217      <\b-opcode>\b- should be an address into which information about
218
219 the I/O operation requested will be placed.  This word contains three
220
221 sections.  The right half of the word contains an integer indicating
222
223 which operation was attempted.  The following table indicates what the
224
225 various integers mean:
226 \fPTDD                                5                        SYS.xx.yy
227
228
229
230        CODE  OPERATIONî       ____  _________
231
232         0    OPEN
233
234         1    IOT (transfer)
235
236         2    STATUS (currently unused)
237
238         3    RESET
239
240         4    RCHST (complete status)
241
242         5    ACCESS
243
244         6    FDELE (for delete or rename while not open)
245
246         7    FDELE (for rename while open)
247
248         8    CALL (see below)
249
250 It is up to the BDH to insure that these I/O operations perform as
251
252 they would for standard ITS devices.
253
254      The top three bits (4.9-4.7) of the op-code word contain the mode
255
256 in which user is attempting to open his channel.  This is only
257
258 meaningful for op-code 0, OPEN.  If either of the next two bits (4.6
259
260 and 4.5) are non-zero, then the user is requesting that a channel be
261
262 closed.  As was mentioned above, the system allows the connection
263
264 between user and BDH to be full dumplex.  If the 4.6 bit of the opcode
265
266 is set, then the user is requesting that his input channel be closed,
267
268 while the 4.5 bit requests a close of the user's output channel.  It
269
270 is possible to get an opcode in which both bits are set.  In the case
271
272 the BDH should perform the obvious task of closing both channels.
273
274      Most I/O operations require more information than just the name
275
276 of the operation.  The third argument to JOBCAL tells the system where
277
278 any additional information that is available should be placed.
279
280 <\b-n>\b- is the largest number of words that the BDH is willing to
281 \fPTDD                                6                        SYS.xx.yy
282
283
284 accept (it should normally be 12).  <\b-data>\b- is the address where
285
286 the first word of the information should be placed.  What information
287
288 is placed in this buffer is determined by the I/O operation being
289
290 attempted.
291
292      If the op-code (in the right half of the op-code word) is less
293
294 than 8, then five words will be written into the buffer (beginning at
295
296 <\b-data>\b-) in response to the JOBCAL.  The meanings of the words are
297
298 given in the following table:
299 \fPTDD                                7                        SYS.xx.yy
300
301
302
303 WORD          OPERATIONS               MEANINGî____          __________               _______
304
305   1      IOT (1)                  Meaningful only for block IOTs.
306                                   This word will contain the user's
307                                   IOT pointer.  The left half of this
308                                   word will be the negative of the
309                                   number of words that the user wants.
310
311   1      ACCESS (5)               The address within the virtual file
312                                   that is open from (or to) which the
313                                   next IOT should be done.  The first
314                                   word of the virtual file is word
315                                   zero.
316
317   1      FDELE (6 or 7)           Zero implies delete requested.
318                                   Non-zero means that a rename is
319                                   requested.  This word is the name
320                                   (in sixbit) to be used as the new
321                                   first file name.
322
323   2      OPEN (0) or FDELE (6)    First name of the file that the user
324                                   is attempting to open, rename or
325                                   delete.
326
327   3      OPEN (0) or FDELE (6)    Second name of the file that the
328                                   user is attempting to open, rename
329                                   or delete.
330
331   4      OPEN (0) or FDELE (6)    Name of directory to be used for
332                                   open, rename or delete.
333
334   5      OPEN (0) or FDELE (6)    Name of device to be used for open,
335                                   rename or delete.
336
337   6      OPEN (0)                 The full 18 bit open mode (right
338                                   justified).
339
340   6      FDELE (6 or 7)           Zero implies delete.  Non-zero means
341                                   that a rename is requested.  This
342                                   word is the name (in sixbit) to be
343                                   used as the new second file name.
344
345      If the op-code returned by JOBCAL is 8, then the user has
346
347 attempted some I/O operation not recognized by the systems JOB/BOJ
348
349 device code (this does not mean that the operation is illegal).  Inî                       ___
350
351 this case, more information is written into the BDH's buffer (up to
352
353 twelve words).  The first of the data words will be the SIXBIT name of
354 \fPTDD                                8                        SYS.xx.yy
355
356
357 the operation being performed.  (This will normally be the name of the
358
359 .CALL executed by the user - see Appendix 1 for a list of
360
361 possiblities.) The second word will contain all of the flags that the
362
363 user has set using the "flag" feature of the .CALL UUO.  The third
364
365 word will be an integer indicating how many input (to the system)
366
367 arguments the user supplied in his .CALL.  It should be noted that if
368
369 this integer is larger than <\b-n>\b-+3, then some information will be
370
371 lost.  The values of the input arguments will appear in the remainder
372
373 of the words in the buffer.  Remember that, in almost all cases, the
374
375 first of the input arguments will be the user's channel number.
376
377 JOBRET SYSTEM CALLî______ ______ ____
378
379      Once the BDH has interpreted the user's request for execution of
380
381 an I/O operation, the BDH must have some way of responding to the
382
383 user.  This is provided with the JOBRET .CALL.  This .CALL serves
384
385 three purposes:
386
387         1.  to unblock the user who is waiting for completion of his
388             I/O request (possibly causing the request to skip)
389
390         2.  to set lossage codes in the user's status words (e.g. for
391             failed opens).
392
393         3.  to return information requested by the user's I/O
394             operation.
395
396 The format of this CALL is as follows:
397
398         .CALL   JOBRET
399         ...             ; error return
400         ...             ; success return
401
402 JOBRET: SETZ
403         SIXBIT /JOBRET/
404         [<\b-BOJ channel number>\b-]
405         [<\b-return>\b-]
406         SETZ [-<\b-n>\b-,,<\b-data>\b-]
407
408
409 where <\b-return>\b- satisfies requirements 1 and 2 above.  If
410 \fPTDD                                9                        SYS.xx.yy
411
412
413 <\b-return>\b- is zero, then the user's I/O call will not skip or set
414
415 status bits.  If <\b-return>\b- is of the form <\b-i>\b-,,<\b-j>\b- , then
416
417 <\b-i>\b- will be placed in the "open-loss" field of the status word for
418
419 the user's channel and the user's I/O call will skip <\b-j>\b- times.  A
420
421 list of all currently recognized open loss codes can be found in
422
423 Appendix 2.
424
425      If the user's I/O call requested data, then the BDH can supply
426
427 this data by supplying the third argument to the JOBRET call.  The
428
429 system will use the <\b-n>\b- words beginning at location <\b-data>\b- as
430
431 the values for the return arguments in the user's call.
432
433 SETIOC AND JOBINT -- INTERRUPT SYSTEM CALLSî______ ___ ______ __ _________ ______ _____
434
435      There are two interrupt oriented functions that the BDH must
436
437 perform and there are CALLs available to perform them.  The first is
438
439 to notify the user when he has done something catastrophic.  The user
440
441 should be notified of his error by causing the system to awaken him
442
443 with an I/O channel error.  This done with the SETIOC call, as
444
445 follows:
446
447         .CALL   SETIOC
448         ...             ; error return (standard reasons
449                                 + illegal IOCERR code)
450         ...             ; success return
451
452 SETIOC: SETZ
453         SIXBIT/SETIOC/
454         [<\b-BOJ channel number>\b-]
455         SETZ [<\b-IOCERR code>\b-]
456
457
458 where <\b-IOCERR code>\b- is an integer identifying the reason for the
459
460 error.  This integer should be chosen from the list that can be found
461
462 in Appendix 2.  Since BDHs are written to handle non-standard devices,
463
464 these error codes will quite often not apply.  Simply choose the code
465
466 that comes closest.
467 \fPTDD                                10                       SYS.xx.yy
468
469
470      Occassionally, the BDH must notify the user of a non-catastrophic
471
472 situation (e.g. the arrival of data).  The JOBINT call allows the BDH
473
474 to give the user a second-word I/O channel interrupt, as follows:
475
476         .CALL   JOBINT
477         ...             ; error return
478         ...             ; success return
479
480 JOBINT: SETZ
481         SIXBIT /JOBINT/
482         SETZ [<\b-BOJ channel number>\b-]
483
484
485 JOBSTS SYSTEM CALLî______ ______ ____
486
487      Finally, the BDH must have some way to notify the system what the
488
489 status of the pseudo-device is.  For this purpose, the JOBSTS call is
490
491 available.  Its calling sequence is as follows:
492
493         .CALL   JOBSTS
494         ...             ; error return
495         ...             ; success return
496
497 JOBSTS: SETZ
498         SIXBIT /JOBSTS/
499         [<\b-BOJ channel number>\b-]
500         SETZ [<\b-new status>\b-]
501
502
503 The right half of <\b-new status>\b- will be given to anyone requesting
504
505 the status of the user's channel until another JOBSTS is done.  It
506
507 should be remembered that the low order six bits (1.1-1.6) should
508
509 contain the device code of the pseudo-device.  Unless, you know what
510
511 you are doing, this should always be 22 octal.
512
513 DATA TRANSFERS - HOW TO IOTî____ _________ _ ___ __ ___
514
515      Since the main purposes of I/O devices is transfer of
516
517 information, let us look at how the BDH manages to respond to the
518
519 user's IOTs.  The method for doing this is very simply.  If we think
520
521 back to the diagram presented early in this memo, we will remember
522 \fPTDD                                11                       SYS.xx.yy
523
524
525 that the BOJ and JOB channels (i.e. the channels belonging to the BDH
526
527 and the user, respectively) are logically connected.  The full meaning
528
529 of this now becomes clear.  If the JOB channel is open for input and
530
531 the BOJ channel is open for output, then anything that BDH outputs on
532
533 the BOJ channel will be available to the user as input on the JOB
534
535 channel.  (For this reason, the BDH must insure that he opens the BOJî                                    ____
536
537 channel in the opposite direction from the user's JOB channel even if
538
539 this requires opening the BOJ channel a second time in the correct
540
541 mode.)
542
543      There are two features of which the BDH implementer should be
544
545 aware when writing the I/O sections of the BDH.  Let us assume for the
546
547 discussion here, that the user has the JOB channel open for reading
548
549 and that the BDH has the BOJ channel open for writing.  Let us also
550
551 assume that the user is currently hung attempting to read 100 words on
552
553 his JOB channel.
554
555      First it should be noted that the BDH does not have to respond toî                                                ___
556
557 this request with a single transfer of 100 words.  The system will act
558
559 as an mediator between different transfer sizes.  The BDH can respond
560
561 to the user's request for 100 words in several ways:
562
563         1.  He can send all 100 words in small pieces (e.g. 10
564
565             transfers of 10 words each.
566
567         2.  He can send all 100 words in a single transfer.
568
569         3.  He can send more than 100 words.  In this case, the BDH
570
571             will remain hung in his IOT until the user has read all of
572
573             the data that the BDH is attempting to send.  (If this is
574
575             undesirable, set the 3.5 in the BOJ open mode.  This will
576
577             cause BOJ IOTs to unhang whenever the user's IOT is
578 \fPTDD                                12                       SYS.xx.yy
579
580
581             satisfied. When that happens, the BOJ IOT pointer will
582
583             have been counted out only partially; the RH will point to
584
585             the first word not transfered)
586
587         4.  He may send less than 100 words.  In this case, the BDH
588
589             must manually awaken the user as described below.
590
591 The user, who is hung awaiting his 100 words, will stay hung until he
592
593 has received all 100 words.  Suppose, however, that the BDH only
594
595 wishes to send 50 words (e.g. the last 50 words of the virtual file).
596
597 To do this, he can send the 50 words normally, but must then use the
598
599 JOBRET call (described above) to awaken the user.  JOBRET should be
600
601 called with the BOJ channel number as the first argument, zero as the
602
603 second argument and no third argument.  Secondly, the BDH implementer
604
605 must be aware that the ITS system guarantees that IOTs to a channel
606
607 open in block mode, will never generate an I/O channel error.  In
608
609 other words, the following algorithm should be followed:
610
611         1.  If the user requests n words and there are n words or more
612
613             left in the "file", give him n words.
614
615         2.  If the user requests n words and there are only m words
616
617             (n>m), give him m words and manually awaken him (using
618
619             JOBRET).
620
621         3.  If the user requests n words and there are no words left,
622
623             then give him nothing and manually awaken him (using
624
625             JOBRET).
626
627 HINTS TO BDH IMPLEMENTERSî_____ __ ___ ____________
628
629      The following hints should ease the task of BDH implementers a
630
631 little.  It is hoped that anyone who attempts to a BDH implementation
632
633 will add his harshly acquired knowledge to this section of this memo.
634 \fPTDD                                13                       SYS.xx.yy
635
636
637 1.  Remember that the BDH is essentially a disowned job and should
638
639     attempt to log out after a close has been requested.
640
641 2.  Be very leery of logging out for any reason other than a requested
642
643     CLOSE.  In particular:
644
645     a.  if a JOBCAL fails, only log out if a request for OPEN has not
646
647         yet been received.
648
649     b.  when you generate an I/O channel error for the user, only log
650
651         out if the error is irrecoverable.  Remember that he can
652
653         correct an access beyond end-of-file by doing an access before
654
655         attempting another IOT.
656
657     c.  if he requests an I/O operation that you do not recognize,
658
659         generate a "mode not available" error (via JOBRET) and wait
660
661         for his next request.
662
663     d.  if you decide, for your own reasons, to make the initial open
664
665         fail, you should log out.
666
667 THE OJB DEVICE -- AN AID FOR DEBUGGING THE BDHî___ ___ ______ __ __ ___ ___ _________ ___ ___
668
669      One of the problems with debugging BDH programs is that when the
670
671 JOB device is used, it is loaded into a newly created job. That job is
672
673 not inferior to any DDT, and there is no way to put breakpoints in it
674
675 before it starts. The OJB device makes it possible to run the BDH
676
677 program under DDT.
678
679      The OJB device acts just like the JOB device except during the
680
681 initial open. When the JOB device would be creating and loading a new
682
683 job, the OJB device is looking for an existing job whose UNAME and
684
685 JNAME are the same as the filenames specified in the open.  If such a
686
687 job is found, it is connected to the job opening the OJB device
688
689 through a standard JOB-BOJ pipeline.  If such a job does not exist,
690 \fPTDD                                14                       SYS.xx.yy
691
692
693 the open of the OJB device fails.  In order to protect innocent jobs
694
695 from being hacked in this matter, the job opened on the OJB device is
696
697 required to have set its OPTOJB bit (this is bit 4.2 in the .OPTION
698
699 varisble, settable with .SUSET).  Also, it must not already be a BDH,
700
701 for the system cannot consider one job to be a BDH through two
702
703 connections at once.  If either of those conditions is not met, the
704
705 OJB open WAITS until they are.
706
707      To remove a possible timing screw, a BOJ device open by a job
708
709 that is not a BDH, which usually fails, will wait instead for the job
710
711 to become a BDH if the job's OPTOJB bit is set.
712
713      The procedure for using the OJB device for debugging is:
714
715
716      1.  create a job to use for the BDH (call it J, in this example).
717
718      2.  run (in another job) the program which would normally open
719
720 the JOB device, but tell it (perhaps by means of a translation) to use
721
722 the OJB device instead.  This program's function is to issue system
723
724 calls so that the BDH's responses to them can be tested.
725
726      Since the OPTOJB bit of job J is now 0, when this program reaches
727
728 the OJB open it will hang.
729
730      3.  ^Z that program, and ^P it. it will go back to hanging in the
731
732 open of the OJB device.
733
734      4.  switch to job J, load in the BDH program.  This RESET's the
735
736 job so that if it had been a BDH before, it will not be one now.
737
738      5.  turn on the OPTOJB bit by depositing from DDT in .OPTION.
739
740 The conditions for a successful OJB open by job JJ have now been met,
741
742 so that job will make some headway, turning job J into a BDH and
743
744 waiting for job J to issue a JOBRET.
745 \fPTDD                                15                       SYS.xx.yy
746
747
748      6.  it is now possible to start running job J, with breakpoints
749
750 as desired, to step through the code for handling the initial open.
751
752 It is unlikely, but theoretically possible, for J to execute its BOJ
753
754 open before JJ gets around to turning J into a BDH.  In this case, J
755
756 will wait for JJ to do so.
757
758      7.  if it becomes necessary to try again after discovering a bug,
759
760 go back to step 2.  The OJB open will hang up this time not because
761
762 the OPTOJB bit is off (since it is still 1) but because J is already a
763
764 BDH.  Loading J in step 4 will make J cease to be a BDH but also turn
765
766 off the OPTOJB bit, so JJ will still be waiting.
767
768      8.  it is possible for job JJ to be "PCLSR'ed" or backed up out
769
770 of its open while job J is being traced through the handling of the
771
772 initial open.  For example, job JJ might receive a real-time
773
774 interrupt.  If that happens, J will cease to be a BDH.  This will not
775
776 interfere with the tracing of J until the next BOJ device system call
777
778 is executed; that call will probably fail.  It is impossible to
779
780 continue after such an occurrence, so the jobs must be restarted by
781
782 returning to step 2.  Of course, if there are no breakpoints before
783
784 the first JOBRET, this is very unlikely to happen.
785
786      9.  if the initial open has been handled successfully, to go on
787
788 to debug handling of other system calls, simply tell JJ to execute
789
790 them with J stopped while JJ is being told, then ^Z^P JJ and go back
791
792 to J.
793
794      10. the usual .LOGOUT in the BDH program will be a no-op when the
795
796 program is run as an inferior in this manner, so it should be followed
797
798 by a .VALUE.
799 \f\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0