2862 lines
63 KiB
C
2862 lines
63 KiB
C
/*
|
|
* Lock Server 1.0
|
|
* Copyright (C) 2003 Cole Tuininga, Andrew Cameron
|
|
* Copyright (C) 2000-2002 Cole Tuininga
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifdef __MINGW32__
|
|
#define FD_SETSIZE 1024
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#ifdef __MINGW32__
|
|
#include "syslog.h"
|
|
#else
|
|
#include <syslog.h>
|
|
#endif
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <dirent.h>
|
|
#ifndef __MINGW32__
|
|
#include <netdb.h>
|
|
#endif
|
|
#include <sys/time.h>
|
|
#include <sys/file.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#ifdef __MINGW32__
|
|
#include <winsock2.h>
|
|
#include <wininet.h>
|
|
#include <windows.h>
|
|
#define ioctl ioctlsocket
|
|
WORD wVersionRequested;
|
|
WSADATA wsaData;
|
|
int err;
|
|
#else
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/resource.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#endif
|
|
|
|
#ifndef SIGSYS
|
|
#define SIGSYS SIGUNUSED
|
|
#endif
|
|
#ifdef __MINGW32__
|
|
#define SIGPIPE 3
|
|
#define SIGHUP 5
|
|
#define SIGTSTP 8
|
|
#define SIGSTOP 16
|
|
#define SIGUSR1 18
|
|
#define SIGUNUSED 99
|
|
#endif
|
|
|
|
#ifndef __MINGW32__
|
|
#ifndef HOME
|
|
#define HOME "/usr/local/lockserver"
|
|
#endif
|
|
#else
|
|
#ifndef HOME
|
|
#define HOME "/lockserver"
|
|
#endif
|
|
#endif
|
|
|
|
#define LOCKFILE ".lf"
|
|
#define REPORTFILE "ls.report"
|
|
#define LOCKDUMP "lockdump"
|
|
#define HOSTS "hosts"
|
|
#define CONFIG "config"
|
|
#define MAGIC "lserv"
|
|
|
|
#define HASHSIZE 40
|
|
#define MAXHOSTS 256
|
|
#define MAXCONQUEUE 500
|
|
#define PORTNUM 8675
|
|
#define SELWAITS 0
|
|
#define SELWAITU 500000
|
|
|
|
/* Commands */
|
|
#define WHOOWNS 0x1
|
|
#define GIMME 0x2
|
|
#define CONTLOC 0x3
|
|
#define RENEW 0x4
|
|
#define RELSPEC 0x5
|
|
#define RELALL 0x6
|
|
#define SHOWCONT 0x7
|
|
#define STATS 0x8
|
|
|
|
typedef struct {
|
|
unsigned long TTL;
|
|
unsigned long TTW;
|
|
time_t RequestTS;
|
|
time_t LastUpdateTS;
|
|
time_t ObtainTS;
|
|
char *key;
|
|
char *index;
|
|
char *owner;
|
|
unsigned short priority;
|
|
} lock;
|
|
|
|
typedef struct lq {
|
|
lock *l;
|
|
struct lq *next;
|
|
} lockqueue;
|
|
|
|
/* Function prototypes */
|
|
void read_hosts(FILE *);
|
|
int read_old_locks(int);
|
|
void write_current_locks(int);
|
|
void noble_no_death();
|
|
void noble_death();
|
|
void noble_death_and_a_core();
|
|
void graceful_death();
|
|
void close_sockets();
|
|
void close_socket(int);
|
|
void reload_configs();
|
|
|
|
int check_ip(char *);
|
|
void do_cleanup();
|
|
void client_deal(int);
|
|
|
|
int hashfunction(char *);
|
|
|
|
lock *find_owner(char *, char *);
|
|
lock *find_lock(char *, char *, char *);
|
|
unsigned int kill_off(char *, char *, char *);
|
|
unsigned int kill_all(char *);
|
|
unsigned int add_contender(lock *);
|
|
unsigned int get_contend_loc(lock *);
|
|
|
|
char *format_time(int);
|
|
|
|
void pd(char *); /* print debug */
|
|
#ifdef __MINGW32__
|
|
int write_socket(SOCKET s, const char *buf, int len);
|
|
int read_socket(SOCKET s, char *buf, int len);
|
|
#endif
|
|
|
|
/* Globals */
|
|
lockqueue *owners[HASHSIZE];
|
|
lockqueue *contenders[HASHSIZE];
|
|
#ifndef __MINGW32__
|
|
int open_sockets[MAXCONQUEUE];
|
|
#else
|
|
SOCKET open_sockets[MAXCONQUEUE];
|
|
#endif
|
|
char *allow_hosts[MAXHOSTS];
|
|
int debug;
|
|
time_t startTS;
|
|
long requests[10];
|
|
long rejects=0;
|
|
long okeedokee=0;
|
|
long badboys=0;
|
|
int graceclose=0;
|
|
fd_set readfds, testfds;
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int fd, i, j, result, cip, len, readytoclose, nread, nb;
|
|
FILE *fh;
|
|
DIR *dp;
|
|
char *lockfile, *lockdump, *hostfile;
|
|
char **addrs=0;
|
|
|
|
struct timeval *selwait;
|
|
#ifndef __MINGW32__
|
|
int server_sockfd, client_sockfd;
|
|
size_t server_len, client_len;
|
|
#else
|
|
SOCKET server_sockfd, client_sockfd;
|
|
size_t server_len, client_len;
|
|
#endif
|
|
struct sockaddr_in server_address;
|
|
struct sockaddr_in client_address;
|
|
struct sockaddr_in sin;
|
|
struct hostent *host;
|
|
|
|
debug = 0;
|
|
if(argc > 1 && !strcmp(argv[1],"-d")) {
|
|
debug = 1;
|
|
}
|
|
/*
|
|
#ifdef __MINGW32__
|
|
debug =1;
|
|
#endif
|
|
*/
|
|
/* If the "HOME" directory doesn't exist, we're
|
|
creating it. So there. 8P~ */
|
|
|
|
pd("Checking \"HOME\" directory...");
|
|
dp=opendir(HOME);
|
|
if(!dp) {
|
|
#ifdef __MINGW32__
|
|
if(mkdir(HOME) == -1) {
|
|
#else
|
|
if(mkdir(HOME, 0700) == -1) {
|
|
#endif
|
|
/* Ok - maybe we're not creating it. 87( */
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR, "Could not create HOME directory.");
|
|
syslog(LOG_ERR, strerror(errno));
|
|
closelog();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} else {
|
|
closedir(dp);
|
|
}
|
|
pd("Okee dokee.\n");
|
|
|
|
/* Let's make sure we're alone out here... */
|
|
pd("Getting lock...");
|
|
lockfile = (char *) malloc(sizeof(char) * \
|
|
( strlen(LOCKFILE) + strlen(HOME) + 2));
|
|
sprintf(lockfile,"%s/%s",HOME,LOCKFILE);
|
|
|
|
fd = open(lockfile, (O_RDWR | O_CREAT | O_EXCL), \
|
|
(S_IRUSR | S_IWUSR));
|
|
if(fd == -1) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR,"Can't get lockfile.");
|
|
syslog(LOG_ERR, strerror(errno));
|
|
closelog();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
close(fd);
|
|
pd("Okee dokee.\n");
|
|
|
|
/* Make sure we have CLEAN hash - none of this imported stuff */
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
owners[i] = (lockqueue *) 0;
|
|
contenders[i] = (lockqueue *) 0;
|
|
}
|
|
|
|
for(i = 0; i < MAXCONQUEUE; i++)
|
|
open_sockets[i] = -1;
|
|
|
|
pd("Reading from old lock file ");
|
|
/* Read from the old lock file */
|
|
lockdump = (char *) malloc (sizeof(char) * \
|
|
(strlen(HOME) + strlen(LOCKDUMP) + 2));
|
|
|
|
sprintf(lockdump, "%s/%s", HOME, LOCKDUMP);
|
|
|
|
fd=open(lockdump, O_RDONLY);
|
|
if(fd != -1) {
|
|
read_old_locks(fd);
|
|
close(fd);
|
|
}
|
|
pd(" done.\n");
|
|
|
|
|
|
pd("Read acceptable hosts ");
|
|
/* Read list of acceptable hosts */
|
|
for(i = 0; i < MAXHOSTS; i++)
|
|
allow_hosts[i]=(char *) 0;
|
|
|
|
hostfile = (char *) malloc (sizeof(char) * \
|
|
(strlen(HOME) + strlen(HOSTS) + 2));
|
|
sprintf(hostfile, "%s/%s", HOME, HOSTS);
|
|
|
|
fh = fopen(hostfile, "r");
|
|
if(!fh) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR, "Can't open allowed hosts file.");
|
|
syslog(LOG_ERR, strerror(errno));
|
|
closelog();
|
|
unlink(lockfile);
|
|
exit(EXIT_FAILURE);
|
|
} else {
|
|
read_hosts(fh);
|
|
fclose(fh);
|
|
}
|
|
free(hostfile);
|
|
pd(" read.\n");
|
|
|
|
time(&startTS);
|
|
|
|
/* Daemonize ourselves... */
|
|
#ifndef __MINGW32__
|
|
if(!debug) {
|
|
if(fork() == 0) {
|
|
int fl;
|
|
int num_fds = getdtablesize();
|
|
for(fl = 0; fl <= num_fds; ++fl)
|
|
close(fl);
|
|
setsid();
|
|
} else exit(EXIT_SUCCESS);
|
|
chdir("/");
|
|
umask(0);
|
|
}
|
|
|
|
#endif
|
|
/* Signal settings */
|
|
signal(SIGINT, noble_death);
|
|
signal(SIGTSTP, noble_death);
|
|
signal(SIGSTOP, noble_death);
|
|
signal(SIGSEGV, noble_death_and_a_core);
|
|
signal(SIGHUP, reload_configs);
|
|
signal(SIGSYS, graceful_death);
|
|
signal(SIGUSR1, noble_no_death);
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
/* Here's the meat folks - this is the stuff that "does it" */
|
|
#ifndef __MINGW32__
|
|
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
#else
|
|
|
|
wVersionRequested = MAKEWORD( 2, 2 );
|
|
err = WSAStartup( wVersionRequested, &wsaData );
|
|
if ( err != 0 )
|
|
{ /* Tell the user that we could not find a usable */
|
|
/* WinSock DLL. */
|
|
pd("Unable to find a Suitable Winsock DLL\n");
|
|
}
|
|
/* Confirm that the WinSock DLL supports 2.2.*/
|
|
/* Note that if the DLL supports versions greater */
|
|
/* than 2.2 in addition to 2.2, it will still return */
|
|
/* 2.2 in wVersion since that is the version we */
|
|
/* requested. */
|
|
if ( LOBYTE( wsaData.wVersion ) != 2 ||
|
|
HIBYTE( wsaData.wVersion ) != 2 ) {
|
|
/* Tell the user that we could not find a usable */
|
|
/* WinSock DLL. */
|
|
WSACleanup( );
|
|
pd("Unable to find a Suitable Winsock DLL\n");
|
|
} /* The WinSock DLL is acceptable. Proceed. */
|
|
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
#endif
|
|
|
|
server_address.sin_family = AF_INET;
|
|
server_address.sin_port = htons(PORTNUM);
|
|
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
server_len = sizeof(server_address);
|
|
|
|
result = bind(server_sockfd, (struct sockaddr *)&server_address,
|
|
server_len);
|
|
if(result == -1) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, "Binding problem.");
|
|
syslog(LOG_WARNING, strerror(errno));
|
|
closelog();
|
|
}
|
|
while(result == -1) {
|
|
sleep(1);
|
|
result = bind(server_sockfd, (struct sockaddr *)&server_address,
|
|
server_len);
|
|
if(result != -1)
|
|
pd("Cool - we finally bound!\n");
|
|
}
|
|
result = listen(server_sockfd, MAXCONQUEUE);
|
|
open_sockets[0] = server_sockfd;
|
|
|
|
selwait = (struct timeval *) malloc (sizeof(struct timeval));
|
|
FD_ZERO(&readfds);
|
|
FD_SET(server_sockfd, &readfds);
|
|
pd("Server socket is set up...\n");
|
|
while(1) {
|
|
selwait->tv_sec = (time_t) SELWAITS;
|
|
selwait->tv_usec = (long) SELWAITU;
|
|
testfds = readfds;
|
|
|
|
result = select(FD_SETSIZE, &testfds, (fd_set *) 0,
|
|
(fd_set *) 0, selwait);
|
|
|
|
if(result == 0) {
|
|
/* Timed out */
|
|
do_cleanup();
|
|
} else if(result != -1) {
|
|
/* Time to deal with a client */
|
|
|
|
do_cleanup();
|
|
|
|
for(fd = 0; fd < FD_SETSIZE; fd++) {
|
|
if(FD_ISSET(fd, &testfds) && fd == server_sockfd) {
|
|
/* Time for a new client */
|
|
client_len=sizeof(client_address);
|
|
#ifndef __MINGW32__
|
|
client_sockfd = accept(server_sockfd,
|
|
(struct sockaddr *)&client_address, &client_len);
|
|
#else
|
|
client_sockfd = accept(server_sockfd,
|
|
(struct sockaddr *)&client_address,&client_len);
|
|
if(client_sockfd == INVALID_SOCKET)
|
|
{
|
|
result = WSAGetLastError();
|
|
}
|
|
#endif
|
|
for(i = 0;
|
|
i < MAXCONQUEUE &&
|
|
open_sockets[i] != -1 &&
|
|
open_sockets[i] != client_sockfd;
|
|
i++);
|
|
|
|
if(i >= MAXCONQUEUE) {
|
|
/* We're full - go away! */
|
|
rejects ++;
|
|
j = 2;
|
|
#ifndef __MINGW32__
|
|
write(client_sockfd, &j, 1);
|
|
#else
|
|
write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
close_socket(client_sockfd);
|
|
} else {
|
|
len = sizeof sin;
|
|
if(getpeername(client_sockfd, (struct sockaddr *) &sin,
|
|
&len) < 0) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR, strerror(errno));
|
|
closelog();
|
|
noble_death();
|
|
} else {
|
|
if((host = gethostbyaddr((char *) &sin.sin_addr,
|
|
sizeof(sin.sin_addr), AF_INET)) == NULL) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR, strerror(errno));
|
|
closelog();
|
|
noble_death();
|
|
} else
|
|
addrs = host->h_addr_list;
|
|
}
|
|
|
|
cip = 0;
|
|
while(*addrs && !cip) {
|
|
if(check_ip(inet_ntoa(*(struct in_addr *)*addrs)))
|
|
cip = 1;
|
|
addrs++;
|
|
}
|
|
|
|
if(!cip) {
|
|
badboys++;
|
|
j = 0;
|
|
write(client_sockfd, &j, 1);
|
|
pd("Host not allowed! Closing connection.\n");
|
|
close_socket(client_sockfd);
|
|
} else {
|
|
okeedokee++;
|
|
j = 1;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
} else {
|
|
open_sockets[i] = client_sockfd;
|
|
pd("Host accepted.\n");
|
|
FD_SET(client_sockfd, &readfds);
|
|
client_deal(client_sockfd);
|
|
}
|
|
}
|
|
}
|
|
} else if(FD_ISSET(fd, &testfds)) {
|
|
ioctl(fd, FIONREAD, &nread);
|
|
|
|
if(nread) {
|
|
/* Client wants something */
|
|
client_deal(fd);
|
|
} else {
|
|
/* Client is gone... */
|
|
close_socket(fd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(graceclose) { /* Check to see if we're ready to die */
|
|
readytoclose = 1;
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
if(owners[i] || contenders[i])
|
|
readytoclose = 0;
|
|
}
|
|
|
|
if(readytoclose) {
|
|
pd("Ok - it's time to go...\n");
|
|
close_sockets();
|
|
|
|
lockfile = (char *) malloc(sizeof(char) * \
|
|
(strlen(LOCKFILE) + strlen(HOME) + 2));
|
|
sprintf(lockfile,"%s/%s",HOME,LOCKFILE);
|
|
unlink(lockfile);
|
|
free(lockfile);
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#ifndef __MINGW32__
|
|
close(server_sockfd);
|
|
#else
|
|
closesocket(server_sockfd);
|
|
#endif
|
|
|
|
unlink(lockfile);
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
int read_old_locks(int fd) {
|
|
lockqueue *search;
|
|
lock *l;
|
|
time_t dt, ut, diff;
|
|
int i, j, oc, hashsize, hashent, numlocks, retval=0;
|
|
int keylen, indlen, ownlen;
|
|
char *c;
|
|
|
|
c = (char *) malloc (sizeof(char) * (strlen(MAGIC) + 1));
|
|
|
|
read(fd, c, strlen(MAGIC));
|
|
c[strlen(MAGIC)] = '\0';
|
|
if(strcmp(c, MAGIC)) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, "Incorrect magic from saved locks. Old lock file unusable.");
|
|
closelog();
|
|
|
|
return -1;
|
|
}
|
|
|
|
free(c);
|
|
|
|
time(&ut);
|
|
read(fd, &dt, sizeof(time_t));
|
|
diff = ut - dt;
|
|
|
|
read(fd, &hashsize, sizeof(int));
|
|
if(hashsize != HASHSIZE) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, "Different hash size in saved locks. Old lock file unusable.");
|
|
closelog();
|
|
|
|
return -1;
|
|
}
|
|
|
|
for(oc = 0; oc < 2; oc ++) {
|
|
for(i = 0; i < hashsize; i++) {
|
|
pd(".");
|
|
read(fd, &hashent, sizeof(int));
|
|
read(fd, &numlocks, sizeof(int));
|
|
|
|
search = 0;
|
|
|
|
for(j = 0; j < numlocks; j++) {
|
|
retval ++;
|
|
l = (lock *) malloc (sizeof(lock));
|
|
|
|
read(fd, &(l->TTL), sizeof(long));
|
|
read(fd, &(l->TTW), sizeof(long));
|
|
read(fd, &(l->RequestTS), sizeof(time_t));
|
|
read(fd, &(l->LastUpdateTS), sizeof(time_t));
|
|
l->LastUpdateTS += diff;
|
|
read(fd, &(l->ObtainTS), sizeof(time_t));
|
|
|
|
read(fd, &keylen, sizeof(int));
|
|
l->key = (char *) malloc (sizeof(char) * (keylen + 1));
|
|
read(fd, l->key, keylen);
|
|
l->key[keylen] = '\0';
|
|
|
|
read(fd, &indlen, sizeof(int));
|
|
l->index = (char *) malloc (sizeof(char) * (indlen + 1));
|
|
read(fd, l->index, indlen);
|
|
l->index[indlen] = '\0';
|
|
|
|
read(fd, &ownlen, sizeof(int));
|
|
l->owner = (char *) malloc (sizeof(char) * (ownlen + 1));
|
|
read(fd, l->owner, ownlen);
|
|
l->owner[ownlen] = '\0';
|
|
|
|
read(fd, &(l->priority), sizeof(short));
|
|
|
|
if(!search) {
|
|
search = (lockqueue *) malloc (sizeof(lockqueue));
|
|
if(!oc) {
|
|
owners[hashent] = search;
|
|
} else {
|
|
contenders[hashent] = search;
|
|
}
|
|
} else {
|
|
search->next = (lockqueue *) malloc (sizeof(lockqueue));
|
|
search = search->next;
|
|
}
|
|
|
|
search->l = l;
|
|
search->next = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
void write_current_locks(int fd) {
|
|
lockqueue *search;
|
|
char *c;
|
|
int i, numqueue, size;
|
|
time_t dt;
|
|
|
|
c = (char *) malloc (sizeof(char) * (strlen(MAGIC) + 1));
|
|
strncpy(c, MAGIC, (strlen(MAGIC) + 1));
|
|
|
|
write(fd, c, strlen(c));
|
|
|
|
free(c);
|
|
|
|
time(&dt);
|
|
write(fd, &dt, sizeof(time_t));
|
|
|
|
numqueue = HASHSIZE;
|
|
write(fd, &numqueue, sizeof(int));
|
|
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
pd(".");
|
|
/* The index */
|
|
write(fd, &i, sizeof(int));
|
|
|
|
/* Num indexes */
|
|
search = owners[i];
|
|
numqueue = 0;
|
|
while(search) {
|
|
numqueue++;
|
|
search = search->next;
|
|
}
|
|
write(fd, &numqueue, sizeof(int));
|
|
|
|
/* The entries */
|
|
search = owners[i];
|
|
while(search) {
|
|
write(fd, &(search->l->TTL), sizeof(long));
|
|
write(fd, &(search->l->TTW), sizeof(long));
|
|
write(fd, &(search->l->RequestTS), sizeof(time_t));
|
|
write(fd, &(search->l->LastUpdateTS), sizeof(time_t));
|
|
write(fd, &(search->l->ObtainTS), sizeof(time_t));
|
|
|
|
size = strlen(search->l->key);
|
|
write(fd, &size, sizeof(int));
|
|
write(fd, search->l->key, strlen(search->l->key));
|
|
|
|
size = strlen(search->l->index);
|
|
write(fd, &size, sizeof(int));
|
|
write(fd, search->l->index, strlen(search->l->index));
|
|
|
|
size = strlen(search->l->owner);
|
|
write(fd, &size, sizeof(int));
|
|
write(fd, search->l->owner, strlen(search->l->owner));
|
|
|
|
write(fd, &(search->l->priority), sizeof(short));
|
|
|
|
search = search->next;
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
pd(".");
|
|
/* The index */
|
|
write(fd, &i, sizeof(int));
|
|
|
|
/* Num indexes */
|
|
search = contenders[i];
|
|
numqueue = 0;
|
|
while(search) {
|
|
numqueue++;
|
|
search = search->next;
|
|
}
|
|
write(fd, &numqueue, sizeof(int));
|
|
|
|
/* The entries */
|
|
search = contenders[i];
|
|
while(search) {
|
|
write(fd, &(search->l->TTL), sizeof(long));
|
|
write(fd, &(search->l->TTW), sizeof(long));
|
|
write(fd, &(search->l->RequestTS), sizeof(time_t));
|
|
write(fd, &(search->l->LastUpdateTS), sizeof(time_t));
|
|
write(fd, &(search->l->ObtainTS), sizeof(time_t));
|
|
|
|
size = strlen(search->l->key);
|
|
write(fd, &size, sizeof(int));
|
|
write(fd, search->l->key, strlen(search->l->key));
|
|
|
|
size = strlen(search->l->index);
|
|
write(fd, &size, sizeof(int));
|
|
write(fd, search->l->index, strlen(search->l->index));
|
|
|
|
size = strlen(search->l->owner);
|
|
write(fd, &size, sizeof(int));
|
|
write(fd, search->l->owner, strlen(search->l->owner));
|
|
|
|
write(fd, &(search->l->priority), sizeof(short));
|
|
|
|
search = search->next;
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void reload_configs() {
|
|
FILE *fh;
|
|
char *hostfile;
|
|
int i;
|
|
|
|
for(i = 0; i < MAXHOSTS; i++) {
|
|
if(allow_hosts[i]) free(allow_hosts[i]);
|
|
allow_hosts[i] = 0;
|
|
}
|
|
|
|
hostfile = (char *) malloc (sizeof(char) * \
|
|
(strlen(HOME) + strlen(HOSTS) + 2));
|
|
sprintf(hostfile, "%s/%s", HOME, HOSTS);
|
|
|
|
fh = fopen(hostfile, "r");
|
|
read_hosts(fh);
|
|
fclose(fh);
|
|
free(hostfile);
|
|
|
|
return;
|
|
}
|
|
|
|
void read_hosts(FILE *fh) {
|
|
char buffer[17];
|
|
int i, j, firstempty = -1;
|
|
|
|
/* Find the first empty entry */
|
|
for(i = 0; i < MAXHOSTS && allow_hosts[i]; i++);
|
|
if(i < MAXHOSTS) firstempty=i;
|
|
|
|
if(firstempty == -1)
|
|
return;
|
|
|
|
for(i = 0; i < MAXHOSTS && fgets(buffer, 17, fh); i++) {
|
|
pd(".");
|
|
buffer[strlen(buffer)-1]='\0';
|
|
|
|
for(j = 0; allow_hosts[j] && strcmp(buffer,allow_hosts[j]) \
|
|
&& j < MAXHOSTS; j++);
|
|
|
|
if(!allow_hosts[i] || j >= MAXHOSTS) {
|
|
allow_hosts[(i + firstempty)] = (char *) malloc \
|
|
(sizeof(char) * (strlen(buffer) + 1));
|
|
strncpy(allow_hosts[(i + firstempty)], buffer, \
|
|
(sizeof(char) * (strlen(buffer) + 1)));
|
|
}
|
|
}
|
|
|
|
if( i >= MAXHOSTS && fgets(buffer, 17, fh)) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, "Hosts table full.");
|
|
closelog();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void close_socket(int fd) {
|
|
int nread, i, garbage;
|
|
|
|
ioctl(fd, FIONREAD, &nread);
|
|
|
|
if(nread)
|
|
for(i = 0; i < nread; i++)
|
|
read(fd, &garbage, 1);
|
|
|
|
for(i = 0; i < MAXCONQUEUE &&
|
|
open_sockets[i] != fd; i++);
|
|
|
|
if(i < MAXCONQUEUE) {
|
|
shutdown(fd, 0);
|
|
#ifdef __MINGW32__
|
|
closesocket(fd);
|
|
#else
|
|
close(fd);
|
|
#endif
|
|
open_sockets[i] = -1;
|
|
FD_CLR(fd, &readfds);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void close_sockets() {
|
|
int i;
|
|
|
|
pd("Closing sockets ... ");
|
|
for(i = 0; i < MAXCONQUEUE; i++) {
|
|
if(open_sockets[i] != -1) {
|
|
#ifndef __MINGW32__
|
|
close(open_sockets[i]);
|
|
#else
|
|
|
|
closesocket(open_sockets[i]);
|
|
#endif
|
|
open_sockets[i] = -1;
|
|
}
|
|
}
|
|
pd("done.\n");
|
|
|
|
return;
|
|
}
|
|
|
|
void noble_no_death() {
|
|
int fd;
|
|
FILE *fh;
|
|
char *ftime;
|
|
char *lockstat = (char *) malloc (sizeof(char) * \
|
|
(strlen(HOME) + strlen(REPORTFILE) + 2));
|
|
char *lockdump = (char *) malloc (sizeof(char) * \
|
|
(strlen(HOME) + strlen(LOCKDUMP) + 2));
|
|
unsigned int i, j;
|
|
unsigned long m;
|
|
lockqueue *s;
|
|
|
|
time_t t,dif;
|
|
|
|
|
|
pd("Dumping stats...");
|
|
sprintf(lockstat, "%s/%s", HOME, REPORTFILE);
|
|
|
|
fh = fopen(lockstat,"w");
|
|
|
|
if(fh) {
|
|
time(&t);
|
|
dif = t - startTS;
|
|
fprintf(fh, "Uptime: ");
|
|
ftime = format_time(dif);
|
|
fprintf(fh, "%s\n", ftime);
|
|
|
|
fprintf(fh, "\n");
|
|
fprintf(fh, "Lock requests: ............ %ld\n", requests[GIMME]);
|
|
fprintf(fh, "Owner lookups: ............ %ld\n", requests[WHOOWNS]);
|
|
fprintf(fh, "Location lookups: ......... %ld\n", requests[CONTLOC]);
|
|
fprintf(fh, "Lock renewals: ............ %ld\n", requests[RENEW]);
|
|
fprintf(fh, "Specific lock releases: ... %ld\n", requests[RELSPEC]);
|
|
fprintf(fh, "General lock releases: .... %ld\n", requests[RELALL]);
|
|
fprintf(fh, "Lock dump requests: ....... %ld\n", requests[SHOWCONT]);
|
|
fprintf(fh, "Statistics requests: ...... %ld\n", requests[STATS]);
|
|
|
|
fprintf(fh, "\n");
|
|
fprintf(fh, "Unknown commands: ......... %ld\n", requests[0]);
|
|
|
|
fprintf(fh, "\n");
|
|
fprintf(fh, "Accepted connections: ..... %ld\n", okeedokee);
|
|
fprintf(fh, "Rejected connections: ..... %ld\n", badboys);
|
|
fprintf(fh, "Too full connections: ..... %ld\n", rejects);
|
|
|
|
for(i = 1, j = 0; i < MAXCONQUEUE; i++)
|
|
if(open_sockets[i] != -1) j++;
|
|
fprintf(fh, "Current connections: ...... %d\n", j);
|
|
|
|
fprintf(fh, "\n");
|
|
|
|
for(i = 0, m = 0; i < HASHSIZE; i++) {
|
|
s = owners[i];
|
|
while(s) {
|
|
m++;
|
|
s = s->next;
|
|
}
|
|
}
|
|
fprintf(fh, "Current lock owners: ...... %ld\n", m);
|
|
|
|
for(i = 0, m = 0; i < HASHSIZE; i++) {
|
|
s = contenders[i];
|
|
while(s) {
|
|
m++;
|
|
s = s->next;
|
|
}
|
|
}
|
|
fprintf(fh, "Current lock contenders: .. %ld\n", m);
|
|
|
|
free(ftime);
|
|
fclose(fh);
|
|
pd("dumped.\n");
|
|
} else
|
|
pd("Unsuccessful dump.\n");
|
|
|
|
pd("Dumping locks to dumpfile ");
|
|
sprintf(lockdump, "%s/%s", HOME, LOCKDUMP);
|
|
|
|
fd = open(lockdump, (O_WRONLY | O_CREAT | O_TRUNC), \
|
|
(S_IRUSR | S_IWUSR));
|
|
if(fd != -1) {
|
|
write_current_locks(fd);
|
|
close(fd);
|
|
}
|
|
|
|
free(lockdump);
|
|
|
|
pd(" done.\n");
|
|
requests[STATS] ++;
|
|
|
|
return;
|
|
}
|
|
|
|
void graceful_death() {
|
|
if(!graceclose) {
|
|
pd("Ahhh ... a graceful closing.\n");
|
|
graceclose = 1;
|
|
} else {
|
|
pd("Changed our minds - not closing down.\n");
|
|
graceclose = 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void noble_death() {
|
|
int fd;
|
|
char *lockfile;
|
|
char *lockdump = (char *) malloc (sizeof(char) * \
|
|
(strlen(HOME) + strlen(LOCKDUMP) + 2));
|
|
|
|
pd("Preparing to die in a noble manner ...\n");
|
|
|
|
close_sockets();
|
|
|
|
pd("Dumping locks to dumpfile ");
|
|
sprintf(lockdump,"%s/%s",HOME,LOCKDUMP);
|
|
|
|
fd = open(lockdump, (O_WRONLY | O_CREAT | O_TRUNC), \
|
|
(S_IRUSR | S_IWUSR));
|
|
|
|
if(fd != -1) {
|
|
write_current_locks(fd);
|
|
close(fd);
|
|
}
|
|
free(lockdump);
|
|
pd(" done.\n");
|
|
|
|
lockfile = (char *) malloc(sizeof(char) * \
|
|
( strlen(LOCKFILE) + strlen(HOME) + 2));
|
|
sprintf(lockfile,"%s/%s",HOME,LOCKFILE);
|
|
unlink(lockfile);
|
|
free(lockfile);
|
|
|
|
pd("Fa\n");
|
|
pd(" r\n");
|
|
pd(" e\n");
|
|
pd("\n");
|
|
pd(" t\n");
|
|
pd(" h\n");
|
|
pd(" e\n");
|
|
pd(" e\n");
|
|
pd("\n");
|
|
pd(" w\n");
|
|
pd(" e\n");
|
|
pd(" l\n");
|
|
pd(" l\n");
|
|
pd(" .\n");
|
|
pd(" .\n");
|
|
pd(" .\n");
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
void noble_death_and_a_core() {
|
|
char *lockfile;
|
|
|
|
pd("Alas ... for I am dying ... I have been slain by the fault of seg...\n");
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR, "Seg fault has occurred. Shutting down.\n");
|
|
closelog();
|
|
|
|
close_sockets();
|
|
|
|
lockfile = (char *) malloc(sizeof(char) * \
|
|
( strlen(LOCKFILE) + strlen(HOME) + 2));
|
|
sprintf(lockfile,"%s/%s",HOME,LOCKFILE);
|
|
unlink(lockfile);
|
|
free(lockfile);
|
|
|
|
pd("Fa\n");
|
|
pd(" r\n");
|
|
pd(" e\n");
|
|
pd("\n");
|
|
pd(" t\n");
|
|
pd(" h\n");
|
|
pd(" e\n");
|
|
pd(" e\n");
|
|
pd("\n");
|
|
pd(" w\n");
|
|
pd(" e\n");
|
|
pd(" l\n");
|
|
pd(" l\n");
|
|
pd(" .\n");
|
|
pd(" .\n");
|
|
pd(" .\n");
|
|
|
|
|
|
abort();
|
|
}
|
|
|
|
int check_ip(char *ip) {
|
|
int i;
|
|
|
|
for(i = 0; allow_hosts[i] && i < MAXHOSTS; i++) {
|
|
if(!strcmp(ip, allow_hosts[i]))
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
typedef struct il {
|
|
char *index;
|
|
struct il *next;
|
|
} index_list;
|
|
|
|
#define MAXSYMBOLS 65536
|
|
char *keys[MAXSYMBOLS], *ct;
|
|
index_list *indexes[MAXSYMBOLS], *iter, *liter;
|
|
/* This is the "reaper" so to speak. It goes through and cleans
|
|
out that which needs cleaning. Usurps some, smacks others...*/
|
|
void do_cleanup() {
|
|
lockqueue *search, *last = 0, *findend, *n;
|
|
int i,j;
|
|
time_t t;
|
|
|
|
/* Clear the stuff */
|
|
for(i = 0; i < MAXSYMBOLS; i++) {
|
|
keys[i] = (char *) 0;
|
|
indexes[i] = (index_list *) 0;
|
|
}
|
|
|
|
time(&t);
|
|
/* First we're going to clean house. If ya be timed out,
|
|
you're getting swept out with the garbage. Now. */
|
|
|
|
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
/* Owners... */
|
|
last = 0;
|
|
search = owners[i];
|
|
while(search) {
|
|
if((t - search->l->LastUpdateTS) > search->l->TTL) {
|
|
/* heh heh ... let the reaping begin! */
|
|
pd("We're reaping an owner. BWAH HAH HAH HAH HAH HA HA!\n");
|
|
pd("\tKey: "); pd(search->l->key); pd("\n");
|
|
pd("\tIndex: "); pd(search->l->index); pd("\n");
|
|
pd("\tOwner: "); pd(search->l->owner); pd("\n");
|
|
if(!last) {
|
|
owners[i] = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = owners[i];
|
|
} else {
|
|
last->next = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = last->next;
|
|
}
|
|
} else {
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
}
|
|
|
|
/* ... and contenders */
|
|
last = 0;
|
|
search = contenders[i];
|
|
while(search) {
|
|
if((t - search->l->LastUpdateTS) > search->l->TTW) {
|
|
/* heh heh ... let the reaping begin! */
|
|
pd("We're reaping a contender. BWAH HAH HAH HAH HAH HA HA!\n");
|
|
pd("\tKey: "); pd(search->l->key); pd("\n");
|
|
pd("\tIndex: "); pd(search->l->index); pd("\n");
|
|
pd("\tOwner: "); pd(search->l->owner); pd("\n");
|
|
if(!last) {
|
|
contenders[i] = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = contenders[i];
|
|
} else {
|
|
last->next = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = last->next;
|
|
}
|
|
} else {
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Ok - now for the fun. We have to decide who gets to become
|
|
* lock owners. Here's the premise. We go through the owners
|
|
* and find out what keys/indexes are already locked. From
|
|
* there we start wading through the contenders, and moving
|
|
* them if appropriate.
|
|
*
|
|
* My apologies if this logic is incomprehensible. 8)
|
|
*/
|
|
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
search = owners[i];
|
|
while(search) {
|
|
for(j = 0;
|
|
keys[j] &&
|
|
strcmp(keys[j], search->l->key) &&
|
|
j < MAXSYMBOLS;
|
|
j++);
|
|
if(keys[j]) {
|
|
iter = indexes[j];
|
|
liter = 0;
|
|
while(iter && strcmp(iter->index, search->l->index)) {
|
|
liter = iter;
|
|
iter = iter->next;
|
|
}
|
|
|
|
if(!iter) {
|
|
iter = (index_list *) malloc (sizeof(index_list));
|
|
iter->index = (char *) malloc (sizeof(char) * \
|
|
(strlen(search->l->index) + 1));
|
|
strncpy(iter->index, search->l->index, \
|
|
(strlen(search->l->index) + 1));
|
|
iter->next = (index_list *) 0;
|
|
if(!liter)
|
|
indexes[j] = iter;
|
|
else
|
|
liter->next = iter;
|
|
}
|
|
} else if (j == MAXSYMBOLS) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR, \
|
|
"Ran out of room for symbols during cleanup.");
|
|
closelog();
|
|
noble_death();
|
|
} else {
|
|
/* Ahh - new key for us */
|
|
keys[j] = (char *) malloc (sizeof(char) * \
|
|
(strlen(search->l->key) + 1));
|
|
strncpy(keys[j], search->l->key,
|
|
(strlen(search->l->key) + 1));
|
|
|
|
iter = (index_list *) malloc (sizeof(index_list));
|
|
iter->index = (char *) malloc (sizeof(char) * \
|
|
(strlen(search->l->index) + 1));
|
|
strncpy(iter->index, search->l->index, \
|
|
(strlen(search->l->index) + 1));
|
|
iter->next = (index_list *) 0;
|
|
|
|
indexes[j] = iter;
|
|
}
|
|
search = search->next;
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
search = contenders[i];
|
|
last = 0;
|
|
while(search) {
|
|
for(j = 0;
|
|
keys[j] &&
|
|
strcmp(keys[j], search->l->key) &&
|
|
j < MAXSYMBOLS;
|
|
j++) {};
|
|
|
|
if(keys[j]) {
|
|
iter = indexes[j];
|
|
|
|
/* If we are looking for a broad based lock and there
|
|
* are any indexes, we have to make sure nobody else
|
|
* goes after the lock, so we fake it as locked. Then
|
|
* we just move on with life. */
|
|
if(indexes[j] && !strcmp(search->l->key,"*")) {
|
|
while(iter->next) iter = iter->next;
|
|
iter->next = (index_list *) malloc (sizeof(index_list));
|
|
iter = iter->next;
|
|
iter->index = (char *) malloc (sizeof(char) * 2);
|
|
iter->next = 0;
|
|
strcpy(iter->index,"*");
|
|
search = search->next;
|
|
continue;
|
|
}
|
|
|
|
/* find if there's an index we care about */
|
|
iter = indexes[j];
|
|
while(iter &&
|
|
strcmp(iter->index, search->l->index) &&
|
|
strcmp(iter->index, "*")) {
|
|
iter = iter->next;
|
|
}
|
|
|
|
if(!iter) {
|
|
iter = indexes[j];
|
|
while(iter->next) iter = iter->next;
|
|
iter->next = (index_list *) malloc (sizeof(index_list));
|
|
iter = iter->next;
|
|
iter->next = 0;
|
|
|
|
iter->index = (char *) malloc (sizeof(char) * \
|
|
(strlen(search->l->index) + 1));
|
|
strncpy(iter->index, search->l->index, \
|
|
(strlen(search->l->index) + 1));
|
|
|
|
if(last)
|
|
last->next = search->next;
|
|
else
|
|
contenders[i] = search->next;
|
|
|
|
findend = owners[i];
|
|
while(findend && findend->next)
|
|
findend = findend->next;
|
|
|
|
n = search;
|
|
n->next = 0;
|
|
time(&t);
|
|
n->l->LastUpdateTS = t;
|
|
n->l->ObtainTS = t;
|
|
if(last)
|
|
search = last->next;
|
|
else
|
|
search = contenders[i];
|
|
|
|
if(findend)
|
|
findend->next = n;
|
|
else
|
|
owners[i] = n;
|
|
|
|
} else /* else somebody already has the lock */
|
|
search = search->next;
|
|
} else if (j == MAXSYMBOLS) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_ERR, \
|
|
"Ran out of room for symbols during cleanup.");
|
|
closelog();
|
|
noble_death();
|
|
} else {
|
|
/* Mark it as locked */
|
|
keys[j] = (char *) malloc (sizeof(char) * \
|
|
(strlen(search->l->key) + 1));
|
|
strncpy(keys[j], search->l->key,
|
|
(strlen(search->l->key) + 1));
|
|
|
|
iter = (index_list *) malloc (sizeof(index_list));
|
|
iter->index = (char *) malloc (sizeof(char) * \
|
|
(strlen(search->l->index) + 1));
|
|
strncpy(iter->index, search->l->index, \
|
|
(strlen(search->l->index) + 1));
|
|
iter->next = (index_list *) 0;
|
|
|
|
indexes[j] = iter;
|
|
|
|
/* And move them to lock */
|
|
if(last)
|
|
last->next = search->next;
|
|
else
|
|
contenders[i] = search->next;
|
|
|
|
findend = owners[i];
|
|
while(findend && findend->next)
|
|
findend = findend->next;
|
|
|
|
n = search;
|
|
n->next = 0;
|
|
time(&t);
|
|
n->l->LastUpdateTS = t;
|
|
if(last)
|
|
search = last->next;
|
|
else
|
|
search = contenders[i];
|
|
|
|
if(findend)
|
|
findend->next = n;
|
|
else
|
|
owners[i] = n;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < MAXSYMBOLS; i++) {
|
|
ct = keys[i];
|
|
if(ct)
|
|
free(ct);
|
|
keys[i] = 0;
|
|
|
|
iter = indexes[i];
|
|
while(iter) {
|
|
liter = iter;
|
|
iter = iter->next;
|
|
free(liter->index);
|
|
free(liter);
|
|
}
|
|
indexes[i] = 0;
|
|
}
|
|
}
|
|
|
|
/* At this point the basic algorithm is to take the ASCII value of
|
|
* each character in the key, sum 'em up and mod by HASHSIZE.
|
|
*
|
|
* Note: In any revisions of this function in the future, it
|
|
* will be important that ANY unique key will generate a unique
|
|
* index into the hash. The data structure for the lock storage
|
|
* will depend on this.
|
|
*/
|
|
int hashfunction(char *key) {
|
|
int i,s,retval=0;
|
|
|
|
s=strlen(key);
|
|
for(i = 0; i < s; i++)
|
|
retval += key[i];
|
|
|
|
retval %= HASHSIZE;
|
|
|
|
return retval;
|
|
}
|
|
|
|
void client_deal(int client_sockfd) {
|
|
int command = 0x0;
|
|
int keysize = 0x0; char *key;
|
|
int indexsize = 0x0; char *index;
|
|
int ownersize = 0x0; char *owner;
|
|
int TTL = 0x0, TTW = 0x0;
|
|
int priority = 0x0;
|
|
int hashind;
|
|
time_t ts;
|
|
lock *l;
|
|
lockqueue *s;
|
|
|
|
char *ret;
|
|
char rlen;
|
|
int nb;
|
|
|
|
int i, j;
|
|
unsigned int contend_loc, mask, k, num_locks;
|
|
unsigned long m;
|
|
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &command, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &command, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
switch(command) {
|
|
case WHOOWNS:
|
|
pd("Who owns the following?\n");
|
|
/* Get key */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &keysize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &keysize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key = (char *) malloc (sizeof(char) * (keysize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, key, keysize);
|
|
#else
|
|
nb = read_socket(client_sockfd, key, keysize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key[keysize] = '\0';
|
|
pd("\tKey: "); pd(key); pd("\n");
|
|
|
|
/* Get index*/
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &indexsize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &indexsize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index = (char *) malloc (sizeof(char) * (indexsize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, index, indexsize);
|
|
#else
|
|
nb = read_socket(client_sockfd, index, indexsize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index[indexsize] = '\0';
|
|
pd("\tIndex: "); pd(index); pd("\n\n");
|
|
|
|
l = find_owner(key, index);
|
|
|
|
if(l) {
|
|
pd("Found an owner:\n");
|
|
ret = (char *) malloc (sizeof(char) * \
|
|
(strlen(l->owner) + 2));
|
|
sprintf(ret, "%c%s", strlen(l->owner), l->owner);
|
|
|
|
rlen=strlen(ret);
|
|
pd("\tOwner: "); pd(l->owner); pd("\n");
|
|
|
|
} else {
|
|
pd("No owner found.\n");
|
|
ret = (char *) malloc (sizeof(char));
|
|
ret[0] = 0;
|
|
rlen = 1;
|
|
}
|
|
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, ret, rlen);
|
|
#else
|
|
nb = write_socket(client_sockfd, ret, rlen);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
free(key);
|
|
free(index);
|
|
free(ret);
|
|
pd("\n");
|
|
|
|
break;
|
|
case GIMME: /* Request Lock */
|
|
pd("I want a lock! Now dammit!\n");
|
|
/* Get key */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &keysize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &keysize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key = (char *) malloc (sizeof(char) * (keysize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, key, keysize);
|
|
#else
|
|
nb = read_socket(client_sockfd, key, keysize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key[keysize] = '\0';
|
|
pd("\tKey: "); pd(key); pd("\n");
|
|
|
|
/* Get index */
|
|
#ifndef __MINGW32__
|
|
read(client_sockfd, &indexsize, 1);
|
|
#else
|
|
read_socket(client_sockfd, &indexsize, 1);
|
|
#endif
|
|
index = (char *) malloc (sizeof(char) * (indexsize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, index, indexsize);
|
|
#else
|
|
nb = read_socket(client_sockfd, index, indexsize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index[indexsize] = '\0';
|
|
pd("\tIndex: "); pd(index); pd("\n");
|
|
|
|
/* Get owner */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &ownersize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &ownersize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner = (char *) malloc (sizeof(char) * (ownersize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, owner, ownersize);
|
|
#else
|
|
nb = read_socket(client_sockfd, owner, ownersize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner[ownersize] = '\0';
|
|
pd("\tOwner: "); pd(owner); pd("\n");
|
|
|
|
/* Get TTL */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &TTL, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &TTL, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
TTL = TTL << 8;
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &TTL, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &TTL, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
/* Get TTW */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &TTW, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &TTW, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
TTW = TTW << 8;
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &TTW, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &TTW, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
/* Get priority */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &priority, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &priority, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
l = find_lock(key, index, owner);
|
|
contend_loc = 0x0;
|
|
if(graceclose) {
|
|
pd("Denying a lock because of graceful close\n");
|
|
contend_loc = 0x0;
|
|
} else if(!l) {
|
|
pd("Ok this is officially a new lock.\n");
|
|
l = (lock *) malloc (sizeof(lock));
|
|
l->TTL = TTL;
|
|
l->TTW = TTW;
|
|
l->priority = priority;
|
|
|
|
l->key = (char *) malloc (sizeof(char) \
|
|
* (strlen(key) + 1));
|
|
strncpy(l->key, key, (strlen(key)+1));
|
|
|
|
l->index = (char *) malloc (sizeof(char) \
|
|
* (strlen(index) + 1));
|
|
strncpy(l->index, index, (strlen(index)+1));
|
|
|
|
l->owner = (char *) malloc (sizeof(char) \
|
|
* (strlen(owner) + 1));
|
|
strncpy(l->owner, owner, (strlen(owner)+1));
|
|
|
|
time(&ts);
|
|
l->RequestTS = ts;
|
|
l->LastUpdateTS = ts;
|
|
|
|
contend_loc = add_contender(l);
|
|
pd("Inserted.\n");
|
|
} else {
|
|
pd("Uh, this lock already exists.\n");
|
|
time(&ts);
|
|
l->LastUpdateTS = ts;
|
|
contend_loc = get_contend_loc(l);
|
|
}
|
|
|
|
mask = 0xffff;
|
|
if(contend_loc & ~mask) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, \
|
|
"Contender location is more than 2 bytes.");
|
|
closelog();
|
|
}
|
|
|
|
mask = 0xff00;
|
|
j = ((contend_loc & mask) >> 8);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
mask = 0xff;
|
|
j = contend_loc & mask;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
free(key);
|
|
free(index);
|
|
free(owner);
|
|
pd("\n");
|
|
|
|
break;
|
|
case CONTLOC: /* Where do I stand? */
|
|
pd("Contender location:\n");
|
|
/* Get key */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &keysize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &keysize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key = (char *) malloc (sizeof(char) * (keysize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, key, keysize);
|
|
#else
|
|
nb = read_socket(client_sockfd, key, keysize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key[keysize] = '\0';
|
|
pd("\tKey: "); pd(key); pd("\n");
|
|
|
|
/* Get index */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &indexsize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &indexsize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index = (char *) malloc (sizeof(char) * (indexsize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, index, indexsize);
|
|
#else
|
|
nb = read_socket(client_sockfd, index, indexsize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index[indexsize] = '\0';
|
|
pd("\tIndex: "); pd(index); pd("\n");
|
|
|
|
/* Get owner */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &ownersize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &ownersize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner = (char *) malloc (sizeof(char) * (ownersize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, owner, ownersize);
|
|
#else
|
|
nb = read_socket(client_sockfd, owner, ownersize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner[ownersize] = '\0';
|
|
pd("\tOwner: "); pd(owner); pd("\n");
|
|
|
|
l = find_lock(key, index, owner);
|
|
if(l) pd("Found lock...\n");
|
|
else pd("Lock not found...\n");
|
|
contend_loc = 0x0;
|
|
if(l) contend_loc = get_contend_loc(l);
|
|
|
|
mask = 0xffff;
|
|
if(contend_loc & ~mask) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, \
|
|
"Contender location is more than 2 bytes.");
|
|
closelog();
|
|
}
|
|
|
|
mask = 0xff00;
|
|
j = ((contend_loc & mask) >> 8);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
mask = 0xff;
|
|
j = contend_loc & mask;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
free(key);
|
|
free(index);
|
|
free(owner);
|
|
pd("\n");
|
|
|
|
break;
|
|
case RENEW: /* I still want it! */
|
|
pd("Let's renew a lock!\n");
|
|
/* Get key */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &keysize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &keysize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key = (char *) malloc (sizeof(char) * (keysize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, key, keysize);
|
|
#else
|
|
nb = read_socket(client_sockfd, key, keysize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key[keysize] = '\0';
|
|
pd("\tKey: "); pd(key); pd("\n");
|
|
|
|
/* Get index */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &indexsize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &indexsize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index = (char *) malloc (sizeof(char) * (indexsize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, index, indexsize);
|
|
#else
|
|
nb = read_socket(client_sockfd, index, indexsize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index[indexsize] = '\0';
|
|
pd("\tIndex: "); pd(index); pd("\n");
|
|
|
|
/* Get owner */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &ownersize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &ownersize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner = (char *) malloc (sizeof(char) * (ownersize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, owner, ownersize);
|
|
#else
|
|
nb = read_socket(client_sockfd, owner, ownersize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner[ownersize] = '\0';
|
|
pd("\tOwner: "); pd(owner); pd("\n");
|
|
|
|
l = find_lock(key, index, owner);
|
|
if(l) {
|
|
pd("Found lock...\n");
|
|
time(&ts);
|
|
l->LastUpdateTS = ts;
|
|
} else
|
|
pd("Lock not found...\n");
|
|
|
|
if(l) j = 1;
|
|
else j = 0;
|
|
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
free(key);
|
|
free(index);
|
|
free(owner);
|
|
|
|
pd("\n");
|
|
|
|
break;
|
|
case RELSPEC: /* Ok - I'm ready to let go ... a little */
|
|
pd("Hmm. We want to release a specific lock...\n");
|
|
/* Get key */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &keysize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &keysize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key = (char *) malloc (sizeof(char) * (keysize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, key, keysize);
|
|
#else
|
|
nb = read_socket(client_sockfd, key, keysize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key[keysize] = '\0';
|
|
pd("\tKey: "); pd(key); pd("\n");
|
|
|
|
/* Get index */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &indexsize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &indexsize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index = (char *) malloc (sizeof(char) * (indexsize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, index, indexsize);
|
|
#else
|
|
nb = read_socket(client_sockfd, index, indexsize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
index[indexsize] = '\0';
|
|
pd("\tIndex: "); pd(index); pd("\n");
|
|
|
|
/* Get owner */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &ownersize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &ownersize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner = (char *) malloc (sizeof(char) * (ownersize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, owner, ownersize);
|
|
#else
|
|
nb = read_socket(client_sockfd, owner, ownersize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner[ownersize] = '\0';
|
|
pd("\tOwner: "); pd(owner); pd("\n");
|
|
|
|
num_locks = kill_off(key, index, owner);
|
|
pd("Killing spree done.\n");
|
|
mask = 0xffff;
|
|
if(num_locks & ~mask) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, \
|
|
"# of locks removed is more than 2 bytes.");
|
|
closelog();
|
|
}
|
|
|
|
mask = 0xff00;
|
|
j = ((num_locks & mask) >> 8);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
mask = 0xff;
|
|
j = num_locks & mask;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
free(key);
|
|
free(index);
|
|
free(owner);
|
|
|
|
pd("\n");
|
|
|
|
break;
|
|
case RELALL: /* Ok - everybody out of the pool... */
|
|
pd("Kill! Kill! Kill 'em all!\n");
|
|
/* Get owner */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &ownersize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &ownersize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner = (char *) malloc (sizeof(char) * (ownersize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, owner, ownersize);
|
|
#else
|
|
nb = read_socket(client_sockfd, owner, ownersize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
owner[ownersize] = '\0';
|
|
pd("\tOwner: "); pd(owner); pd("\n");
|
|
|
|
num_locks = kill_all(owner);
|
|
pd("Bloodbath completed.\n");
|
|
mask = 0xffff;
|
|
if(num_locks & ~mask) {
|
|
openlog("lockserver", LOG_PID, LOG_DAEMON);
|
|
syslog(LOG_WARNING, \
|
|
"# of locks removed is more than 2 bytes.");
|
|
closelog();
|
|
}
|
|
|
|
mask = 0xff00;
|
|
j = ((num_locks & mask) >> 8);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
mask = 0xff;
|
|
j = num_locks & mask;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
free(owner);
|
|
pd("\n");
|
|
|
|
break;
|
|
case SHOWCONT:
|
|
/* Get key */
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, &keysize, 1);
|
|
#else
|
|
nb = read_socket(client_sockfd, &keysize, 1);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key = (char *) malloc (sizeof(char) * (keysize + 1));
|
|
#ifndef __MINGW32__
|
|
nb = read(client_sockfd, key, keysize);
|
|
#else
|
|
nb = read_socket(client_sockfd, key, keysize);
|
|
#endif
|
|
if(!nb) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
key[keysize] = '\0';
|
|
|
|
/* Gotta find out how many first */
|
|
hashind = hashfunction(key);
|
|
num_locks = 0;
|
|
|
|
s = owners[hashind];
|
|
while(s) {
|
|
if(!strcmp(s->l->key, key))
|
|
num_locks++;
|
|
s = s->next;
|
|
}
|
|
|
|
s = contenders[hashind];
|
|
while(s) {
|
|
if(!strcmp(s->l->key, key))
|
|
num_locks++;
|
|
s = s->next;
|
|
}
|
|
|
|
mask = 0xff00;
|
|
j = ((num_locks & mask) >> 8);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
mask = 0xff;
|
|
j = num_locks & mask;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
/* Ok - time to send da stuff */
|
|
|
|
for(i=0; i<2; i++) {
|
|
if(!i) s = owners[hashind];
|
|
else s = contenders[hashind];
|
|
|
|
while(s) {
|
|
if(!strcmp(s->l->key, key)) {
|
|
/* priority */
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &(s->l->priority), 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &(s->l->priority), 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
/* TTL */
|
|
mask = 0xff00;
|
|
j = ((s->l->TTL & mask) >> 8);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
mask = 0xff;
|
|
j = s->l->TTL & mask;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
/* TTW */
|
|
mask = 0xff00;
|
|
j = ((s->l->TTW & mask) >> 8);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
mask = 0xff;
|
|
j = s->l->TTW & mask;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
/* Index */
|
|
j = strlen(s->l->index);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
nb = write(client_sockfd, s->l->index, j);
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
/* Owner */
|
|
j = strlen(s->l->owner);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, s->l->owner, j);
|
|
#else
|
|
nb = write_socket(client_sockfd, s->l->owner, j);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
j = !i;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
s = s->next;
|
|
}
|
|
}
|
|
|
|
free(key);
|
|
|
|
break;
|
|
case STATS: /* So, like, what's happenin' man? */
|
|
/* Send uptime (4 bytes) # of seconds */
|
|
time(&ts);
|
|
ts = ts - startTS;
|
|
for(i = (sizeof(time_t) - 1); i >= 0; i--) {
|
|
j = ((ts >> (i * 8)) & 0xFF);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Send stats, starting with 0x0 - going to 0x8 (4 bytes each) */
|
|
for(i = 0; i < 9; i++) {
|
|
for(j = (sizeof(long) - 1); j >= 0; j--) {
|
|
k = ((requests[i] >> (j * 8)) & 0xFF);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &k, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &k, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Connection stats */
|
|
/* Accepted */
|
|
for(i = sizeof(long) - 1; i >= 0; i--) {
|
|
j = ((okeedokee >> (i * 8)) & 0xFF);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Rejected */
|
|
for(i = sizeof(long) - 1; i >= 0; i--) {
|
|
j = ((badboys >> (i * 8)) & 0xFF);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Too busy denies */
|
|
for(i = sizeof(long) - 1; i >= 0; i--) {
|
|
j = ((rejects >> (i * 8)) & 0xFF);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Owners */
|
|
m = 0;
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
s = owners[i];
|
|
while(s) {
|
|
m++;
|
|
s = s->next;
|
|
}
|
|
}
|
|
for(i = sizeof(long) - 1; i >= 0; i--) {
|
|
j = ((m >> (i * 8)) & 0xFF);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Contenders */
|
|
m = 0;
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
s = contenders[i];
|
|
while(s) {
|
|
m++;
|
|
s = s->next;
|
|
}
|
|
}
|
|
for(i = sizeof(long) - 1; i >= 0; i--) {
|
|
j = ((m >> (i * 8)) & 0xFF);
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Current connections */
|
|
k=0;
|
|
for(i = 1; i < MAXCONQUEUE; i++)
|
|
if(open_sockets[i] != -1) k++;
|
|
|
|
j = (k >> 8) & 0xFF;
|
|
#ifndef __MINGE32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
j = k & 0xFF;
|
|
#ifndef __MINGW32__
|
|
nb = write(client_sockfd, &j, 1);
|
|
#else
|
|
nb = write_socket(client_sockfd, &j, 1);
|
|
#endif
|
|
if(nb == -1 && errno == EPIPE) {
|
|
close_socket(client_sockfd);
|
|
return;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
command = 0;
|
|
};
|
|
requests[command] ++;
|
|
return;
|
|
}
|
|
|
|
lock *find_owner(char *key, char *index) {
|
|
int hashind;
|
|
lockqueue *search;
|
|
|
|
hashind = hashfunction(key);
|
|
|
|
search = owners[hashind];
|
|
while(search && (
|
|
strcmp(search->l->key, key) ||
|
|
(strcmp(search->l->index,index) &&
|
|
strcmp(search->l->index,"*")))) {
|
|
search=search->next;
|
|
}
|
|
|
|
if(search) return (search->l);
|
|
|
|
return (lock *) 0;
|
|
}
|
|
|
|
lock *find_lock(char *key, char *index, char *owner) {
|
|
int hashind;
|
|
lockqueue *search;
|
|
|
|
hashind = hashfunction(key);
|
|
|
|
/* Start looking in owner */
|
|
search = owners[hashind];
|
|
while(search && (
|
|
(strcmp(search->l->key, key) ||
|
|
strcmp(search->l->owner, owner) ||
|
|
(strcmp(search->l->index, index) &&
|
|
strcmp(search->l->index, "*"))))) {
|
|
|
|
search = search->next;
|
|
}
|
|
|
|
if(search) return(search->l);
|
|
|
|
/* Ok - not an owner. At least a contender? */
|
|
search = contenders[hashind];
|
|
while(search && (
|
|
strcmp(search->l->key, key) ||
|
|
strcmp(search->l->owner, owner) ||
|
|
(strcmp(search->l->index, index) &&
|
|
strcmp(search->l->index, "*")))) {
|
|
search = search->next;
|
|
}
|
|
|
|
if(search) return(search->l);
|
|
|
|
return (lock *) 0;
|
|
}
|
|
|
|
unsigned int add_contender(lock *l) {
|
|
int hashind, retval=0;
|
|
lockqueue *last, *search, *insertion;
|
|
|
|
/* Let's get the data ready to be dropped in */
|
|
insertion = (lockqueue *) malloc (sizeof(lockqueue));
|
|
insertion->l = l;
|
|
insertion->next = (lockqueue *) 0;
|
|
|
|
hashind = hashfunction(l->key);
|
|
|
|
last = 0;
|
|
/* Let's try ownership first. Maybe they'll get lucky */
|
|
search = owners[hashind];
|
|
while(search && (
|
|
strcmp(search->l->key, l->key) ||
|
|
(strcmp(l->index, search->l->index) &&
|
|
strcmp(search->l->index, "*") &&
|
|
strcmp(l->index, "*")))) {
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
|
|
if(!search) {
|
|
/* Sweet! We get it immediately */
|
|
if(!owners[hashind]) { /* We're the only folks in the queue */
|
|
owners[hashind] = insertion;
|
|
} else /* Going in at the end */
|
|
last->next = insertion;
|
|
|
|
return(1);
|
|
} else
|
|
retval = 2;
|
|
|
|
/* Oh boy ... we get to wade through the contenders */
|
|
|
|
search = contenders[hashind];
|
|
last = (lockqueue *) 0;
|
|
while(search && search->l->priority <= l->priority) {
|
|
if(!strcmp(search->l->key, l->key) &&
|
|
(!strcmp(search->l->index, l->index) ||
|
|
!strcmp(search->l->index, "*") ||
|
|
!strcmp(l->index, "*")))
|
|
retval ++;
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
|
|
if(!contenders[hashind]) /* Ok - first in line */
|
|
contenders[hashind] = insertion;
|
|
else if(!last) {
|
|
contenders[hashind] = insertion;
|
|
insertion->next = search;
|
|
} else { /* We're in the queue ... somewhere */
|
|
insertion->next = search;
|
|
last->next = insertion;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
unsigned int get_contend_loc(lock *l) {
|
|
int hashind, retval=0;
|
|
lockqueue *search;
|
|
|
|
hashind = hashfunction(l->key);
|
|
|
|
/* Ownership area */
|
|
search = owners[hashind];
|
|
while(search && (search->l != l)) {
|
|
if(!strcmp(search->l->key, l->key) &&
|
|
(!strcmp(search->l->index, l->index) ||
|
|
(!strcmp(search->l->index, "*"))))
|
|
retval++;
|
|
search=search->next;
|
|
}
|
|
|
|
if(search) return(1);
|
|
|
|
retval = 2;
|
|
search = contenders[hashind];
|
|
/* (In a raspy voice): I coulda beena contenda... */
|
|
while(search && (search->l != l)) {
|
|
if(!strcmp(search->l->key, l->key) &&
|
|
(!strcmp(search->l->index, l->index) ||
|
|
(!strcmp(search->l->index, "*") ||
|
|
!strcmp(l->index,"*"))))
|
|
retval++;
|
|
search=search->next;
|
|
}
|
|
|
|
if(!search) retval=0;
|
|
|
|
return retval;
|
|
}
|
|
|
|
unsigned int kill_off(char *key, char *index, char *owner) {
|
|
int retval = 0;
|
|
int hashind;
|
|
lockqueue *search, *last = 0;
|
|
|
|
hashind = hashfunction(key);
|
|
|
|
/* Check owner area first */
|
|
search = owners[hashind];
|
|
while(search) {
|
|
if(!strcmp(search->l->key, key) &&
|
|
(!strlen(owner) ||
|
|
!strcmp(search->l->owner, owner)) &&
|
|
(!strcmp(search->l->index, index) ||
|
|
!strcmp(index,"*"))) {
|
|
/* Ah hah! It needs deadifying */
|
|
if(!last) {
|
|
owners[hashind] = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = owners[hashind];
|
|
retval ++;
|
|
} else {
|
|
last->next = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = last->next;
|
|
retval ++;
|
|
}
|
|
} else {
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
}
|
|
|
|
/* And now the contenders */
|
|
search = contenders[hashind];
|
|
last = 0;
|
|
while(search) {
|
|
if(!strcmp(search->l->key, key) &&
|
|
(!strlen(owner) ||
|
|
!strcmp(search->l->owner, owner)) &&
|
|
(!strcmp(search->l->index, index) ||
|
|
!strcmp(index, "*"))) {
|
|
/* Ah hah! It needs deadifying */
|
|
if(!last) {
|
|
contenders[hashind] = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = contenders[hashind];
|
|
retval ++;
|
|
} else {
|
|
last->next = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = last->next;
|
|
retval ++;
|
|
}
|
|
} else {
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
unsigned int kill_all(char *owner) {
|
|
int retval = 0, i;
|
|
lockqueue *search, *last = 0;
|
|
|
|
/* Clean out the owners... */
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
search = owners[i];
|
|
last = 0;
|
|
|
|
while(search) {
|
|
if(!strlen(owner) || !strcmp(search->l->owner,owner)) {
|
|
retval ++;
|
|
/* Ok, now we take 'im out */
|
|
if(!last) {
|
|
owners[i] = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = owners[i];
|
|
} else {
|
|
last->next = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = last->next;
|
|
}
|
|
} else {
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* And then the contenders... */
|
|
for(i = 0; i < HASHSIZE; i++) {
|
|
search = contenders[i];
|
|
last = 0;
|
|
|
|
while(search) {
|
|
if(!strlen(owner) || !strcmp(search->l->owner,owner)) {
|
|
retval ++;
|
|
/* Ok, now we take 'im out */
|
|
if(!last) {
|
|
contenders[i] = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = contenders[i];
|
|
} else {
|
|
last->next = search->next;
|
|
free(search->l->key);
|
|
free(search->l->index);
|
|
free(search->l->owner);
|
|
free(search->l);
|
|
free(search);
|
|
search = last->next;
|
|
}
|
|
} else {
|
|
last = search;
|
|
search = search->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
void pd(char *message) {
|
|
if(message && debug) fprintf(stderr,"%s",message);
|
|
return;
|
|
}
|
|
|
|
char *format_time(int seconds) {
|
|
int play, op=0;
|
|
char *retval = 0;
|
|
char *addon = 0;
|
|
|
|
retval = (char *) malloc (sizeof(char));
|
|
retval[0] = 0;
|
|
|
|
/* Days */
|
|
play = seconds / (60*60*24);
|
|
if(play) {
|
|
addon = (char *) malloc (sizeof(char) * 12);
|
|
sprintf(addon, "%d day%s", play, (play > 1) ? "s" : "");
|
|
seconds %= (60*60*24);
|
|
|
|
play = sizeof(char) * (strlen(retval) + strlen(addon) + 1);
|
|
op = strlen(retval);
|
|
if(op) play += 2;
|
|
|
|
retval = realloc(retval,play);
|
|
if(op) strcpy(&retval[strlen(retval)], ", ");
|
|
strcpy(&retval[strlen(retval)], addon);
|
|
|
|
free(addon);
|
|
}
|
|
|
|
/* Hours */
|
|
play = seconds / (60*60);
|
|
if(play) {
|
|
addon = (char *) malloc (sizeof(char) * 10);
|
|
sprintf(addon, "%d hour%s", play, (play > 1) ? "s" : "");
|
|
seconds %= (60*60);
|
|
|
|
play = sizeof(char) * (strlen(retval) + strlen(addon) + 1);
|
|
op = strlen(retval);
|
|
if(op) play += 2;
|
|
|
|
retval = realloc(retval,play);
|
|
if(op) strcpy(&retval[strlen(retval)], ", ");
|
|
strcpy(&retval[strlen(retval)], addon);
|
|
|
|
free(addon);
|
|
}
|
|
|
|
/* Minutes */
|
|
play = seconds / 60;
|
|
if(play) {
|
|
addon = (char *) malloc (sizeof(char) * 13);
|
|
sprintf(addon, "%d minute%s", play, (play > 1) ? "s" : "");
|
|
seconds %= 60;
|
|
|
|
play = sizeof(char) * (strlen(retval) + strlen(addon) + 1);
|
|
op = strlen(retval);
|
|
if(op) play += 2;
|
|
|
|
retval = realloc(retval,play);
|
|
if(op) strcpy(&retval[strlen(retval)], ", ");
|
|
strcpy(&retval[strlen(retval)], addon);
|
|
|
|
free(addon);
|
|
}
|
|
|
|
/* Seconds */
|
|
play = seconds;
|
|
if(play) {
|
|
addon = (char *) malloc (sizeof(char) * 13);
|
|
sprintf(addon, "%d second%s", play, (play > 1) ? "s" : "");
|
|
|
|
play = sizeof(char) * (strlen(retval) + strlen(addon) + 1);
|
|
op = strlen(retval);
|
|
if(op) play += 2;
|
|
|
|
retval = realloc(retval,play);
|
|
if(op) strcpy(&retval[strlen(retval)], ", ");
|
|
strcpy(&retval[strlen(retval)], addon);
|
|
|
|
free(addon);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
#ifdef __MINGW32__
|
|
|
|
/* Example code to log to Event log. */
|
|
|
|
|
|
#define TBUF_LEN 2048
|
|
#define FMT_LEN 1024
|
|
|
|
|
|
void syslog(int pri, char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
vsyslog(pri, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void vsyslog(int pri, char *fmt, va_list ap){
|
|
char ch, *p, *t;
|
|
int tbuf_left, fmt_left, prlen, saved_errno;
|
|
char tbuf[TBUF_LEN], fmt_cpy[FMT_LEN];
|
|
|
|
p = tbuf;
|
|
tbuf_left = TBUF_LEN;
|
|
|
|
saved_errno = errno;
|
|
|
|
/*
|
|
* We wouldn't need this mess if printf handled %m, or if
|
|
* strerror() had been invented before syslog().
|
|
*/
|
|
for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt); ++fmt) {
|
|
if (ch == '%' && fmt[1] == 'm') {
|
|
++fmt;
|
|
prlen = _snprintf(t, fmt_left, "%s",
|
|
strerror(saved_errno));
|
|
if (prlen >= fmt_left)
|
|
prlen = fmt_left - 1;
|
|
t += prlen;
|
|
fmt_left -= prlen;
|
|
} else {
|
|
if (fmt_left > 1) {
|
|
*t++ = ch;
|
|
fmt_left--;
|
|
}
|
|
}
|
|
}
|
|
*t = '\0';
|
|
|
|
_vsnprintf(p, tbuf_left, fmt_cpy, ap);
|
|
|
|
|
|
/* Now, actually report it. */
|
|
/****************************/
|
|
puts(fmt_cpy);
|
|
return;
|
|
}
|
|
|
|
void openlog(char *ident, int logstat, int logfac){
|
|
|
|
}
|
|
|
|
void closelog()
|
|
{
|
|
}
|
|
|
|
int write_socket(SOCKET s, const char *buf, int len)
|
|
{
|
|
int result;
|
|
result = send(s,buf,len,0);
|
|
if(result == SOCKET_ERROR)
|
|
{
|
|
errno = WSAGetLastError();
|
|
if(errno == WSAENOTCONN)
|
|
{
|
|
errno = EPIPE;
|
|
return -1;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int read_socket(SOCKET s, char *buf, int len)
|
|
{
|
|
int result;
|
|
result = recv(s,buf,len,0);
|
|
if(result == 0)
|
|
{
|
|
errno = EPIPE;
|
|
return -1;
|
|
}
|
|
if(result == SOCKET_ERROR)
|
|
{
|
|
errno = WSAGetLastError();
|
|
if(errno == WSAENOTCONN)
|
|
{
|
|
errno = EPIPE;
|
|
return -1;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
#endif
|