1 /* @(#)vms.c	1.11 17/07/17 joerg */
2 #ifndef lint
3 static	char sccsid[] =
4 	"@(#)vms.c	1.11 17/07/17 joerg";
5 
6 #endif
7 /*
8  * File vms.c - assorted bletcherous hacks for VMS.
9  *
10  * Written by Eric Youngdale (1993).
11  *
12  */
13 
14 #include <schily/mconfig.h>
15 #ifdef VMS
16 #define	opendir	fake_opendir
17 #include "mkisofs.h"
18 #undef opendir
19 #include <rms.h>
20 #include <descrip.h>
21 #include <ssdef.h>
22 
23 static struct RAB	*rab;		/* used for external mailfiles */
24 static int		rms_status;
25 
26 static
error_exit(char * text)27 error_exit(char *text)
28 {
29 	fprintf(stderr, "%s\n", text);
30 	exit(33);
31 }
32 
33 
34 char *strrchr(const char *, char);
35 
36 int
VMS_stat(char * path,struct stat * spnt)37 VMS_stat(char *path, struct stat * spnt)
38 {
39 	char		*spath;
40 	char		sbuffer[255];
41 	char		*pnt,
42 			*ppnt;
43 	char		*pnt1;
44 
45 	ppnt = strrchr(path, ']');
46 	if (ppnt)
47 		ppnt++;
48 	else
49 		ppnt = path;
50 
51 	spath = path;
52 
53 	if (strcmp(ppnt, ".") == 0 || strcmp(ppnt, "..") == 0) {
54 		strcpy(sbuffer, path);
55 
56 		/* Find end of actual name */
57 		pnt = strrchr(sbuffer, ']');
58 		if (!pnt)
59 			return (0);
60 
61 		pnt1 = pnt;
62 		while (*pnt1 != '[' && *pnt1 != '.')
63 			pnt1--;
64 
65 		if (*pnt1 != '[' && strcmp(ppnt, "..") == 0) {
66 			pnt1--;
67 			while (*pnt1 != '[' && *pnt1 != '.')
68 				pnt1--;
69 		};
70 
71 		if (*pnt1 == '.') {
72 			*pnt1 = ']';
73 			pnt = pnt1;
74 			while (*pnt != '.' && *pnt != ']')
75 				pnt++;
76 			*pnt++ = ']';
77 			while (*pnt != '.' && *pnt != ']')
78 				pnt++;
79 			*pnt = 0;
80 			strcat(sbuffer, ".DIR;1");
81 		};
82 
83 		if (*pnt1 == '[') {
84 			pnt1++;
85 			*pnt1 = 0;
86 			strcat(pnt1, "000000]");
87 			pnt1 = strrchr(path, '[') + 1;
88 			pnt = sbuffer + strlen(sbuffer);
89 			while (*pnt1 && *pnt1 != '.' && *pnt1 != ']')
90 				*pnt++ = *pnt1++;
91 			*pnt = 0;
92 			strcat(sbuffer, ".DIR;1");
93 		};
94 
95 		spath = sbuffer;
96 	};
97 	return (stat_filter(spath, spnt));
98 }
99 
100 static int		dircontext[32] = {0, };
101 static char		*searchpath[32];
102 static struct direct	d_entry[32];
103 
104 int			optind = 0;
105 char			*optarg;
106 
107 int
getopt(int argc,char * argv[],char * flags)108 getopt(int argc, char *argv[], char *flags)
109 {
110 	char		*pnt;
111 	char		c;
112 
113 	optind++;
114 	if (*argv[optind] != '-')
115 		return (EOF);
116 	optarg = 0;
117 
118 	c = *(argv[optind] + 1);
119 	pnt = (char *) strchr(flags, c);
120 	if (!pnt)
121 		return (c);	/* Not found */
122 	if (pnt[1] == ':') {
123 		optind++;
124 		optarg = argv[optind];
125 	};
126 	return (c);
127 }
128 
129 void
vms_path_fixup(char * name)130 vms_path_fixup(char *name)
131 {
132 	char		*pnt1;
133 
134 	pnt1 = name + strlen(name) - 6;
135 
136 	/* First strip the .DIR;1 */
137 	if (strcmp(pnt1, ".DIR;1") == 0)
138 		*pnt1 = 0;
139 
140 	pnt1 = (char *) strrchr(name, ']');
141 	if (pnt1) {
142 		if (pnt1[1] == 0)
143 			return;
144 		*pnt1 = '.';
145 		strcat(name, "]");
146 		return;
147 	};
148 	pnt1 = (char *) strrchr(name, '>');
149 	if (pnt1) {
150 		if (pnt1[1] == 0)
151 			return;
152 		*pnt1 = '.';
153 		strcat(name, ">");
154 		return;
155 	};
156 }
157 
158 int
opendir(char * path)159 opendir(char *path)
160 {
161 	int		i;
162 
163 	for (i = 1; i < 32; i++) {
164 		if (dircontext[i] == 0) {
165 			dircontext[i] = -1;
166 			searchpath[i] = (char *) e_malloc(strlen(path) + 6);
167 			strcpy(searchpath[i], path);
168 			vms_path_fixup(searchpath[i]);
169 			strcat(searchpath[i], "*.*.*");
170 			return (i);
171 		};
172 	};
173 	exit(0);
174 }
175 
176 struct direct  *
readdir(int context)177 readdir(int context)
178 {
179 	int		i;
180 	char		cresult[100];
181 	char		*pnt;
182 	int		status;
183 
184 	$DESCRIPTOR(dpath, searchpath[context]);
185 	$DESCRIPTOR(result, cresult);
186 
187 	if (dircontext[context] == -1) {
188 		dircontext[context] = -2;
189 		strcpy(d_entry[context].d_name, ".");
190 		return (&d_entry[context]);
191 	};
192 
193 	if (dircontext[context] == -2) {
194 		dircontext[context] = -3;
195 		strcpy(d_entry[context].d_name, "..");
196 		return (&d_entry[context]);
197 	};
198 
199 	if (dircontext[context] == -3)
200 		dircontext[context] = 0;
201 
202 	dpath.dsc$w_length = strlen(searchpath[context]);
203 	lib$find_file(&dpath, &result, &dircontext[context],
204 		0, 0, &status, 0);
205 
206 	if (status == SS$_NOMOREFILES)
207 		return (0);
208 
209 	/* Now trim trailing spaces from the name */
210 	i = result.dsc$w_length - 1;
211 	while (i && cresult[i] == ' ')
212 		i--;
213 	cresult[i + 1] = 0;
214 
215 	/* Now locate the actual portion of the file we want */
216 
217 	pnt = (char *) strrchr(cresult, ']');
218 	if (pnt)
219 		pnt++;
220 	else
221 		pnt = cresult;
222 
223 	strcpy(d_entry[context].d_name, pnt);
224 	return (&d_entry[context]);
225 }
226 
227 void
closedir(int context)228 closedir(int context)
229 {
230 	lib$find_file_end(&dircontext[context]);
231 	free(searchpath[context]);
232 	searchpath[context] = (char *) 0;
233 	dircontext[context] = 0;
234 }
235 
236 static
open_file(char * fn)237 open_file(char *fn)
238 {
239 	/*
240 	 * this routine initializes a rab and  fab required to get the
241 	 * correct definition of the external data file used by mail
242 	 */
243 	struct FAB	*fab;
244 
245 	rab = (struct RAB *) e_malloc(sizeof (struct RAB));
246 	fab = (struct FAB *) e_malloc(sizeof (struct FAB));
247 
248 	*rab = cc$rms_rab;	/* initialize RAB */
249 	rab->rab$l_fab = fab;
250 
251 	*fab = cc$rms_fab;	/* initialize FAB */
252 	fab->fab$l_fna = fn;
253 	fab->fab$b_fns = strlen(fn);
254 	fab->fab$w_mrs = 512;
255 	fab->fab$b_fac = FAB$M_BIO | FAB$M_GET;
256 	fab->fab$b_org = FAB$C_SEQ;
257 	fab->fab$b_rfm = FAB$C_FIX;
258 	fab->fab$l_xab = (char *) 0;
259 
260 	rms_status = sys$open(rab->rab$l_fab);
261 	if (rms_status != RMS$_NORMAL && rms_status != RMS$_CREATED)
262 		error_exit("$OPEN");
263 	rms_status = sys$connect(rab);
264 	if (rms_status != RMS$_NORMAL)
265 		error_exit("$CONNECT");
266 	return (1);
267 }
268 
269 static
close_file(struct RAB * prab)270 close_file(struct RAB * prab)
271 {
272 	rms_status = sys$close(prab->rab$l_fab);
273 	free(prab->rab$l_fab);
274 	free(prab);
275 	if (rms_status != RMS$_NORMAL)
276 		error_exit("$CLOSE");
277 }
278 
279 #define	NSECT 16
280 extern unsigned int last_extent_written;
281 
282 int
vms_write_one_file(char * filename,off_t size,FILE * outfile)283 vms_write_one_file(char *filename, off_t size, FILE * outfile)
284 {
285 	int		status,
286 			i;
287 	char		buffer[SECTOR_SIZE * NSECT];
288 	int		count;
289 	int		use;
290 	off_t		remain;
291 
292 	open_file(filename);
293 
294 	remain = size;
295 
296 	while (remain > 0) {
297 		use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT * SECTOR_SIZE : remain);
298 		use = ISO_ROUND_UP(use); /* Round up to nearest sector boundary */
299 		memset(buffer, 0, use);
300 		rab->rab$l_ubf = buffer;
301 		rab->rab$w_usz = sizeof (buffer);
302 		status = sys$read(rab);
303 		fwrite(buffer, 1, use, outfile);
304 		last_extent_written += use / SECTOR_SIZE;
305 		if ((last_extent_written % 1000) < use / SECTOR_SIZE)
306 			fprintf(stderr, "%d..", last_extent_written);
307 		remain -= use;
308 	};
309 
310 	close_file(rab);
311 }
312 
313 #endif
314