From 3f619478f796eddbba6e39502fe941b285dd97b1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 20:00:34 +0200 Subject: Adding upstream version 1:10.11.6. Signed-off-by: Daniel Baumann --- storage/connect/plugutil.cpp | 646 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 storage/connect/plugutil.cpp (limited to 'storage/connect/plugutil.cpp') diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp new file mode 100644 index 00000000..a39c5846 --- /dev/null +++ b/storage/connect/plugutil.cpp @@ -0,0 +1,646 @@ +/************** PlugUtil C Program Source Code File (.C) ***************/ +/* */ +/* PROGRAM NAME: PLUGUTIL */ +/* ------------- */ +/* Version 3.1 */ +/* */ +/* COPYRIGHT: */ +/* ---------- */ +/* (C) Copyright to the author Olivier BERTRAND 1993-2020 */ +/* */ +/* WHAT THIS PROGRAM DOES: */ +/* ----------------------- */ +/* This program are initialization and utility Plug routines. */ +/* */ +/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */ +/* -------------------------------------- */ +/* */ +/* REQUIRED FILES: */ +/* --------------- */ +/* See Readme.C for a list and description of required SYSTEM files. */ +/* */ +/* PLUG.C - Source code */ +/* GLOBAL.H - Global declaration file */ +/* OPTION.H - Option declaration file */ +/* */ +/* REQUIRED LIBRARIES: */ +/* ------------------- */ +/* */ +/* OS2.LIB - OS2 libray */ +/* LLIBCE.LIB - Protect mode/standard combined large model C */ +/* library */ +/* */ +/* REQUIRED PROGRAMS: */ +/* ------------------ */ +/* */ +/* IBM C Compiler */ +/* IBM Linker */ +/* */ +/***********************************************************************/ + +/***********************************************************************/ +/* */ +/* Include relevant MariaDB header file. */ +/* */ +/***********************************************************************/ +#include "my_global.h" +#if defined(_WIN32) +//#include +#else +#if defined(UNIX) || defined(UNIV_LINUX) +#include +#include +//#define __stdcall +#else +#include +#endif +#include +#endif + +#if defined(WIN) +#include +#endif +#include /* definitions of ERANGE ENOMEM */ +#if !defined(UNIX) && !defined(UNIV_LINUX) +#include /* Directory management library */ +#endif + +/***********************************************************************/ +/* */ +/* Include application header files */ +/* */ +/* global.h is header containing all global declarations. */ +/* */ +/***********************************************************************/ +#define STORAGE /* Initialize global variables */ + +#include "m_string.h" +#include "osutil.h" +#include "global.h" +#include "plgdbsem.h" +#if defined(NEWMSG) +#include "rcmsg.h" +#endif // NEWMSG + +#if defined(_WIN32) +extern HINSTANCE s_hModule; /* Saved module handle */ +#endif // _WIN32 + +#if defined(XMSG) +extern char *msg_path; +char *msglang(void); +#endif // XMSG + +/***********************************************************************/ +/* Local Definitions and static variables */ +/***********************************************************************/ +typedef struct { + ushort Segsize; + ushort Size; +} AREASIZE; + +ACTIVITY defActivity = { /* Describes activity and language */ + NULL, /* Points to user work area(s) */ + "Unknown"}; /* Application name */ + +#if defined(XMSG) || defined(NEWMSG) + static char stmsg[200]; +#endif // XMSG || NEWMSG + +#if defined(UNIX) || defined(UNIV_LINUX) +#include "rcmsg.h" +#endif // UNIX + +/**************************************************************************/ +/* Conditional tracing output function. */ +/**************************************************************************/ +void xtrc(uint x, char const *fmt, ...) +{ + if (GetTraceValue() & x) { + va_list ap; + va_start(ap, fmt); + + vfprintf(stderr, fmt, ap); + va_end(ap); + } // endif x + +} // end of xtrc + +/**************************************************************************/ +/* Tracing output function. */ +/**************************************************************************/ +void htrc(char const* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + vfprintf(stderr, fmt, ap); + va_end(ap); +} // end of htrc + +/***********************************************************************/ +/* Plug initialization routine. */ +/* Language points on initial language name and eventual path. */ +/* Return value is the pointer to the Global structure. */ +/***********************************************************************/ +PGLOBAL PlugInit(LPCSTR Language, size_t worksize) +{ + PGLOBAL g; + + if (trace(2)) + htrc("PlugInit: Language='%-.256s'\n", + ((!Language) ? "Null" : (char*)Language)); + + try { + g = new GLOBAL; + } catch (...) { + fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL)); + return NULL; + } // end try/catch + + g->Sarea = NULL; + g->Createas = false; + g->Alchecked = 0; + g->Mrr = 0; + g->Activityp = NULL; + g->Xchk = NULL; + g->N = 0; + g->More = 0; + g->Saved_Size = 0; + strcpy(g->Message, ""); + + /*******************************************************************/ + /* Allocate the main work segment. */ + /*******************************************************************/ + if (worksize && AllocSarea(g, worksize)) { + char errmsg[MAX_STR]; + snprintf(errmsg, sizeof(errmsg) - 1, MSG(WORK_AREA), g->Message); + strcpy(g->Message, errmsg); + } // endif Sarea + + g->jump_level = -1; /* New setting to allow recursive call of Plug */ + return(g); +} /* end of PlugInit */ + +/***********************************************************************/ +/* PlugExit: Terminate Plug operations. */ +/***********************************************************************/ +PGLOBAL PlugExit(PGLOBAL g) +{ + if (g) { + PDBUSER dup = PlgGetUser(g); + + if (dup) + free(dup); + + FreeSarea(g); + delete g; + } // endif g + + return NULL; +} // end of PlugExit + +/***********************************************************************/ +/* Remove the file type from a file name. */ +/* Note: this routine is not really implemented for Unix. */ +/***********************************************************************/ +LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName) +{ +#if defined(_WIN32) + char drive[_MAX_DRIVE]; +#else + char *drive = NULL; +#endif + char direc[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ftype[_MAX_EXT]; + + _splitpath(FileName, drive, direc, fname, ftype); + + if (trace(2)) { + htrc("after _splitpath: FileName=%-.256s\n", FileName); + htrc("drive=%-.256s dir=%-.256s fname=%-.256s ext=%-.256s\n", + SVP(drive), direc, fname, ftype); + } // endif trace + + _makepath(pBuff, drive, direc, fname, ""); + + if (trace(2)) + htrc("buff='%-.256s'\n", pBuff); + + return pBuff; +} // end of PlugRemoveType + +BOOL PlugIsAbsolutePath(LPCSTR path) +{ +#if defined(_WIN32) + return ((path[0] >= 'a' && path[0] <= 'z') || + (path[0] >= 'A' && path[0] <= 'Z')) && path[1] == ':'; +#else + return path[0] == '/'; +#endif +} + +/***********************************************************************/ +/* Set the full path of a file relatively to a given path. */ +/* Note: this routine is not really implemented for Unix. */ +/***********************************************************************/ +LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) +{ + char newname[_MAX_PATH]; + char direc[_MAX_DIR], defdir[_MAX_DIR], tmpdir[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ftype[_MAX_EXT]; +#if defined(_WIN32) + char drive[_MAX_DRIVE], defdrv[_MAX_DRIVE]; +#else + char *drive = NULL, *defdrv = NULL; +#endif + + if (trace(2)) + htrc("prefix=%-.256s fn=%-.256s path=%-.256s\n", prefix, FileName, defpath); + + if (strlen(FileName) >= _MAX_PATH) + { + *pBuff= 0; /* Hope this is treated as error of some kind*/ + return FileName; + } + + if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) { + strcpy(pBuff, FileName); // Remote file + return pBuff; + } // endif + + if (PlugIsAbsolutePath(FileName)) + { + strcpy(pBuff, FileName); // FileName includes absolute path + return pBuff; + } // endif + +#if !defined(_WIN32) + if (*FileName == '~') { + if (_fullpath(pBuff, FileName, _MAX_PATH)) { + if (trace(2)) + htrc("pbuff='%-.256s'\n", pBuff); + + return pBuff; + } else + return FileName; // Error, return unchanged name + + } // endif FileName +#endif // !_WIN32 + + if (prefix && strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath)) + { + char tmp[_MAX_PATH]; + int len= snprintf(tmp, sizeof(tmp) - 1, "%s%s%s", + prefix, defpath, FileName); + memcpy(pBuff, tmp, (size_t) len); + pBuff[len]= '\0'; + return pBuff; + } + + _splitpath(FileName, drive, direc, fname, ftype); + + if (defpath) { + char c = defpath[strlen(defpath) - 1]; + + strcpy(tmpdir, defpath); + + if (c != '/' && c != '\\') + strcat(tmpdir, "/"); + + } else + strcpy(tmpdir, "./"); + + _splitpath(tmpdir, defdrv, defdir, NULL, NULL); + + if (trace(2)) { + htrc("after _splitpath: FileName=%-.256s\n", FileName); +#if defined(_WIN32) + htrc("drive=%-.256s dir=%-.256s fname=%-.256s ext=%-.256s\n", drive, direc, fname, ftype); + htrc("defdrv=%-.256s defdir=%-.256s\n", defdrv, defdir); +#else + htrc("dir=%-.256s fname=%-.256s ext=%-.256s\n", direc, fname, ftype); +#endif + } // endif trace + + if (drive && !*drive) + strcpy(drive, defdrv); + + switch (*direc) { + case '\0': + snprintf(direc, sizeof(direc), "%s", defdir); + break; + case '\\': + case '/': + break; + default: + // This supposes that defdir ends with a SLASH + safe_strcat(defdir, sizeof(defdir), direc); + snprintf(direc, sizeof(direc), "%s", defdir); + } // endswitch + + _makepath(newname, drive, direc, fname, ftype); + + if (trace(2)) + htrc("newname='%-.256s'\n", newname); + + if (_fullpath(pBuff, newname, _MAX_PATH)) { + if (trace(2)) + htrc("pbuff='%-.256s'\n", pBuff); + + return pBuff; + } else + return FileName; // Error, return unchanged name + +} // end of PlugSetPath + +#if defined(XMSG) +/***********************************************************************/ +/* PlugGetMessage: get a message from the message file. */ +/***********************************************************************/ +char *PlugReadMessage(PGLOBAL g, int mid, char *m) +{ + char msgfile[_MAX_PATH], msgid[32], buff[256]; + char *msg; + FILE *mfile = NULL; + +//GetPrivateProfileString("Message", msglang, "Message\\english.msg", +// msgfile, _MAX_PATH, plgini); +//strcat(strcat(strcpy(msgfile, msg_path), msglang()), ".msg"); + strcat(strcpy(buff, msglang()), ".msg"); + PlugSetPath(msgfile, NULL, buff, msg_path); + + if (!(mfile = fopen(msgfile, "rt"))) { + snprintf(stmsg, sizeof(stmsg), "Fail to open message file %s", msgfile); + goto err; + } // endif mfile + + for (;;) + if (!fgets(buff, 256, mfile)) { + snprintf(stmsg, sizeof(stmsg), "Cannot get message %d %s", mid, SVP(m)); + goto fin; + } else + if (atoi(buff) == mid) + break; + + if (sscanf(buff, " %*d %.31s \"%.255[^\"]", msgid, stmsg) < 2) { + // Old message file + if (!sscanf(buff, " %*d \"%.255[^\"]", stmsg)) { + snprintf(stmsg, sizeof(stmsg), "Bad message file for %d %s", mid, SVP(m)); + goto fin; + } else + m = NULL; + + } // endif sscanf + + if (m && strcmp(m, msgid)) { + // Message file is out of date + strcpy(stmsg, m); + goto fin; + } // endif m + + fin: + fclose(mfile); + + err: + if (g) { + // Called by STEP + msg = PlugDup(g, stmsg); + } else // Called by MSG or PlgGetErrorMsg + msg = stmsg; + + return msg; +} // end of PlugReadMessage + +#elif defined(NEWMSG) +/***********************************************************************/ +/* PlugGetMessage: get a message from the resource string table. */ +/***********************************************************************/ +char *PlugGetMessage(PGLOBAL g, int mid) +{ + char *msg; + +#if 0 // was !defined(UNIX) && !defined(UNIV_LINUX) + int n = LoadString(s_hModule, (uint)mid, (LPTSTR)stmsg, 200); + + if (n == 0) { + DWORD rc = GetLastError(); + const int BUF_SIZE= 512; + msg = (char*)PlugSubAlloc(g, NULL, BUF_SIZE); // Extend buf allocation + n = snprintf(msg, BUF_SIZE, "Message %d, rc=%d: ", mid, rc); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, + (LPTSTR)(msg + n), BUF_SIZE - n, NULL); + return msg; + } // endif n + +#else // ALL + if (!GetRcString(mid, stmsg, 200)) + snprintf(stmsg, sizeof(stmsg) "Message %d not found", mid); +#endif // ALL + + if (g) { + // Called by STEP + msg = PlugDup(g, stmsg); + } else // Called by MSG or PlgGetErrorMsg + msg = stmsg; + + return msg; +} // end of PlugGetMessage +#endif // NEWMSG + +#if defined(_WIN32) +/***********************************************************************/ +/* Return the line length of the console screen buffer. */ +/***********************************************************************/ +short GetLineLength(PGLOBAL g) +{ + CONSOLE_SCREEN_BUFFER_INFO coninfo; + HANDLE hcons = GetStdHandle(STD_OUTPUT_HANDLE); + BOOL b = GetConsoleScreenBufferInfo(hcons, &coninfo); + + return (b) ? coninfo.dwSize.X : 0; +} // end of GetLineLength +#endif // _WIN32 + +/***********************************************************************/ +/* Program for memory allocation of work and language areas. */ +/***********************************************************************/ +bool AllocSarea(PGLOBAL g, size_t size) +{ + /*********************************************************************/ + /* This is the allocation routine for the WIN32/UNIX/AIX version. */ + /*********************************************************************/ +#if defined(_WIN32) + if (size >= 1048576) // 1M + g->Sarea = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + else +#endif + g->Sarea = malloc(size); + + if (!g->Sarea) { + snprintf(g->Message, sizeof(g->Message), MSG(MALLOC_ERROR), "malloc"); + g->Sarea_Size = 0; + } else { + g->Sarea_Size = size; + PlugSubSet(g->Sarea, size); + } // endif Sarea + +#if defined(DEVELOPMENT) + if (true) { +#else + if (trace(8)) { +#endif + if (g->Sarea) { + htrc("Work area of %zd allocated at %p\n", size, g->Sarea); + } else + htrc("SareaAlloc: %-.256s\n", g->Message); + + } // endif trace + + return (!g->Sarea); +} // end of AllocSarea + +/***********************************************************************/ +/* Program for memory freeing the work area. */ +/***********************************************************************/ +void FreeSarea(PGLOBAL g) +{ + if (g->Sarea) { +#if defined(_WIN32) + if (g->Sarea_Size >= 1048576) // 1M + VirtualFree(g->Sarea, 0, MEM_RELEASE); + else +#endif + free(g->Sarea); + +#if defined(DEVELOPMENT) + if (true) +#else + if (trace(8)) +#endif + htrc("Freeing Sarea at %p size = %zd\n", g->Sarea, g->Sarea_Size); + + g->Sarea = NULL; + g->Sarea_Size = 0; + } // endif Sarea + + return; +} // end of FreeSarea + +/***********************************************************************/ +/* Program for SubSet initialization of memory pools. */ +/* Here there should be some verification done such as validity of */ +/* the address and size not larger than memory size. */ +/***********************************************************************/ +BOOL PlugSubSet(void *memp, size_t size) +{ + PPOOLHEADER pph = (PPOOLHEADER)memp; + + pph->To_Free = (size_t)sizeof(POOLHEADER); + pph->FreeBlk = size - pph->To_Free; + return FALSE; +} /* end of PlugSubSet */ + +/***********************************************************************/ +/* Use it to export a function that do throwing. */ +/***********************************************************************/ +static void *DoThrow(int n) +{ + throw n; +} /* end of DoThrow */ + +/***********************************************************************/ +/* Program for sub-allocating one item in a storage area. */ +/* The simple way things are done here is based on the fact */ +/* that no freeing of suballocated blocks is permitted in CONNECT. */ +/***********************************************************************/ +void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size) +{ + PPOOLHEADER pph; /* Points on area header. */ + + if (!memp) + /*******************************************************************/ + /* Allocation is to be done in the Sarea. */ + /*******************************************************************/ + memp = g->Sarea; + + size = ROUNDUP_TO_8(size); /* Round up size to multiple of 8 */ + pph = (PPOOLHEADER)memp; + + if (trace(16)) + htrc("SubAlloc in %p size=%zd used=%zd free=%zd\n", + memp, size, pph->To_Free, pph->FreeBlk); + + if (size > pph->FreeBlk) { /* Not enough memory left in pool */ + PCSZ pname = "Work"; + + snprintf(g->Message, sizeof(g->Message), + "Not enough memory in %-.256s area for request of %zu (used=%zu free=%zu)", + pname, size, pph->To_Free, pph->FreeBlk); + + if (trace(1)) + htrc("PlugSubAlloc: %-.256s\n", g->Message); + + DoThrow(1234); + } /* endif size OS32 code */ + + /*********************************************************************/ + /* Do the suballocation the simplest way. */ + /*********************************************************************/ + memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */ + pph->To_Free += size; /* New offset of pool free block */ + pph->FreeBlk -= size; /* New size of pool free block */ + + if (trace(16)) + htrc("Done memp=%p used=%zd free=%zd\n", + memp, pph->To_Free, pph->FreeBlk); + + return (memp); +} /* end of PlugSubAlloc */ + +/***********************************************************************/ +/* Program for sub-allocating and copying a string in a storage area. */ +/***********************************************************************/ +char *PlugDup(PGLOBAL g, const char *str) +{ + if (str) { + char *sm = (char*)PlugSubAlloc(g, NULL, strlen(str) + 1); + + snprintf(sm, strlen(str) + 1, "%s", str); + return sm; + } else + return NULL; + +} // end of PlugDup + +/*************************************************************************/ +/* This routine makes a pointer from an offset to a memory pointer. */ +/*************************************************************************/ +void* MakePtr(void* memp, size_t offset) +{ + // return ((offset == 0) ? NULL : &((char*)memp)[offset]); + return (!offset) ? NULL : (char *)memp + offset; +} /* end of MakePtr */ + +/*************************************************************************/ +/* This routine makes an offset from a pointer new format. */ +/*************************************************************************/ +size_t MakeOff(void* memp, void* ptr) +{ + if (ptr) { +#if defined(_DEBUG) || defined(DEVELOPMENT) + if (ptr <= memp) { + fprintf(stderr, "ptr %p <= memp %p", ptr, memp); + DoThrow(999); + } // endif ptr +#endif // _DEBUG || DEVELOPMENT + return (size_t)(((char*)ptr) - ((char*)memp)); + } else + return 0; + +} /* end of MakeOff */ + +/*---------------------- End of PLUGUTIL program ------------------------*/ -- cgit v1.2.3