GSM: Define mncc_send() as it is no longer available from OpenBSC headers
[lcr.git] / macro.h
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** Macros to do safe string operations to avoid buffer overflows             **
9 ** Macros for memory allocation, feeing and error handling                   **
10 **                                                                           **
11 \*****************************************************************************/ 
12
13
14 /* safe strcpy/strncpy */
15
16 #define SCPY(dst, src) scpy(dst, src, sizeof(dst))
17 static inline void scpy(char *dst, const char *src, unsigned int siz)
18 {
19         strncpy(dst, src, siz);
20         dst[siz-1] = '\0';
21 }
22
23 /* safe strcat/strncat */
24
25 #define SCAT(dst, src) scat(dst, src, sizeof(dst)-strlen(dst)-1)
26 static inline void scat(char *dst, const char *src, unsigned int siz)
27 {
28         strncat(dst, src, siz);
29         dst[siz-1] = '\0';
30 }
31
32 /* safe concat of a byte */
33
34 #define SCCAT(dst, src) sccat(dst, src, sizeof(dst))
35 static inline void sccat(char *dst, char chr, unsigned int siz)
36 {
37         if (strlen(dst) < siz-1)
38         {
39                 dst[strlen(dst)+1] = '\0';
40                 dst[strlen(dst)] = chr;
41         }
42 }
43
44 /* safe sprintf/snprintf */
45
46 #define SPRINT(dst, fmt, arg...) sprint(dst, sizeof(dst), fmt, ## arg)
47 static inline void sprint(char *dst, unsigned int siz, const char *fmt, ...)
48 {
49         va_list args;
50
51         va_start(args, fmt);
52         vsnprintf(dst, siz, fmt, args);
53         dst[siz-1] = '\0';
54         va_end(args);
55 }
56
57 /* unsafe */
58 #define UCPY strcpy
59 #define UNCPY strncpy
60 #define UCAT strcat
61 #define UNCAT strncat
62 #define UPRINT sprintf
63 #define UNPRINT snprintf
64 #define VUNPRINT vsnprintf
65
66 /* fatal error with error message and exit */
67 #define FATAL(fmt, arg...) fatal(__FUNCTION__, __LINE__, fmt, ##arg)
68 static inline void fatal(const char *function, int line, const char *fmt, ...)
69 {
70         va_list args;
71         char buffer[256];
72
73         va_start(args, fmt);
74         vsnprintf(buffer, sizeof(buffer), fmt, args);
75         va_end(args);
76         buffer[sizeof(buffer)-1] = '\0';
77         fprintf(stderr, "FATAL ERROR in function %s, line %d: %s", function, line, buffer);
78         fprintf(stderr, "This error is not recoverable, must exit here.\n");
79 #ifdef DEBUG_FUNC
80         debug(function, line, "FATAL", buffer);
81         debug(function, line, "FATAL", (char *)"This error is not recoverable, must exit here.\n");
82 #endif
83         exit(EXIT_FAILURE);
84 }
85
86 /* memory allocation with setting to zero */
87 #define MALLOC(size) _malloc(size, __FUNCTION__, __LINE__)
88 static inline void *_malloc(unsigned int size, const char *function, int line)
89 {
90         void *addr;
91         addr = malloc(size);
92         if (!addr)
93                 fatal(function, line, "No memory for %d bytes.\n", size);
94         memset(addr, 0, size);
95         return addr;
96 }
97
98 /* memory freeing with clearing memory to prevent using freed memory */
99 #define FREE(addr, size) _free(addr, size)
100 static inline void _free(void *addr, int size)
101 {
102         if (size)
103                 memset(addr, 0, size);
104         free(addr);
105 }
106
107 /* fill buffer and be sure that it's result is 0-terminated, also remove newline */
108 #define GETLINE(buffer, fp) _getline(buffer, sizeof(buffer), fp)
109 static inline char *_getline(char *buffer, int size, FILE *fp)
110 {
111         if (!fgets(buffer, size-1, fp))
112                 return NULL;
113         buffer[size-1] = '\0';
114         if (!buffer[0])
115                 return buffer;
116         if (buffer[strlen(buffer)-1] == '\n')
117                 buffer[strlen(buffer)-1] = '\0';
118         if (buffer[strlen(buffer)-1] == '\r')
119                 buffer[strlen(buffer)-1] = '\0';
120         return buffer;
121 }
122
123