From 69d24d869bf97978b31a51fe8e8d08cac4874d67 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Dec 1999 04:54:30 +0000 Subject: 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) --- source3/include/proto.h | 6 + source3/include/smb.h | 28 ++-- source3/script/mkproto.awk | 4 + source3/smbd/connection.c | 225 +++++++++----------------- source3/smbd/reply.c | 2 +- source3/smbd/service.c | 8 +- source3/tdb/README | 9 +- source3/tdb/tdb.c | 39 ++++- source3/tdb/tdb.h | 1 + source3/utils/status.c | 384 ++++++++++++++++++++++----------------------- source3/web/statuspage.c | 117 +++++++------- 11 files changed, 400 insertions(+), 423 deletions(-) (limited to 'source3') 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;icnum) - 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=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("%d%s%s%s\n", + (int)crec.pid, + crec.machine,crec.addr, + tstring(crec.start)); + if (geteuid() == 0) { + printf("\n", + (int)crec.pid); + } + printf("\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("%s%s%s%d%s%s\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("

Server Status

\n"); @@ -159,8 +198,7 @@ void status_page(void) printf("

\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("\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("%d%s%s%s\n", - (int)crec.pid, - crec.machine,crec.addr, - tstring(crec.start)); - if (geteuid() == 0) { - printf("\n", - (int)crec.pid); - } - printf("\n"); - } - } + if (tdb) tdb_traverse(tdb, traverse_fn2); printf("

\n"); - if (f) fseek(f, 0, SEEK_SET); - printf("

Active Shares

\n"); printf("\n"); printf("\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("\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("
ShareUserGroupPIDClientDate
%s%s%s%d%s%s

\n"); @@ -257,7 +266,7 @@ void status_page(void) locking_end(); printf("\n"); - if (f) fclose(f); + tdb_close(tdb); printf("\n"); -- cgit