1/* VMS functions
2Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
32006 Free Software Foundation, Inc.
4This file is part of GNU Make.
5
6GNU Make is free software; you can redistribute it and/or modify it under the
7terms of the GNU General Public License as published by the Free Software
8Foundation; either version 2, or (at your option) any later version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15GNU Make; see the file COPYING.  If not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
17
18#include "make.h"
19#include "debug.h"
20#include "job.h"
21
22#ifdef __DECC
23#include <starlet.h>
24#endif
25#include <descrip.h>
26#include <rms.h>
27#include <iodef.h>
28#include <atrdef.h>
29#include <fibdef.h>
30#include "vmsdir.h"
31
32#ifdef HAVE_VMSDIR_H
33
34DIR *
35opendir (char *dspec)
36{
37  struct DIR *dir  = (struct DIR *)xmalloc (sizeof (struct DIR));
38  struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM));
39  struct FAB *dfab = &dir->fab;
40  char *searchspec = (char *)xmalloc (MAXNAMLEN + 1);
41
42  memset (dir, 0, sizeof *dir);
43
44  *dfab = cc$rms_fab;
45  *dnam = cc$rms_nam;
46  sprintf (searchspec, "%s*.*;", dspec);
47
48  dfab->fab$l_fna = searchspec;
49  dfab->fab$b_fns = strlen (searchspec);
50  dfab->fab$l_nam = dnam;
51
52  *dnam = cc$rms_nam;
53  dnam->nam$l_esa = searchspec;
54  dnam->nam$b_ess = MAXNAMLEN;
55
56  if (! (sys$parse (dfab) & 1))
57    {
58      free (dir);
59      free (dnam);
60      free (searchspec);
61      return (NULL);
62    }
63
64  return dir;
65}
66
67#define uppercasify(str) \
68  do \
69    { \
70      char *tmp; \
71      for (tmp = (str); *tmp != '\0'; tmp++) \
72        if (islower ((unsigned char)*tmp)) \
73          *tmp = toupper ((unsigned char)*tmp); \
74    } \
75  while (0)
76
77struct direct *
78readdir (DIR *dir)
79{
80  struct FAB *dfab = &dir->fab;
81  struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
82  struct direct *dentry = &dir->dir;
83  int i;
84
85  memset (dentry, 0, sizeof *dentry);
86
87  dnam->nam$l_rsa = dir->d_result;
88  dnam->nam$b_rss = MAXNAMLEN;
89
90  DB (DB_VERBOSE, ("."));
91
92  if (!((i = sys$search (dfab)) & 1))
93    {
94      DB (DB_VERBOSE, (_("sys$search failed with %d\n"), i));
95      return (NULL);
96    }
97
98  dentry->d_off = 0;
99  if (dnam->nam$w_fid == 0)
100    dentry->d_fileno = 1;
101  else
102    dentry->d_fileno = dnam->nam$w_fid[0] + (dnam->nam$w_fid[1] << 16);
103
104  dentry->d_reclen = sizeof (struct direct);
105  dentry->d_namlen = dnam->nam$b_name + dnam->nam$b_type;
106  strncpy (dentry->d_name, dnam->nam$l_name, dentry->d_namlen);
107  dentry->d_name[dentry->d_namlen] = '\0';
108
109#ifdef HAVE_CASE_INSENSITIVE_FS
110  uppercasify (dentry->d_name);
111#endif
112
113  return (dentry);
114}
115
116int
117closedir (DIR *dir)
118{
119  if (dir != NULL)
120    {
121      struct FAB *dfab = &dir->fab;
122      struct NAM *dnam = (struct NAM *)(dfab->fab$l_nam);
123      if (dnam != NULL)
124	free (dnam->nam$l_esa);
125      free (dnam);
126      free (dir);
127    }
128
129  return 0;
130}
131#endif /* compiled for OpenVMS prior to V7.x */
132
133char *
134getwd (char *cwd)
135{
136  static char buf[512];
137
138  if (cwd)
139    return (getcwd (cwd, 512));
140  else
141    return (getcwd (buf, 512));
142}
143
144int
145vms_stat (char *name, struct stat *buf)
146{
147  int status;
148  int i;
149
150  static struct FAB Fab;
151  static struct NAM Nam;
152  static struct fibdef Fib;	/* short fib */
153  static struct dsc$descriptor FibDesc =
154  { sizeof (Fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (char *) &Fib };
155  static struct dsc$descriptor_s DevDesc =
156  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &Nam.nam$t_dvi[1] };
157  static char EName[NAM$C_MAXRSS];
158  static char RName[NAM$C_MAXRSS];
159  static struct dsc$descriptor_s FileName =
160  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
161  static struct dsc$descriptor_s string =
162  { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
163  static unsigned long Rdate[2];
164  static unsigned long Cdate[2];
165  static struct atrdef Atr[] =
166  {
167#if defined(VAX)
168    /* Revision date */
169    { sizeof (Rdate), ATR$C_REVDATE, (unsigned int) &Rdate[0] },
170    /* Creation date */
171    { sizeof (Cdate), ATR$C_CREDATE, (unsigned int) &Cdate[0] },
172#else
173    /* Revision date */
174    { sizeof (Rdate), ATR$C_REVDATE, &Rdate[0] },
175    /* Creation date */
176    { sizeof (Cdate), ATR$C_CREDATE, &Cdate[0]},
177#endif
178    { 0, 0, 0 }
179  };
180  static short int DevChan;
181  static short int iosb[4];
182
183  name = vmsify (name, 0);
184
185  /* initialize RMS structures, we need a NAM to retrieve the FID */
186  Fab = cc$rms_fab;
187  Fab.fab$l_fna = name;		/* name of file */
188  Fab.fab$b_fns = strlen (name);
189  Fab.fab$l_nam = &Nam;		/* FAB has an associated NAM */
190
191  Nam = cc$rms_nam;
192  Nam.nam$l_esa = EName;	/* expanded filename */
193  Nam.nam$b_ess = sizeof (EName);
194  Nam.nam$l_rsa = RName;	/* resultant filename */
195  Nam.nam$b_rss = sizeof (RName);
196
197  /* do $PARSE and $SEARCH here */
198  status = sys$parse (&Fab);
199  if (!(status & 1))
200    return -1;
201
202  DevDesc.dsc$w_length = Nam.nam$t_dvi[0];
203  status = sys$assign (&DevDesc, &DevChan, 0, 0);
204  if (!(status & 1))
205    return -1;
206
207  FileName.dsc$a_pointer = Nam.nam$l_name;
208  FileName.dsc$w_length = Nam.nam$b_name + Nam.nam$b_type + Nam.nam$b_ver;
209
210  /* Initialize the FIB */
211  for (i = 0; i < 3; i++)
212    {
213#ifndef __VAXC
214      Fib.fib$w_fid[i] = Nam.nam$w_fid[i];
215      Fib.fib$w_did[i] = Nam.nam$w_did[i];
216#else
217      Fib.fib$r_fid_overlay.fib$w_fid[i] = Nam.nam$w_fid[i];
218      Fib.fib$r_did_overlay.fib$w_did[i] = Nam.nam$w_did[i];
219#endif
220    }
221
222  status = sys$qiow (0, DevChan, IO$_ACCESS, &iosb, 0, 0,
223		     &FibDesc, &FileName, 0, 0, &Atr, 0);
224  sys$dassgn (DevChan);
225  if (!(status & 1))
226    return -1;
227  status = iosb[0];
228  if (!(status & 1))
229    return -1;
230
231  status = stat (name, buf);
232  if (status)
233    return -1;
234
235  buf->st_mtime = ((Rdate[0] >> 24) & 0xff) + ((Rdate[1] << 8) & 0xffffff00);
236  buf->st_ctime = ((Cdate[0] >> 24) & 0xff) + ((Cdate[1] << 8) & 0xffffff00);
237
238  return 0;
239}
240
241char *
242cvt_time (unsigned long tval)
243{
244  static long int date[2];
245  static char str[27];
246  static struct dsc$descriptor date_str =
247  { 26, DSC$K_DTYPE_T, DSC$K_CLASS_S, str };
248
249  date[0] = (tval & 0xff) << 24;
250  date[1] = ((tval >> 8) & 0xffffff);
251
252  if ((date[0] == 0) && (date[1] == 0))
253    return ("never");
254
255  sys$asctim (0, &date_str, date, 0);
256  str[26] = '\0';
257
258  return (str);
259}
260
261int
262strcmpi (const char *s1, const char *s2)
263{
264  while (*s1 != '\0' && toupper(*s1) == toupper(*s2))
265    {
266      s1++;
267      s2++;
268    }
269
270  return toupper(*(unsigned char *) s1) - toupper(*(unsigned char *) s2);
271}
272