|
Packit Service |
f629e6 |
/* [.vms]vms_popen.c -- substitute routines for missing pipe calls.
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
Copyright (C) 1991-1993, 1996, 2010, 2011, 2014
|
|
Packit Service |
f629e6 |
the Free Software Foundation, Inc.
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
f629e6 |
it under the terms of the GNU General Public License as published by
|
|
Packit Service |
f629e6 |
the Free Software Foundation; either version 2, or (at your option)
|
|
Packit Service |
f629e6 |
any later version.
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
This program is distributed in the hope that it will be useful,
|
|
Packit Service |
f629e6 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
f629e6 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
f629e6 |
GNU General Public License for more details.
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
You should have received a copy of the GNU General Public License
|
|
Packit Service |
f629e6 |
along with this program; if not, write to the Free Software Foundation,
|
|
Packit Service |
f629e6 |
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifndef NO_VMS_PIPES
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include "awk.h" /* really "../awk.h" */
|
|
Packit Service |
f629e6 |
#include <stdio.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifndef PIPES_SIMULATED
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
FILE *
|
|
Packit Service |
f629e6 |
popen( const char *command, const char *mode )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
fatal(" Cannot open pipe `%s' (not implemented)", command);
|
|
Packit Service |
f629e6 |
/* NOT REACHED */
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
pclose( FILE *current )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
fatal(" Internal error ('pclose' not implemented)");
|
|
Packit Service |
f629e6 |
/* NOT REACHED */
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
fork( void )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
fatal(" Internal error ('fork' not implemented)");
|
|
Packit Service |
f629e6 |
/* NOT REACHED */
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#else /*PIPES_SIMULATED*/
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Simulate pipes using temporary files; hope that the user
|
|
Packit Service |
f629e6 |
* doesn't expect pipe i/o to be interleaved with other i/o ;-}.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* This was initially based on the MSDOS version, but cannot
|
|
Packit Service |
f629e6 |
* use a static array to hold pipe info, because there's no
|
|
Packit Service |
f629e6 |
* fixed limit on the range of valid 'fileno's. Another
|
|
Packit Service |
f629e6 |
* difference is that redirection is handled using LIB$SPAWN
|
|
Packit Service |
f629e6 |
* rather than constructing a command for system() which uses
|
|
Packit Service |
f629e6 |
* '<' or '>'.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
#include "vms.h"
|
|
Packit Service |
f629e6 |
#include <errno.h>
|
|
Packit Service |
f629e6 |
#include <lnmdef.h> /* logical name definitions */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifndef STDC_HEADERS
|
|
Packit Service |
f629e6 |
extern int strcmp(const char*, const char *);
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
extern char *mktemp(char *);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void push_logicals(void);
|
|
Packit Service |
f629e6 |
static void pop_logicals(void);
|
|
Packit Service |
f629e6 |
static Itm *save_translation(const struct dsc$descriptor_s *);
|
|
Packit Service |
f629e6 |
static void restore_translation(const struct dsc$descriptor_s *, const Itm *);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
typedef enum { unopened = 0, reading, writing } pipemode;
|
|
Packit Service |
f629e6 |
typedef struct pipe_info {
|
|
Packit Service |
f629e6 |
char *command;
|
|
Packit Service |
f629e6 |
char *name;
|
|
Packit Service |
f629e6 |
pipemode pmode;
|
|
Packit Service |
f629e6 |
} PIPE;
|
|
Packit Service |
f629e6 |
static PIPE *pipes;
|
|
Packit Service |
f629e6 |
static int pipes_lim = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#define psize(n) ((n) * sizeof(PIPE))
|
|
Packit Service |
f629e6 |
#define expand_pipes(k) do { PIPE *new_p; \
|
|
Packit Service |
f629e6 |
int new_p_lim = ((k) / _NFILE + 1) * _NFILE; \
|
|
Packit Service |
f629e6 |
emalloc(new_p, PIPE *, psize(new_p_lim), "expand_pipes"); \
|
|
Packit Service |
f629e6 |
if (pipes_lim > 0) \
|
|
Packit Service |
f629e6 |
memcpy(new_p, pipes, psize(pipes_lim)), free(pipes); \
|
|
Packit Service |
f629e6 |
memset(new_p + psize(pipes_lim), 0, psize(new_p_lim - pipes_lim)); \
|
|
Packit Service |
f629e6 |
pipes = new_p, pipes_lim = new_p_lim; } while(0)
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
FILE *
|
|
Packit Service |
f629e6 |
popen( const char *command, const char *mode )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
FILE *current;
|
|
Packit Service |
f629e6 |
char *name;
|
|
Packit Service |
f629e6 |
int cur;
|
|
Packit Service |
f629e6 |
pipemode curmode;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (strcmp(mode, "r") == 0)
|
|
Packit Service |
f629e6 |
curmode = reading;
|
|
Packit Service |
f629e6 |
else if (strcmp(mode, "w") == 0)
|
|
Packit Service |
f629e6 |
curmode = writing;
|
|
Packit Service |
f629e6 |
else
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* make a name for the temporary file */
|
|
Packit Service |
f629e6 |
if ((name = mktemp(strdup("sys$scratch:gawk-pipe_XXXXXX.tmp"))) == 0)
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (curmode == reading) {
|
|
Packit Service |
f629e6 |
/* an input pipe reads a temporary file created by the command */
|
|
Packit Service |
f629e6 |
vms_execute(command, (char *)0, name); /* 'command >tempfile' */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
if ((current = fopen(name, mode, "mbc=24", "mbf=2")) == NULL) {
|
|
Packit Service |
f629e6 |
free(name);
|
|
Packit Service |
f629e6 |
return NULL;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
cur = fileno(current);
|
|
Packit Service |
f629e6 |
if (cur >= pipes_lim) expand_pipes(cur);
|
|
Packit Service |
f629e6 |
/* assert( cur >= 0 && cur < pipes_lim ); */
|
|
Packit Service |
f629e6 |
pipes[cur].name = name;
|
|
Packit Service |
f629e6 |
pipes[cur].pmode = curmode;
|
|
Packit Service |
f629e6 |
pipes[cur].command = strdup(command);
|
|
Packit Service |
f629e6 |
return current;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
pclose( FILE *current )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
int rval, cur = fileno(current);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* assert( cur >= 0 && cur < pipes_lim ); */
|
|
Packit Service |
f629e6 |
if ((cur < 0) || (pipes[cur].pmode == unopened))
|
|
Packit Service |
f629e6 |
return -1; /* should never happen, but does with two-way */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
rval = fclose(current); /* close temp file; if reading, we're done */
|
|
Packit Service |
f629e6 |
if (pipes[cur].pmode == writing) {
|
|
Packit Service |
f629e6 |
/* an output pipe feeds the temporary file to the other program */
|
|
Packit Service |
f629e6 |
rval = vms_execute(pipes[cur].command, pipes[cur].name, (char *)0);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
/* clean up */
|
|
Packit Service |
f629e6 |
unlink(pipes[cur].name); /* get rid of the temporary file */
|
|
Packit Service |
f629e6 |
pipes[cur].pmode = unopened;
|
|
Packit Service |
f629e6 |
free(pipes[cur].name), pipes[cur].name = 0;
|
|
Packit Service |
f629e6 |
free(pipes[cur].command), pipes[cur].command = 0;
|
|
Packit Service |
f629e6 |
return rval;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Create a process and execute a command in it. This is essentially
|
|
Packit Service |
f629e6 |
* the same as system() but allows us to specify SYS$INPUT (stdin)
|
|
Packit Service |
f629e6 |
* and/or SYS$OUTPUT (stdout) for the process.
|
|
Packit Service |
f629e6 |
* [With more work it could truly simulate a pipe using mailboxes.]
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
int
|
|
Packit Service |
f629e6 |
vms_execute( const char *command, const char *input, const char *output )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
struct dsc$descriptor_s cmd, in, out, *in_p, *out_p;
|
|
Packit Service |
f629e6 |
U_Long sts, cmpltn_sts;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
cmd.dsc$w_length = strlen(cmd.dsc$a_pointer = (char *)command);
|
|
Packit Service |
f629e6 |
cmd.dsc$b_dtype = DSC$K_DTYPE_T;
|
|
Packit Service |
f629e6 |
cmd.dsc$b_class = DSC$K_CLASS_S;
|
|
Packit Service |
f629e6 |
if (input) {
|
|
Packit Service |
f629e6 |
in.dsc$w_length = strlen(in.dsc$a_pointer = (char *)input);
|
|
Packit Service |
f629e6 |
in_p = ∈
|
|
Packit Service |
f629e6 |
in.dsc$b_dtype = DSC$K_DTYPE_T;
|
|
Packit Service |
f629e6 |
in.dsc$b_class = DSC$K_CLASS_S;
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
in_p = 0;
|
|
Packit Service |
f629e6 |
if (output) {
|
|
Packit Service |
f629e6 |
out.dsc$w_length = strlen(out.dsc$a_pointer = (char *)output);
|
|
Packit Service |
f629e6 |
out_p = &out;
|
|
Packit Service |
f629e6 |
out.dsc$b_dtype = DSC$K_DTYPE_T;
|
|
Packit Service |
f629e6 |
out.dsc$b_class = DSC$K_CLASS_S;
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
out_p = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
push_logicals(); /* guard against user-mode definitions of sys$Xput */
|
|
Packit Service |
f629e6 |
sts = LIB$SPAWN(&cmd, in_p, out_p, (U_Long *)0,
|
|
Packit Service |
f629e6 |
(struct dsc$descriptor_s *)0, (U_Long *)0, &cmpltn_sts);
|
|
Packit Service |
f629e6 |
pop_logicals(); /* restore environment */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (vmswork(sts) && vmsfail(cmpltn_sts)) sts = cmpltn_sts;
|
|
Packit Service |
f629e6 |
if (vmsfail(sts)) {
|
|
Packit Service |
f629e6 |
errno = EVMSERR, vaxc$errno = sts;
|
|
Packit Service |
f629e6 |
return -1;
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
return 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*----*
|
|
Packit Service |
f629e6 |
This rigmarole is to guard against interference from the current
|
|
Packit Service |
f629e6 |
environment. User-mode definitions of SYS$INPUT and/or SYS$OUTPUT
|
|
Packit Service |
f629e6 |
will interact with spawned subprocesses--including LIB$SPAWN with
|
|
Packit Service |
f629e6 |
explicit input and/or output arguments specified--if they were
|
|
Packit Service |
f629e6 |
defined without the 'CONFINED' attribute. The definitions created
|
|
Packit Service |
f629e6 |
in vms_args.c as part of command line I/O redirection happened to
|
|
Packit Service |
f629e6 |
fall into this category :-(, but even though that's been fixed,
|
|
Packit Service |
f629e6 |
there's still the possibility of the user doing something like
|
|
Packit Service |
f629e6 |
|$ define/user sys$output foo.out
|
|
Packit Service |
f629e6 |
prior to starting the program. Without ``/name_attr=confine'',
|
|
Packit Service |
f629e6 |
that will really screw up pipe simulation, so we've got to work-
|
|
Packit Service |
f629e6 |
around it here. This is true whether pipes are implemented via
|
|
Packit Service |
f629e6 |
mailboxes or temporary files, as long as lib$spawn() is being used.
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
push_logicals() calls save_translation() the first time it's
|
|
Packit Service |
f629e6 |
invoked; the latter allocates some memory to hold a full logical
|
|
Packit Service |
f629e6 |
name translation and uses $trnlnm to fill that in. Then if either
|
|
Packit Service |
f629e6 |
sys$input or sys$output has a user-mode, non-confined translation,
|
|
Packit Service |
f629e6 |
push_logicals() will delete the definition(s) using $dellnm.
|
|
Packit Service |
f629e6 |
After the spawned command has returned, pop_logicals() is called;
|
|
Packit Service |
f629e6 |
it calls restore_translation() for any deleted values; the latter
|
|
Packit Service |
f629e6 |
uses $crllnm or $crelog to recreate the original definition.
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
SYS$ERROR is currently ignored; perhaps it should receive the same
|
|
Packit Service |
f629e6 |
treatment...
|
|
Packit Service |
f629e6 |
*----*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* logical name table, and names of interest; these are all constant */
|
|
Packit Service |
f629e6 |
static const Descrip(lnmtable,"LNM$PROCESS_TABLE");
|
|
Packit Service |
f629e6 |
static const Descrip(sys_input,"SYS$INPUT");
|
|
Packit Service |
f629e6 |
static const Descrip(sys_output,"SYS$OUTPUT");
|
|
Packit Service |
f629e6 |
static const unsigned char acmode = PSL$C_USER; /* only care about user-mode */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* macros for simplfying the code a bunch */
|
|
Packit Service |
f629e6 |
#define DelTrans(l) SYS$DELLNM(&lnmtable, (l), &acmode)
|
|
Packit Service |
f629e6 |
#define GetTrans(l,i) SYS$TRNLNM((U_Long *)0, &lnmtable, (l), &acmode, (i))
|
|
Packit Service |
f629e6 |
#define SetTrans(l,i) SYS$CRELNM((U_Long *)0, &lnmtable, (l), &acmode, (i))
|
|
Packit Service |
f629e6 |
/* itemlist manipulation macros; separate versions for aggregate and scalar */
|
|
Packit Service |
f629e6 |
#define SetItmA(i,c,p,r) ((i).code = (c), (i).len = sizeof (p),\
|
|
Packit Service |
f629e6 |
(i).buffer = (p), (i).retlen = (U_Short *)(r))
|
|
Packit Service |
f629e6 |
#define SetItmS(i,c,p) ((i).code = (c), (i).len = sizeof *(p),\
|
|
Packit Service |
f629e6 |
(i).buffer = (p), (i).retlen = (U_Short *)0)
|
|
Packit Service |
f629e6 |
#define EndItm0(i) ((i).code = (i).len = 0)
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* translate things once, then hold the results here for multiple re-use */
|
|
Packit Service |
f629e6 |
static Itm *input_definition, *output_definition;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void
|
|
Packit Service |
f629e6 |
push_logicals( void ) /* deassign sys$input and/or sys$output */
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
static int init_done = 0;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (!init_done) { /* do logical name lookups one-time only */
|
|
Packit Service |
f629e6 |
input_definition = save_translation(&sys_input);
|
|
Packit Service |
f629e6 |
output_definition = save_translation(&sys_output);
|
|
Packit Service |
f629e6 |
init_done = 1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
if (input_definition) DelTrans(&sys_input); /* kill sys$input */
|
|
Packit Service |
f629e6 |
if (output_definition) DelTrans(&sys_output); /* and sys$output */
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void
|
|
Packit Service |
f629e6 |
pop_logicals( void ) /* redefine sys$input and/or sys$output */
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
if (input_definition) restore_translation(&sys_input, input_definition);
|
|
Packit Service |
f629e6 |
if (output_definition) restore_translation(&sys_output, output_definition);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static Itm *
|
|
Packit Service |
f629e6 |
save_translation( const struct dsc$descriptor_s *logname )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
Itm trans[4], *itmlst;
|
|
Packit Service |
f629e6 |
long trans_attr, max_trans_indx; /* 0-based translation index count */
|
|
Packit Service |
f629e6 |
unsigned char trans_acmode; /* translation's access mode */
|
|
Packit Service |
f629e6 |
unsigned itmlst_size;
|
|
Packit Service |
f629e6 |
register int i, j;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
itmlst = 0;
|
|
Packit Service |
f629e6 |
/* Want translation index count for non-confined, user-mode definition;
|
|
Packit Service |
f629e6 |
unfortunately, $trnlnm does not provide that much control. Try to
|
|
Packit Service |
f629e6 |
fetch several values of interest, then decide based on the result.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
SetItmS(trans[0], LNM$_MAX_INDEX, &max_trans_indx), max_trans_indx = -1;
|
|
Packit Service |
f629e6 |
SetItmS(trans[1], LNM$_ACMODE, &trans_acmode), trans_acmode = 0;
|
|
Packit Service |
f629e6 |
SetItmS(trans[2], LNM$_ATTRIBUTES, &trans_attr), trans_attr = 0;
|
|
Packit Service |
f629e6 |
EndItm0(trans[3]);
|
|
Packit Service |
f629e6 |
if (vmswork(GetTrans(logname, trans)) && max_trans_indx >= 0
|
|
Packit Service |
f629e6 |
&& trans_acmode == PSL$C_USER && !(trans_attr & LNM$M_CONFINE)) {
|
|
Packit Service |
f629e6 |
/* Now know that definition of interest exists;
|
|
Packit Service |
f629e6 |
allocate and initialize an item list and associated buffers;
|
|
Packit Service |
f629e6 |
use three entries for each translation.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
itmlst_size = (3 * (max_trans_indx + 1) + 1) * sizeof(Itm);
|
|
Packit Service |
f629e6 |
emalloc(itmlst, Itm *, itmlst_size, "save_translation");
|
|
Packit Service |
f629e6 |
for (i = 0; i <= max_trans_indx; i++) {
|
|
Packit Service |
f629e6 |
struct def { U_Long indx, attr; U_Short len;
|
|
Packit Service |
f629e6 |
char str[LNM$C_NAMLENGTH], eos; } *wrk;
|
|
Packit Service |
f629e6 |
emalloc(wrk, struct def *, sizeof (struct def), "save_translation");
|
|
Packit Service |
f629e6 |
wrk->indx = (U_Long)i; /* this one's an input value for $trnlnm */
|
|
Packit Service |
f629e6 |
SetItmS(itmlst[3*i+0], LNM$_INDEX, &wrk->indx);
|
|
Packit Service |
f629e6 |
SetItmS(itmlst[3*i+1], LNM$_ATTRIBUTES, &wrk->attr), wrk->attr = 0;
|
|
Packit Service |
f629e6 |
SetItmA(itmlst[3*i+2], LNM$_STRING, &wrk->str, &wrk->len), wrk->len = 0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
EndItm0(itmlst[3*i]); /* assert( i == max_trans_indx+1 ); */
|
|
Packit Service |
f629e6 |
/* Time to perform full logical name translation,
|
|
Packit Service |
f629e6 |
then update item list for subsequent restoration.
|
|
Packit Service |
f629e6 |
If there are any holes [don't know whether that's possible]
|
|
Packit Service |
f629e6 |
collapse them out of the list; don't want them at restore time.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
if (vmswork(GetTrans(logname, itmlst))) {
|
|
Packit Service |
f629e6 |
for (i = 0, j = -1; i <= max_trans_indx; i++) {
|
|
Packit Service |
f629e6 |
U_Long *attr_p;
|
|
Packit Service |
f629e6 |
attr_p = itmlst[3*i+1].buffer; /* copy (void *) to true type */
|
|
Packit Service |
f629e6 |
if (*attr_p & LNM$M_EXISTS) {
|
|
Packit Service |
f629e6 |
*attr_p &= ~LNM$M_EXISTS; /* must clear this bit */
|
|
Packit Service |
f629e6 |
if (++j < i) itmlst[3*j+0] = itmlst[3*i+0],
|
|
Packit Service |
f629e6 |
itmlst[3*j+1] = itmlst[3*i+1],
|
|
Packit Service |
f629e6 |
itmlst[3*j+2] = itmlst[3*i+2];
|
|
Packit Service |
f629e6 |
if (itmlst[3*j+2].retlen) { /* fixup buffer length */
|
|
Packit Service |
f629e6 |
itmlst[3*j+2].len = *itmlst[3*j+2].retlen;
|
|
Packit Service |
f629e6 |
itmlst[3*j+2].retlen = (U_Short *)0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
if (++j < i) EndItm0(itmlst[3*j]);
|
|
Packit Service |
f629e6 |
} else /* should never happen; tolerate potential memory leak */
|
|
Packit Service |
f629e6 |
free(itmlst), itmlst = 0; /*('wrk' buffer(s) will become lost)*/
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
return itmlst;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static void
|
|
Packit Service |
f629e6 |
restore_translation( const struct dsc$descriptor_s *logname,
|
|
Packit Service |
f629e6 |
const Itm *itemlist )
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
struct dsc$descriptor_s trans_val;
|
|
Packit Service |
f629e6 |
U_Long *attr_p;
|
|
Packit Service |
f629e6 |
# define LOG_PROCESS_TABLE 2 /* <obsolete> */
|
|
Packit Service |
f629e6 |
# define LOG_USERMODE PSL$C_USER
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* assert( itemlist[1].code == LNM$_ATTRIBUTES ); */
|
|
Packit Service |
f629e6 |
attr_p = itemlist[1].buffer; /* copy (void *) to (U_Long *) */
|
|
Packit Service |
f629e6 |
if (*attr_p & LNM$M_CRELOG) { /* check original creation method */
|
|
Packit Service |
f629e6 |
/* $crelog values can have only one translation;
|
|
Packit Service |
f629e6 |
so it'll be the first string entry in the itemlist.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
/* assert( itemlist[2].code == LNM$_STRING ); */
|
|
Packit Service |
f629e6 |
trans_val.dsc$a_pointer = itemlist[2].buffer;
|
|
Packit Service |
f629e6 |
trans_val.dsc$w_length = itemlist[2].len;
|
|
Packit Service |
f629e6 |
trans_val.dsc$b_dtype = DSC$K_DTYPE_T;
|
|
Packit Service |
f629e6 |
trans_val.dsc$b_class = DSC$K_CLASS_S;
|
|
Packit Service |
f629e6 |
(void) SYS$CRELOG(LOG_PROCESS_TABLE, logname, &trans_val, LOG_USERMODE);
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
/* $crelnm definition; itemlist could specify multiple translations,
|
|
Packit Service |
f629e6 |
but has already been setup properly for use as-is.
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
(void) SetTrans(logname, itemlist);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /*PIPES_SIMULATED*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#endif /*!NO_VMS_PIPES*/
|