summaryrefslogtreecommitdiff
path: root/vms/ldrset.c
blob: c0efd0cd7a2825143a41aca6b37b13cb4bc76041 (plain)
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
/* LDRSET - Set the state of the LDR flag in UCB$L_DEVCHAR2 for a
**     SCSI magtape.  REQUIRES CMKRNL privilege.
**
**  Copyright 1999 by TECSys Development, Inc. http://www.tditx.com
**
**  This program is free software; you may redistribute and/or modify it under
**  the terms of the GNU General Public License Version 2 as published by the
**  Free Software Foundation.
**
**  This program is distributed in the hope that it will be useful, but
**  WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
**  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
**  for complete details.
**
** Description:
**   This is a small KERNEL MODE utility program to go set or reset
**   the DEV$M_LDR flag in UCB$L_DEVCHAR2 for a specified device. While
**   a certain amount of checking is performed, and while the author
**   believes that this utility is safe, ONLY YOU can make that
**   determination with respect to your environment. There are NO
**   GUARANTEES WHATSOEVER that use of this program will not CRASH
**   YOUR SYSTEM or worse. TDI disclaims any responsibility for any
**   losses or damages from the use of this program.
**
**   With all that said... this utility can be used [example: system
**   startup] to set the LDR flag for the autoloader tape device.
**   With the loader flag properly set, you can re-enable the LDR
**   check section in MTX and be fairly well certain that the MTX
**   utility will not be used against a drive that is not a SCSI
**   MAGTAPE with a LOADER attached.
**
**
** LDRSET.CLD:
**	define verb LDRSET
**		image		sys$disk:[]ldrset.exe
**		parameter	p1,		label=device,
**						prompt="Device",
**						value(required,type=$FILE)
**		qualifier	SET, nonnegatable
**		qualifier	RESET, nonnegatable
**		disallow	any2 (SET, RESET)
**		disallow	NOT SET AND NOT RESET
*/
#ifdef __DECC
#pragma module LDRSET "V01-00"
#else
#module LDRSET "V01-00"
#endif

#include <ssdef.h>
#include <dcdef.h>
#include <devdef.h>
#include <dvidef.h>
#include <descrip.h>
#include <stdio.h>
#include <string.h>
#include <lib$routines.h>
#include <starlet.h>

#ifndef DESCR_CNT
#define DESCR_CNT 16
/* MUST BE of the form 2^N!, big enough for max concurrent usage */
#endif

static struct dsc$descriptor_s *
descr(
  char *str)
{
static struct dsc$descriptor_s d_descrtbl[DESCR_CNT];  /* MAX usage! */
static unsigned short int descridx=0;
  struct dsc$descriptor_s *d_ret = &d_descrtbl[descridx];

  descridx = (descridx+1)&(DESCR_CNT-1);

  d_ret->dsc$w_length = strlen((const char *)str);
  d_ret->dsc$a_pointer = (char *)str;

  d_ret->dsc$b_class =
  d_ret->dsc$b_dtype = 0;
  return(d_ret);
}

extern unsigned long int finducb();
extern unsigned long int _setldr();
extern unsigned long int _clrldr();

unsigned long int
set_ldrstate(
  int devch,
  int setstate)
{
  unsigned long int ret;
  struct ucbdef *ucb;

  if (~(ret=finducb(devch,&ucb))&1)
    return(ret);

  if (setstate)
    return(_setldr(ucb));
  else
    return(_clrldr(ucb));
}

extern unsigned long int CLI$PRESENT();
extern unsigned long int CLI$GET_VALUE();

static unsigned long int
cld_special(
  char *kwd_name)
{
  lib$establish(lib$sig_to_ret);
  return(CLI$PRESENT(descr(kwd_name)));
}

int
main(){
  unsigned long int ret;
  unsigned long int ismnt = 0;
  unsigned long int dvcls = 0;
  unsigned long int dchr2 = 0;
  struct itmlst_3 {
    unsigned short int ilen;
    unsigned short int code;
    unsigned long int *returnP;
    unsigned long int ignored;
  } dvi_itmlst[] = {
    {4, DVI$_MNT, 0/*&ismnt*/, 0},
    {4, DVI$_DEVCLASS, 0/*&dvcls*/, 0},
    {4, DVI$_DEVCHAR2, 0/*&dchr2*/, 0},
    {0,0,0,0} };
  unsigned long int iosb[2];
  struct dsc$descriptor_s *dp_tmp;
  struct dsc$descriptor_d dy_devn = { 0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0 };
  unsigned long int devch=0;

  dvi_itmlst[0].returnP = &ismnt;
  dvi_itmlst[1].returnP = &dvcls;
  dvi_itmlst[2].returnP = &dchr2;

  if (~(ret=CLI$PRESENT(dp_tmp=descr("DEVICE")))&1) {
    printf("?Error obtaining CLD DEVICE parameter\n");
    return(ret); }
  if (~(ret=CLI$GET_VALUE(dp_tmp,&dy_devn,0))&1) {
    printf("?Error obtaining CLD DEVICE value\n");
    return(ret); }

  if (~(ret=sys$alloc(&dy_devn,0,0,0,0))&1) {
    printf("?Error allocating specified device\n");
    return(ret); }

  if (~(ret=sys$assign(&dy_devn,&devch,0,0))&1) {
    printf("?Error assigning a channel to specified device\n");
    return(ret); }

  if (~(ret=sys$getdviw(0,devch,0,&dvi_itmlst,&iosb,0,0,0))&1) {
    printf("?Error obtaining device information(1)\n");
    return(ret); }
  if (~(ret=iosb[0])&1) {
    printf("?Error obtaining device information(2)\n");
    return(ret); }

  if (dvcls != DC$_TAPE) {
    printf("?Device is not a tape drive\n");
    return(SS$_IVDEVNAM); }

  if (~dchr2 & DEV$M_SCSI) {
    printf("?Device is not a SCSI device\n");
    return(SS$_IVDEVNAM); }

  if (ismnt) {
    printf("?Device is mounted\n");
    return(SS$_DEVMOUNT); }

  if (cld_special("SET")&1)
    return(set_ldrstate(devch,1));

  if (cld_special("RESET")&1)
    return(set_ldrstate(devch,0));

  /* Either SET or RESET above must be present to win */
  printf("?CLD structural error - see source\n");
  return(SS$_BADPARAM);
}