-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLD.C
More file actions
6045 lines (5565 loc) · 196 KB
/
LD.C
File metadata and controls
6045 lines (5565 loc) · 196 KB
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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#define LD_MODULE "X-20"
#define LD_VERSION "V9.8"
#ifdef SYSINIT_OPCCRASH
#pragma module LD_SYSINIT_OPCCRASH LD_MODULE
#else
#pragma module LD LD_MODULE
#endif
//**********************************************************************//
// //
// These sources for LDdriver are based on the sources provided in the //
// LD V9.7 kit as provided by Jur van den Burg on digiater.nl. //
// VMS Software, Inc (VSI) has put its changes to these sources in the //
// public domain. //
// //
// The original license statement for LD 9.7 reads as follows: //
// //
// LDdriver is freeware. It may be freely downloaded and used. The //
// sources are available in the kit, and support is limited. In case of //
// problems report them and they may get fixed. We are not responsible //
// for any malfunction or data loss caused by this software. //
// //
//**********************************************************************//
//
// Facility:
//
// VAX/VMS Logical Disk Utility
//
// Abstract:
//
// This utility enables the user to create, setup and display
// information of the Logical Disks available in the system,
// via the LDDRIVER.
//
// Author:
//
// Jur van der Burg 13-OCT-1992 Version 2.0
// (lddriver@digiater.nl)
//
// Rewritten from original MACRO version (by A. Sweep) for easier
// maintenance.
//
// Revision:
//
// X-20 CMOS Christian Moser 20-Jun-2022
// Remove setting NOLOCK bit in the FIB when accessing a tape container.
//
// X-19 RAB Richard A. Bishop 23-Aug-2021
// Tweaks to the changes in X-18.
// - Allow for DEVICEINUSE in addition to FILEINUSE and
// DUPUNIT when retrying the SYSINIT connection.
// - The attempt limit of 100 is dumb. Change it to 5,
// which is still likely to be way more than enough.
//
// X-18 RAB Richard A. Bishop 12-Jul-2021
// Add support for unique memory disk unit numbers.
// There's a lot of repositioning of conditionals so the
// correct code is available for the SYSINIT/OPCCRASH/
// regular utility cases, plus:
// - We need the unit seed code in the SYSINIT version
// - The handler around the SYSINIT code needs to be in
// a called routine so that the unwind ends up at the
// correct place to try again (up to 100 times). The
// actual unit number used is passed back to SYSINIT.
// - Use the same handler jacket for the disconnect
// (OPCCRASH) case.
// - The created device must be shared if we're in a
// cluster and must have the same allocation class as
// the system disk.
// - We must try to use the given unit number (from
// SYS$MD.FID) and only try a new number if that
// clashes.
// - The data block passed by SYSINIT is now a copy of
// the SYSMD structure in pool, including the SYSMD.FID
// constants and other data.
//
// X-17 RAB Richard A. Bishop 30-Sep-2020
// Tweak the code that splits the memory disk device/DID/FID string
// into sections. There's now another segment (the logical name to
// be given to the memory disk container). It's not used here, but
// the code in connect_one() has to allow for its presence.
//
// X-16 RAB Richard A. Bishop 20-Apr-2020
// We can't use anything we want from DECC$SHR in the SYSINIT/OPCCRASH
// build variant. malloc, sscanf, etc. have to be avoided so that
// KERNEL.OLB can be used. Adjust the conditionals so that nothing
// that's not needed in the SYSINIT/OPCCRASH variant gets pulled in.
//
// X-15 RCL Rick Lord
// LD$UTILITY checks to see if the command by which it was invoked was LM
// or LD by checking argv[0], but on X86 argv[0] currently references a
// NULL string. Modify main() to conditionally check argv[0], and if it's
// NULL or if it references a NULL string then assume that we were invoked
// to access logical disk, not a logical tape.
//
// X-14 RAB Richard A. Bishop 10-Jan-2018
// Widen scope of SYSINIT-callable variant to be used by OPCCRASH too.
// This mostly involves changingroutine names and comments to reflect
// the additional usage, and shuffling some declarations around to group
// globals and externals used by the variant together. There's a new
// entry point for OPCCRASH and some additional routines are included
// in the variant.
// (For simplicity, there's only a single variant, used by both SYSINIT
// and OPCCRASH).
// Also: remove all references to V82_UP and V83_UP. For VSI, post-V8.4
// is the only scenario of interest.
//
// X-13 RAB Richard A. Bishop 15-Aug-2016
//
// Correctly cast the $PUTMSG action routine argument to match the
// definition. C needs to think it returns void not int, requiring
// this cast: (void (*)())
//
// X-12 RAB Richard A. Bishop 01-Aug-2016
//
// Inserted page breaks between routines.
// Conditional code added to allow connection to the memory disk
// container file during SYSINIT. All code not needed by SYSINIT
// gets skipped, some new code is added (including the routine
// SYSINIT_LD, called by SYSINIT, and "replacing" MAIN). The
// routine OPEN_FILE will accept a DID/FID combination for SYSINIT's
// benefit.
//
// (Fixed ident & audit trail to match CMS/VDE generation)
//
// X-14 RAB Richard A. Bishop 07-Jun-2016
//
// Use contiguous-best-try on CREATE if /CONTIGUOUS not requested.
//
// X-13 RAB Richard A. Bishop 23-Oct-2015
//
// Allow for systems with SCSNODE="" (e.g. booted from a kit disk).
//
// X-12 JvdB Jur van der Burg 7-Aug-2012
//
// Change device search wildcard from *LD* to *$LD* as the devicename
// may contain LD in the nodename, which will give the wrong device
// in return. This affects SHOW/ALL and DISCONNECt/ALL.
//
// X-11 JvdB Jur van der Burg 31-Dec-2010
//
// On disconnect modify the file attributes to no_caching if not set
// correctly. Not doing that may leave data in the cache from previous
// operations like copy, unzip, etc. Flushing the XFC cache by an
// open/read/write/close sequence may not always get rid of the data.
// The best would be a new call to XFC to remove a file from the cache,
// but that's not currently there so we change the file characteristics
// which ensures that a subsequent open will bypass the cache.
// Correct bug in display of delta trace time (microseconds part). That
// field contained garbage.
//
// X-10 JvdB Jur van der Burg 22-Jan-2009
//
// Add CONNECT/EXTEND/LIMIT to allow dynamic extension of containerfiles
// for tape. This implies opening the container file for write.
// Change method for connecting a containerfile by using the channel
// instead of the SBK. Keep the old method around so we don't break
// compatibility with other applications. The same holds true for
// file-based watchpoiints.
// Add DISCONNECT/TRUNCATE.
// Allow creation of a 1 block container file.
// Change default create size to 512 for disk and 5000 for tape.
// Don't write tape metadata when extending a file.
// Don't erase tape metadata when erasing a file.
// Add check for data beyond metadata size in analyze.
//
// X-9 JvdB Jur van der Burg 10-Sep-2006
//
// Use Ansi C. Obsolete vax.
// Change display to use accurate timestamps (V8.3 and up)
// Add keywords for /TIMESTAMP=START and END
// Add CREATE/ERASE.
// Add warning when creating big files while highwater
// marking is on (V8.2 and up).
// Add /LOGICAL=(NAME=logical-name[,TABLE=table][,MODE=mode])
// for CONNECT.
// Add ANALYZE command.
// Add SWITCH, LOAD and UNLOAD commands.
// Add CONNECT/INIT.
//
// X-8 JvdB Jur van der Burg 22-Mar-2006
// Adapt time calculations to new trace structure definitions
//
// X-7 JvdB Jur van der Burg 24-Feb-2006
// Show usage of MON driver in version command, and add
// VMS version and hardware info.
// Correct definitions for channel variables from int
// to short.
// Make some structures static in open_file.
// Correct create/extend logic to properly position eof.
//
// X-6 JvdB Jur van der Burg 25-Oct-2005
// Use info from command table to see if privileges are
// needed or not.
// Allow creation of containerfile on NFS mounted filesystem.
//
// X-5 JvdB Jur van der Burg 12-Oct-2005
//
// Add itemlist to sys$device_scan to look for disk devices only.
// Failure occurs when the name of the system includes LD....
// Remove privilege handling for VAX as VAX does not support
// PRV$K_PRVMASK_IMAGE. Some privs needed for some functions
// (CMKRNL, WORLD) would always be disabled and prevent correct
// functioning.
// Add check for loaded driver and correctly installed image.
// Allow only a controller letter as a hint to for device
// connection to allow other controllers than 'A'.
// Add LD VERSION
// Add LD CONNECT/[NO]FORCED_ERROR
// Add LD CREATE/EXTEND
//
// X-4 JvdB Jur van der Burg 24-Sep-2005
//
// Rework container file creation. The old way could result in a
// SS$_HEADERFULL error when setting the container file metadata.
// If there is a default ACL applied to the file's parent directory
// we will inherit that during file creation, which inhibits the
// reserved area to be written.
// Add support for LD CONNECT/LOCK to prevent container file
// deletion. Not that it could be deleted, but it could be
// marked for delete.
// Add logical name as a parameter for connect.
// Disable privileges at the start, and only enable them
// when needed.
//
// X-3 JvdB Jur van der Burg 6-Dec-2004
//
// Add support for disk lbn mapping:
// LD CONNECT /BLOCK=(START=xxx,END=xxx,COUNT=xxx)
// [/OVERRIDE]
// Add IO$M_BYPASS_VALID_CHK modifier check
// Protect unit assignment with locks from other users.
// Properly check sys$enq status.
// Update ident to match VDE.
//
// Jur van der Burg 14-Jan-2004 Version 7.0
//
// Reworked edit history
// Add /CLONE
// Add PROTECT /PERMANENT
// Add saving of geometry in fileheader
// Disable caching of containerfile on create and open
// Flush eventual XFC cache contents of container file
// Add LD HELP
//
// Jur van der Burg 5-JUL-2000 Version 6.3
//
// Add optional FDT logging
// Add accurate timing logging (only used on Alpha)
// Modify status display
// Modify disconnect logging info
// Drop requirement for inputfilespec on disconnect. This allows deleted
// containerfiles to be disconnected without /ABORT.
//
// Jur van der Burg 19-AUG-1998 Version 6.2
//
// Added a way to use more controller letters to bypass the limit of
// 9999 cloned devices. Do this by specifying another device on connect:
// LD CONNECT FILE.DSK LDC44. The driver can already handle this.
//
// Jur van der Burg 15-NOV-1996 Version 6.0
//
// Lifted restriction for contiguous container file
// Corrected problem setting virtual watchpoint on a file
// Make sure filename is terminated in open_file to prevent errors
// during LD DISCONNECT/ALL/LOG with lots of devices
// Add /FUNCTION=ALL to watchpoint to allow trapping of all I/O's
//
// Jur van der Burg 28-OCT-1994 Version 5.1
//
// Add /SYMBOL qualifier for CONNECT
// Add /SHARE qualifier to allow sharing of containerfiles clusterwide
// Add /TRACKS, /SECTORS, /CYLINDERS and /MAXBLOCKS switches to
// CONNECT to specify geometry, removed /ALLOCATED (superceeded by
// /MAXBLOCKS). Also added /ALLOCLASS to set allocation class which
// may be different from the system parameter ALLOCLASS.
//
// Jur van der Burg 14-OCT-1993 Version 5.0
//
// Add WATCH commands
// Adapted for new interface with LDdriver
//
// Jur van der Burg 8-JUL-1993 Version 4.1
//
// Corrected bytecount display and iosb display to use longword
// instead of word field for data.
// Bumped datafile versionnumber because of change in trace data
// layout.
//
// Jur van der Burg 14-APR-1993 Version 4.0
//
// Modified command interface to use DCLTABLES
// Added cloned device support
// Reworked error handling and display.
// Add remote trace stop
//
// Jur van der Burg 23-FEB-1993 Version 3.1
//
// Expand given devicespec in 'replace' mode to full spec instead
// of spec from the commandline.
// Add more trace functionality
//
// Jur van der Burg 17-FEB-1993 Version 3.0
//
// Added trace commands
// Minor bugfixes
//
//
// Commands:
//
// - LD CREATE [/LOG] [/SIZE=xxx] [/BACKUP] [/CONTIGUOUS] [/LBN=xxx]
// [/TRACKS=xxx] [/SECTORS=xxx] [/CYLINDERS=xxx] [/ERASE]
// [/MAXBLOCKS=xxx] [/CLONE=device] [/EXTEND] Filespec
// - LD CONNECT [/LOG] [/SYMBOL] [/REPLACE] [/SHARE] [/CLONE=device]
// [/TRACKS=xxx] [/SECTORS=xxx] [/CYLINDERS=xxx] [/FULL]
// [/MAXBLOCKS=xxx] [/ALLOCLASS=xxx] [/AUTOGEOMETRY]
// [/SAVE] [/LBN=(START=xxx,END=xxx,COUNT=xxx)] [/OVERRIDE]
// [/LOGICAL=(NAME=logical-name[,TABLE=table][,MODE=mode])]
// [/LOCK] [/FORCED_ERROR] [/INIT] [/[NO]LOAD] [/EXTEND[=n]]
// [/LIMIT[=n]] Filespec [LDan:] [Logicalname]
// - LD LOAD Filespec LDan: (Qualifiers like CONNECT)
// - LD SWITCH Filespec LDan: (Qualifiers like CONNECT)
// - LD DISCONNECT [/ALL] [/LOG] [/ABORT] [/TRUNCATE] LDan:
// - LD UNLOAD [/LOG] [/TRUNCATE] LDan:
// - LD TRACE [/ACCURATE] [/FDT] [/SIZE=xxx] [/RESET] [/ALL] LDan:
// - LD TRACE/STOP [/ALL] [LDan:]
// - LD NOTRACE LDan:
// - LD WATCH LDan: lbn [,lbn...] [/FUNCTION=READ,WRITE,ALL,CODE=xxx]
// [/ACTION=SUSPEND,CRASH,OPCOM,ERROR[=xxx]]
// [/FILE=filespec]
// - LD NOWATCH LDan: [lbn [,lbn...]] [/INDEX=n]
// - LD WATCH/RESUME LDan: [lbn [,lbn...]] [/INDEX=n]
// - LD PROTECT [/PERMANENT] LDan:
// - LD NOPROTECT [/PERMANENT] LDan:
// - LD SHOW [/ALL] [/FULL] [LDan:]
// - LD SHOW/WATCH LDan: [lbn [,lbn...]]
// - LD SHOW/TRACE [/STATUS] [/RESET] [/OUTPUT=Filespec] [/INPUT=filespec]
// [/BINARY] [/ENTRIES=[(XXX,YYY)]] [/HEADER] [/CONTINUOUS]
// [/VERSION_LIMIT=xxx] [/BLOCKS=xxx] [/WARNINGS]
// [/NUMBER] [/PID] [/LBN] [/BYTECOUNT]
// [/IOSB[=COMBINATION,TEXT,HEX,LONGHEX]]
// [/TIMESTAMP[=ABSOLUTE,ELAPSED,COMBINATION,DELTA,START,END]]
// [/FUNCTION[=TEXT,HEX]] [/ACCURATE] [/FDT] [/SYMBOL] LDan:
// - LD ANALYZE [/RECORDS[=HEX,DECIMAL]] [/DATA] [/DIRECTORY[=HEX,DECIMAL]]
// [/CONTINUE] [/OUTPUT=Filespec] Filespec
// - LD HELP [topic]
// - LD VERSION
//
//
#include "ld.h"
#pragma message disable funcredecl
//
// Internal routine declarations
//
int getqual(struct dsc$descriptor_s *arg);
int getqualvalue(struct dsc$descriptor_s *arg);
int getmulqualvalue(struct dsc$descriptor_s *arg, int *more);
char *getqualstring(struct dsc$descriptor_s *arg);
void connect_one(int exist);
void disconnect_one(char *dev, int abortflag, int truncate, int single, int keep);
void open_file(char *name, int sharing, int *maxblk, int mode);
char *nodename();
char *build_lock(char *dev);
int convert_error(int oldstatus, int *newstatus);
void setup_fab();
char *fulldevspec(char *name);
void signal_error(int st1, int st2, int reason);
void getdevnam(unsigned short chan, char *s_device);
int get_unit(char *str, int exist);
void set_exclusive();
void clear_exclusive();
void cvt_timestamps();
void enable_privs(int64 which);
void disable_privs();
void check_requirements();
void create_filename(char *device, FIDDEF *fid, char *outbuf);
void setfilechar(int how);
void set_seed(int num, char *device);
extern int exe$kprintf();
#ifdef SYSINIT_OPCCRASH
int sysinit_opccrash_handler(struct chf$signal_array *sigarr, struct chf$mech_array *mecharr);
int sysinit_opccrash_action(struct dsc$descriptor_s *message, int actprm);
void init_rms_structures ();
void connect_one_jacket ();
void disconnect_one_jacket (char *dev);
#else // SYSINIT_OPCCRASH
void setfilemetadata(LD_METADATA *mdat);
int getfilemetadata(LD_METADATA *mdat);
int getclonedata(int *tracks, int *sectors, int *cylinders, int *maxblock);
void close_file(char *filename);
void flush_xfc(char *name, int sharing);
void show();
int show_one(char *which, int single);
void addarg(char **strbuf, char *inpstr, int width, unsigned int *arglist, int *argidx);
void connect_unit();
void load_unit();
void unload_unit();
void switch_unit();
int get_term_width();
void setlogical(char *device);
void findshareddevice(char *filename, int *ctrlr, int *unit, int *alloclass);
void trace();
void notrace();
void protect();
void noprotect();
void protect_common(int how);
void watch();
void show_watch();
void display_watch(WATCHPT *wpt, int wptcnt, int *blkpnt, int blkcnt, SUSPEND_LIST *slist, int slistcnt);
void nowatch();
int *getlist(struct dsc$descriptor_s *sw, int *cnt);
void stop_trace();
void stop_one(char *which, int single);
void process_trace(char *buf, int size, LD_OVRRUN *ovrbuf, int overrun, char *nname, char *when, int inited);
void show_trace_data(TRACE_ENT *p, int numpack, int from, FILE *outfile, char *node,
char *device, char *when, int inited, LD_OVRRUN *ovrbuf, int overrun);
void show_trace();
char *ssdef(int code);
void process_input();
char *decode_func(int what);
void chk_mod(int *modifier, int mask, char *modifstr, char *outstr);
char *cvttime(uint64 *time, int how, int full);
void disconnect_unit();
void analyze();
int analyze_handler(struct chf$signal_array *sigarr, struct chf$mech_array *mecharr);
void show_tape_metadata(LDTPMD *md);
void init_tape_metadata(LDTPMD *md, int size);
void init_tape_eod(void *rec);
int calc_checksum(void * buffer, int size);
void dumpbuf(char *vp, int len);
void dumpdir(char *vp, int len, LDTPMD *md, int records, int directory_hex);
void create();
void erasefile(int start, int end);
char *fullfilespec(char *name, char *defname);
void set_outband();
void purge_file(int limit, char *name);
void ld_exit(int param);
void help();
void version();
//
// HELP routines
//
$DESCRIPTOR(LBRSHR_DESC, "LBRSHR");
$DESCRIPTOR(LBR$OUTPUT_HELP_DESC, "LBR$OUTPUT_HELP");
int (*output_help_addr)();
int lbr$output_help();
#endif // SYSINIT_OPCCRASH
//
// General defines
//
#define MAX_OPTS 100 // Maximum number of option arguments for SHOW
#define HIGHWATER_WARNING 100000 // Warning threshold for highwater marking
#define OVERFLOW_AREA_SIZE (65536 + sizeof(LDTPHD) + sizeof(LDTPTR))
#define DATA_BUFFER_SIZE (512*1024)
#define RECBUF_SIZE (OVERFLOW_AREA_SIZE + DATA_BUFFER_SIZE)
//
// Logical nametable strings
//
#define SYSTEM_STR "SYSTEM"
#define SYSTEM_TBL "LNM$SYSTEM_TABLE"
#define GROUP_STR "GROUP"
#define GROUP_TBL "LNM$GROUP"
#define JOB_STR "JOB"
#define JOB_TBL "LNM$JOB"
#define PROCESS_STR "PROCESS"
#define PROCESS_TBL "LNM$PROCESS_TABLE"
#define EXECUTIVE_STR "EXECUTIVE"
#define SUPERVISOR_STR "SUPERVISOR"
#define USER_STR "USER"
#ifndef SYSINIT_OPCCRASH
//
// Internal routines dispatch table
//
typedef struct _ld_cmndtbl {
char *ldcmd$l_what;
void (*ldcmd$a_where)();
int ldcmd$l_needprivs;
} LD_CMNDTBL;
//
// Dispatch table to internal commands
// The parameter indicates if extra privileges are needed
//
LD_CMNDTBL cmnds[] = {
"CREA", &create, 0,
"CONN", &connect_unit, 1,
"DISC", &disconnect_unit, 1,
"SHOW", &show, 1,
"TRAC", &trace, 1,
"NOTR", ¬race, 1,
"WATC", &watch, 1,
"NOWA", &nowatch, 1,
"PROT", &protect, 1,
"NOPR", &noprotect, 1,
"SWIT", &switch_unit, 1,
"LOAD", &load_unit, 1,
"UNLO", &unload_unit, 1,
"ANAL", &analyze, 0,
"HELP", &help, 0,
"VERS", &version, 1,
0, 0, 0
};
#endif // SYSINIT_OPCCRASH
#define LD_PREFIX "LD"
#define LM_PREFIX "LM"
#define LD_WILDNAME "*$LD*"
#define LM_WILDNAME "*$LM*"
#define LD_WILDNAME_NONODE "_LD*"
#define LM_WILDNAME_NONODE "_LM*"
#define LD_UNIT0 "LDA0:"
#define LM_UNIT0 "LMA0:"
#define LD_TRACE_ASCII_NAME "LD_TRACE.LOG"
#define LM_TRACE_ASCII_NAME "LM_TRACE.LOG"
#define LD_TRACE_BINARY_NAME "LD_TRACE.DAT"
#define LM_TRACE_BINARY_NAME "LM_TRACE.DAT"
#define LD_ANALYZE_NAME "LD_ANALYZE.LOG"
#define LM_ANALYZE_NAME "LM_ANALYZE.LOG"
#define LD_UNIT_SYMBOL "LD_UNIT"
#define LM_UNIT_SYMBOL "LM_UNIT"
#define LD_CONTAINER_SYMBOL "LD_CONTAINER"
#define LM_CONTAINER_SYMBOL "LM_CONTAINER"
char lx_prefix[sizeof(LD_PREFIX)+1];
char lx_wildname[sizeof(LD_WILDNAME)+1];
char lx_wildname_nonode[sizeof(LD_WILDNAME_NONODE)+1];
char lx_unit0[sizeof(LD_UNIT0)+1];
char lx_trace_ascii_name[sizeof(LD_TRACE_ASCII_NAME)+1];
char lx_trace_binary_name[sizeof(LD_TRACE_BINARY_NAME)+1];
char lx_analyze_name[sizeof(LD_ANALYZE_NAME)+1];
char lx_unit_symbol[sizeof(LD_UNIT_SYMBOL)+1];
char lx_container_symbol[sizeof(LD_CONTAINER_SYMBOL)+1];
#ifdef SYSINIT_OPCCRASH
char sysdevice_string[14] = "SYS$SYSDEVICE";
$DESCRIPTOR(sysdevice,sysdevice_string);
char sysinit_device [256] = "";
char fulldevspec_string [256] = "";
#endif // SYSINIT_OPCCRASH
int sharing = 0;
int alloclass = 0;
int tape;
char cmdbuf[1024];
$DESCRIPTOR(commandline, cmdbuf);
#define LDTPHD_TAG "LmHd"
#define LDTPHD_TAG "LmHd"
#define LDTPHD_TAG_HEX 0x64486D4C
#define LDTPTR_TAG "LmTr"
#define LDTPTR_TAG_HEX 0x72546D4C
#define LDTPMD_TAG "LmMt"
#define LDTPMD_TAG_HEX 0x744D6D4C
#define LDTPDIR_TAG "LmDr"
#define LDTPDIR_TAG_HEX 0x72446D4C
static const char *hex = "0123456789ABCDEF";
static const char printable[257] = {
"................" /* 0x */
"................" /* 1x */
" !\"#$%&'()*+,-./" /* 2x */
"0123456789:;<=>?" /* 3x */
"@ABCDEFGHIJKLMNO" /* 4x */
"PQRSTUVWXYZ[\\]^_" /* 5x */
"`abcdefghijklmno" /* 6x */
"pqrstuvwxyz{|}~." /* 7x */
"................" /* 8x */
"................" /* 9x */
"................" /* ax */
"................" /* bx */
"................" /* cx */
"................" /* dx */
"................" /* ex */
"................" /* fx */
};
// File characteristics to set
#define FC_NOMOVE 0x01
#define FC_NOBACKUP 0x02
#define FC_NOCACHING 0x04
#ifndef SYSINIT_OPCCRASH
//
// Main processing
//
main(int argc, char *argv[])
{
int stat;
int length;
short rlen;
char *p;
LD_CMNDTBL *q;
ld_fab = cc$rms_fab;
ld_rab = cc$rms_rab;
ld_rab64 = cc$rms_rab64;
ld_nam = cc$rms_nam;
ld_xabfhc = cc$rms_xabfhc;
ld_xaball = cc$rms_xaball;
ld_xabpro = cc$rms_xabpro;
tape = -1;
/* X-15 */
#if __x86_64
{
if ((argv[0] == NULL) || (argv[0][0] == '\0'))
{
tape = 0;
}
}
#endif
/* Step past any directory specification */
if ((p = strrchr(argv[0],']')) || (p = strrchr(argv[0],'>'))) {
p++;
if (tolower(*p++) == 'l') {
if (tolower(*p) == 'd')
tape = 0; // Disk function
else if (tolower(*p) == 'm')
tape = 1; // Tape function
}
}
if (tape < 0) // Not named as LD or LM utility, quit
exit(SS$_ABORT);
if (!tape) {
//
// Init parameters like a disk
//
strcpy(lx_prefix, LD_PREFIX);
strcpy(lx_wildname, LD_WILDNAME);
strcpy(lx_wildname_nonode, LD_WILDNAME_NONODE);
strcpy(lx_unit0, LD_UNIT0);
strcpy(lx_trace_ascii_name, LD_TRACE_ASCII_NAME);
strcpy(lx_trace_binary_name, LD_TRACE_BINARY_NAME);
strcpy(lx_analyze_name, LD_ANALYZE_NAME);
strcpy(lx_unit_symbol, LD_UNIT_SYMBOL);
strcpy(lx_container_symbol, LD_CONTAINER_SYMBOL);
} else {
//
// Init parameters like a tape
//
strcpy(lx_prefix, LM_PREFIX);
strcpy(lx_wildname, LM_WILDNAME);
strcpy(lx_wildname_nonode, LM_WILDNAME_NONODE);
strcpy(lx_unit0, LM_UNIT0);
strcpy(lx_trace_ascii_name, LM_TRACE_ASCII_NAME);
strcpy(lx_trace_binary_name, LM_TRACE_BINARY_NAME);
strcpy(lx_analyze_name, LM_ANALYZE_NAME);
strcpy(lx_unit_symbol, LM_UNIT_SYMBOL);
strcpy(lx_container_symbol, LM_CONTAINER_SYMBOL);
}
//
// Get the rest of the commandline
//
stat = lib$get_foreign(&commandline, 0, &rlen, 0);
signal_error(stat, 0, 0);
commandline.dsc$w_length = rlen;
p = getqualstring(&command);
length = strlen(p) >= 4 ? 4 : strlen(p);
q = cmnds;
while (q->ldcmd$l_what) {
if (strncmp(p, (char *) q->ldcmd$l_what, length) == 0) {
if (q->ldcmd$l_needprivs)
check_requirements(); // Check for loaded driver and installed image
disable_privs(); // Initially no privileges needed
(*(q->ldcmd$a_where))(); // Call command
exit(1);
}
q++;
}
signal_error(CLI$_NOCOMD, 0, 0); // Command not found
}
#else // SYSINIT_OPCCRASH
//
// Main entry point when called from SYSINIT
//
// If the connect fails because the unit number is already in use, we have to bump the
// unit number. It can't be just one or two higher because that interferes with the seeding
// of the next free number so we're using 13 as the increment. Why? because it's a prime
// number, it's an obtuse choice, and I'm not superstitious.
//
int sysinit_ld(int original_unit, SYSMD* connect_args, char** device_name)
{
int attempts = 5;
//
// Init parameters like a disk
//
strcpy(lx_prefix, LD_PREFIX);
strcpy(lx_wildname, LD_WILDNAME);
strcpy(lx_wildname_nonode, LD_WILDNAME_NONODE);
strcpy(lx_unit0, LD_UNIT0);
strcpy(lx_trace_ascii_name, LD_TRACE_ASCII_NAME);
strcpy(lx_trace_binary_name, LD_TRACE_BINARY_NAME);
strcpy(lx_analyze_name, LD_ANALYZE_NAME);
strcpy(lx_unit_symbol, LD_UNIT_SYMBOL);
strcpy(lx_container_symbol, LD_CONTAINER_SYMBOL);
init_rms_structures ();
outfile = stdout;
tape = 0;
alloclass = connect_args->sysmd$w_alloclass;
if (clu$gl_club != NULL)
sharing = 1;
desired_unit = original_unit;
sysinit_status = (unsigned int)&ld_fileinuse;
while (((sysinit_status == (unsigned int)&ld_fileinuse)
|| (sysinit_status == (unsigned int)&ld_deviceinuse)
|| (sysinit_status == (unsigned int)&ld_dupunit))
&& (attempts > 0))
{
sysinit_status = SS$_NORMAL;
strncpy(cmdbuf, &connect_args->sysmd$t_info [0], sizeof(cmdbuf));
connect_one_jacket ();
desired_unit += 13;
if (desired_unit > 9999)
desired_unit -= 9000;
attempts--;
}
connect_args->sysmd$w_used_unitnum = actual_unit;
*device_name = sysinit_device;
return sysinit_status;
}
void connect_one_jacket()
{
lib$establish(&sysinit_opccrash_handler); // Establish handler (any errors will come from here)
connect_one(0);
return;
}
//
// Main entry point when called from OPCCRASH
//
int opccrash_ld(char* device_name)
{
lib$establish(&sysinit_opccrash_handler); // Establish handler (any errors will come from here)
//
// Init parameters like a disk
//
strcpy(lx_prefix, LD_PREFIX);
strcpy(lx_wildname, LD_WILDNAME);
strcpy(lx_wildname_nonode, LD_WILDNAME_NONODE);
strcpy(lx_unit0, LD_UNIT0);
strcpy(lx_trace_ascii_name, LD_TRACE_ASCII_NAME);
strcpy(lx_trace_binary_name, LD_TRACE_BINARY_NAME);
strcpy(lx_analyze_name, LD_ANALYZE_NAME);
strcpy(lx_unit_symbol, LD_UNIT_SYMBOL);
strcpy(lx_container_symbol, LD_CONTAINER_SYMBOL);
init_rms_structures ();
outfile = stdout;
tape = 0;
disconnect_one_jacket(device_name);
return SS$_NORMAL;
}
void disconnect_one_jacket(char *dev)
{
lib$establish(&sysinit_opccrash_handler); // Establish handler (any errors will come from here)
disconnect_one(dev, 0, 0, 1, 0);
return;
}
//
// Condition handler for SYSINIT/OPCCRASH-specific code
//
int sysinit_opccrash_handler(struct chf$signal_array *sigarr,
struct chf$mech_array *mecharr)
{
if (sigarr->chf$l_sig_name == SS$_UNWIND)
return SS$_RESIGNAL;
if (sigarr->chf$l_sig_name & 1)
return SS$_CONTINUE;
sysinit_status = sigarr->chf$l_sig_name;
sigarr->chf$l_sig_args -= 2; // remove PC,PSL
sys$putmsg(sigarr,(void (*)())sysinit_opccrash_action,0,0);
sys$unwind(NULL,NULL);
return SS$_RESIGNAL;
}
//
// Action routine for SYSINIT/OPCCRASH condition handler
//
int sysinit_opccrash_action(struct dsc$descriptor_s *message, int actprm)
{
exe$kprintf("\n%*.*s\r", message->dsc$w_length, message->dsc$w_length, message->dsc$a_pointer);
return 0;
}
//
// Initialize RMS structures "manually" for the SYSINIT/OPCCRASH case.
//
void init_rms_structures ()
{
memset (&ld_fab, 0, sizeof (ld_fab));
ld_fab.fab$b_bid = FAB$C_BID;
ld_fab.fab$b_bln = sizeof (FABDEF);
memset (&ld_rab, 0, sizeof (ld_rab));
ld_rab.rab$b_bid = RAB$C_BID;
ld_rab.rab$b_bln = sizeof (RABDEF);
memset (&ld_rab64, 0, sizeof (ld_rab64));
ld_rab64.rab64$b_bid = RAB64$C_BID;
ld_rab64.rab64$b_bln = sizeof (RAB64DEF);
memset (&ld_nam, 0, sizeof (ld_nam));
ld_nam.nam$b_bid = NAM$C_BID;
ld_nam.nam$b_bln = sizeof (NAMDEF);
memset (&ld_xabfhc, 0, sizeof (ld_xabfhc));
ld_xabfhc.xab$b_cod = XAB$C_FHC;
ld_xabfhc.xab$b_bln = sizeof (XABFHCDEF);
memset (&ld_xaball, 0, sizeof (ld_xaball));
ld_xaball.xab$b_cod = XAB$C_ALL;
ld_xaball.xab$b_bln = sizeof (XABALLDEF);
memset (&ld_xabpro, 0, sizeof (ld_xabpro));
ld_xabpro.xab$b_cod = XAB$C_PRO;
ld_xabpro.xab$b_bln = sizeof (XABPRODEF);
return;
}
#endif // SYSINIT_OPCCRASH
//
// Get a single qualifier
//
// Return value: 1 - qualifier present
// 0 - absent
// -1 - negated
//
int getqual(struct dsc$descriptor_s *arg)
{
#ifndef SYSINIT_OPCCRASH
int stat;
stat = cli$present(arg); // Get qualifier presence
if (stat == CLI$_PRESENT ||
stat == CLI$_LOCPRES ||
stat == CLI$_DEFAULTED)
return (1); // It's there
else if (stat == CLI$_NEGATED || stat == CLI$_LOCNEG)
return (-1); // Negated
else if (stat == CLI$_ABSENT)
return (0); // Not there
signal_error(stat, 0, 0);
#else // SYSINIT_OPCCRASH
return 0;
#endif // SYSINIT_OPCCRASH
}
//
// Get a qualifier integer value
//
// Return value: 0 or the qualifier's value
//
int getqualvalue(struct dsc$descriptor_s *arg)
{
#ifndef SYSINIT_OPCCRASH
char value[256];
$DESCRIPTOR(out, value);
int val;
short rlen;
*value = 0;
if ((cli$present(arg) & 1) && // If present...
(cli$get_value(arg, &out, &rlen) & 1)) { // Get it's value
*(value + (rlen & 0377)) = 0;
return ((sscanf(value, "%d", &val)) ? val : 0);
} else
return (0); // Default
#else // SYSINIT_OPCCRASH
return 0;
#endif // SYSINIT_OPCCRASH
}
//
// Get multiple qualifier integer values
//
// Return value: 0 or the qualifier's value
// the second argument indicates if there's more to fetch
//
int getmulqualvalue(struct dsc$descriptor_s *arg, int *more)
{
#ifndef SYSINIT_OPCCRASH
int stat;
char value[256];
$DESCRIPTOR(out, value);
int val;
short rlen;
*value = 0;
if (*more < 0)
if (!(cli$present(arg) & 1)) // If not present...
return (0);
stat = cli$get_value(arg, &out, &rlen); // Get it's value
*more = 0;
if (!(stat & 1))
return (0);
if (stat == CLI$_COMMA)
*more = 1; // Got comma, more to fetch
*(value + (rlen & 0377)) = 0;
return ((sscanf(value, "%d", &val)) ? val : 0);
#else // SYSINIT_OPCCRASH
return 0;
#endif // SYSINIT_OPCCRASH
}
//
// Get a qualifier string value
//
// Return value: 0 or the qualifier's string
//
char *getqualstring(struct dsc$descriptor_s *arg)
{
#ifndef SYSINIT_OPCCRASH
char *string, *p;
LD_DSC out;
short rlen;
p = string = malloc(256); // Get some memory
if (!p)
signal_error(SS$_INSFMEM, 0, 0);
out.dsc$a_dpointer = string; // Setup pointer
out.dsc$l_length = 256; // and size
if ((cli$present(arg) & 1) && // If present...
(cli$get_value(arg, &out, &rlen) & 1)) { // Get it's value
p += rlen; // Point to end of string
*p = '\0'; // Place terminator
return (string);
} else
return (0); // Default
#else // SYSINIT_OPCCRASH