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 kermit: proc;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 debug
48
49
50
51
52
53
54
55
56
57
58 dcl true bit (1) static options (constant) init ("1"b);
59 dcl false bit (1) static options (constant) init ("0"b);
60
61 dcl Subsystem_Name char (6) static options (constant)
62 init ("kermit");
63 dcl Subsystem_Version char (3) static options (constant)
64 init ("1.5");
65 dcl Subsystem_Info_Dir char (168) static options (constant)
66 init (">doc>subsystem>kermit");
67 dcl Default_prompt char (29) static options (constant)
68 init ("^/Multics-Kermit^[ (^d)^]:^2x");
69
70
71
72 dcl com_err_ entry() options(variable);
73 dcl cu_$arg_count_rel entry (fixed bin, ptr, fixed bin(35));
74 dcl cu_$arg_list_ptr entry (ptr);
75 dcl cu_$arg_ptr_rel entry (fixed bin, ptr, fixed bin(21),
76 fixed bin(35), ptr);
77 dcl expand_pathname_ entry (char(*), char(*), char(*),
78 fixed bin(35));
79 dcl expand_pathname_$add_suffix
80 entry (char(*), char(*), char(*), char(*),
81 fixed bin(35));
82 dcl get_system_free_area_ entry() returns(ptr);
83 dcl initiate_file_ entry (char(*), char(*), bit(*), ptr,
84 fixed bin(24), fixed bin(35));
85 dcl iox_$attach_name entry (char (*), ptr, char (*), ptr, fixed bin (35));
86 dcl iox_$close entry (ptr, fixed bin (35));
87 dcl iox_$detach_iocb entry (ptr, fixed bin (35));
88 dcl iox_$look_iocb entry (char(*), ptr, fixed bin(35));
89 dcl iox_$open entry (ptr, fixed bin, bit (1) aligned, fixed bin (35));
90 dcl pathname_ entry (char(*), char(*)) returns(char(168));
91 dcl ssu_$add_request_table entry (ptr, ptr, fixed bin, fixed bin(35));
92 dcl ssu_$create_invocation entry (char(*), char(*), ptr, ptr, char(*),
93 ptr, fixed bin(35));
94 dcl ssu_$destroy_invocation entry (ptr);
95 dcl ssu_$execute_start_up entry () options (variable);
96 dcl ssu_$execute_string entry (ptr, char(*), fixed bin(35));
97 dcl ssu_$get_temp_segment entry (ptr, char(*), ptr);
98 dcl ssu_$listen entry (ptr, ptr, fixed bin(35));
99 dcl ssu_$release_temp_segment
100 entry (ptr, ptr);
101 dcl ssu_$set_abbrev_info entry (ptr, ptr, ptr, bit(1) aligned);
102 dcl ssu_$set_prompt entry (ptr, char(64) var);
103 dcl ssu_$set_prompt_mode entry (ptr, bit(*));
104 dcl unique_chars_ entry (bit (*)) returns (char (15));
105
106
107
108 dcl error_table_$badopt external fixed bin (35);
109 dcl error_table_$noarg external fixed bin (35);
110 dcl error_table_$noentry external fixed bin (35);
111 dcl iox_$user_input ptr ext static;
112 dcl iox_$user_io ptr ext static;
113 dcl kermit_requests_$requests
114 bit(36) aligned external;
115 dcl ssu_et_$subsystem_aborted
116 external fixed bin (35);
117 dcl ssu_request_tables_$standard_requests
118 bit(36) aligned external;
119
120
121
122 dcl 01 info aligned like kermit_info;
123 dcl 01 kermit_args aligned,
124 02 flags aligned,
125 03 request_loop bit (1) unaligned,
126 03 abbrev bit (1) unaligned,
127 03 prompt bit (1) unaligned,
128 03 start_up bit (1) unaligned,
129 03 debug bit (1) unaligned,
130 03 prompt_given bit (1) unaligned,
131 03 profile_given bit (1) unaligned,
132 03 switchname_given bit (1) unaligned,
133 03 request_given bit (1) unaligned,
134 03 pad bit (27) unaligned,
135 02 prompt char (64) varying,
136 02 profile char (168),
137 02 switchname char (32),
138 02 request char (512) varying,
139 02 debug_path char (168) unaligned;
140
141
142
143 dcl arg_listp ptr;
144 dcl ec fixed bin (35);
145
146
147
148 dcl cleanup condition;
149
150
151
152 dcl addr builtin;
153 dcl index builtin;
154 dcl null builtin;
155
156
157
158 %include access_mode_values;
159 ^L
160 %include iox_modes;
161 ^L
162 %include kermit_info;
163 ^L
164 %include kermit_dcls;
165 ^L
166 %include kermit_mode_info;
167 ^L
168 %include ssu_prompt_modes;
169 ^L
170 %include terminate_file;
171
172
173 ^L
174
175
176
177
178
179
180 info.version = kermit_info_version;
181 info.sci_ptr = null;
182 info.perm_modesp = null;
183 info.temp_modesp = null;
184 info.log_infop = null;
185 info.comm_infop = null;
186
187 on cleanup call kermit_cleanup (addr (info));
188
189
190
191 call cu_$arg_list_ptr (arg_listp);
192
193 call parse_command_line (arg_listp, addr (kermit_args));
194
195
196
197 call kermit_initialization (addr (kermit_args), addr (info));
198
199
200
201 if kermit_args.request_loop
202 then call ssu_$listen (info.sci_ptr, iox_$user_input, ec);
203
204 call kermit_cleanup (addr (info));
205
206 return;
207
208
209 ^L
210
211
212
213 parse_command_line: proc (arg_listp, argsp);
214
215
216
217
218
219
220
221
222
223
224
225
226 debug
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 debug
280
281
282
283
284
285 dcl arg_listp ptr;
286 dcl argsp ptr;
287
288
289
290 dcl 01 args aligned like kermit_args based (argsp);
291
292
293
294 dcl arg char (argl) based (argp);
295
296
297
298 dcl argl fixed bin (21);
299 dcl argp ptr;
300 dcl debug_pending bit (1);
301 dcl ec fixed bin (35);
302 dcl i fixed bin;
303 dcl nargs fixed bin;
304 dcl profile_pending bit (1);
305 dcl prompt_pending bit (1);
306 dcl request_pending bit (1);
307 dcl switchname_pending bit (1);
308
309
310
311 args.flags.request_loop = true;
312 args.flags.abbrev = false;
313 args.flags.prompt = true;
314 args.flags.start_up = true;
315 args.flags.debug = false;
316 args.flags.prompt_given = false;
317 args.flags.profile_given = false;
318 args.flags.switchname_given = false;
319 args.flags.request_given = false;
320 args.prompt = "";
321 args.profile = "";
322 args.switchname = "";
323 args.request = "";
324 args.debug_path = "";
325
326 profile_pending = false;
327 prompt_pending = false;
328 request_pending = false;
329 switchname_pending = false;
330 debug_pending = false;
331
332
333
334 call cu_$arg_count_rel (nargs, arg_listp, ec);
335 if ec ^= 0
336 then call abort (ec, "");
337
338 do i = 1 to nargs;
339
340 call cu_$arg_ptr_rel (i, argp, argl, ec, arg_listp);
341 if ec ^= 0
342 then call abort (ec, "");
343
344
345
346 if prompt_pending
347 then do;
348 if index (arg, "-") = 1
349 then call abort (error_table_$noarg, "Prompt string expected.");
350 prompt_pending = false;
351 args.flags.prompt_given = true;
352 args.prompt = arg;
353 end;
354
355
356
357 else if profile_pending
358 then do;
359 if index (arg, "-") = 1
360 then call abort (error_table_$noarg, "Profile pathname expected.");
361 profile_pending = false;
362 args.flags.profile_given = true;
363 args.flags.abbrev = true;
364 args.profile = arg;
365 end;
366
367
368
369 else if request_pending
370 then do;
371 if index (arg, "-") = 1
372 then call abort (error_table_$noarg, "Request expected.");
373 request_pending = false;
374 args.flags.request_given = true;
375 args.request = arg;
376 end;
377
378
379
380 else if switchname_pending
381 then do;
382 if index (arg, "-") = 1
383 then call abort (error_table_$noarg, "Switch name expected.");
384 switchname_pending = false;
385 args.flags.switchname_given = true;
386 args.switchname = arg;
387 end;
388
389 debugdebug
390
391 else if debug_pending
392 then do;
393 if index (arg, "-") = 1
394 then call abort (error_table_$noarg, "Debug pathname expected.");
395 debug_pending = false;
396 args.flags.debug = true;
397 args.debug_path = arg;
398 end;
399
400
401
402 else if arg = "-abbrev" | arg = "-ab"
403 then args.flags.abbrev = true;
404
405 debug
406
407 else if arg = "-debug" | arg = "-db"
408 then debug_pending = true;
409
410
411
412 else if arg = "-io_switch" | arg = "-iosw"
413 then switchname_pending = true;
414
415
416
417 else if arg = "-no_abbrev" | arg = "-nab"
418 then args.flags.abbrev = false;
419
420
421
422 else if arg = "-no_prompt" | arg = "-npmt"
423 then args.flags.prompt = false;
424
425
426
427 else if arg = "-no_start_up" | arg = "-nsu" | arg = "-ns"
428 then args.flags.start_up = false;
429
430
431
432 else if arg = "-profile" | arg = "-pfl"
433 then profile_pending = true;
434
435
436
437 else if arg = "-prompt" | arg = "-pmt"
438 then prompt_pending = true;
439
440
441
442 else if arg = "-quit" | arg = "-no_request_loop" | arg = "-nrql"
443 then args.flags.request_loop = false;
444
445
446
447 else if arg = "-request" | arg = "-rq"
448 then request_pending = true;
449
450
451
452 else if arg = "-request_loop" | arg = "-rql"
453 then args.flags.request_loop = true;
454
455
456
457 else if arg = "-start_up" | arg = "-su"
458 then args.flags.start_up = true;
459
460
461
462 else call abort (error_table_$badopt, arg);
463 end;
464
465
466
467
468 if request_pending
469 then call abort (error_table_$noarg, "Request expected.");
470 if profile_pending
471 then call abort (error_table_$noarg, "Profile pathname expected.");
472 if switchname_pending
473 then call abort (error_table_$noarg, "Switch name expected.");
474 if prompt_pending
475 then call abort (error_table_$noarg, "Prompt string expected.");
476 if debug_pending
477 then call abort (error_table_$noarg, "Debug path expected.");
478
479 end parse_command_line;
480
481
482 ^L
483
484
485
486 kermit_initialization: proc (argsp, infop);
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509 dcl argsp ptr;
510 dcl infop ptr;
511
512
513
514 dcl 01 args aligned like kermit_args based (argsp);
515 dcl 01 info aligned like kermit_info based (infop);
516 dcl 01 log_info aligned like kermit_log_info
517 based (info.log_infop);
518 dcl 01 perm_modes aligned like kermit_perm_modes
519 based (info.perm_modesp);
520 dcl 01 temp_modes aligned like kermit_temp_modes
521 based (info.temp_modesp);
522 dcl 01 comm_info aligned like kermit_comm_info
523 based (info.comm_infop);
524 dcl sys_area area based (system_free_areap);
525
526
527
528 dcl dname char (168);
529 dcl ec fixed bin (35);
530 dcl ename char (32);
531 dcl system_free_areap ptr;
532 dcl profile_ptr ptr;
533 dcl prompt_mode bit (2);
534
535
536
537 system_free_areap = get_system_free_area_ ();
538
539
540
541 allocate log_info in (sys_area);
542
543
544
545 log_info.log_file.iocbp = null;
546 log_info.version = kermit_log_info_version;
547
548 allocate perm_modes in (sys_area);
549 perm_modes.version = kermit_perm_modes_version;
550
551 allocate temp_modes in (sys_area);
552 temp_modes.version = kermit_temp_modes_version;
553
554 allocate comm_info in (sys_area);
555
556
557
558 comm_info.input_buffer.bufferp = null;
559 comm_info.debug_segp = null;
560 comm_info.version = kermit_comm_info_version;
561 comm_info.server = "0"b;
562 comm_info.transfer_modes_set = "0"b;
563
564
565
566 call ssu_$create_invocation (Subsystem_Name, Subsystem_Version, infop,
567 addr (ssu_request_tables_$standard_requests),
568 Subsystem_Info_Dir, info.sci_ptr, ec);
569
570 if ec ^= 0
571 then call abort (ec, "Unable to create subsystem invocation.");
572
573
574
575 call ssu_$add_request_table (info.sci_ptr, addr (kermit_requests_$requests),
576 1, ec);
577
578
579
580 if ^args.flags.prompt_given
581 then args.prompt = Default_prompt;
582
583 call ssu_$set_prompt (info.sci_ptr, args.prompt);
584
585 if args.flags.prompt
586 then prompt_mode = PROMPT | PROMPT_AFTER_NULL_LINES;
587 else prompt_mode = DONT_PROMPT | PROMPT_AFTER_NULL_LINES;
588
589 call ssu_$set_prompt_mode (info.sci_ptr, prompt_mode);
590
591
592
593 if args.flags.profile_given
594 then do;
595 call expand_pathname_$add_suffix ((args.profile), "profile", dname,
596 ename, ec);
597 if ec ^= 0
598 then call abort (ec, (args.profile));
599 call initiate_file_ (dname, ename, R_ACCESS, profile_ptr, (0), ec);
600 if profile_ptr = null
601 then if ec = error_table_$noentry
602 then call com_err_ (ec, Subsystem_Name, "^/^a does not exist.",
603 pathname_ (dname, ename));
604 else call abort (ec, (args.profile));
605 end;
606 else profile_ptr = null;
607
608
609
610 call ssu_$set_abbrev_info (info.sci_ptr, profile_ptr, profile_ptr,
611 (args.flags.abbrev));
612
613
614
615
616 if args.flags.switchname_given
617 then do;
618 call iox_$look_iocb ((args.switchname), comm_info.ft_iocbp, ec);
619 if ec ^= 0
620 then call abort (ec, (args.switchname));
621 end;
622 else comm_info.ft_iocbp = iox_$user_io;
623
624
625
626 call kermit_mode_mgr_$store (infop, Permanent, Store_all,
627 addr (Perm_defaults), ec);
628 call kermit_mode_mgr_$store (infop, Temporary, Store_all,
629 addr (Temp_defaults), ec);
630
631
632
633 log_info.flags.enabled = false;
634 log_info.flags.stats_valid = false;
635
636
637
638 call ssu_$get_temp_segment (info.sci_ptr, "buffer", comm_info.bufferp);
639
640
641
642 comm_info.bufferl = 0;
643 comm_info.old_modes = "";
644 comm_info.old_framing_chars.start_char = "^@";
645 comm_info.old_framing_chars.end_char = "^@";
646 comm_info.old_wake_table.breaks (*) = false;
647 comm_info.old_wake_table.mbz = ""b;
648
649 debug
650
651 if args.flags.debug
652 then do;
653 call expand_pathname_ (args.debug_path, dname, ename, ec);
654 if ec ^= 0
655 then call abort (ec, args.debug_path);
656 call iox_$attach_name ("kermit.debug." || unique_chars_ ("0"b),
657 comm_info.debug_segp, "vfile_ " || pathname_ (dname, ename),
658 null(), ec);
659 call iox_$open (comm_info.debug_segp, Stream_output, "0"b, ec);
660 if ec ^= 0
661 then call abort (ec, pathname_ (dname, ename));
662 end;
663
664
665
666 if args.flags.start_up
667 then do;
668 call ssu_$execute_start_up (info.sci_ptr, ec);
669 if ec = ssu_et_$subsystem_aborted
670 then call abort (ec, "^/Abort occurred while executing start_up.");
671 end;
672
673
674
675 if args.flags.request_given
676 then do;
677 call ssu_$execute_string (info.sci_ptr, (args.request), ec);
678 if ec = ssu_et_$subsystem_aborted
679 then args.request_loop = false;
680 end;
681
682 end kermit_initialization;
683
684
685 ^L
686
687
688
689 kermit_cleanup: proc (infop);
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707 dcl infop ptr;
708
709
710
711 dcl 01 comm_info aligned like kermit_comm_info
712 based (info.comm_infop);
713 dcl 01 info aligned like kermit_info based (infop);
714 dcl 01 log_info aligned like kermit_log_info
715 based (info.log_infop);
716 dcl 01 perm_modes aligned like kermit_perm_modes
717 based (info.perm_modesp);
718 dcl sys_area area based (system_free_areap);
719 dcl 01 temp_modes aligned like kermit_temp_modes
720 based (info.temp_modesp);
721
722
723
724 dcl system_free_areap ptr;
725
726
727
728 system_free_areap = get_system_free_area_ ();
729
730
731
732 if info.comm_infop ^= null
733 then do;
734
735
736
737 if comm_info.input_buffer.bufferp ^= null
738 then call ssu_$release_temp_segment (info.sci_ptr,
739 comm_info.input_buffer.bufferp);
740
741 debug
742
743 if comm_info.debug_segp ^= null
744 then do;
745 call iox_$close (comm_info.debug_segp, ec);
746 call iox_$detach_iocb (comm_info.debug_segp, ec);
747 end;
748
749
750
751 free comm_info in (sys_area);
752 end;
753
754 if info.perm_modesp ^= null
755 then free perm_modes in (sys_area);
756 if info.temp_modesp ^= null
757 then free temp_modes in (sys_area);
758 if info.log_infop ^= null
759 then do;
760
761
762
763 call kermit_log_mgr_$disable (infop, ec);
764 call kermit_log_mgr_$close_log (infop, ec);
765
766
767
768 free log_info in (sys_area);
769 end;
770
771
772
773 if info.sci_ptr ^= null
774 then call ssu_$destroy_invocation (info.sci_ptr);
775
776 end kermit_cleanup;
777
778
779 ^L
780
781
782
783 abort: proc (code, message);
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799 dcl code fixed bin (35);
800 dcl message char (*);
801
802
803
804 call kermit_cleanup (addr (info));
805
806 call com_err_ (code, Subsystem_Name, message);
807 goto ABORT;
808
809 end abort;
810
811 ABORT:
812 return;
813
814 end kermit;