misc.c 5.17 KB
Newer Older
1 2
/*-------
 * Module:			misc.c
3
 *
4 5
 * Description:		This module contains miscellaneous routines
 *					such as for debugging/logging and string functions.
6
 *
7
 * Classes:			n/a
8
 *
9
 * API functions:	none
10
 *
11
 * Comments:		See "notice.txt" for copyright and license information.
12
 *-------
13
 */
14

15 16
#include "psqlodbc.h"

17
#include <stdio.h>
18
#include <stdlib.h>
Tom Lane's avatar
Tom Lane committed
19
#include <stdarg.h>
20
#include <string.h>
21

22 23 24 25 26 27 28
#ifndef WIN32
#if HAVE_PWD_H
#include <pwd.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#else
29 30
#include <process.h>			/* Byron: is this where Windows keeps def.
								 * of getpid ? */
31
#endif
32

33
extern GLOBAL_VALUES globals;
34
void		generate_filename(const char *, const char *, char *);
35

36

37
void
38
generate_filename(const char *dirname, const char *prefix, char *filename)
39
{
40 41
	int			pid = 0;

42 43
#ifndef WIN32
	struct passwd *ptr = 0;
44

45 46 47
	ptr = getpwuid(getuid());
#endif
	pid = getpid();
48
	if (dirname == 0 || filename == 0)
49 50
		return;

51 52 53 54
	strcpy(filename, dirname);
	strcat(filename, DIRSEPARATOR);
	if (prefix != 0)
		strcat(filename, prefix);
55
#ifndef WIN32
56
	strcat(filename, ptr->pw_name);
57
#endif
58
	sprintf(filename, "%s%u%s", filename, pid, ".log");
59 60
	return;
}
61

62 63 64 65
static int	mylog_on = 0,
			qlog_on = 0;
void
logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
66
{
67 68 69 70
	static int	mylog_on_count = 0,
				mylog_off_count = 0,
				qlog_on_count = 0,
				qlog_off_count = 0;
71 72 73

	if (mylog_onoff)
		mylog_on_count += cnopen;
74
	else
75 76 77 78 79 80 81 82 83
		mylog_off_count += cnopen;
	if (mylog_on_count > 0)
		mylog_on = 1;
	else if (mylog_off_count > 0)
		mylog_on = 0;
	else
		mylog_on = globals.debug;
	if (qlog_onoff)
		qlog_on_count += cnopen;
84
	else
85 86 87 88 89 90 91 92
		qlog_off_count += cnopen;
	if (qlog_on_count > 0)
		qlog_on = 1;
	else if (qlog_off_count > 0)
		qlog_on = 0;
	else
		qlog_on = globals.commlog;
}
93

94
#ifdef MY_LOG
95
void
96
mylog(char *fmt,...)
97
{
98 99
	va_list		args;
	char		filebuf[80];
100
	static FILE *LOGFP = NULL;
101

102
	if (mylog_on)
103
	{
Tom Lane's avatar
Tom Lane committed
104
		va_start(args, fmt);
105

106 107 108
		if (!LOGFP)
		{
			generate_filename(MYLOGDIR, MYLOGFILE, filebuf);
109
			LOGFP = fopen(filebuf, PG_BINARY_W);
110 111 112 113 114 115 116 117 118 119 120 121 122
			setbuf(LOGFP, NULL);
		}

		if (LOGFP)
			vfprintf(LOGFP, fmt, args);

		va_end(args);
	}
}
#endif


#ifdef Q_LOG
Tom Lane's avatar
Tom Lane committed
123
void
124
qlog(char *fmt,...)
125
{
126 127
	va_list		args;
	char		filebuf[80];
128
	static FILE *LOGFP = NULL;
129

130
	if (qlog_on)
131
	{
Tom Lane's avatar
Tom Lane committed
132
		va_start(args, fmt);
133

134 135 136
		if (!LOGFP)
		{
			generate_filename(QLOGDIR, QLOGFILE, filebuf);
137
			LOGFP = fopen(filebuf, PG_BINARY_W);
138 139 140 141 142 143 144 145 146 147 148
			setbuf(LOGFP, NULL);
		}

		if (LOGFP)
			vfprintf(LOGFP, fmt, args);

		va_end(args);
	}
}
#endif

149

150 151 152 153
/*
 *	returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied
 *	(not including null term)
 */
154
int
155
my_strcpy(char *dst, int dst_len, const char *src, int src_len)
156 157 158 159
{
	if (dst_len <= 0)
		return STRCPY_FAIL;

160 161
	if (src_len == SQL_NULL_DATA)
	{
162
		dst[0] = '\0';
163
		return STRCPY_NULL;
164
	}
165 166
	else if (src_len == SQL_NTS)
		src_len = strlen(src);
167

168
	if (src_len <= 0)
169
		return STRCPY_FAIL;
170 171 172 173
	else
	{
		if (src_len < dst_len)
		{
174
			memcpy(dst, src, src_len);
175
			dst[src_len] = '\0';
176
		}
177 178 179 180
		else
		{
			memcpy(dst, src, dst_len - 1);
			dst[dst_len - 1] = '\0';	/* truncated */
181 182
			return STRCPY_TRUNCATED;
		}
183
	}
184 185 186 187

	return strlen(dst);
}

188 189 190 191 192 193 194

/*
 * strncpy copies up to len characters, and doesn't terminate
 * the destination string if src has len characters or more.
 * instead, I want it to copy up to len-1 characters and always
 * terminate the destination string.
 */
195 196
char *
strncpy_null(char *dst, const char *src, int len)
197
{
198
	int			i;
199 200


201 202 203 204 205
	if (NULL != dst)
	{
		/* Just in case, check for special lengths */
		if (len == SQL_NULL_DATA)
		{
206 207
			dst[0] = '\0';
			return NULL;
208
		}
209 210 211
		else if (len == SQL_NTS)
			len = strlen(src) + 1;

212
		for (i = 0; src[i] && i < len - 1; i++)
213 214
			dst[i] = src[i];

215
		if (len > 0)
216 217 218 219 220
			dst[i] = '\0';
	}
	return dst;
}

221 222 223 224 225 226 227 228

/*------
 *	Create a null terminated string (handling the SQL_NTS thing):
 *		1. If buf is supplied, place the string in there
 *		   (assumes enough space) and return buf.
 *		2. If buf is not supplied, malloc space and return this string
 *------
 */
229
char *
230
make_string(const char *s, int len, char *buf)
231
{
232 233
	int			length;
	char	   *str;
234

235 236
	if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
	{
237 238
		length = (len > 0) ? len : strlen(s);

239 240 241
		if (buf)
		{
			strncpy_null(buf, s, length + 1);
242 243 244
			return buf;
		}

245
		str = malloc(length + 1);
246
		if (!str)
247 248
			return NULL;

249
		strncpy_null(str, s, length + 1);
250 251 252 253 254 255
		return str;
	}

	return NULL;
}

256 257 258 259 260 261 262

/*
 *	Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing.
 *	"fmt" must contain somewhere in it the single form '%.*s'.
 *	This is heavily used in creating queries for info routines (SQLTables, SQLColumns).
 *	This routine could be modified to use vsprintf() to handle multiple arguments.
 */
263
char *
264
my_strcat(char *buf, const char *fmt, const char *s, int len)
265
{
266 267 268
	if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
	{
		int			length = (len > 0) ? len : strlen(s);
269

270
		int			pos = strlen(buf);
271 272 273 274 275 276 277

		sprintf(&buf[pos], fmt, length, s);
		return buf;
	}
	return NULL;
}

278

279 280
void
remove_newlines(char *string)
281
{
282 283
	unsigned int i;

284 285 286 287
	for (i = 0; i < strlen(string); i++)
	{
		if ((string[i] == '\n') ||
			(string[i] == '\r'))
288 289
			string[i] = ' ';
	}
290 291
}

292

293 294 295
char *
trim(char *s)
{
296
	int			i;
297

298 299
	for (i = strlen(s) - 1; i >= 0; i--)
	{
300 301 302 303 304 305 306 307
		if (s[i] == ' ')
			s[i] = '\0';
		else
			break;
	}

	return s;
}