Logo Search packages:      
Sourcecode: tacacs+ version File versions  Download package

utils.c

/*
 * $Id: utils.c,v 1.14 2009-03-18 21:22:28 heas Exp $
 *
 * Copyright (c) 1995-1998 by Cisco systems, Inc.
 *
 * Permission to use, copy, modify, and distribute this software for
 * any purpose and without fee is hereby granted, provided that this
 * copyright and permission notice appear on all copies of the
 * software and supporting documentation, the name of Cisco Systems,
 * Inc. not be used in advertising or publicity pertaining to
 * distribution of the program without specific prior permission, and
 * notice be given in supporting documentation that modification,
 * copying and distribution is by permission of Cisco Systems, Inc.
 *
 * Cisco Systems, Inc. makes no representations about the suitability
 * of this software for any purpose.  THIS SOFTWARE IS PROVIDED ``AS
 * IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "tac_plus.h"

char *
tac_malloc(int size)
{
    char *p;

    /* some mallocs don't like requests for zero length */
    if (size == 0) {
      size++;
    }

    p = (char *)malloc(size);

    if (p == NULL) {
      report(LOG_ERR, "malloc %d failure: %s", size, strerror(errno));
      tac_exit(1);
    }
    return(p);
}

char *
tac_realloc(char *ptr, int size)
{
    char *p;

    if (ptr == NULL) {
      /* realloc(0, size) is not portable */
      p = tac_malloc(size);
    } else {
      p = (char *)realloc(ptr, size);
    }

    if (p == NULL) {
      report(LOG_ERR, "realloc %d failure", size);
      tac_exit(1);
    }
    return(p);
}

RETSIGTYPE
tac_exit(int status)
{
    if (debug & DEBUG_FORK_FLAG)
      report(LOG_DEBUG, "exit status=%d", status);
    exit(status);
}

char *
tac_strdup(char *p)
{
    char *n = strdup(p);

    if (n == NULL) {
      report(LOG_ERR, "strdup allocation failure");
      tac_exit(1);
    }
    return(n);
}

char *
tac_make_string(u_char *p, int len)
{
    char *string;
    int new_len = len;

    /*
     * Add space for a null terminator if needed. Also, no telling
     * what various mallocs will do when asked for a length of zero.
     */
    if (len == 0 || p[len - 1])
      new_len++;

    string = (char *)tac_malloc(new_len);

    memset(string, 0, new_len);
    memcpy(string, p, len);
    return(string);
}

/*
 * return a pointer to the end of substring in string, or NULL. Substring
 * must begin at start of string.
 */
char *
tac_find_substring(char *substring, char *string)
{
    int len;

    if (!(substring && string)) {
      return(NULL);
    }

    len = strlen(substring);

    if (len > (int)strlen(string)) {
      return(NULL);
    }

    if (strncmp(substring, string, len)) {
      /* no match */
      return(NULL);
    }
    return(string + len);
}

/*
 * Lock a file descriptor using fcntl. Returns 1 on successfully
 * acquiring the lock. The lock disappears when we close the file.
 *
 * Note that if the locked file is on an NFS-mounted partition, you
 * are at the mercy of NFS server's lockd, which is probably a bad idea.
 */
int
tac_lockfd(char *filename, int lockfd)
{
    int tries;
    struct flock flock;
    int status;

    flock.l_type   = F_WRLCK;
    flock.l_whence = SEEK_SET; /* relative to bof */
    flock.l_start  = 0L; /* from offset zero */
    flock.l_len    = 0L; /* lock to eof */

    if (debug & DEBUG_LOCK_FLAG) {
      syslog(LOG_ERR, "Attempting to lock %s fd %d", filename, lockfd);
    }

    for (tries = 0; tries < 10; tries++) {
      errno = 0;
      status = fcntl(lockfd, F_SETLK, &flock);
      if (status == -1) {
          if (errno == EACCES || errno == EAGAIN) {
            sleep(1);
            continue;
          } else {
            syslog(LOG_ERR, "fcntl lock error status %d on %s %d %s",
                   status, filename, lockfd, strerror(errno));
            return(0);
          }
      }
      /* successful lock */
      break;
    }

    if (errno != 0) {
      syslog(LOG_ERR, "Cannot lock %s fd %d in %d tries %s",
             filename, lockfd, tries+1, strerror(errno));

      /* who is hogging this lock */
      flock.l_type   = F_WRLCK;
      flock.l_whence = SEEK_SET; /* relative to bof */
      flock.l_start  = 0L; /* from offset zero */
      flock.l_len    = 0L; /* lock to eof */
#ifdef HAS_FLOCK_SYSID
      flock.l_sysid  = 0L;
#endif
      flock.l_pid    = 0;

      status = fcntl(lockfd, F_GETLK, &flock);
      if ((status == -1) || (flock.l_type == F_UNLCK)) {
          syslog(LOG_ERR, "Cannot determine %s lockholder status=%d type=%d",
               filename, status, flock.l_type);
          return(0);
      }

      if (debug & DEBUG_LOCK_FLAG) {
          syslog(LOG_ERR, "Lock on %s is being held by sys=%u pid=%d",
               filename,
#ifdef HAS_FLOCK_SYSID
               flock.l_sysid,
#else
               0,
#endif
               (int)flock.l_pid);
      }
      return(0);
    }

    if (debug & DEBUG_LOCK_FLAG) {
      syslog(LOG_ERR, "Successfully locked %s fd %d after %d tries",
             filename, lockfd, tries+1);
    }
    return(1);
}

/*
 * Unlock a file descriptor using fcntl. Returns 1 on successfully
 * releasing a lock. The lock dies when we close the file.
 *
 * Note that if the locked file is on an NFS-mounted partition, you
 * are at the mercy of SUN's lockd, which is probably a bad idea.
 */
int
tac_unlockfd(char *filename, int lockfd)
{
    struct flock flock;
    int status;

    flock.l_type   = F_WRLCK;
    flock.l_whence = SEEK_SET; /* relative to bof */
    flock.l_start  = 0L; /* from offset zero */
    flock.l_len    = 0L; /* lock to eof */

    if (debug & DEBUG_LOCK_FLAG) {
      syslog(LOG_ERR, "Attempting to unlock %s fd %d", filename, lockfd);
    }

    status = fcntl(lockfd, F_UNLCK, &flock);
    if (status == -1) {
      syslog(LOG_ERR, "fcntl unlock error status %d on %s %d %s",
             status, filename, lockfd, strerror(errno));
      return(1);
    }

    if (debug & DEBUG_LOCK_FLAG) {
      syslog(LOG_ERR, "Successfully unlocked %s fd %d",
             filename, lockfd);
    }
    return(0);
}

Generated by  Doxygen 1.6.0   Back to index