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