/
zalloc.c
206 lines (170 loc) · 5.16 KB
/
zalloc.c
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
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utmpx.h>
#include <pwd.h>
#define import_spp
#define import_alloc
#define import_kernel
#define import_knames
#include <iraf.h>
/*
* ZALLOC.C -- Device allocation interface. Requires the dev$devices table,
* which is read by the high level code before we are called.
*
* zdvall (device, allflg, status) allocate/deallocate device
* zdvown (device, owner, maxch, status) query device allocation
*
* Status returns (import_alloc):
*
* OK operation successful
* ERR cannot allocate device
* DV_DEVALLOC device is already allocated
* DV_DEVINUSE device is in use by someone else
* DV_DEVFREE device is free and can be allocated
*
* The DEVICE name is a list of aliases for the physical device. On UNIX there
* can be multiple elements in the list (e.g., for a tape drive), but on other
* systems there may never be more than one device name. The elements of the
* list are delimited by whitespace. On host systems that do not support
* multiple device aliases, the kernel may assume that DEVICE is a scalar.
*/
#define ALLOCEXE "alloc.e"
static int u_allocstat (char *aliases);
/* ZDVALL -- Allocate or deallocate a device. UNIX does not explicitly support
* device allocation, so we fake it by setting the device owner and removing
* group and other permissions. This requires superuser privilege, hence a
* separate process HLIB$ALLOC.E is used to set/remove device allocation.
*/
int
ZDVALL (
PKCHAR *aliases, /* list of aliases for device */
XINT *allflg, /* allocate or deallocate device? */
XINT *status /* receives status word */
)
{
PKCHAR cmd[SZ_LINE+1], nullstr[1];
extern int ZOSCMD ();
/* Syntax: $host/hlib/alloc.e -[ad] aliases
*/
strcpy ((char *)cmd, irafpath(ALLOCEXE));
strcat ((char *)cmd, *allflg ? " -a " : " -d ");
strcat ((char *)cmd, (char *)aliases);
*nullstr = XEOS;
(void) ZOSCMD (cmd, nullstr, nullstr, nullstr, status);
if (*status == DV_ERROR)
*status = XERR;
return (*status);
}
/* ZDVOWN -- Query device allocation. Tells whether or not the named device
* is allocated, and if so returns the "name" of the owner in the owner
* string. Just what the "name" string is is not precisely defined, it is
* merely printed for the user to tell them the status of the device.
* Note that the device is not considered to be allocated if the owner
* is not currently logged in.
*
* Device files may be specified by a full pathname, as a user directory
* relative pathname, or by the device name in /dev or /dev/rmt.
*/
int
ZDVOWN (
PKCHAR *device, /* device name (not a list) */
PKCHAR *owner, /* receives owner string */
XINT *maxch, /* max chars out */
XINT *status /* receives allocation status */
)
{
register int uid;
char *dev, devname[SZ_FNAME+1];
struct passwd *pw, *getpwuid();
struct stat fi;
/* Get device pathname. */
dev = (char *)device;
if (dev[0] == '/') {
strcpy (devname, dev);
} else if (dev[0] == '~' && dev[1] == '/') {
/* User home directory relative pathname. */
struct passwd *pwd;
pwd = getpwuid (getuid());
if (pwd != NULL) {
strcpy (devname, pwd->pw_dir);
strcat (devname, &dev[1]);
endpwent();
}
} else {
sprintf (devname, "/dev/%s", dev);
if (access (devname, 0) == ERR)
sprintf (devname, "/dev/rmt/%s", dev);
}
if (stat (devname, &fi) == ERR) {
*status = XERR;
return (XERR);
}
uid = fi.st_uid;
*owner = XEOS;
if (uid == 0)
*status = DV_DEVFREE;
else if (uid == getuid())
*status = DV_DEVALLOC;
/* else if (!loggedin (uid)) */
else if (u_allocstat ((char *)device) == DV_DEVFREE)
*status = DV_DEVFREE;
else {
if ((pw = getpwuid (uid)) == NULL)
sprintf ((char *)owner, "%d", uid);
else
strncpy ((char *)owner, pw->pw_name, *maxch);
*status = DV_DEVINUSE;
}
return (*status);
}
/* LOGGEDIN -- Return 1 if uid is logged in, else 0.
*/
int
loggedin (int uid)
{
struct utmpx ubuf;
struct passwd *pw, *getpwuid();
FILE *ufp;
if ((ufp = fopen ("/var/run/utmp", "r")) == NULL) {
printf ("zdvown: cannot open /var/run/utmp\n");
return (1);
}
if ((pw = getpwuid (uid)) == NULL) {
fclose (ufp);
return (0);
}
do {
if (fread (&ubuf, sizeof (struct utmpx), 1, ufp) == (size_t) 0) {
fclose (ufp);
return (0);
}
} while (strncmp (ubuf.ut_user, pw->pw_name, 8) != 0);
fclose (ufp);
return (1);
}
/* U_ALLOCSTAT -- Call alloc.e to get the device status. Currently, this has
* to be done by a priviledged process as the process table is used in some
* cases.
*/
static int
u_allocstat (
char *aliases /* list of aliases for device */
)
{
PKCHAR cmd[SZ_LINE+1], nullstr[1];
XINT x_status;
extern int ZOSCMD();
/* Syntax: $host/hlib/alloc.e -s aliases
*/
strcpy ((char *)cmd, irafpath(ALLOCEXE));
strcat ((char *)cmd, " -s ");
strcat ((char *)cmd, aliases);
*nullstr = XEOS;
(void) ZOSCMD (cmd, nullstr, nullstr, nullstr, &x_status);
if (x_status == DV_ERROR)
x_status = XERR;
return (x_status);
}