summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1999-12-21 04:54:30 +0000
committerAndrew Tridgell <tridge@samba.org>1999-12-21 04:54:30 +0000
commit69d24d869bf97978b31a51fe8e8d08cac4874d67 (patch)
tree30ec2bcdc8491098dd9b3f0c4e3432092b73f23a
parent0c4b1ea0140ed5418fcbde3077d424ffa08a2dcf (diff)
downloadsamba-69d24d869bf97978b31a51fe8e8d08cac4874d67.tar.gz
samba-69d24d869bf97978b31a51fe8e8d08cac4874d67.tar.bz2
samba-69d24d869bf97978b31a51fe8e8d08cac4874d67.zip
first cut at using the tdb code for the connections structure, the
SWAT status page and smbstatus. It made the code _much_ simpler, I wish we'd done a database module a long time ago! (This used to be commit 4951755413c11d4c5b9af4699a6e622056d52433)
-rw-r--r--source3/include/proto.h6
-rw-r--r--source3/include/smb.h28
-rw-r--r--source3/script/mkproto.awk4
-rw-r--r--source3/smbd/connection.c225
-rw-r--r--source3/smbd/reply.c2
-rw-r--r--source3/smbd/service.c8
-rw-r--r--source3/tdb/README9
-rw-r--r--source3/tdb/tdb.c39
-rw-r--r--source3/tdb/tdb.h1
-rw-r--r--source3/utils/status.c384
-rw-r--r--source3/web/statuspage.c117
11 files changed, 400 insertions, 423 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index c933a93222..125ef3a27c 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2375,7 +2375,9 @@ void conn_free(connection_struct *conn);
/*The following definitions come from smbd/connection.c */
+TDB_CONTEXT *open_db(char *name);
BOOL yield_connection(connection_struct *conn,char *name,int max_connections);
+int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf);
BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear);
/*The following definitions come from smbd/dfree.c */
@@ -2796,10 +2798,14 @@ int smbw_stat(const char *fname, struct stat *st);
/*The following definitions come from tdb/tdb.c */
int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf);
+TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf));
+TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
+TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
+TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode);
int tdb_close(TDB_CONTEXT *tdb);
int tdb_writelock(TDB_CONTEXT *tdb);
int tdb_writeunlock(TDB_CONTEXT *tdb);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index d3d64a2edf..6c3d7488c3 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -839,19 +839,23 @@ struct passdb_ops {
#endif
};
-/* this is used for smbstatus */
+/* key and data in the connections database - used in smbstatus and smbd */
+struct connections_key {
+ pid_t pid;
+ int cnum;
+ fstring name;
+};
-struct connect_record
-{
- int magic;
- pid_t pid;
- int cnum;
- uid_t uid;
- gid_t gid;
- char name[24];
- char addr[24];
- char machine[128];
- time_t start;
+struct connections_data {
+ int magic;
+ pid_t pid;
+ int cnum;
+ uid_t uid;
+ gid_t gid;
+ char name[24];
+ char addr[24];
+ char machine[128];
+ time_t start;
};
/* the following are used by loadparm for option lists */
diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk
index 923624c3a2..fd0cbcd2f8 100644
--- a/source3/script/mkproto.awk
+++ b/source3/script/mkproto.awk
@@ -98,6 +98,10 @@ END {
gotstart = 1;
}
+ if( $0 ~ /^TDB_CONTEXT|^TDB_DATA/ ) {
+ gotstart = 1;
+ }
+
if( $0 ~ /^long|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|^FILE|^SMB_OFF_T|^size_t|^ssize_t|^SMB_BIG_UINT/ ) {
gotstart = 1;
}
diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c
index 393a3e7372..f88d707983 100644
--- a/source3/smbd/connection.c
+++ b/source3/smbd/connection.c
@@ -27,202 +27,117 @@ extern fstring remote_machine;
extern int DEBUGLEVEL;
/****************************************************************************
-simple routines to do connection counting
+open the connections database
****************************************************************************/
-BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
+TDB_CONTEXT *open_db(char *name)
{
- struct connect_record crec;
pstring fname;
- int fd;
- pid_t mypid = getpid();
- int i;
-
- DEBUG(3,("Yielding connection to %s\n",name));
-
- if (max_connections <= 0)
- return(True);
-
- memset((char *)&crec,'\0',sizeof(crec));
pstrcpy(fname,lp_lockdir());
trim_string(fname,"","/");
-
- pstrcat(fname,"/");
- pstrcat(fname,name);
- pstrcat(fname,".LCK");
-
- fd = sys_open(fname,O_RDWR,0);
- if (fd == -1) {
- DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
- return(False);
+
+ if (!directory_exist(fname,NULL)) {
+ mkdir(fname,0755);
}
+
+ pstrcat(fname,"/connections.tdb");
+
+ return tdb_open(fname, 0, O_RDWR | O_CREAT, 0644);
+}
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) {
- DEBUG(0,("ERROR: can't get lock on %s\n", fname));
- return False;
- }
- /* find the right spot */
- for (i=0;i<max_connections;i++) {
- if (read(fd, &crec,sizeof(crec)) != sizeof(crec)) {
- DEBUG(2,("Entry not found in lock file %s\n",fname));
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
- DEBUG(0,("ERROR: can't release lock on %s\n", fname));
- }
- close(fd);
- return(False);
- }
- if (crec.pid == mypid && crec.cnum == conn->cnum)
- break;
- }
- if (crec.pid != mypid || crec.cnum != conn->cnum) {
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
- DEBUG(0,("ERROR: can't release lock on %s\n", fname));
- }
- close(fd);
- DEBUG(2,("Entry not found in lock file %s\n",fname));
- return(False);
- }
+/****************************************************************************
+delete a connection record
+****************************************************************************/
+BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
+{
+ struct connections_key key;
+ TDB_DATA kbuf;
+ TDB_CONTEXT *tdb;
- memset((void *)&crec,'\0',sizeof(crec));
-
- /* remove our mark */
- if (sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) ||
- write(fd, &crec,sizeof(crec)) != sizeof(crec)) {
- DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
- DEBUG(0,("ERROR: can't release lock on %s\n", fname));
- }
- close(fd);
- return(False);
- }
+ if (!(tdb = open_db(name))) return False;
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
- DEBUG(0,("ERROR: can't release lock on %s\n", fname));
- }
+ DEBUG(3,("Yielding connection to %s\n",name));
- DEBUG(3,("Yield successful\n"));
+ ZERO_STRUCT(key);
+ key.pid = getpid();
+ if (conn) key.cnum = conn->cnum;
+ fstrcpy(key.name, name);
- close(fd);
+ kbuf.dptr = (char *)&key;
+ kbuf.dsize = sizeof(key);
+
+ tdb_delete(tdb, kbuf);
+ tdb_close(tdb);
return(True);
}
/****************************************************************************
-simple routines to do connection counting
+claim an entry in the connections database
+****************************************************************************/
+int delete_dead(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
+{
+ struct connections_key key;
+ memcpy(&key, kbuf.dptr, sizeof(key));
+ if (!process_exists(key.pid)) tdb_delete(tdb, kbuf);
+ return 0;
+}
+
+
+/****************************************************************************
+claim an entry in the connections database
****************************************************************************/
BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear)
{
+ struct connections_key key;
+ struct connections_data crec;
+ TDB_DATA kbuf, dbuf;
+ TDB_CONTEXT *tdb;
extern int Client;
- struct connect_record crec;
- pstring fname;
- int fd=-1;
- int i,foundi= -1;
- int total_recs;
-
+
if (max_connections <= 0)
return(True);
- DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
-
- pstrcpy(fname,lp_lockdir());
- trim_string(fname,"","/");
-
- if (!directory_exist(fname,NULL))
- mkdir(fname,0755);
-
- pstrcat(fname,"/");
- pstrcat(fname,name);
- pstrcat(fname,".LCK");
-
- if (!file_exist(fname,NULL)) {
- fd = sys_open(fname,O_RDWR|O_CREAT|O_EXCL, 0644);
- }
+ if (!(tdb = open_db(name))) return False;
- if (fd == -1) {
- fd = sys_open(fname,O_RDWR,0);
- }
-
- if (fd == -1) {
- DEBUG(1,("couldn't open lock file %s\n",fname));
- return(False);
- }
+ DEBUG(5,("claiming %s %d\n",name,max_connections));
+
+ ZERO_STRUCT(key);
+ key.pid = getpid();
+ key.cnum = conn?conn->cnum:-1;
+ fstrcpy(key.name, name);
+
+ kbuf.dptr = (char *)&key;
+ kbuf.dsize = sizeof(key);
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) {
- DEBUG(0,("ERROR: can't get lock on %s\n", fname));
- return False;
+ if (Clear) {
+ tdb_traverse(tdb, delete_dead);
}
- total_recs = get_file_size(fname) / sizeof(crec);
-
- /* find a free spot */
- for (i=0;i<max_connections;i++) {
- if (i>=total_recs ||
- sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) ||
- read(fd,&crec,sizeof(crec)) != sizeof(crec)) {
- if (foundi < 0) foundi = i;
- break;
- }
-
- if (Clear && crec.pid && !process_exists(crec.pid)) {
- if(sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec)) {
- DEBUG(0,("claim_connection: ERROR: sys_lseek failed to seek \
-to %d\n", (int)(i*sizeof(crec)) ));
- continue;
- }
- memset((void *)&crec,'\0',sizeof(crec));
- write(fd, &crec,sizeof(crec));
- if (foundi < 0) foundi = i;
- continue;
- }
- if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) {
- foundi=i;
- if (!Clear) break;
- }
- }
-
- if (foundi < 0) {
- DEBUG(3,("no free locks in %s\n",fname));
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
- DEBUG(0,("ERROR: can't release lock on %s\n", fname));
- }
- close(fd);
- return(False);
- }
-
/* fill in the crec */
- memset((void *)&crec,'\0',sizeof(crec));
+ ZERO_STRUCT(crec);
crec.magic = 0x280267;
crec.pid = getpid();
+ crec.cnum = conn?conn->cnum:-1;
if (conn) {
- crec.cnum = conn->cnum;
crec.uid = conn->uid;
crec.gid = conn->gid;
StrnCpy(crec.name,
lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
- } else {
- crec.cnum = -1;
}
crec.start = time(NULL);
StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
- StrnCpy(crec.addr,client_addr(Client),sizeof(crec.addr)-1);
-
- /* make our mark */
- if (sys_lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) ||
- write(fd, &crec,sizeof(crec)) != sizeof(crec)) {
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
- DEBUG(0,("ERROR: can't release lock on %s\n", fname));
- }
- close(fd);
- return(False);
- }
+ StrnCpy(crec.addr,conn?conn->client_address:client_addr(Client),sizeof(crec.addr)-1);
- if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
- DEBUG(0,("ERROR: can't release lock on %s\n", fname));
- }
-
- close(fd);
- return(True);
+ dbuf.dptr = (char *)&crec;
+ dbuf.dsize = sizeof(crec);
+
+ if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) return False;
+
+ tdb_close(tdb);
+
+ return True;
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 54f646e091..aa7e95294d 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -123,7 +123,7 @@ int reply_special(char *inbuf,char *outbuf)
reopen_logs();
if (lp_status(-1)) {
- claim_connection(NULL,"STATUS.",MAXSTATUS,True);
+ claim_connection(NULL,"",MAXSTATUS,True);
}
break;
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 92807e2d43..ec723e13b9 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -458,7 +458,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
}
if (lp_status(SNUM(conn)))
- claim_connection(conn,"STATUS.",
+ claim_connection(conn,"",
MAXSTATUS,False);
} /* IS_IPC */
@@ -484,7 +484,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
lp_servicename(SNUM(conn)),
lp_max_connections(SNUM(conn)));
if (lp_status(SNUM(conn))) {
- yield_connection(conn,"STATUS.",MAXSTATUS);
+ yield_connection(conn,"",MAXSTATUS);
}
}
conn_free(conn);
@@ -501,7 +501,7 @@ connection_struct *make_connection(char *service,char *user,char *password, int
lp_servicename(SNUM(conn)),
lp_max_connections(SNUM(conn)));
if (lp_status(SNUM(conn)))
- yield_connection(conn,"STATUS.",MAXSTATUS);
+ yield_connection(conn,"",MAXSTATUS);
}
conn_free(conn);
*ecode = ERRinvnetname;
@@ -582,7 +582,7 @@ void close_cnum(connection_struct *conn, uint16 vuid)
lp_max_connections(SNUM(conn)));
if (lp_status(SNUM(conn)))
- yield_connection(conn,"STATUS.",MAXSTATUS);
+ yield_connection(conn,"",MAXSTATUS);
file_close_conn(conn);
dptr_closecnum(conn);
diff --git a/source3/tdb/README b/source3/tdb/README
index fc99a68acc..3c0059c5cb 100644
--- a/source3/tdb/README
+++ b/source3/tdb/README
@@ -11,7 +11,7 @@ Compilation
-----------
add HAVE_MMAP=1 to use mmap instead of read/write
-add TDB_DEBUG for verbose debug info
+add TDB_DEBUG=1 for verbose debug info
add NOLOCK=1 to disable locking code
Testing
@@ -21,6 +21,12 @@ Compile tdbtest.c and link with gdbm for testing. tdbtest will perform
identical operations via tdb and gdbm then make sure the result is the
same
+Also included is tdbtool, which allows simple database manipulation
+on the commandline.
+
+tdbtest and tdbtool are not built as part of Samba, but are included
+for completeness.
+
Interface
---------
@@ -31,3 +37,4 @@ The interface is very similar to gdbm except for the following:
- no tdbm_reorganise() function
- no tdbm_sync() function. No operations are cached in the library anyway
- added a tdb_traverse() function for traversing the whole database
+
diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c
index dacecf9572..01d2e740f7 100644
--- a/source3/tdb/tdb.c
+++ b/source3/tdb/tdb.c
@@ -102,10 +102,39 @@ static tdb_off tdb_hash_top(TDB_CONTEXT *tdb, unsigned hash)
return ret;
}
+
+/* check for an out of bounds access - if it is out of bounds then
+ see if the database has been expanded by someone else and expand
+ if necessary */
+static int tdb_oob(TDB_CONTEXT *tdb, tdb_off offset)
+{
+ struct stat st;
+ if (offset < tdb->map_size) return 0;
+
+ fstat(tdb->fd, &st);
+ if (st.st_size <= tdb->map_size) return -1;
+
+#if HAVE_MMAP
+ if (tdb->map_ptr) {
+ munmap(tdb->map_ptr, tdb->map_size);
+ tdb->map_ptr = NULL;
+ }
+#endif
+
+ tdb->map_size = st.st_size;
+#if HAVE_MMAP
+ tdb->map_ptr = (void *)mmap(NULL, tdb->map_size,
+ tdb->read_only?PROT_READ:PROT_READ|PROT_WRITE,
+ MAP_SHARED | MAP_FILE, tdb->fd, 0);
+#endif
+ return 0;
+}
+
+
/* write a lump of data at a specified offset */
static int tdb_write(TDB_CONTEXT *tdb, tdb_off offset, char *buf, tdb_len len)
{
- if (offset + len > tdb->map_size) {
+ if (tdb_oob(tdb, offset + len) != 0) {
/* oops - trying to write beyond the end of the database! */
#if TDB_DEBUG
printf("write error of length %u at offset %u (max %u)\n",
@@ -128,7 +157,7 @@ static int tdb_write(TDB_CONTEXT *tdb, tdb_off offset, char *buf, tdb_len len)
/* read a lump of data at a specified offset */
static int tdb_read(TDB_CONTEXT *tdb, tdb_off offset, char *buf, tdb_len len)
{
- if (offset + len > tdb->map_size) {
+ if (tdb_oob(tdb, offset + len) != 0) {
/* oops - trying to read beyond the end of the database! */
#if TDB_DEBUG
printf("read error of length %u at offset %u (max %u)\n",
@@ -514,6 +543,7 @@ int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
/* traverse the entire database - calling fn(tdb, key, data) on each element.
return -1 on error or the record count traversed
+ if fn is NULL then it is not called
a non-zero return value from fn() indicates that the traversal should stop
*/
int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf))
@@ -552,7 +582,7 @@ int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB
dbuf.dsize = rec.data_len;
count++;
- if (fn(tdb, key, dbuf) != 0) {
+ if (fn && fn(tdb, key, dbuf) != 0) {
/* they want us to stop traversing */
free(data);
return count;
@@ -915,9 +945,10 @@ TDB_CONTEXT *tdb_open(char *name, int hash_size, int flags, mode_t mode)
/* map the database and fill in the return structure */
tdb.name = (char *)strdup(name);
tdb.map_size = st.st_size;
+ tdb.read_only = ((flags & O_ACCMODE) == O_RDONLY);
#if HAVE_MMAP
tdb.map_ptr = (void *)mmap(NULL, st.st_size,
- (flags & O_ACCMODE) == O_RDONLY? PROT_READ : PROT_READ|PROT_WRITE,
+ tdb.read_only? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED | MAP_FILE, tdb.fd, 0);
#endif
tdb.header = header;
diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h
index 316338606b..111b804f71 100644
--- a/source3/tdb/tdb.h
+++ b/source3/tdb/tdb.h
@@ -39,6 +39,7 @@ typedef struct {
void *map_ptr; /* where it is currently mapped */
int fd; /* open file descriptor for the database */
tdb_len map_size; /* how much space has been mapped */
+ int read_only; /* opened read-only */
int write_locked; /* set if we have the db locked */
struct tdb_header header; /* a cached copy of the header */
} TDB_CONTEXT;
diff --git a/source3/utils/status.c b/source3/utils/status.c
index 2cbfbfdaf5..594783bd39 100644
--- a/source3/utils/status.c
+++ b/source3/utils/status.c
@@ -36,8 +36,6 @@
#include "includes.h"
-struct connect_record crec;
-
struct session_record{
pid_t pid;
uid_t uid;
@@ -50,12 +48,13 @@ extern int DEBUGLEVEL;
extern FILE *dbf;
static pstring Ucrit_username = ""; /* added by OH */
-pid_t Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
-int Ucrit_MaxPid=0; /* added by OH */
-unsigned int Ucrit_IsActive = 0; /* added by OH */
-
-int shares_only = 0; /* Added by RJS */
-int locks_only = 0; /* Added by RJS */
+static pid_t Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
+static int Ucrit_MaxPid=0; /* added by OH */
+static unsigned int Ucrit_IsActive = 0; /* added by OH */
+static int verbose, brief;
+static int shares_only = 0; /* Added by RJS */
+static int locks_only = 0; /* Added by RJS */
+static BOOL processes_only=False;
/* we need these because we link to locking*.o */
void become_root(BOOL save_dir) {}
@@ -161,197 +160,198 @@ static int profile_dump(void)
}
+static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
+{
+ static pid_t last_pid;
+ struct session_record *ptr;
+ struct connections_data crec;
+ static int doneone;
+
+ memcpy(&crec, dbuf.dptr, sizeof(crec));
+
+ if (crec.cnum == -1) return 0;
+
+ if (!process_exists(crec.pid) || !Ucrit_checkUsername(uidtoname(crec.uid))) {
+ return 0;
+ }
+
+ if (brief) {
+ if (!doneone) {
+ printf("\nSamba version %s\n",VERSION);
+ printf("PID Username Machine Time logged in\n");
+ printf("-------------------------------------------------------------------\n");
+ doneone = 1;
+ }
+
+ ptr=srecs;
+ while (ptr!=NULL) {
+ if ((ptr->pid==crec.pid)&&(strncmp(ptr->machine,crec.machine,30)==0)) {
+ if (ptr->start > crec.start)
+ ptr->start=crec.start;
+ break;
+ }
+ ptr=ptr->next;
+ }
+ if (ptr==NULL) {
+ ptr=(struct session_record *) malloc(sizeof(struct session_record));
+ ptr->uid=crec.uid;
+ ptr->pid=crec.pid;
+ ptr->start=crec.start;
+ strncpy(ptr->machine,crec.machine,30);
+ ptr->machine[30]='\0';
+ ptr->next=srecs;
+ srecs=ptr;
+ }
+ } else {
+ if (!doneone) {
+ printf("\nSamba version %s\n",VERSION);
+ printf("Service uid gid pid machine\n");
+ printf("----------------------------------------------\n");
+ doneone = 1;
+ }
+
+ Ucrit_addPid(crec.pid);
+ if (processes_only) {
+ if (last_pid != crec.pid)
+ printf("%d\n",(int)crec.pid);
+ last_pid = crec.pid; /* XXXX we can still get repeats, have to
+ add a sort at some time */
+ } else {
+ printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s",
+ crec.name,uidtoname(crec.uid),gidtoname(crec.gid),(int)crec.pid,
+ crec.machine,crec.addr,
+ asctime(LocalTime(&crec.start)));
+ }
+ }
+
+ return 0;
+}
+
+
+
int main(int argc, char *argv[])
{
- FILE *f;
- pstring fname;
- int c;
- static pstring servicesf = CONFIGFILE;
- extern char *optarg;
- int verbose = 0, brief =0;
- BOOL processes_only=False;
- pid_t last_pid=(pid_t)0;
- struct session_record *ptr;
- int profile_only = 0;
-
- TimeInit();
- setup_logging(argv[0],True);
-
- charset_initialise();
-
- DEBUGLEVEL = 0;
- dbf = stderr;
-
- if (getuid() != geteuid()) {
- printf("smbstatus should not be run setuid\n");
- return(1);
- }
-
- while ((c = getopt(argc, argv, "pdLSs:u:bP")) != EOF) {
- switch (c) {
- case 'b':
- brief = 1;
- break;
- case 'd':
- verbose = 1;
- break;
- case 'L':
- locks_only = 1;
- break;
- case 'p':
- processes_only = 1;
- break;
- case 'P':
- profile_only = 1;
- break;
- case 'S':
- shares_only = 1;
- break;
- case 's':
- pstrcpy(servicesf, optarg);
- break;
- case 'u': /* added by OH */
- Ucrit_addUsername(optarg); /* added by OH */
- break;
- default:
- fprintf(stderr, "Usage: %s [-P] [-d] [-L] [-p] [-S] [-s configfile] [-u username]\n", *argv); /* changed by OH */
- return (-1);
- }
- }
-
- if (!lp_load(servicesf,False,False,False)) {
- fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
- return (-1);
- }
-
- if (verbose) {
- printf("using configfile = %s\n", servicesf);
- printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL");
- }
-
- if (profile_only) {
- return profile_dump();
- }
-
- pstrcpy(fname,lp_lockdir());
- standard_sub_basic(fname);
- trim_string(fname,"","/");
- pstrcat(fname,"/STATUS..LCK");
-
- f = sys_fopen(fname,"r");
- if (!f) {
- printf("Couldn't open status file %s\n",fname);
- if (!lp_status(-1))
- printf("You need to have status=yes in your smb config file\n");
- return(0);
- }
- else if (verbose) {
- printf("Opened status file %s\n", fname);
- }
-
- if (!locks_only) {
-
- if (!processes_only) {
- printf("\nSamba version %s\n",VERSION);
-
- if (brief)
- {
- printf("PID Username Machine Time logged in\n");
- printf("-------------------------------------------------------------------\n");
- }
- else
- {
- printf("Service uid gid pid machine\n");
- printf("----------------------------------------------\n");
+ pstring fname;
+ int c;
+ static pstring servicesf = CONFIGFILE;
+ extern char *optarg;
+ int profile_only = 0;
+ TDB_CONTEXT *tdb;
+ struct session_record *ptr;
+
+ TimeInit();
+ setup_logging(argv[0],True);
+
+ charset_initialise();
+
+ DEBUGLEVEL = 0;
+ dbf = stderr;
+
+ if (getuid() != geteuid()) {
+ printf("smbstatus should not be run setuid\n");
+ return(1);
}
- }
-
- while (!feof(f))
- {
- if (fread(&crec,sizeof(crec),1,f) != 1)
- break;
- if (crec.cnum == -1) continue;
- if ( crec.magic == 0x280267 && process_exists(crec.pid)
- && Ucrit_checkUsername(uidtoname(crec.uid)) /* added by OH */
- )
- {
- if (brief)
- {
- ptr=srecs;
- while (ptr!=NULL)
- {
- if ((ptr->pid==crec.pid)&&(strncmp(ptr->machine,crec.machine,30)==0))
- {
- if (ptr->start > crec.start)
- ptr->start=crec.start;
+
+ while ((c = getopt(argc, argv, "pdLSs:u:bP")) != EOF) {
+ switch (c) {
+ case 'b':
+ brief = 1;
break;
- }
- ptr=ptr->next;
- }
- if (ptr==NULL)
- {
- ptr=(struct session_record *) malloc(sizeof(struct session_record));
- ptr->uid=crec.uid;
- ptr->pid=crec.pid;
- ptr->start=crec.start;
- strncpy(ptr->machine,crec.machine,30);
- ptr->machine[30]='\0';
- ptr->next=srecs;
- srecs=ptr;
- }
- }
- else
- {
- Ucrit_addPid(crec.pid); /* added by OH */
- if (processes_only) {
- if (last_pid != crec.pid)
- printf("%d\n",(int)crec.pid);
- last_pid = crec.pid; /* XXXX we can still get repeats, have to
- add a sort at some time */
+ case 'd':
+ verbose = 1;
+ break;
+ case 'L':
+ locks_only = 1;
+ break;
+ case 'p':
+ processes_only = 1;
+ break;
+ case 'P':
+ profile_only = 1;
+ break;
+ case 'S':
+ shares_only = 1;
+ break;
+ case 's':
+ pstrcpy(servicesf, optarg);
+ break;
+ case 'u': /* added by OH */
+ Ucrit_addUsername(optarg); /* added by OH */
+ break;
+ default:
+ fprintf(stderr, "Usage: %s [-P] [-d] [-L] [-p] [-S] [-s configfile] [-u username]\n", *argv); /* changed by OH */
+ return (-1);
}
- else
- printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s",
- crec.name,uidtoname(crec.uid),gidtoname(crec.gid),(int)crec.pid,
- crec.machine,crec.addr,
- asctime(LocalTime(&crec.start)));
- }
- }
- }
- fclose(f);
- }
- if (processes_only) exit(0);
+ }
+
+ if (!lp_load(servicesf,False,False,False)) {
+ fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
+ return (-1);
+ }
+
+ if (verbose) {
+ printf("using configfile = %s\n", servicesf);
+ printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL");
+ }
+
+ if (profile_only) {
+ return profile_dump();
+ }
+
+ pstrcpy(fname,lp_lockdir());
+ standard_sub_basic(fname);
+ trim_string(fname,"","/");
+ pstrcat(fname,"/connections.tdb");
+
+ tdb = tdb_open(fname, 0, O_RDONLY, 0);
+ if (!tdb) {
+ printf("Couldn't open status file %s\n",fname);
+ if (!lp_status(-1))
+ printf("You need to have status=yes in your smb config file\n");
+ return(0);
+ } else if (verbose) {
+ printf("Opened status file %s\n", fname);
+ }
+
+ if (locks_only) goto locks;
+
+ tdb_traverse(tdb, traverse_fn1);
+
+ locks:
+ if (processes_only) exit(0);
- if (brief)
- {
- ptr=srecs;
- while (ptr!=NULL)
- {
- printf("%-8d%-10.10s%-30.30s%s",(int)ptr->pid,uidtoname(ptr->uid),ptr->machine,asctime(LocalTime(&(ptr->start))));
- ptr=ptr->next;
- }
- printf("\n");
- exit(0);
- }
-
- printf("\n");
-
- if (!shares_only) {
- if (!locking_init(1)) {
- printf("Can't initialise shared memory - exiting\n");
- exit(1);
- }
+ if (brief) {
+ ptr=srecs;
+ while (ptr!=NULL) {
+ printf("%-8d%-10.10s%-30.30s%s",
+ (int)ptr->pid,uidtoname(ptr->uid),
+ ptr->machine,
+ asctime(LocalTime(&(ptr->start))));
+ ptr=ptr->next;
+ }
+ printf("\n");
+ exit(0);
+ }
+
+ printf("\n");
+
+ if (!shares_only) {
+ if (!locking_init(1)) {
+ printf("Can't initialise shared memory - exiting\n");
+ exit(1);
+ }
+
+ if (share_mode_forall(print_share_mode) <= 0)
+ printf("No locked files\n");
+
+ printf("\n");
+
+ share_status(stdout);
+
+ locking_end();
+ }
- if (share_mode_forall(print_share_mode) <= 0)
- printf("No locked files\n");
-
- printf("\n");
-
- share_status(stdout);
-
- locking_end();
- }
-
- return (0);
+ return (0);
}
diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c
index 304a122e23..8b7108c0b5 100644
--- a/source3/web/statuspage.c
+++ b/source3/web/statuspage.c
@@ -71,15 +71,68 @@ static void print_share_mode(share_mode_entry *e, char *fname)
}
+/* kill off any connections chosen by the user */
+static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
+{
+ struct connections_data crec;
+ memcpy(&crec, dbuf.dptr, sizeof(crec));
+
+ if (crec.cnum == -1 && process_exists(crec.pid)) {
+ char buf[30];
+ slprintf(buf,sizeof(buf)-1,"kill_%d", (int)crec.pid);
+ if (cgi_variable(buf)) {
+ kill_pid(crec.pid);
+ }
+ }
+ return 0;
+}
+
+/* traversal fn for showing machine connections */
+static int traverse_fn2(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
+{
+ struct connections_data crec;
+ memcpy(&crec, dbuf.dptr, sizeof(crec));
+
+ if (crec.cnum != -1 || !process_exists(crec.pid)) return 0;
+
+ printf("<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td>\n",
+ (int)crec.pid,
+ crec.machine,crec.addr,
+ tstring(crec.start));
+ if (geteuid() == 0) {
+ printf("<td><input type=submit value=\"X\" name=\"kill_%d\"></td>\n",
+ (int)crec.pid);
+ }
+ printf("</tr>\n");
+
+ return 0;
+}
+
+/* traversal fn for showing share connections */
+static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf)
+{
+ struct connections_data crec;
+ memcpy(&crec, dbuf.dptr, sizeof(crec));
+
+ if (crec.cnum != -1 || !process_exists(crec.pid)) return 0;
+
+ printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td></tr>\n",
+ crec.name,uidtoname(crec.uid),
+ gidtoname(crec.gid),(int)crec.pid,
+ crec.machine,
+ tstring(crec.start));
+ return 0;
+}
+
+
/* show the current server status */
void status_page(void)
{
- struct connect_record crec;
pstring fname;
- FILE *f;
char *v;
int autorefresh=0;
int refresh_interval=30;
+ TDB_CONTEXT *tdb;
if (cgi_variable("smbd_restart")) {
if (smbd_running())
@@ -123,24 +176,10 @@ void status_page(void)
pstrcpy(fname,lp_lockdir());
standard_sub_basic(fname);
trim_string(fname,"","/");
- pstrcat(fname,"/STATUS..LCK");
-
-
- f = sys_fopen(fname,"r");
- if (f) {
- while (!feof(f)) {
- if (fread(&crec,sizeof(crec),1,f) != 1) break;
- if (crec.magic == 0x280267 && crec.cnum == -1 &&
- process_exists(crec.pid)) {
- char buf[30];
- slprintf(buf,sizeof(buf)-1,"kill_%d", (int)crec.pid);
- if (cgi_variable(buf)) {
- kill_pid(crec.pid);
- }
- }
- }
- fclose(f);
- }
+ pstrcat(fname,"/connections.tdb");
+
+ tdb = tdb_open(fname, 0, O_RDONLY, 0);
+ if (tdb) tdb_traverse(tdb, traverse_fn1);
printf("<H2>Server Status</H2>\n");
@@ -159,8 +198,7 @@ void status_page(void)
printf("<p>\n");
- f = sys_fopen(fname,"r");
- if (!f) {
+ if (!tdb) {
/* open failure either means no connections have been
made or status=no */
if (!lp_status(-1))
@@ -207,44 +245,15 @@ void status_page(void)
}
printf("</tr>\n");
- while (f && !feof(f)) {
- if (fread(&crec,sizeof(crec),1,f) != 1)
- break;
- if (crec.magic == 0x280267 &&
- crec.cnum == -1 &&
- process_exists(crec.pid)) {
- printf("<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td>\n",
- (int)crec.pid,
- crec.machine,crec.addr,
- tstring(crec.start));
- if (geteuid() == 0) {
- printf("<td><input type=submit value=\"X\" name=\"kill_%d\"></td>\n",
- (int)crec.pid);
- }
- printf("</tr>\n");
- }
- }
+ if (tdb) tdb_traverse(tdb, traverse_fn2);
printf("</table><p>\n");
- if (f) fseek(f, 0, SEEK_SET);
-
printf("<p><h3>Active Shares</h3>\n");
printf("<table border=1>\n");
printf("<tr><th>Share</th><th>User</th><th>Group</th><th>PID</th><th>Client</th><th>Date</th></tr>\n\n");
- while (f && !feof(f)) {
- if (fread(&crec,sizeof(crec),1,f) != 1)
- break;
- if (crec.cnum == -1) continue;
- if (crec.magic == 0x280267 && process_exists(crec.pid)) {
- printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td></tr>\n",
- crec.name,uidtoname(crec.uid),
- gidtoname(crec.gid),(int)crec.pid,
- crec.machine,
- tstring(crec.start));
- }
- }
+ if (tdb) tdb_traverse(tdb, traverse_fn3);
printf("</table><p>\n");
@@ -257,7 +266,7 @@ void status_page(void)
locking_end();
printf("</table>\n");
- if (f) fclose(f);
+ tdb_close(tdb);
printf("</FORM>\n");