1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <sys/resource.h>
30#include <sys/time.h>
31#include <stdlib.h>
32#include <libintl.h>
33#include <string.h>
34#include <stdio.h>
35#include <errno.h>
36#include <stdarg.h>
37#include <poll.h>
38#include <unistd.h>
39#include <project.h>
40#include <pwd.h>
41#include <pthread.h>
42
43#include "rdfile.h"
44#include "rdimpl.h"
45#include "rdutil.h"
46
47static char PRG_FMT[] = "%s: ";
48static char ERR_FMT[] = ": %s\n";
49static char *modulname = "srm provider";
50
51extern jmp_buf  dm_jmpbuffer;
52extern char errmsg[];
53extern void monitor_stop();
54
55extern pthread_mutex_t logLock;
56
57/*PRINTFLIKE1*/
58void
59format_err(char *format, ...)
60{
61	int pos = 0;
62	va_list alist;
63	pos += sprintf(errmsg, PRG_FMT, modulname);
64	va_start(alist, format);
65	pos += vsprintf(errmsg + pos, format, alist);
66	va_end(alist);
67	if (strchr(format, '\n') == NULL)
68		(void) sprintf(errmsg + pos, "\n");
69}
70
71/*PRINTFLIKE1*/
72void
73format_errno(char *format, ...)
74{
75	int err = errno, pos = 0;
76	va_list alist;
77	pos += sprintf(errmsg, PRG_FMT, modulname);
78	va_start(alist, format);
79	pos += vsprintf(errmsg + pos, format, alist);
80	va_end(alist);
81	if (strchr(format, '\n') == NULL)
82		pos += sprintf(errmsg + pos, ERR_FMT,
83				(err != 0) ? strerror(err) : "");
84}
85
86/*PRINTFLIKE1*/
87void
88dmerror(char *format, ...)
89{
90	int err = errno, pos = 0;
91	va_list alist;
92
93	pos += sprintf(errmsg, PRG_FMT, modulname);
94	va_start(alist, format);
95	pos += vsprintf(errmsg + pos, format, alist);
96	va_end(alist);
97	if (strchr(format, '\n') == NULL)
98		pos += sprintf(errmsg + pos, ERR_FMT, strerror(err));
99	longjmp(dm_jmpbuffer, 1);
100}
101
102void *
103Realloc(void *ptr, size_t size)
104{
105	int	cnt = 0;
106	void    *sav = ptr;
107
108eagain: if ((ptr = realloc(ptr, size)))
109		return (ptr);
110
111	log_err("realloc(ptr=0x%p, size=%u)", (void *)ptr, (uint_t)size);
112	if ((++cnt <= 3) && (errno == EAGAIN)) {
113		napms(5000); /* wait for 5 seconds */
114		ptr = sav;
115		goto eagain;
116	}
117	ptr = sav;
118	dmerror("not enough memory");
119	/*NOTREACHED*/
120	return (NULL);	/* keep gcc happy */
121}
122
123void *
124Malloc(size_t size)
125{
126	return (Realloc(NULL, size));
127}
128
129void *
130Zalloc(size_t size)
131{
132	return (memset(Realloc(NULL, size), 0, size));
133}
134
135void
136Free(void *ptr)
137{
138	free(ptr);
139}
140
141int
142Setrlimit()
143{
144	struct rlimit rlim;
145	int rv, fd_limit;
146
147	if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
148		dmerror("getrlimit failed");
149	fd_limit = (int)rlim.rlim_cur;
150
151	rlim.rlim_cur = rlim.rlim_max;
152
153	if (setrlimit(RLIMIT_NOFILE, &rlim) == -1)
154	    rv = fd_limit;
155	else
156	    rv = (int)rlim.rlim_cur;
157
158	log_msg("fd_limit set to %d\n", rv);
159
160	return (rv);
161}
162
163void
164list_alloc(list_t *list, int size)
165{
166	if (size > 0) {
167		list->l_size = size;
168		list->l_ptrs = Zalloc(sizeof (void *) * (size + 1));
169	}
170}
171
172void
173list_init(list_t *list, int type)
174{
175	if (list == NULL)
176		return;
177
178	list->l_type = type;
179
180	list->l_type = type;
181}
182
183
184void
185getusrname(int uid, char *name, int length)
186{
187	struct passwd *pwd;
188
189	if ((pwd = getpwuid(uid)) == NULL) {
190		log_err("getpwuid(uid=%d,..)", uid);
191		(void) snprintf(name, length, "%d", uid);
192	} else {
193		(void) snprintf(name, length, "%s", pwd->pw_name);
194	}
195}
196
197void
198getprojname(projid_t projid, char *str, int len)
199{
200	struct project proj;
201	char projbuf[PROJECT_BUFSZ];
202
203	if (getprojbyid(projid, &proj, projbuf, PROJECT_BUFSZ) != NULL) {
204	    (void) snprintf(str, len, "%s", proj.pj_name);
205	} else {
206	    log_err("getprojbyid(projid=%ld,..)", (long)projid);
207	    (void) snprintf(str, len, "%-6ld", (long)projid);
208	}
209
210}
211
212
213void
214napms(int ms)
215{
216
217	(void) poll(NULL, 0, ms);
218}
219
220longlong_t get_timestamp() {
221	struct timeval tv;
222	struct timezone tz;
223
224	(void) gettimeofday(&tv, &tz);
225	return (tv.tv_usec  + ((longlong_t)tv.tv_sec * MICROSEC));
226}
227
228
229static FILE *logf = NULL;
230static char buf[RDS_MAXLINE];
231static hrtime_t hrt_base = 0;
232static int call_cnt = 0;
233static int bytes_written = 0;
234
235void
236log_open(char *file)
237{
238	if (strcmp(file, "stderr") == 0)
239		logf = stderr;
240	else
241		logf = fopen(file, "w+");
242}
243
244
245void
246log_close()
247{
248	if (logf != NULL && logf != stderr)
249		(void) fclose(logf);
250}
251
252
253/*PRINTFLIKE1*/
254void
255log_msg(char *fmt, ...)
256{
257	va_list	ap;
258	int n;
259	hrtime_t hrt;
260
261	if (logf == NULL)
262		return;
263	if (pthread_mutex_lock(&logLock) == 0) {
264	    if (logf != stderr && bytes_written > RDS_MAXLOG_FILE) {
265		bytes_written = 0;
266		rewind(logf);
267	    }
268
269	    if (hrt_base == 0)
270		hrt_base =  gethrtime() / 1000000;
271
272	    hrt = gethrtime() / 1000000;
273	    va_start(ap, fmt);
274	    (void) vsnprintf(buf, RDS_MAXLINE, fmt, ap);
275	    if ((n = fprintf(logf, "%4d:%08lld ms:%s",
276			call_cnt++, hrt - hrt_base, buf)) != -1)
277		bytes_written += n;
278	    (void) fflush(logf);
279	    va_end(ap);
280
281	    if (pthread_mutex_unlock(&logLock) != 0)
282		perror("log pthread_mutex_unlock");
283
284	} else
285	    perror("log pthread_mutex_lock");
286}
287
288/*PRINTFLIKE1*/
289void
290log_err(char *fmt, ...)
291{
292	va_list	ap;
293	int n;
294	hrtime_t hrt;
295	int err = errno;
296
297	if (logf == NULL)
298		return;
299	if (pthread_mutex_lock(&logLock) == 0) {
300	    if (logf != stderr && bytes_written > RDS_MAXLOG_FILE) {
301		    bytes_written = 0;
302		    rewind(logf);
303	    }
304
305	    if (hrt_base == 0)
306		    hrt_base =  gethrtime() / 1000000;
307
308	    hrt = gethrtime() / 1000000;
309	    va_start(ap, fmt);
310	    (void) vsnprintf(buf, RDS_MAXLINE, fmt, ap);
311	    if ((n = fprintf(logf, "%4d:%08lld ms:ERROR: %s: (errno %d), %s\n",
312			    call_cnt++, hrt - hrt_base, buf, err,
313			    (err != 0) ? strerror(err) : "")) != -1)
314		    bytes_written += n;
315	    (void) fflush(logf);
316	    va_end(ap);
317
318	    if (pthread_mutex_unlock(&logLock) != 0)
319		perror("log pthread_mutex_unlock");
320
321	} else
322	    perror("log pthread_mutex_lock");
323}
324