- added Sean's opendht entry
[codemux.git] / codemuxlib.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/time.h>
4 #include <netinet/in.h>
5 #include <ctype.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <time.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include "debug.h"
14 #include "codemuxlib.h"
15
16 /*-----------------------------------------------------------------*/
17 static char *
18 GetNextLineBack(FILE *file, int lower, int stripComments)
19 {
20   /* reads the next non-blank line of the file. strips off any leading
21      space, any comments, and any trailing space.  returns a lowercase
22      version of the line that has been malloc'd */
23   char line[1024];
24
25   while (fgets(line, sizeof(line), file) != NULL) {
26     char *temp;
27     int len;
28
29     /* strip off any comments, leading and trailing whitespace */
30     if (stripComments) {
31       if ((temp = strchr(line, '#')) != NULL)
32         *temp = 0;
33     }
34     len = strlen(line);
35     while (len > 0 && isspace((int) line[len-1])) {
36       len--;
37       line[len] = 0;
38     }
39     temp = line;
40     while (isspace((int) *temp))
41       temp++;
42     if (temp[0] == 0)
43       continue;                 /* blank line, move on */
44
45     if (lower)
46       return(StrdupLower(temp));
47     return(xstrdup(temp));
48   }
49
50   return(NULL);
51 }
52 /*-----------------------------------------------------------------*/
53 char *
54 GetLowerNextLine(FILE *file)
55 {
56   return(GetNextLineBack(file, TRUE, TRUE));
57 }
58 /*-----------------------------------------------------------------*/
59 char *
60 GetNextLine(FILE *file)
61 {
62   return(GetNextLineBack(file, FALSE, TRUE));
63 }
64 /*-----------------------------------------------------------------*/
65 char *
66 GetNextLineNoCommStrip(FILE *file)
67 {
68   return(GetNextLineBack(file, FALSE, FALSE));
69 }
70 /*-----------------------------------------------------------------*/
71 int
72 DoesSuffixMatch(char *start, int len, char *suffix)
73 {
74   int sufLen = strlen(suffix);
75
76   if (len < 1)
77     len = strlen(start);
78   if (len < sufLen)
79     return(FALSE);
80   if (strncasecmp(start+len-sufLen, suffix, sufLen))
81     return(FALSE);
82   return(TRUE);
83 }
84 /*-----------------------------------------------------------------*/
85 int
86 DoesDotlessSuffixMatch(char *start, int len, char *suffix)
87 {
88   /* ignores any dots on end of start, suffix */
89   int sufLen = strlen(suffix);
90
91   if (len < 1)
92     len = strlen(start);
93
94   while (len > 1 && start[len-1] == '.')
95     len--;
96   while (sufLen > 1 && suffix[sufLen-1] == '.')
97     sufLen--;
98
99   if (len < sufLen)
100     return(FALSE);
101   if (strncasecmp(start+len-sufLen, suffix, sufLen))
102     return(FALSE);
103   return(TRUE);
104 }
105 /*-----------------------------------------------------------------*/
106 int
107 WordCount(char *buf)
108 {
109   int count = 0;
110   int wasSpace = TRUE;
111
112   while (*buf != '\0') {
113     int isSpace = isspace(*buf);
114     if (wasSpace && (!isSpace))
115       count++;
116     wasSpace = isSpace;
117     buf++;
118   }
119   return(count);
120 }
121 /*-----------------------------------------------------------------*/
122 char *
123 GetField(const char *start, int whichField)
124 {
125   int currField;
126
127   /* move to first non-blank char */
128   while (isspace(*start))
129     start++;
130
131   if (*start == '\0')
132     return(NULL);
133
134   for (currField = 0; currField < whichField; currField++) {
135     /* move over this field */
136     while (*start != '\0' && (!isspace(*start)))
137       start++;
138     /* move over blanks before next field */
139     while (isspace(*start))
140       start++;
141     if (*start == '\0')
142       return(NULL);
143   }
144   return((char *) start);
145 }
146 /* ---------------------------------------------------------------- */
147 char *
148 GetWord(const char *start, int whichWord)
149 {
150   /* returns a newly allocated string containing the desired word,
151      or NULL if there was a problem */
152   unsigned char *temp;
153   int len = 0;
154   char *res;
155
156   temp = (unsigned char *) GetField(start, whichWord);
157   if (!temp)
158     return(NULL);
159   while (!(temp[len] == '\0' || isspace(temp[len])))
160     len++;
161   if (!len)
162     NiceExit(-1, "internal error");
163   res = (char *)xcalloc(1, len+1);
164   if (!res) 
165     NiceExit(-1, "out of memory");
166   memcpy(res, temp, len);
167   return(res);
168 }
169 /*-----------------------------------------------------------------*/
170 static int 
171 CreatePrivateAcceptSocketEx(int portNum, int nonBlocking, int loopbackOnly)
172 {
173   int doReuse = 1;
174   struct linger doLinger;
175   int sock;
176   struct sockaddr_in sa;
177   
178   /* Create socket. */
179   if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
180     return(-1);
181   
182   /* don't linger on close */
183   doLinger.l_onoff = doLinger.l_linger = 0;
184   if (setsockopt(sock, SOL_SOCKET, SO_LINGER, 
185                  &doLinger, sizeof(doLinger)) == -1) {
186     close(sock);
187     return(-1);
188   }
189   
190   /* reuse addresses */
191   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 
192                  &doReuse, sizeof(doReuse)) == -1) {
193     close(sock);
194     return(-1);
195   }
196
197   if (nonBlocking) {
198     /* make listen socket nonblocking */
199     if (fcntl(sock, F_SETFL, O_NDELAY) == -1) {
200       close(sock);
201       return(-1);
202     }
203   }
204   
205   /* set up info for binding listen */
206   memset(&sa, 0, sizeof(sa));
207   sa.sin_family = AF_INET;
208   sa.sin_addr.s_addr = (loopbackOnly) ? htonl(INADDR_LOOPBACK) 
209                                       : htonl(INADDR_ANY);
210   sa.sin_port = htons(portNum);
211
212   /* bind the sock */
213   if (bind(sock, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
214     close(sock);
215     return(-1);
216   }
217   
218   /* start listening */
219   if (listen(sock, 32) == -1) {
220     close(sock);
221     return(-1);
222   }
223   
224   return(sock);
225 }
226 /*-----------------------------------------------------------------*/
227 int
228 CreatePrivateAcceptSocket(int portNum, int nonBlocking)
229 {
230   return CreatePrivateAcceptSocketEx(portNum, nonBlocking, FALSE);
231 }
232 /*-----------------------------------------------------------------*/
233 char *
234 StrdupLower(const char *orig)
235 {
236   char *temp;
237   int i;
238
239   if ((temp = xstrdup(orig)) == NULL)
240     NiceExit(-1, "no memory in strduplower");
241   for (i = 0; temp[i]; i++) {
242     if (isupper((int) temp[i]))
243       temp[i] = tolower(temp[i]);
244   }
245   return(temp);
246 }
247
248 /*-----------------------------------------------------------------*/
249 void 
250 StrcpyLower(char *dest, const char *src)
251 {
252   /* copy 'src' to 'dest' in lower cases. 
253      'dest' should have enough free space to hold src */
254   int i;
255
256   for (i = 0; src[i]; i++) {
257     dest[i] = (isupper((int) src[i])) ? tolower(src[i]) : src[i];
258   }
259
260   /* mark it as NULL */
261   dest[i] = 0;
262 }
263 /*-----------------------------------------------------------------*/
264 void
265 NiceExitBack(int val, char *reason, char *file, int line)
266 {
267   char buf[1024];
268   time_t currT = time(NULL);
269
270   sprintf(buf, "[%s, %d] %.24s %s\n", file, line, ctime(&currT), reason);
271   fprintf(stderr, "%s", buf);
272   exit(val);
273 }