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