8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-26 07:23:08 +01:00
firebird-mirror/src/jrd/isc.cpp

1510 lines
32 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
* MODULE: isc.c
* DESCRIPTION: General purpose but non-user routines.
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Added TCP_NO_DELAY option for superserver on Linux
* FSG 16.03.2001
* Solaris x86 changes - Konstantin Kuznetsov, Neil McCalden
*/
/*
2001-07-12 07:46:06 +02:00
$Id: isc.cpp,v 1.2 2001-07-12 05:46:05 bellardo Exp $
2001-05-23 15:26:42 +02:00
*/
#include "../jrd/ib_stdio.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include "../jrd/common.h"
#include "../jrd/codes.h"
#include "../jrd/isc.h"
#include "../jrd/ibase.h"
#include "../jrd/jrd.h"
#include "../jrd/scl.h"
#include "../jrd/flu_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/isc_proto.h"
#include "../jrd/jrd_proto.h"
/* Initialize the structure that hold all the config information */
static struct cfgtbl ISC_def_cfg_tbl[] = {
ISCCFG_LOCKMEM, ISCCFG_LOCKMEM_KEY, ISCCFG_LOCKMEM_DEF,
ISCCFG_LOCKMEM_DEF,
ISCCFG_LOCKSEM, ISCCFG_LOCKSEM_KEY, ISCCFG_LOCKSEM_DEF,
ISCCFG_LOCKSEM_DEF,
ISCCFG_LOCKSIG, ISCCFG_LOCKSIG_KEY, ISCCFG_LOCKSIG_DEF,
ISCCFG_LOCKSIG_DEF,
ISCCFG_EVNTMEM, ISCCFG_EVNTMEM_KEY, ISCCFG_EVNTMEM_DEF,
ISCCFG_EVNTMEM_DEF,
ISCCFG_DBCACHE, ISCCFG_DBCACHE_KEY, ISCCFG_DBCACHE_DEF,
ISCCFG_DBCACHE_DEF,
ISCCFG_PRIORITY, ISCCFG_PRIORITY_KEY, ISCCFG_PRIORITY_DEF,
ISCCFG_PRIORITY_DEF,
ISCCFG_IPCMAP, ISCCFG_IPCMAP_KEY, ISCCFG_IPCMAP_DEF, ISCCFG_IPCMAP_DEF,
ISCCFG_MEMMIN, ISCCFG_MEMMIN_KEY, ISCCFG_MEMMIN_DEF, ISCCFG_MEMMIN_DEF,
ISCCFG_MEMMAX, ISCCFG_MEMMAX_KEY, ISCCFG_MEMMAX_DEF, ISCCFG_MEMMAX_DEF,
ISCCFG_LOCKORDER, ISCCFG_LOCKORDER_KEY, ISCCFG_LOCKORDER_DEF,
ISCCFG_LOCKORDER_DEF,
ISCCFG_ANYLOCKMEM, ISCCFG_ANYLOCKMEM_KEY, ISCCFG_ANYLOCKMEM_DEF,
ISCCFG_ANYLOCKMEM_DEF,
ISCCFG_ANYLOCKSEM, ISCCFG_ANYLOCKSEM_KEY, ISCCFG_ANYLOCKSEM_DEF,
ISCCFG_ANYLOCKSEM_DEF,
ISCCFG_ANYLOCKSIG, ISCCFG_ANYLOCKSIG_KEY, ISCCFG_ANYLOCKSIG_DEF,
ISCCFG_ANYLOCKSIG_DEF,
ISCCFG_ANYEVNTMEM, ISCCFG_ANYEVNTMEM_KEY, ISCCFG_ANYEVNTMEM_DEF,
ISCCFG_ANYEVNTMEM_DEF,
ISCCFG_LOCKHASH, ISCCFG_LOCKHASH_KEY, ISCCFG_LOCKHASH_DEF,
ISCCFG_LOCKHASH_DEF,
ISCCFG_DEADLOCK, ISCCFG_DEADLOCK_KEY, ISCCFG_DEADLOCK_DEF,
ISCCFG_DEADLOCK_DEF,
ISCCFG_LOCKSPIN, ISCCFG_LOCKSPIN_KEY, ISCCFG_LOCKSPIN_DEF,
ISCCFG_LOCKSPIN_DEF,
ISCCFG_CONN_TIMEOUT, ISCCFG_CONN_TIMEOUT_KEY, ISCCFG_CONN_TIMEOUT_DEF,
ISCCFG_CONN_TIMEOUT_DEF,
ISCCFG_DUMMY_INTRVL, ISCCFG_DUMMY_INTRVL_KEY, ISCCFG_DUMMY_INTRVL_DEF,
ISCCFG_DUMMY_INTRVL_DEF,
ISCCFG_TRACE_POOLS, ISCCFG_TRACE_POOLS_KEY, ISCCFG_TRACE_POOLS_DEF,
ISCCFG_TRACE_POOLS_DEF,
ISCCFG_REMOTE_BUFFER, ISCCFG_REMOTE_BUFFER_KEY, ISCCFG_REMOTE_BUFFER_DEF,
ISCCFG_REMOTE_BUFFER_DEF,
#ifdef SET_TCP_NO_DELAY
ISCCFG_NO_NAGLE, ISCCFG_NO_NAGLE_KEY, ISCCFG_NO_NAGLE_DEF,
ISCCFG_NO_NAGLE_DEF,
#endif
NULL, 0, 0, 0
};
static struct cfgtbl *ISC_cfg_tbl = NULL;
/* Temporary file management specific stuff */
#include "../jrd/fil.h"
#include "../jrd/dls_proto.h"
static BOOLEAN dls_init = FALSE;
static BOOLEAN dls_flag = FALSE;
static BOOLEAN fdls_init = FALSE;
static BOOLEAN fdls_flag = FALSE;
/* End of temporary file management specific stuff */
#ifdef SOLARIS
#include <sys/utsname.h>
#endif
#ifdef SCO_EV
#include <sys/utsname.h>
#endif
#ifdef SUN3_3
typedef unsigned short uid_t;
#endif
static TEXT user_name[256];
static USHORT ast_count;
/* VMS Specific Stuff */
#ifdef VMS
#include <rms.h>
#include <descrip.h>
#include <ssdef.h>
#include <jpidef.h>
#include <prvdef.h>
#include <secdef.h>
#include <lckdef.h>
#include "../jrd/lnmdef.h"
#include "../jrd/prv_m_bypass.h"
#include <signal.h>
#define LOGICAL_NAME_TABLE "LNM$FILE_DEV"
#define WAKE_LOCK "gds__process_%d"
static POKE pokes;
static LKSB wake_lock;
#endif /* of ifdef VMS */
/* Unix specific stuff */
#if defined(UNIX)
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <pwd.h>
#include <unistd.h>
#ifndef O_RDWR
#include <fcntl.h>
#endif
#ifdef DGUX
#include <fcntl.h>
#endif
#ifdef DELTA
#include <sys/sysmacros.h>
#include <sys/param.h>
#endif
#ifdef IMP
typedef unsigned int mode_t;
typedef int pid_t;
#endif
extern struct passwd *getpwnam(), *getpwuid();
#endif
void isc_internal_set_config_value(UCHAR, ULONG*, ULONG*);
#ifdef VMS
static void blocking_ast(void);
static void poke_ast(POKE);
static int wait_test(SSHORT *);
#endif
#ifndef MAXHOSTLEN
#define MAXHOSTLEN 64
#endif
#ifndef FOPEN_READ_TYPE
#define FOPEN_READ_TYPE "r"
#define FOPEN_WRITE_TYPE "w"
#endif
#ifdef SHLIB_DEFS
#define strchr (*_libgds_strchr)
#define geteuid (*_libgds_geteuid)
#define getpwuid (*_libgds_getpwuid)
#define _ctype (*_libgds__ctype)
#define readlink (*_libgds_readlink)
#define gethostname (*_libgds_gethostname)
#define endpwent (*_libgds_endpwent)
#define getegid (*_libgds_getegid)
extern SCHAR *strchr();
extern uid_t geteuid();
extern struct passwd *getpwuid();
extern SCHAR _ctype[];
extern int readlink();
extern void gethostname();
extern void endpwent();
extern gid_t getegid();
#endif
#ifndef REQUESTER
void DLL_EXPORT ISC_ast_enter(void)
{
/**************************************
*
* I S C _ a s t _ e n t e r
*
**************************************
*
* Functional description
* Enter ast mode.
*
**************************************/
++ast_count;
}
#endif
#ifndef REQUESTER
void DLL_EXPORT ISC_ast_exit(void)
{
/**************************************
*
* I S C _ a s t _ e x i t
*
**************************************
*
* Functional description
* Enter ast mode.
*
**************************************/
--ast_count;
}
#endif
#if !defined(WIN_NT) // implemented in isc_win32.cpp
int DLL_EXPORT ISC_check_process_existence(SLONG pid,
SLONG xl_pid,
USHORT super_user)
{
/**************************************
*
* I S C _ c h e c k _ p r o c e s s _ e x i s t e n c e
*
**************************************
*
* Functional description
* Return TRUE if the indicated process
* exists. FALSE otherwise.
*
**************************************/
#if defined(UNIX)
#define CHECK_EXIST
return (kill((int) pid, 0) == -1 &&
(errno == ESRCH
|| (super_user && errno == EPERM)) ? FALSE : TRUE);
#endif
#ifdef VMS
#define CHECK_EXIST
ULONG item;
item = JPI$_PID;
return (lib$getjpi(&item, &pid, NULL, NULL, NULL, NULL) == SS$_NONEXPR) ?
FALSE : TRUE;
#endif
#ifndef CHECK_EXIST
return TRUE;
#else
#undef CHECK_EXIST
#endif
}
#endif // !WIN_NT
#ifdef VMS
int ISC_expand_logical_once(
TEXT * file_name,
USHORT file_length, TEXT * expanded_name)
{
/**************************************
*
* I S C _ e x p a n d _ l o g i c a l _ o n c e
*
**************************************
*
* Functional description
* Expand a logical name. If it doesn't exist, return 0.
*
**************************************/
int attr;
USHORT l;
TEXT *p;
ITM items[2];
struct dsc$descriptor_s desc1, desc2;
if (!file_length)
file_length = strlen(file_name);
ISC_make_desc(file_name, &desc1, file_length);
ISC_make_desc(LOGICAL_NAME_TABLE, &desc2, sizeof(LOGICAL_NAME_TABLE) - 1);
items[0].itm_length = 256;
items[0].itm_code = LNM$_STRING;
items[0].itm_buffer = expanded_name;
items[0].itm_return_length = &l;
items[1].itm_length = 0;
items[1].itm_code = 0;
attr = LNM$M_CASE_BLIND;
if (!(sys$trnlnm(&attr, &desc2, &desc1, NULL, items) & 1)) {
while (file_length--)
*expanded_name++ = *file_name++;
*expanded_name = 0;
return 0;
}
expanded_name[l] = 0;
return l;
}
#endif
void DLL_EXPORT ISC_get_config(TEXT * config_file, IPCCFG config_table)
{
/*************************************
*
* I S C _ g e t _ c o n f i g
*
*************************************
*
* Functional description
* Read user-defined values for shared memory and
* semaphores, and temporary directory list
* from a configuration file.
*
************************************/
IPCCFG h;
struct cfgtbl *tbl;
if (ISC_cfg_tbl == NULL) {
IB_FILE *fd;
TEXT *p, *q, buf[80];
TEXT buffer[256];
#ifdef SUPERSERVER
int n;
TEXT dir_name[MAX_PATH_LENGTH];
ULONG size;
#endif
gds__prefix(buffer, config_file);
config_file = buffer;
/* Read the configuration file into a local buffer. This
local buffer knows about all valid configuration options.
Later requests for configuration information will read it
from the in-memory copy rather than the disk copy */
ISC_cfg_tbl = ISC_def_cfg_tbl;
if (fd = ib_fopen(config_file, FOPEN_READ_TYPE))
{
while (p = ib_fgets(buf, sizeof(buf), fd))
{
/* The same keyword can be used more than once for
temp directory definition hence it should be handled
in its own way */
if (strncmp(buf, ISCCFG_TMPDIR, sizeof(ISCCFG_TMPDIR) - 1) == 0)
{
#ifdef SUPERSERVER
/* Note that this should be #ifdef SERVER once we implement that flag.
* We want this code to execute in classic servers as well as superserver,
* but not in client libraries, or in tools which link with a private
* copy of our object file, such as alice and dudley.
* This needs to be changed in time for the first Classic port of V6.0
*/
/* there is temp. directory definition */
if (!dls_init)
if ((n = sscanf(buf + sizeof(ISCCFG_TMPDIR) - 1,
" %ld \"%[^\"]", &size,
dir_name)) == 2)
{
if (DLS_add_dir(size, dir_name))
dls_flag = TRUE;
else {
gds__log
("Unable to use config parameter %s : No memory ",
ISCCFG_TMPDIR);
dls_flag = FALSE;
}
}
#endif
continue;
}
/* The external function directory keyword can also be used
more than once, so handle it separately. */
if (0 == strncmp(buf, ISCCFG_EXT_FUNC_DIR,
sizeof(ISCCFG_EXT_FUNC_DIR) - 1))
{
#ifdef SUPERSERVER
/* Note that this should be #ifdef SERVER once we implement that flag.
* We want this code to execute in classic servers as well as superserver,
* but not in client libraries, or in tools which link with a private
* copy of our object file, such as alice and dudley.
* This needs to be changed in time for the first Classic port of V6.0
*/
/* There is external function directory definition */
if (!fdls_init)
if (1 == sscanf(buf + sizeof(ISCCFG_EXT_FUNC_DIR) - 1,
" \"%[^\"]", dir_name))
{
if (DLS_add_func_dir(dir_name))
fdls_flag = TRUE;
else
{
gds__log
("Unable to use config parameter %s : No memory ",
ISCCFG_EXT_FUNC_DIR);
fdls_flag = FALSE;
}
}
#endif
continue;
}
for (tbl = ISC_cfg_tbl; q = tbl->cfgtbl_keyword; tbl++)
{
p = buf;
/* Scan until we see the end of the keyword or
a mismatch */
while (*q && (*p == *q))
{
p++;
q++;
};
/* If we reached the end of the keyword we've got
a match! The remainder of the input line had
better be spaces and numbers */
if (!*q && (isspace(*p) || isdigit(*p))) {
tbl->cfgtbl_value = atol(p);
break;
}
} /* for */
} /* while */
ib_fclose(fd);
} /* if ib_fopen */
else
{
/* Error opening file. Log a message only if file exists */
if (errno != ENOENT)
gds__log("Unable to open config file \"%s\": errno = %d",
config_file, errno);
}
if (!dls_flag)
{
/* Temp. directory configuration has not been defined.
Let's make default configuration */
if (!(q = getenv("INTERBASE_TMP")) &&
!(q = getenv("TMP")) &&
!(q = getenv("TEMP")))
{
q = WORKDIR;
}
if (!DLS_add_dir(ALLROOM, q))
{
/* we are out of memory, also we can only get here during
server start hence let us exit with an exit status indicating
to the guardian that the server need not be restarted */
gds__log
("Unable to set configuration parameters : No Memory");
exit(STARTUP_ERROR);
}
dls_flag = TRUE;
}
dls_init = TRUE; /* Temp dir config should be read only once */
fdls_init = TRUE; /* Ext func dir config should be read only once. */
} /* if ICS_cfg_tbl == NULL */
/* The master configuration options are in memory, now for
this request for option values mark each one as not found
and search the memory table for each one. */
for (h = config_table; h->ipccfg_keyword; h++)
{
h->ipccfg_found = FALSE;
}
for (h = config_table; h->ipccfg_keyword; h++)
{
if (!h->ipccfg_parent_offset ||
!h[h->ipccfg_parent_offset].ipccfg_found)
{
for (tbl = ISC_cfg_tbl; tbl->cfgtbl_keyword; tbl++)
{
if (!strcmp(tbl->cfgtbl_keyword, h->ipccfg_keyword))
{
*h->ipccfg_variable = tbl->cfgtbl_value;
h->ipccfg_key = tbl->cfgtbl_key;
h->ipccfg_found = TRUE;
break;
}
}
}
}
}
#ifndef SUPERCLIENT
int DLL_EXPORT ISC_set_config(TEXT * config_file, IPCCFG config_table)
{
/*************************************
*
* I S C _ s e t _ c o n f i g
*
*************************************
*
* Functional description
* Set new values in the configuration file
* and make them take affect if possible.
*
************************************/
IB_FILE *fd = NULL;
IPCCFG h;
struct cfgtbl *t;
TEXT buffer[256];
int ret = 1;
if (config_file)
{
gds__prefix(buffer, config_file);
config_file = buffer;
fd = ib_fopen(config_file, FOPEN_WRITE_TYPE);
}
if ((ISC_cfg_tbl != NULL) && (!config_file || fd))
{
ULONG config_mask = 0;
ULONG *valptr = 0;
ret = 0;
/* If config_table = NULL then assume we want to restore defaults,
* otherwise get the users values and use them.
*/
for (t = ISC_def_cfg_tbl; t->cfgtbl_keyword; t++)
{
if (config_table)
{
for (h = config_table; h->ipccfg_variable; h++)
{
if (h->ipccfg_keyword ?
!strcmp(t->cfgtbl_keyword, h->ipccfg_keyword) :
h->ipccfg_key == t->cfgtbl_key)
{
config_mask |= (1 << t->cfgtbl_key);
t->cfgtbl_value = *h->ipccfg_variable;
break;
}
}
}
else if (t->cfgtbl_value != t->cfgtbl_def_value)
{
config_mask |= (1 << t->cfgtbl_key);
t->cfgtbl_value = t->cfgtbl_def_value;
}
}
/* if one of the working set sizes has been set the make sure they're
* both set.
*/
if (config_mask &
((1 << ISCCFG_MEMMIN_KEY) | (1 << ISCCFG_MEMMAX_KEY))) config_mask
|= ((1 << ISCCFG_MEMMIN_KEY) | (1 << ISCCFG_MEMMAX_KEY));
for (t = ISC_def_cfg_tbl; config_mask && t->cfgtbl_keyword; t++)
{
#ifdef SUPERSERVER
if (config_mask & (1 << t->cfgtbl_key))
{
switch (t->cfgtbl_key)
{
case ISCCFG_MEMMIN_KEY:
valptr = &(t->cfgtbl_value);
break;
case ISCCFG_MEMMAX_KEY:
isc_internal_set_config_value( t->cfgtbl_key,
valptr,
&(t->cfgtbl_value));
break;
default:
isc_internal_set_config_value( t->cfgtbl_key,
&(t->cfgtbl_value),
NULL);
break;
}
}
#endif /* SUPERSERVER */
if (fd)
{
char *p, *q, buf[80];
int tabs;
p = buf;
if (t->cfgtbl_value == t->cfgtbl_def_value)
*p++ = '#';
q = t->cfgtbl_keyword;
while (*q)
*p++ = *q++;
tabs = 4 - (p - buf) / 8;
while (tabs--)
*p++ = '\t';
*p = '\0';
if (ib_fprintf(fd, "%s%ld\n", buf, t->cfgtbl_value) < 0)
gds__log("Error writing config file \"%s\" : errno = %d",
config_file, errno);
}
}
if (fd) {
ib_fclose(fd);
gds__log("Config file \"%s\" has been modified.", config_file);
}
}
return ret;
}
#endif /* ! SUPERCLIENT */
#if (defined SOLARIS || defined SCO_EV)
#define GET_HOST
TEXT *INTERNAL_API_ROUTINE ISC_get_host(TEXT * string, USHORT length)
{
/**************************************
*
* I S C _ g e t _ h o s t ( S O L A R I S )
*
**************************************
*
* Functional description
* Get host name.
*
**************************************/
struct utsname name;
if (uname(&name) >= 0)
strncpy(string, name.nodename, length);
else
strcpy(string, "local");
return string;
}
#endif
#ifdef VMS
#define GET_HOST
TEXT *INTERNAL_API_ROUTINE ISC_get_host(TEXT * string, USHORT length)
{
/**************************************
*
* I S C _ g e t _ h o s t ( V M S )
*
**************************************
*
* Functional description
* Get host name.
*
**************************************/
TEXT *p;
if (!ISC_expand_logical_once("SYS$NODE", sizeof("SYS$NODE") - 1, string))
strcpy(string, "local");
else {
p = string;
if (*p == '_')
++p;
for (; *p && *p != ':'; p++)
if (*p >= 'A' && *p <= 'Z')
*p = *p - 'A' + 'a';
*p = 0;
}
return string;
}
#endif
#ifdef NETWARE_386
#define GET_HOST
TEXT *INTERNAL_API_ROUTINE ISC_get_host(TEXT * string, USHORT length)
{
/**************************************
*
* I S C _ g e t _ h o s t ( N E T W A R E _ 3 8 6 )
*
**************************************
*
* Functional description
* Get host name.
*
**************************************/
SCHAR buffer[49];
GetFileServerName(0, buffer);
if (strlen(buffer) > (length - 1))
*string = 0;
else
strcpy((SCHAR *) string, buffer);
return string;
}
#endif
#if !defined(WIN_NT) // implemented in isc_win32.cpp
#ifndef GET_HOST
TEXT *INTERNAL_API_ROUTINE ISC_get_host(TEXT * string, USHORT length)
{
/**************************************
*
* I S C _ g e t _ h o s t ( G E N E R I C )
*
**************************************
*
* Functional description
* Get host name.
*
**************************************/
gethostname(string, length);
return string;
}
#endif
#endif // !WIN_NT
#if !defined(WIN_NT) // implemented in isc_win32.cpp
#ifdef PC_PLATFORM
#ifndef NETWARE_386
int INTERNAL_API_ROUTINE ISC_get_user(TEXT* name,
int* id,
int* group,
TEXT* project,
TEXT* organization,
int* node,
TEXT* user_string)
{
/**************************************
*
* I S C _ g e t _ u s e r D O S
*
**************************************
*
* Functional description
* Find out who the user is. (On a PC,
* there's only 1 user anyway...)
*
**************************************/
if (name)
strcpy(name, (user_name[0]) ? user_name : "user");
if (id)
*id = 0;
if (group)
*group = 0;
if (project)
*project = 0;
if (organization)
*organization = 0;
if (node)
*node = 0;
return TRUE;
}
#endif
#endif
#endif // !WIN_NT
#ifdef UNIX
int INTERNAL_API_ROUTINE ISC_get_user(TEXT* name,
int* id,
int* group,
TEXT* project,
TEXT* organization,
int* node,
TEXT* user_string)
{
/**************************************
*
* I S C _ g e t _ u s e r ( U N I X )
*
**************************************
*
* Functional description
* Find out who the user is.
*
**************************************/
/* egid and euid need to be signed, uid_t is unsigned on SUN! */
SLONG egid, euid;
TEXT *p, *q, user_name[256];
struct passwd *passwd;
if (user_string && *user_string) {
for (p = user_name, q = user_string; (*p = *q++) && *p != '.'; p++);
*p = 0;
p = user_name;
egid = euid = -1;
if (*q) {
egid = atoi(q);
while (*q && (*q != '.'))
q++;
if (*q == '.') {
q++;
euid = atoi(q);
}
}
}
else {
euid = (SLONG) geteuid();
egid = (SLONG) getegid();
passwd = getpwuid(euid);
if (passwd)
p = passwd->pw_name;
else
p = "";
endpwent();
}
if (name)
strcpy(name, p);
if (id)
*id = euid;
if (group)
*group = egid;
if (project)
*project = 0;
if (organization)
*organization = 0;
if (node)
*node = 0;
return (euid == 0);
}
#endif
#ifdef VMS
int INTERNAL_API_ROUTINE ISC_get_user(
TEXT * name,
int *id,
int *group,
TEXT * project,
TEXT * organization, int *node, TEXT * user_string)
{
/**************************************
*
* I S C _ g e t _ u s e r ( V M S )
*
**************************************
*
* Functional description
* Find out who the user is.
*
**************************************/
SLONG status, privileges[2];
USHORT uic[2], len0, len1, len2;
TEXT *p, *q, *end, user_name[256];
ITM items[4];
if (user_string && *user_string) {
for (p = user_name, q = user_string; (*p = *q++) && *p != '.'; p++);
*p = 0;
p = user_name;
uic[0] = uic[1] = -1;
if (*q) {
uic[1] = atoi(q);
while (*q && (*q != '.'))
q++;
if (*q == '.') {
q++;
uic[0] = atoi(q);
}
}
privileges[0] = 0;
if (name) {
for (p = user_name; *p && *p != ' ';)
*name++ = *p++;
*name = 0;
}
}
else {
items[0].itm_code = JPI$_UIC;
items[0].itm_length = sizeof(uic);
items[0].itm_buffer = uic;
items[0].itm_return_length = &len0;
items[1].itm_code = JPI$_USERNAME;
items[1].itm_length = sizeof(user_name);
items[1].itm_buffer = user_name;
items[1].itm_return_length = &len1;
items[2].itm_code = JPI$_CURPRIV;
items[2].itm_length = sizeof(privileges);
items[2].itm_buffer = privileges;
items[2].itm_return_length = &len2;
items[3].itm_code = 0;
items[3].itm_length = 0;
status = sys$getjpiw(NULL, NULL, NULL, items, NULL, NULL, NULL);
if (!(status & 1)) {
len1 = 0;
uic[0] = uic[1] = 0;
}
user_name[len1] = 0;
if (name) {
for (p = user_name; *p && *p != ' ';)
*name++ = *p++;
*name = 0;
}
}
if (id)
*id = uic[0];
if (group)
*group = uic[1];
if (project)
*project = 0;
if (organization)
*organization = 0;
if (node)
*node = 0;
return (privileges[0] & (SLONG) PRV$M_BYPASS);
}
#endif
#ifdef NETWARE_386
int INTERNAL_API_ROUTINE ISC_get_user(
TEXT * name,
int *id,
int *group,
TEXT * project,
TEXT * organization, int *node, TEXT * user_string)
{
/**************************************
*
* I S C _ g e t _ u s e r ( N E T W A R E _ 3 8 6 )
*
**************************************
*
* Functional description
* Find out who the user is.
*
**************************************/
SLONG name_len;
if (id)
*id = -1;
if (group)
*group = -1;
if (project)
*project = 0;
if (organization)
*organization = 0;
if (node)
*node = 0;
return !strcmp(name, "administrator");
}
#endif
#ifdef VMS
int ISC_make_desc(TEXT * string, struct dsc$descriptor *desc, USHORT length)
{
/**************************************
*
* I S C _ m a k e _ d e s c
*
**************************************
*
* Functional description
* Make a VMS string descriptor out of a string. Return
* length of string.
*
**************************************/
desc->dsc$b_dtype = DSC$K_DTYPE_T;
desc->dsc$b_class = DSC$K_CLASS_S;
desc->dsc$a_pointer = string;
if (length)
desc->dsc$w_length = length;
else {
desc->dsc$w_length = 0;
while (*string++)
++desc->dsc$w_length;
}
return desc->dsc$w_length;
}
#endif
SLONG API_ROUTINE ISC_get_prefix(TEXT * passed_string)
{
/**************************************
*
* i s c _ g e t _ p r e f i x
*
**************************************
*
* Functional description
* Parse the 'H' argument further for 'HL' 'HM' or 'H'
*
**************************************/
char c = *passed_string;
int arg_type;
switch (UPPER(c)) {
case '\0':
arg_type = IB_PREFIX_TYPE;
break;
case 'L':
arg_type = IB_PREFIX_LOCK_TYPE;
++passed_string;
break;
case 'M':
arg_type = IB_PREFIX_MSG_TYPE;
++passed_string;
break;
default:
return (-1);
break;
}
return (gds__get_prefix(arg_type, ++passed_string));
}
void API_ROUTINE ISC_prefix(TEXT * string, TEXT * root)
{
/**************************************
*
* i s c _ $ p r e f i x
*
**************************************
*
* Functional description
* Wrapper function for gds__prefix.
*
**************************************/
gds__prefix(string, root);
return;
}
void API_ROUTINE ISC_prefix_lock(TEXT * string, TEXT * root)
{
/**************************************
*
* i s c _ $ p r e f i x _ l o c k
*
**************************************
*
* Functional description
* Wrapper function for gds__prefix_lock.
*
**************************************/
gds__prefix_lock(string, root);
return;
}
void API_ROUTINE ISC_prefix_msg(TEXT * string, TEXT * root)
{
/**************************************
*
* i s c _ $ p r e f i x _ m s g
*
**************************************
*
* Functional description
* Wrapper function for gds__prefix_msg.
*
**************************************/
gds__prefix_msg(string, root);
return;
}
#ifndef REQUESTER
void ISC_set_user(TEXT * string)
{
/**************************************
*
* I S C _ s e t _ u s e r
*
**************************************
*
* Functional description
* Set user name for feeble operating system that don't
* support the concept, or support it badly.
*
**************************************/
strcpy(user_name, string);
}
#endif
#ifdef VMS
void ISC_wait(SSHORT * iosb, SLONG event_flag)
{
/**************************************
*
* I S C _ w a i t ( V M S )
*
**************************************
*
* Functional description
* Wait for a asynchronous VMS event.
*
**************************************/
if (*iosb)
return;
/* If we're at AST state, and we're not running under
a AST invoked thread, wait locally. */
if (ast_count && !gds__ast_active()) {
sys$synch(event_flag, iosb);
return;
}
gds__thread_wait(wait_test, iosb);
}
#endif
#ifdef VMS
void ISC_wake(SLONG process_id)
{
/**************************************
*
* I S C _ w a k e
*
**************************************
*
* Functional description
* Wake up another VMS process. Process can be local or
* remote (but on the same CPU).
*
**************************************/
int status;
POKE poke;
TEXT string[32];
struct dsc$descriptor_s desc;
/* Try to do a simple wake. If this succeeds, we're done. */
status = sys$wake(&process_id, 0);
#ifdef __ALPHA
THREAD_wakeup();
#endif
if (status & 1)
return;
/* Do wake by siezing a lock, delivering a blocking ast */
/* Find a free poke block to use */
for (poke = pokes; poke; poke = poke->poke_next)
if (!poke->poke_use_count)
break;
if (!poke) {
poke = (POKE) gds__alloc((SLONG) sizeof(struct poke));
/* FREE: apparently never freed */
if (!poke) { /* NOMEM: */
DEV_REPORT("ISC_wake: out of memory condition");
return; /* error handling too difficult here */
}
poke->poke_next = pokes;
pokes = poke;
}
++poke->poke_use_count;
sprintf(string, WAKE_LOCK, process_id);
ISC_make_desc(string, &desc, 0);
status = sys$enq(0, /* event flag */
LCK$K_PWMODE, /* lock mode */
&poke->poke_lksb, /* Lock status block */
LCK$M_SYSTEM, /* flags */
&desc, /* resource name */
0, /* parent id */
poke_ast, /* ast address */
poke, /* ast argument */
0, /* blocking ast */
0, /* access mode */
0);
}
#endif
#ifdef VMS
void ISC_wake_init(void)
{
/**************************************
*
* I S C _ w a k e _ i n i t
*
**************************************
*
* Functional description
* Set up to be awakened by another process thru a blocking AST.
*
**************************************/
int status;
TEXT string[32];
FPTR_INT master;
struct dsc$descriptor_s desc;
#ifdef GATEWAY
/* See if the shared image knows abouts wake_init.
If it does, rely on it. */
if (master = ISC_lookup_entrypoint("GDSSHR", "gds__wake_init", NULL)) {
(*master) ();
return;
}
#endif
/* If we already have lock, we're done */
if (wake_lock.lksb_lock_id)
return;
sprintf(string, WAKE_LOCK, getpid());
ISC_make_desc(string, &desc, 0);
status = sys$enqw(0, /* event flag */
LCK$K_PWMODE, /* lock mode */
&wake_lock, /* Lock status block */
LCK$M_SYSTEM, /* flags */
&desc, /* resource name */
0, /* parent id */
0, /* ast address */
0, /* ast argument */
blocking_ast, /* blocking ast */
0, /* access mode */
0);
}
#endif
#ifdef VMS
static void blocking_ast(void)
{
/**************************************
*
* b l o c k i n g _ a s t
*
**************************************
*
* Functional description
* Somebody else is trying to post a lock.
*
**************************************/
int status;
/* Initially down grade the lock to let the other guy complete */
status = sys$enqw(0, /* event flag */
LCK$K_NLMODE, /* lock mode */
&wake_lock, /* Lock status block */
LCK$M_CONVERT, /* flags */
0, /* resource name */
0, /* parent id */
0, /* ast address */
0, /* ast argument */
0, /* blocking ast */
0, /* access mode */
0);
/* Wake us up */
status = sys$wake(0, 0);
/* Now try to upgrade lock */
status = sys$enq(0, /* event flag */
LCK$K_PRMODE, /* lock mode */
&wake_lock, /* Lock status block */
LCK$M_CONVERT, /* flags */
0, /* resource name */
0, /* parent id */
0, /* ast address */
0, /* ast argument */
blocking_ast, /* blocking ast */
0, /* access mode */
0);
}
#endif
#ifdef VMS
static void poke_ast(POKE poke)
{
/**************************************
*
* p o k e _ a s t
*
**************************************
*
* Functional description
* Lock to poke event has completed. Update value block
* and deque the lock.
*
**************************************/
int status;
LKSB *lksb;
lksb = &poke->poke_lksb;
status = sys$deq(lksb->lksb_lock_id, 0, 0, 0);
--poke->poke_use_count;
}
#endif
#ifdef VMS
static int wait_test(SSHORT * iosb)
{
/**************************************
*
* w a i t _ t e s t
*
**************************************
*
* Functional description
* Return true if an I/O event is complete.
*
**************************************/
return *iosb;
}
#endif
#if defined(SUPERSERVER) && !defined(WIN_NT)
// Win32 SUPERSERVER version of isc_internal_set_config_value()
// is implemented in isc_win32.cpp
void isc_internal_set_config_value(UCHAR key, ULONG * value1, ULONG * value2)
{
switch (key) {
case ISCCFG_DBCACHE_KEY:
JRD_set_cache_default(value1);
break;
case ISCCFG_PRIORITY_KEY:
/*
* This is where you should call your OS specific function to set the
* Process priority (if available).
*/
break;
case ISCCFG_MEMMAX_KEY:
case ISCCFG_MEMMIN_KEY:
/*
* This is where you should call your OS specific function to set the
* Process priority (if available).
*/
break;
}
}
#endif // SUPERSERVER
#ifdef UNIX
2001-07-12 07:46:06 +02:00
#ifdef AIX_PPC
#define _UNIX95
#endif
#include <grp.h>
#ifdef AIX_PPC
#undef _UNIX95
#endif
2001-05-23 15:26:42 +02:00
SLONG ISC_get_user_group_id(TEXT * user_group_name)
{
/**************************************
*
* I S C _ g e t _ u s e r _ g r o u p _ n a n e
*
**************************************
*
* Functional description
*
* Return user group id if user group name found,
* Otherwise return 0.
*
* --- for UNIX platform ---
*
**************************************/
2001-07-12 07:46:06 +02:00
#ifndef DARWIN
2001-05-23 15:26:42 +02:00
extern struct group *getgrnam();
2001-07-12 07:46:06 +02:00
#endif
2001-05-23 15:26:42 +02:00
struct group *user_group;
SLONG n;
n = 0;
if (user_group = getgrnam(user_group_name))
n = user_group->gr_gid;
return (n);
}
#else
SLONG ISC_get_user_group_id(TEXT * user_group_name)
{
/**************************************
*
* I S C _ g e t _ u s e r _ g r o u p _ n a n e
*
* --- for non-UNIX platform ---
*
**************************************
*
* Functional description
*
* needed to be developed for non-unix platform
*
* Currently it just returns 0.
*
**************************************/
SLONG n;
n = 0;
return (n);
}
#endif /* end of ifdef UNIX */