Bump version to 0.3.5next
[archipelago] / xseg / peers / user / common.c
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 /* 
36  *
37  * vkoukis.c
38  *
39  * Some commonly used functions
40  */
41
42 #define _GNU_SOURCE
43
44 #include "pthread.h"
45
46 #include <time.h>
47 #include <errno.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <stdarg.h>
52 #include <unistd.h>
53 #include <signal.h>
54
55 #include <sys/time.h>
56 #include <sys/types.h>
57
58 #include "common.h"
59
60 static char *perr_prog_name = NULL;
61
62 /*
63  * perr_func:           Main error reporting function
64  */
65 void perr_func(enum perr_type type, int want_errno, char *fmt, ...)
66 {
67         va_list ap;
68         time_t timeval;
69         int err_number = errno;         /* We need errno NOW */
70         char buf[PERR_BUF_SIZE], errbuf[PERR_BUF_SIZE], timebuf[PERR_BUF_SIZE];
71         char *t = NULL, *p = buf;
72
73         va_start(ap, fmt);
74         switch (type) {
75                 case PFE: t = "Fatal error"; break;
76                 case PE: t = "Error"; break;
77                 case PW: t = "Warning"; break;
78                 case PI: t = "Info"; break;
79                 case PD: t = "Debug"; break;
80                 default: raise(SIGABRT);
81         }
82         if (!perr_prog_name) {
83                 perr_prog_name = "Internal perr error";
84                 perr(1, 0, "init_perr has not been called");
85         }
86
87         time(&timeval);
88         ctime_r(&timeval, timebuf);
89         *strchr(timebuf, '\n') = '\0';
90
91         p += sprintf(p, "%s: %s: ", perr_prog_name, t);
92         p += sprintf(p, "Thread %lu, PID %lu\n\t",
93                         (unsigned long)pthread_self(), (unsigned long)getpid());
94
95         p += sprintf(p, "%s (%ld):\n\t", timebuf, timeval);
96
97         p += vsprintf(p, fmt, ap);
98         p += sprintf(p, "\n");
99
100         if (want_errno == 1)
101                 /* Print last error returned from system call */
102                 p += sprintf(p, "\tErrno was: %d - %s\n",
103                                 err_number, strerror_r(err_number, errbuf, PERR_BUF_SIZE));
104
105         /*
106          * Output the buffer to stderr with a single call to fprintf,
107          * which is thread-safe and locks the stderr semaphore
108          */
109         fprintf(stderr, "%s", buf);
110         fflush(stderr);
111         va_end(ap);
112
113         if (type > 0)
114                 exit(1);
115 }
116
117 void init_perr(char *prog_name)
118 {
119         perr_prog_name = prog_name;
120 }
121
122 /*
123  * Adapted from FreeBSD source:
124  *
125  * Appends src to string dst of size siz (unlike strncat, siz is the
126  * full size of dst, not space left).  At most siz-1 characters
127  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
128  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
129  * If retval >= siz, truncation occurred.
130  */
131 size_t strlcat(char *dst, const char *src, size_t siz)
132 {
133         char *d = dst;
134         const char *s = src;
135         size_t n = siz;
136         size_t dlen;
137
138         /* Find the end of dst and adjust bytes left but don't go past end */
139         while (n-- != 0 && *d != '\0')
140                 d++;
141         dlen = d - dst;
142         n = siz - dlen;
143
144         if (n == 0)
145                 return(dlen + strlen(s));
146         while (*s != '\0') {
147                 if (n != 1) {
148                         *d++ = *s;
149                         n--;
150                 }
151                 s++;
152         }
153         *d = '\0';
154
155         return (dlen + (s - src));      /* count does not include NUL */
156 }
157
158 /*
159  * Adapted from FreeBSD source:
160  *
161  * Copy src to string dst of size siz.  At most siz-1 characters
162  * will be copied.  Always NUL terminates (unless siz == 0).
163  * Returns strlen(src); if retval >= siz, truncation occurred.
164  */
165 size_t strlcpy(char *dst, const char *src, size_t siz)
166 {
167         char *d = dst;
168         const char *s = src;
169         size_t n = siz;
170
171         /* Copy as many bytes as will fit */
172         if (n != 0 && --n != 0) {
173                 do {
174                         if ((*d++ = *s++) == 0)
175                                 break;
176                 } while (--n != 0);
177         }
178
179         /* Not enough room in dst, add NUL and traverse rest of src */
180         if (n == 0) {
181                 if (siz != 0)
182                         *d = '\0';              /* NUL-terminate dst */
183                 while (*s++)
184                         ;
185         }
186
187         return (s - src - 1);   /* count does not include NUL */
188 }
189