1
/* @(#)osh.c 19.1 (ES0-DMD) 02/25/03 13:56:12 */
2
/*===========================================================================
3
Copyright (C) 1995 European Southern Observatory (ESO)
5
This program is free software; you can redistribute it and/or
6
modify it under the terms of the GNU General Public License as
7
published by the Free Software Foundation; either version 2 of
8
the License, or (at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public
16
License along with this program; if not, write to the Free
17
Software Foundation, Inc., 675 Massachusetss Ave, Cambridge,
20
Corresponding concerning ESO-MIDAS should be addressed as follows:
21
Internet e-mail: midas@eso.org
22
Postal address: European Southern Observatory
23
Data Management Division
24
Karl-Schwarzschild-Strasse 2
25
D 85748 Garching bei Muenchen
27
===========================================================================*/
29
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33
.AUTHOR IPG-ESO Garching
34
.CATEGORY Host operating system interfaces. Host services.
35
.ENVIRONMENT VAX/VMS Version
37
Provide miscellaneous host services.
38
The routines return time and date stamps,
39
return cpu time used by the current process,
40
translate logicals (environment)
41
executes host commands.
42
Time resolution is host dependent parameter.
43
The routines return always
44
a non-negative integer number on successful return.
45
Otherwise, a value of -1 is set to indicate an error
46
condition and the variable ``oserror'' contains the
48
.VERSION 0.0 25-Aug-1986 Definition. J. D. Ponz
49
.VERSION 1.8 10-Feb-1988 VMS Version. F. ochsenbein.
50
Difference oshgmt / oshtime
51
.VERSION 1.9 05-Sep-1989 Changed some `unclever' macros...
52
.VERSION 2.0 08-Aug-1990 Added oshtm / oshtl (time conversions)
53
------------------------------------------------------------*/
63
MID_EXTERN int oserror;
64
MID_EXTERN int vmserror;
66
#include <time.h> /* System */
67
#include <errno.h> /* System */
68
#include <ssdef.h> /* System */
69
#include <descrip.h> /* System */
70
#include <lnmdef.h> /* System */
72
#define TR_MAX LNM$C_NAMLENGTH /* Maximal length translation */
73
#define len dsc$w_length
74
#define s dsc$a_pointer
76
typedef struct dsc$descriptor descript;
77
#define void_string {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL_PTR(char)}
78
#define InitDescript(text) \
79
{sizeof(text)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S,text}
81
#define SET_STRING(dsc,str) dsc.s = str, dsc.len = strlen(str) \
82
/* Set address & length of a string */
83
struct item { /* For TRNLNM system service */
84
unsigned short int len;
85
unsigned short int item_code;
89
static long returned_len = 0;
91
static char tr_buf[TR_MAX+1] = "";
93
#define FINISH goto FIN
94
#define RETURN(x) FIN: return (oserror ? -1 : x)
96
/*==========================================================================
97
* Logical Name Translations
98
*==========================================================================*/
100
/*==========================================================================*/
101
int oshset(logname, translation)
102
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
104
Inserts a logical name in the Environment.
105
.RETURNS 0 (success) / -1 (failure)
107
------------------------------------------------------------*/
108
char *logname; /* IN : logical name */
109
char *translation; /* IN : Equivalence String */
111
static descript sdv_table = InitDescript("LNM$PROCESS_TABLE");
112
static descript sdv_in = void_string;
114
struct item Item; /* Equivalence string */
117
{0, LNM$_STRING, 0, &returned_len},
122
SET_STRING(sdv_in, logname);
123
item_eq.Item.addr = translation, item_eq.Item.len = strlen(translation);
125
vmserror = SYS$CRELNM(0,&sdv_table,&sdv_in,0,&item_eq);
126
if ((vmserror&1) == 0) { oserror = ENXIO; FINISH;}
129
return(oserror ? -1 : 0);
132
/*==========================================================================*/
133
char *oshenv(logname, table)
134
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
136
Translate logical names into physical names., according to a table.
137
.RETURNS Address of equivalence name / NULL when logname not found
138
.REMARKS table is used only in VMS environment (default is LNM$FILE_DEV).
139
Translation is not case-dependent on VMS. Use recursive translation.
140
------------------------------------------------------------*/
141
char *logname; /* IN : logical name */
142
char *table; /* IN : name of the table to look for (VMS only) */
144
static unsigned int lnmlength = 0;
145
static unsigned int attr_case = LNM$M_CASE_BLIND;
146
static unsigned int attr_list = 0;
147
static descript sdv_table = void_string;
148
static descript sdv_in = void_string;
149
static descript sdv_out = InitDescript(tr_buf);
151
struct item Item; /* Equivalence string */
154
{TR_MAX, LNM$_STRING, tr_buf, &sdv_out},
157
struct item Item; /* Attributes of logical */
160
{sizeof(attr_list), LNM$_ATTRIBUTES, &attr_list, &lnmlength},
166
SET_STRING(sdv_in, logname);
167
p = (table ? table : "LNM$FILE_DEV");
168
p = (*p ? p : "LNM$FILE_DEV"); /* In case of void string */
169
SET_STRING(sdv_table, p); /* Write info as descriptors */
172
vmserror = SYS$TRNLNM(&attr_case,&sdv_table,&sdv_in,0,&item_attr);
173
if (vmserror != SS$_NORMAL) { oserror = ENXIO; FINISH;}
175
/* Continue Translations while a translation exists */
176
while (attr_list & (LNM$M_EXISTS))
177
{ SYS$TRNLNM(&attr_case,&sdv_table,&sdv_in,0,&item_eq);
178
tr_buf[sdv_out.len] = EOS; /* Append the EOS character */
180
if (*p == 033) p += 4; /* Terminal translation */
181
if (tr_buf[--(sdv_out.len)] != ':') (sdv_out.len)++;
182
sdv_in.s = sdv_out.s; sdv_in.len = sdv_out.len;
183
if (SYS$TRNLNM(&attr_case,&sdv_table,&sdv_in,0,&item_attr)
184
!= SS$_NORMAL) FINISH;
185
if (attr_list & (LNM$M_CONCEALED | LNM$M_TERMINAL)) FINISH;
189
return(oserror ? NULL_PTR(char) : p);
193
/*==========================================================================*/
194
int oshtr(logname, phname, size)
195
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
197
Translate logical names into physical names. i.e. $KEYS ==> myfile.key
198
.RETURNS Value 0 on normal return, -1 when logname not found (phname then
199
contains an empty string)
200
.REMARKS Simply use oshenv.
201
------------------------------------------------------------*/
202
char *logname; /* IN : logical name */
203
char *phname; /* OUT : logical physical name */
204
int size; /* IN : size of phname */
206
register char *p, *q;
208
if (size < 2) { oserror = EINVAL; FINISH; } /* Output too small */
211
p = oshenv(logname, NULL_PTR(char));
212
if (!p) FINISH; /* No translation... */
213
if (strlen(p) >= (size-1)) /* Translation is too long */
214
{ oserror = ERANGE; FINISH;}
216
for (q=phname; *p; p++, q++) *q = *p;
219
return (oserror ? -1 : 0);
223
/*==========================================================================
224
* Date / Time Services
225
*==========================================================================*/
227
/*======================================================================*/
228
static long vmstime(q)
230
.PURPOSE Converts the VAX time to standard
231
.RETURNS Time as seconds elapsed since Jan. 1, 1970
232
.REMARKS The VAX time is 64 bits; origin = Nov. 17, 1858; units = 100ns.
233
(40587 days before Jan 1, 1970)
235
unsigned long *q; /* IN: VAX time */
240
tt = q[1] * 4294967296e0;
242
tt = tt / 1.e7 - (40587.e0 * 86400.e0);
249
/*==========================================================================*/
251
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
252
.PURPOSE Retrieves current (local!) time in seconds elapsed since Jan. 1, 1970, 0h.
253
.RETURNS The time in seconds.
255
------------------------------------------------------------*/
257
static long qtime[2];
261
return(vmstime(qtime));
265
#define Jan1_1970 135140L /* Date in 400-yr cycle */
266
#define Jan1_1980 138792L /* Date in 400-yr cycle */
267
#define Jan1_2000 0L /* Date in 400-yr cycle */
270
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
271
.PURPOSE Convert time structure into seconds since Jan. 1, 1970
272
.RETURNS The time in seconds.
273
.REMARKS Computation is done here, system call seems to be non-existent...
274
------------------------------------------------------------*/
275
struct tm *T; /* IN: Time structure to convert */
277
register long int j, y, t;
279
/* Compute Day of 400 yr cycle */
281
if (y < 1000) y += 1900;
283
y += 400; /* To be sure j is positive */
284
j = y - (11 - T->tm_mon)/10;
285
t = ((1461L*j)/4 + (306L * ((T->tm_mon+10)%12) + 5)/10
286
- (3* ((j + 100L)/100L))/4 + T->tm_mday + 59L) % 146097L;
287
/* Compute Week day */
288
T->tm_wday = (t+6L)%7L;
290
t -= Jan1_1970; /* Origin = Jan 1, 1970 */
291
if (t < -24855) t += 146097L;
292
if (t > 24855) t -= 146097L;
295
/* Transform Day into seconds */
296
if (t < -24855) t = -24855;
297
if (t > 24855) t = 24855;
298
t = t * 86400L + T->tm_hour * 3600L + T->tm_min * 60L + T->tm_sec;
302
struct tm *oshtm(clock)
303
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
304
.PURPOSE Convert time (long) as time structure
305
.RETURNS Equivalent structure with filled items
306
.REMARKS VMS localtime is completely wrong for dates < Jan 1, 1970 !!!
307
------------------------------------------------------------*/
308
long clock; /* IN: Time as seconds since Jan. 1, 1970 */
312
static unsigned char month[12]={31,28,31,30,31,30,31,31,30,31,30,31};
319
days += (t/86400L); t %= 86400L;
320
T.tm_sec = t%60; t /= 60;
324
/* Compute Week day */
325
T.tm_wday = (days+Jan1_1970+6L)%7L;
327
days += (70L*365L + 18L); /* Offset 1900 */
330
T.tm_yday = days - 365L*y - (y+3)/4;
332
/* Compute mon + mday from yday */
334
month[1] = (y&3 ? 28 : 29);
336
for (y=T.tm_yday, t=0; y>=month[t]; y -= month[t], t++) ;
343
/*==========================================================================*/
345
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
346
.PURPOSE Retrieves GMT time in seconds elapsed since Jan. 1, 1970, 0h.
347
.RETURNS The time in seconds.
349
------------------------------------------------------------*/
351
static long qtime[2] ;
356
p = oshenv("TIMEZONE", NULL_PTR(char));
357
if (p) TU = atoi(p); /* Get GMT difference */
360
return(vmstime(qtime) - TU*60);
364
/*==========================================================================*/
365
long oshcpu(op, ftime)
366
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
367
.PURPOSE Gets CPU time. Precision is : hundreds of seconds.
368
Cpu time returned is the sum of the time spend for both system
369
tasks and process itself needed for the completion of the task.
370
.RETURNS Elapsed CPU time in `clock-ticks' (1/100 s) for VMS
371
-1 if the operation to do is unknown or if
372
the get operation was not preceded by an initialization.
373
.REMARKS On MS-DOS, cpu time is equated to elapsed time...
374
------------------------------------------------------------*/
375
int op; /* IN : operation to execute : INIT_CLOCK / GET_CLOCK */
376
float *ftime; /* OUT: CPU time in seconds */
379
static long firstime = 0;
380
static int param = 2;
383
if (ftime) *ftime = 0.e0;
385
{ case INIT_CLOCK : /**** Initialize timer */
387
vmserror = LIB$INIT_TIMER();
388
if (!(vmserror&1)) oserror = EINTR;
391
case GET_CLOCK : /**** get time */
392
vmserror = LIB$STAT_TIMER(¶m,&lastime);
393
if (ftime) *ftime = lastime, *ftime /= 1.e2;
394
if (!(vmserror&1)) oserror = EINTR;
397
default : /**** Operation code error */
402
return (oserror ? -1 : lastime);
405
/*==========================================================================*/
406
long oshela(op, ftime)
407
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
408
.PURPOSE Gets ELAPSED time. Precision is : 1 seconds.
409
.RETURNS Elapsed time (s) on normal return.
410
Value -1 if the operation to do is unknown or if
411
the get operation was not preceded by an initialization.
413
------------------------------------------------------------*/
414
int op; /* IN: operation INIT_CLOCK / GET_CLOCK */
415
long *ftime; /* OUT: Elapsed time in seconds */
417
static long firstime = 0;
418
register long lastime;
420
if (ftime) *ftime = 0;
423
{ case INIT_CLOCK : /**** Initialize timer */
425
firstime = oshtime();
427
case GET_CLOCK : /**** get time */
428
lastime = oshtime() - firstime;
429
if (ftime) *ftime = lastime;
431
default : /**** Operation code error */
435
return (oserror ? -1 : lastime);
439
/*==========================================================================*/
440
int oshcmd(command, input, output, error)
441
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
442
.PURPOSE Executes system command(maybe with arguments).
443
The routine defines also
444
the pathnames for standard input, output and error units.
445
Enviroment variable SHELL must be defined.
446
.RETURNS Value 0 on normal return / -1 if error.
447
.REMARKS error parameter ignored for VMS.
448
------------------------------------------------------------*/
449
char *command; /* IN : system command */
450
char *input; /* IN : standard input stream */
451
char *output; /* IN : standard output stream */
452
char *error; /* IN : error output stream */
454
static unsigned int attr_list = 0;
455
static descript sdv_com = void_string;
456
static descript sdv_in = void_string;
458
static descript sdv_out = InitDescript(tr_buf);
461
SET_STRING(sdv_com, command);
462
in = (input ? &sdv_in : 0);
463
out = (output ? &sdv_out: 0);
464
if (in) SET_STRING(sdv_in, input);
465
if (out) SET_STRING(sdv_out, output);
466
vmserror = LIB$SPAWN(&sdv_com, in, out);
467
if (!(vmserror&1)) oserror = EINTR;
469
return (oserror ? -1 : 0);
472
/*==========================================================================*/
474
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
475
.PURPOSE Executes system command(maybe with arguments).
476
.RETURNS Value 0 on normal return / -1 if error.
477
.REMARKS Stops the program !
478
------------------------------------------------------------*/
479
char *command; /* IN : system command */
481
static descript sdv_com = void_string;
484
SET_STRING(sdv_com, command);
485
vmserror = LIB$DO_COMMAND(&sdv_com);
486
if (!(vmserror&1)) oserror = EINTR;
488
return (oserror ? -1 : 0);
491
char * oshmcpy(s1, s2, n)
492
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
493
.PURPOSE copies n characters from memory area s2 to s1.
494
.RETURNS It returns s1.
495
.REMARKS System dependencies: none.
496
------------------------------------------------------------*/
497
register char *s1, *s2;
500
register char *os1 = s1;
507
int oshdate(date_string, date_struct)
508
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
509
.PURPOSE Gets date and time stamp. No special structure adopted.
510
.RETURNS A pointer to the time structure is defined in <time.h> (system)
511
{\begin{TeX} \begin{itemize} \item int tm_year number
512
\item int tm_mon number [0-11] \item int tm_mday [1-31]
513
\item int tm_yday [0-355] \item int tm_wday [0-6] (Sunday = 0)
514
\item int tm_hour [0-23] \item int tm_min [0-59]
515
\item int tm_sec [0-59]. \item int tm_saving
516
\end{itemize} \end{TeX}}
517
.REMARKS System dependencies:
518
--Not implemented for VMS
519
------------------------------------------------------------*/
520
char date_string[28]; /* OUT : date-time stamp */
521
struct tm *date_struct; /* OUT : date-time structure (see description) */
527
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
528
.PURPOSE Change current working directory.
529
.RETURNS Value 0 on normal return. -1 on failure and oserror set.
530
.REMARKS System dependencies:
532
------------------------------------------------------------*/
535
if (chdir(path) == -1) {