postgresql/contrib/miscutil/misc_utils.c
Tom Lane 65da0d66b4 Fix misuse of StrNCpy to copy and add null to non-null-terminated data.
Does not work since it fetches one byte beyond the source data, and when
the phase of the moon is wrong, the source data is smack up against the
end of backend memory and you get SIGSEGV.  Don't laugh, this is a fix
for an actual user bug report.
2000-07-07 21:12:53 +00:00

157 lines
2.7 KiB
C

/*
* misc_utils.c --
*
* This file defines miscellaneous PostgreSQL utility functions.
*
* Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
*
* This file is distributed under the GNU General Public License
* either version 2, or (at your option) any later version.
*/
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup.h"
#include "access/relscan.h"
#include "access/skey.h"
#include "access/tupdesc.h"
#include "catalog/catname.h"
#include "catalog/pg_listener.h"
#include "fmgr.h"
#include "storage/lmgr.h"
#include "utils/fmgroids.h"
#include "utils/palloc.h"
#include "utils/rel.h"
#include "utils/tqual.h"
#include "misc_utils.h"
#undef MIN
#define MIN(x,y) ((x)<=(y) ? (x) : (y))
extern int ExecutorLimit(int limit);
extern void Async_Unlisten(char *relname, int pid);
extern int assertTest(int val);
#ifdef ASSERT_CHECKING_TEST
extern int assertEnable(int val);
#endif
int
query_limit(int limit)
{
return ExecutorLimit(limit);
}
int
backend_pid()
{
return getpid();
}
int
unlisten(char *relname)
{
Async_Unlisten(relname, getpid());
return 0;
}
int
max(int x, int y)
{
return ((x > y) ? x : y);
}
int
min(int x, int y)
{
return ((x < y) ? x : y);
}
/*
* Return the number of active listeners on a relation name.
*/
int
active_listeners(text *relname)
{
HeapTuple lTuple;
Relation lRel;
HeapScanDesc sRel;
TupleDesc tdesc;
ScanKeyData key;
Datum d;
bool isnull;
int len,
pid;
int count = 0;
int ourpid = getpid();
char listen_name[NAMEDATALEN];
lRel = heap_openr(ListenerRelationName, AccessShareLock);
tdesc = RelationGetDescr(lRel);
if (relname && (VARSIZE(relname) > VARHDRSZ))
{
MemSet(listen_name, 0, NAMEDATALEN);
len = MIN(VARSIZE(relname) - VARHDRSZ, NAMEDATALEN - 1);
memcpy(listen_name, VARDATA(relname), len);
ScanKeyEntryInitialize(&key, 0,
Anum_pg_listener_relname,
F_NAMEEQ,
PointerGetDatum(listen_name));
sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, &key);
}
else
sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
{
d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull);
pid = DatumGetInt32(d);
if ((pid == ourpid) || (kill(pid, SIGTSTP) == 0))
{
/* elog(NOTICE, "%d ok", pid); */
count++;
}
}
heap_endscan(sRel);
heap_close(lRel, AccessShareLock);
return count;
}
#ifdef USE_ASSERT_CHECKING
int
assert_enable(int val)
{
return assertEnable(val);
}
#ifdef ASSERT_CHECKING_TEST
int
assert_test(int val)
{
return assertTest(val);
}
#endif
#endif
/* end of file */
/*
* Local Variables:
* tab-width: 4
* c-indent-level: 4
* c-basic-offset: 4
* End:
*/