2 Copyright (c) 1995-1998 by Cisco systems, Inc.
4 Permission to use, copy, modify, and distribute this software for
5 any purpose and without fee is hereby granted, provided that this
6 copyright and permission notice appear on all copies of the
7 software and supporting documentation, the name of Cisco Systems,
8 Inc. not be used in advertising or publicity pertaining to
9 distribution of the program without specific prior permission, and
10 notice be given in supporting documentation that modification,
11 copying and distribution is by permission of Cisco Systems, Inc.
13 Cisco Systems, Inc. makes no representations about the suitability
14 of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
15 IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
16 WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS FOR A PARTICULAR PURPOSE.
23 #include <stdlib.h> /* malloc() can be found in <stdlib.h> OR <malloc.h> */
29 #include <fcntl.h> /* for "struct flock" */
38 #ifdef HAVE_SYS_SYSLOG_H
39 #include <sys/syslog.h>
47 void *tac_malloc TAC_ARGS((int size));
55 /* some mallocs don't like requests for zero length */
60 p = (char *) malloc(size);
63 report(LOG_ERR, "malloc %d failure", size);
69 void *tac_realloc TAC_ARGS((void *ptr, int size));
72 tac_realloc(ptr, size)
79 /* realloc(0, size) is not portable */
82 p = (char *)realloc(ptr, size);
86 report(LOG_ERR, "realloc %d failure", size);
92 void tac_exit TAC_ARGS((int status)) G_GNUC_NORETURN;
98 if (debug & DEBUG_FORK_FLAG)
99 report(LOG_DEBUG, "exit status=%d", status);
103 char *tac_strdup TAC_ARGS((const char *p));
112 report(LOG_ERR, "strdup allocation failure");
118 char *tac_make_string TAC_ARGS((u_char *p, int len));
121 tac_make_string(p, len)
129 * Add space for a null terminator if needed. Also, no telling
130 * what various mallocs will do when asked for a length of zero.
132 if (len == 0 || p[len - 1])
135 string = (char *) tac_malloc(new_len);
137 bzero(string, new_len);
138 bcopy(p, string, len);
142 /* return a pointer to the end of substring in string, or NULL. Substring
143 must begin at start of string.
146 const char *tac_find_substring TAC_ARGS((const char *substring, const char *string));
149 tac_find_substring(substring, string)
150 const char *substring;
155 if (!(substring && string)) {
159 len = strlen(substring);
161 if (len > (int) strlen(string)) {
165 if (strncmp(substring, string, len)) {
169 return(string + len);
183 for (n=0; n < len; n++) {
190 register char *s1, *s2;
208 if (*s1++ != *s2++) {
214 #endif /* NEED_BZERO */
216 /* Lock a file descriptor using fcntl. Returns 1 on successfully
217 acquiring the lock. The lock disappears when we close the file.
219 Note that if the locked file is on an NFS-mounted partition, you
220 are at the mercy of SUN's lockd, which is probably a bad idea
223 int tac_lockfd TAC_ARGS((char *filename, int lockfd));
226 tac_lockfd (filename, lockfd)
234 flock.l_type = F_WRLCK;
235 flock.l_whence = SEEK_SET; /* relative to bof */
236 flock.l_start = 0L; /* from offset zero */
237 flock.l_len = 0L; /* lock to eof */
239 if (debug & DEBUG_LOCK_FLAG) {
240 syslog(LOG_ERR, "Attempting to lock %s fd %d", filename, lockfd);
243 for (tries = 0; tries < 10; tries++) {
245 status = fcntl(lockfd, F_SETLK, &flock);
247 if (errno == EACCES || errno == EAGAIN) {
251 syslog(LOG_ERR, "fcntl lock error status %d on %s %d %s",
252 status, filename, lockfd, sys_errlist[errno]);
256 /* successful lock */
261 syslog(LOG_ERR, "Cannot lock %s fd %d in %d tries %s",
262 filename, lockfd, tries+1, sys_errlist[errno]);
264 /* who is hogging this lock */
265 flock.l_type = F_WRLCK;
266 flock.l_whence = SEEK_SET; /* relative to bof */
267 flock.l_start = 0L; /* from offset zero */
268 flock.l_len = 0L; /* lock to eof */
269 #ifdef HAS_FLOCK_SYSID
274 status = fcntl(lockfd, F_GETLK, &flock);
275 if ((status == -1) || (flock.l_type == F_UNLCK)) {
276 syslog(LOG_ERR, "Cannot determine %s lockholder status=%d type=%d",
277 filename, status, flock.l_type);
281 if (debug & DEBUG_LOCK_FLAG) {
282 syslog(LOG_ERR, "Lock on %s is being held by sys=%u pid=%d",
284 #ifdef HAS_FLOCK_SYSID
294 if (debug & DEBUG_LOCK_FLAG) {
295 syslog(LOG_ERR, "Successfully locked %s fd %d after %d tries",
296 filename, lockfd, tries+1);
301 /* Unlock a file descriptor using fcntl. Returns 1 on successfully
302 releasing a lock. The lock dies when we close the file.
304 Note that if the locked file is on an NFS-mounted partition, you
305 are at the mercy of SUN's lockd, which is probably a bad idea
310 tac_unlockfd (filename,lockfd)
317 flock.l_type = F_WRLCK;
318 flock.l_whence = SEEK_SET; /* relative to bof */
319 flock.l_start = 0L; /* from offset zero */
320 flock.l_len = 0L; /* lock to eof */
322 if (debug & DEBUG_LOCK_FLAG) {
323 syslog(LOG_ERR, "Attempting to unlock %s fd %d", filename, lockfd);
326 status = fcntl(lockfd, F_UNLCK, &flock);
328 syslog(LOG_ERR, "fcntl unlock error status %d on %s %d %s",
329 status, filename, lockfd, sys_errlist[errno]);
333 if (debug & DEBUG_LOCK_FLAG) {
334 syslog(LOG_ERR, "Successfully unlocked %s fd %d",
341 /* Management of bidirectional lists.
344 #ifdef TAC_LIST_PARANOIA
346 static void tac_list_check_magic TAC_ARGS((const struct tac_list *list));
349 tac_list_check_magic(list)
350 const struct tac_list *list;
352 if (list->_magic != TAC_LIST_MAGIC)
353 report(LOG_ERR, "MAGIC fail for tac_list");
356 static void tac_list_node_check_magic TAC_ARGS((const struct tac_list_node *node));
359 tac_list_node_check_magic(node)
360 const struct tac_list_node *node;
362 if (node->_magic != TAC_LIST_NODE_MAGIC)
363 report(LOG_ERR, "MAGIC fail for tac_list_node");
365 #else /* TAC_LIST_PARANOIA */
367 #define tac_list_check_magic(list)
368 #define tac_list_node_check_magic(node)
370 #endif /* TAC_LIST_PARANOIA */
373 void tac_list_init TAC_ARGS((struct tac_list *list));
377 struct tac_list *list;
379 #ifdef TAC_LIST_PARANOIA
380 list->_magic = TAC_LIST_MAGIC;
385 tac_list_check_magic(list);
388 void tac_list_node_init TAC_ARGS((struct tac_list_node *node));
391 tac_list_node_init(node)
392 struct tac_list_node *node;
394 #ifdef TAC_LIST_PARANOIA
395 node->_magic = TAC_LIST_NODE_MAGIC;
399 tac_list_node_check_magic(node);
402 struct tac_list *tac_list_node_get_list TAC_ARGS((struct tac_list_node *node));
405 tac_list_node_get_list(node)
406 struct tac_list_node *node;
408 tac_list_node_check_magic(node);
410 return (node->_list);
413 struct tac_list_node *tac_list_first_node TAC_ARGS((struct tac_list *list));
415 struct tac_list_node *
416 tac_list_first_node(list)
417 struct tac_list *list;
419 tac_list_check_magic(list);
421 return (list->_head);
425 struct tac_list_node *tac_list_last_node TAC_ARGS((struct tac_list *list));
427 struct tac_list_node *
428 tac_list_last_node(list)
429 struct tac_list *list;
431 tac_list_check_magic(list);
433 return (list->_tail);
437 void tac_list_addhead TAC_ARGS((struct tac_list *list, struct tac_list_node *node));
440 tac_list_addhead(list, node)
441 struct tac_list *list;
442 struct tac_list_node *node;
444 tac_list_check_magic(list);
445 tac_list_node_check_magic(node);
447 if ((node->_next = list->_head))
448 node->_next->_prev = node;
456 void tac_list_addtail TAC_ARGS((struct tac_list *list, struct tac_list_node *node));
459 tac_list_addtail(list, node)
460 struct tac_list *list;
461 struct tac_list_node *node;
463 tac_list_check_magic(list);
464 tac_list_node_check_magic(node);
466 if ((node->_prev = list->_tail))
467 node->_prev->_next = node;
475 struct tac_list_node *tac_list_node_next TAC_ARGS((struct tac_list_node *node));
477 struct tac_list_node *
478 tac_list_node_next(node)
479 struct tac_list_node *node;
481 tac_list_node_check_magic(node);
483 return (node->_next);
487 struct tac_list_node *tac_list_node_prev TAC_ARGS((struct tac_list_node *node));
489 struct tac_list_node *
490 tac_list_node_prev(node)
491 struct tac_list_node *node;
493 tac_list_node_check_magic(node);
495 return (node->_prev);
499 void tac_list_node_remove TAC_ARGS((struct tac_list_node *node));
502 tac_list_node_remove(node)
503 struct tac_list_node *node;
505 tac_list_node_check_magic(node);
506 tac_list_check_magic(node->_list);
509 node->_next->_prev = node->_prev;
511 node->_list->_tail = node->_prev;
514 node->_prev->_next = node->_next;
516 node->_list->_head = node->_next;