Imported Upstream version 1.2.16rel
[debian/mtx] / vms / ldrset.c
1 /* LDRSET - Set the state of the LDR flag in UCB$L_DEVCHAR2 for a
2 **     SCSI magtape.  REQUIRES CMKRNL privilege.
3 **
4 **  Copyright 1999 by TECSys Development, Inc. http://www.tditx.com
5 **
6 **  This program is free software; you may redistribute and/or modify it under
7 **  the terms of the GNU General Public License Version 2 as published by the
8 **  Free Software Foundation.
9 **
10 **  This program is distributed in the hope that it will be useful, but
11 **  WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
12 **  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 **  for complete details.
14 **
15 ** Description:
16 **   This is a small KERNEL MODE utility program to go set or reset
17 **   the DEV$M_LDR flag in UCB$L_DEVCHAR2 for a specified device. While
18 **   a certain amount of checking is performed, and while the author
19 **   believes that this utility is safe, ONLY YOU can make that
20 **   determination with respect to your environment. There are NO
21 **   GUARANTEES WHATSOEVER that use of this program will not CRASH
22 **   YOUR SYSTEM or worse. TDI disclaims any responsibility for any
23 **   losses or damages from the use of this program.
24 **
25 **   With all that said... this utility can be used [example: system
26 **   startup] to set the LDR flag for the autoloader tape device.
27 **   With the loader flag properly set, you can re-enable the LDR
28 **   check section in MTX and be fairly well certain that the MTX
29 **   utility will not be used against a drive that is not a SCSI
30 **   MAGTAPE with a LOADER attached.
31 **
32 **
33 ** LDRSET.CLD:
34 **      define verb LDRSET
35 **              image           sys$disk:[]ldrset.exe
36 **              parameter       p1,             label=device,
37 **                                              prompt="Device",
38 **                                              value(required,type=$FILE)
39 **              qualifier       SET, nonnegatable
40 **              qualifier       RESET, nonnegatable
41 **              disallow        any2 (SET, RESET)
42 **              disallow        NOT SET AND NOT RESET
43 */
44 #ifdef __DECC
45 #pragma module LDRSET "V01-00"
46 #else
47 #module LDRSET "V01-00"
48 #endif
49
50 #include <ssdef.h>
51 #include <dcdef.h>
52 #include <devdef.h>
53 #include <dvidef.h>
54 #include <descrip.h>
55 #include <stdio.h>
56 #include <string.h>
57 #include <lib$routines.h>
58 #include <starlet.h>
59
60 #ifndef DESCR_CNT
61 #define DESCR_CNT 16
62 /* MUST BE of the form 2^N!, big enough for max concurrent usage */
63 #endif
64
65 static struct dsc$descriptor_s *
66 descr(
67   char *str)
68 {
69 static struct dsc$descriptor_s d_descrtbl[DESCR_CNT];  /* MAX usage! */
70 static unsigned short int descridx=0;
71   struct dsc$descriptor_s *d_ret = &d_descrtbl[descridx];
72
73   descridx = (descridx+1)&(DESCR_CNT-1);
74
75   d_ret->dsc$w_length = strlen((const char *)str);
76   d_ret->dsc$a_pointer = (char *)str;
77
78   d_ret->dsc$b_class =
79   d_ret->dsc$b_dtype = 0;
80   return(d_ret);
81 }
82
83 extern unsigned long int finducb();
84 extern unsigned long int _setldr();
85 extern unsigned long int _clrldr();
86
87 unsigned long int
88 set_ldrstate(
89   int devch,
90   int setstate)
91 {
92   unsigned long int ret;
93   struct ucbdef *ucb;
94
95   if (~(ret=finducb(devch,&ucb))&1)
96     return(ret);
97
98   if (setstate)
99     return(_setldr(ucb));
100   else
101     return(_clrldr(ucb));
102 }
103
104 extern unsigned long int CLI$PRESENT();
105 extern unsigned long int CLI$GET_VALUE();
106
107 static unsigned long int
108 cld_special(
109   char *kwd_name)
110 {
111   lib$establish(lib$sig_to_ret);
112   return(CLI$PRESENT(descr(kwd_name)));
113 }
114
115 int
116 main(){
117   unsigned long int ret;
118   unsigned long int ismnt = 0;
119   unsigned long int dvcls = 0;
120   unsigned long int dchr2 = 0;
121   struct itmlst_3 {
122     unsigned short int ilen;
123     unsigned short int code;
124     unsigned long int *returnP;
125     unsigned long int ignored;
126   } dvi_itmlst[] = {
127     {4, DVI$_MNT, 0/*&ismnt*/, 0},
128     {4, DVI$_DEVCLASS, 0/*&dvcls*/, 0},
129     {4, DVI$_DEVCHAR2, 0/*&dchr2*/, 0},
130     {0,0,0,0} };
131   unsigned long int iosb[2];
132   struct dsc$descriptor_s *dp_tmp;
133   struct dsc$descriptor_d dy_devn = { 0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0 };
134   unsigned long int devch=0;
135
136   dvi_itmlst[0].returnP = &ismnt;
137   dvi_itmlst[1].returnP = &dvcls;
138   dvi_itmlst[2].returnP = &dchr2;
139
140   if (~(ret=CLI$PRESENT(dp_tmp=descr("DEVICE")))&1) {
141     printf("?Error obtaining CLD DEVICE parameter\n");
142     return(ret); }
143   if (~(ret=CLI$GET_VALUE(dp_tmp,&dy_devn,0))&1) {
144     printf("?Error obtaining CLD DEVICE value\n");
145     return(ret); }
146
147   if (~(ret=sys$alloc(&dy_devn,0,0,0,0))&1) {
148     printf("?Error allocating specified device\n");
149     return(ret); }
150
151   if (~(ret=sys$assign(&dy_devn,&devch,0,0))&1) {
152     printf("?Error assigning a channel to specified device\n");
153     return(ret); }
154
155   if (~(ret=sys$getdviw(0,devch,0,&dvi_itmlst,&iosb,0,0,0))&1) {
156     printf("?Error obtaining device information(1)\n");
157     return(ret); }
158   if (~(ret=iosb[0])&1) {
159     printf("?Error obtaining device information(2)\n");
160     return(ret); }
161
162   if (dvcls != DC$_TAPE) {
163     printf("?Device is not a tape drive\n");
164     return(SS$_IVDEVNAM); }
165
166   if (~dchr2 & DEV$M_SCSI) {
167     printf("?Device is not a SCSI device\n");
168     return(SS$_IVDEVNAM); }
169
170   if (ismnt) {
171     printf("?Device is mounted\n");
172     return(SS$_DEVMOUNT); }
173
174   if (cld_special("SET")&1)
175     return(set_ldrstate(devch,1));
176
177   if (cld_special("RESET")&1)
178     return(set_ldrstate(devch,0));
179
180   /* Either SET or RESET above must be present to win */
181   printf("?CLD structural error - see source\n");
182   return(SS$_BADPARAM);
183 }