2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 12 aug 96: Erik.Devriendt@te6.siemens.be
22 added support for shared memory implementation of share mode locking
24 21-Jul-1998: rsharpe@ns.aus.com (Richard Sharpe)
25 Added -L (locks only) -S (shares only) flags and code
30 * This program reports current SMB connections
34 #include "lib/util/server_id.h"
35 #include "smbd/globals.h"
36 #include "system/filesys.h"
37 #include "lib/cmdline/cmdline.h"
38 #include "dbwrap/dbwrap.h"
39 #include "dbwrap/dbwrap_open.h"
40 #include "../libcli/security/security.h"
42 #include "locking/share_mode_lock.h"
43 #include "locking/proto.h"
45 #include "librpc/gen_ndr/open_files.h"
46 #include "smbd/smbd.h"
47 #include "librpc/gen_ndr/notify.h"
50 #include "status_profile.h"
52 #include "status_json.h"
53 #include "smbd/notifyd/notifyd_db.h"
54 #include "cmdline_contexts.h"
55 #include "locking/leases_db.h"
56 #include "lib/util/string_wrappers.h"
60 #include "audit_logging.h" /* various JSON helpers */
61 #include "auth/common_auth.h"
62 #endif /* HAVE_JANSSON */
64 #define SMB_MAXPIDS 2048
65 static uid_t Ucrit_uid
= 0; /* added by OH */
66 static struct server_id Ucrit_pid
[SMB_MAXPIDS
]; /* Ugly !!! */ /* added by OH */
67 static int Ucrit_MaxPid
=0; /* added by OH */
68 static unsigned int Ucrit_IsActive
= 0; /* added by OH */
70 static bool verbose
, brief
;
71 static bool shares_only
; /* Added by RJS */
72 static bool locks_only
; /* Added by RJS */
73 static bool processes_only
;
75 static bool numeric_only
;
76 static bool do_checks
= true;
78 const char *username
= NULL
;
81 static void Ucrit_addUid(uid_t uid
)
87 static unsigned int Ucrit_checkUid(uid_t uid
)
89 if ( !Ucrit_IsActive
)
92 if ( uid
== Ucrit_uid
)
98 static unsigned int Ucrit_checkPid(struct server_id pid
)
102 if ( !Ucrit_IsActive
)
105 for (i
=0;i
<Ucrit_MaxPid
;i
++) {
106 if (server_id_equal(&pid
, &Ucrit_pid
[i
])) {
114 static bool Ucrit_addPid( struct server_id pid
)
116 if ( !Ucrit_IsActive
)
119 if ( Ucrit_MaxPid
>= SMB_MAXPIDS
) {
120 fprintf(stderr
, "ERROR: More than %d pids for user %s!\n",
121 SMB_MAXPIDS
, uidtoname(Ucrit_uid
));
126 Ucrit_pid
[Ucrit_MaxPid
++] = pid
;
131 static int print_share_mode_stdout(struct traverse_state
*state
,
133 const char *user_name
,
134 const char *denymode
,
138 const char *servicepath
,
139 const char *filename
,
143 d_printf("\nLocked files:\n");
144 d_printf("Pid User(ID) DenyMode Access R/W Oplock SharePath Name Time\n");
145 d_printf("--------------------------------------------------------------------------------------------------\n");
147 state
->first
= false;
150 d_printf("%-11s %-9s %-10s 0x%-8x %-10s %-14s %s %s %s",
151 pid
, user_name
, denymode
, access_mask
, rw
, oplock
,
152 servicepath
, filename
, timestr
);
156 static int prepare_share_mode(struct traverse_state
*state
)
158 if (!state
->json_output
) {
159 /* only print header line if there are open files */
162 add_section_to_json(state
, "open_files");
167 static int print_share_mode(struct file_id fid
,
168 const struct share_mode_data
*d
,
169 const struct share_mode_entry
*e
,
172 const char *denymode
= NULL
;
174 const char *oplock
= NULL
;
175 const char *pid
= NULL
;
176 const char *rw
= NULL
;
177 const char *filename
= NULL
;
178 const char *timestr
= NULL
;
179 const char *user_str
= NULL
;
181 struct traverse_state
*state
= (struct traverse_state
*)private_data
;
183 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
184 if (tmp_ctx
== NULL
) {
188 if (do_checks
&& !is_valid_share_mode_entry(e
)) {
189 TALLOC_FREE(tmp_ctx
);
193 if (do_checks
&& !serverid_exists(&e
->pid
)) {
194 /* the process for this entry does not exist any more */
195 TALLOC_FREE(tmp_ctx
);
199 if (Ucrit_checkPid(e
->pid
)) {
200 struct server_id_buf tmp
;
201 pid
= server_id_str_buf(e
->pid
, &tmp
);
202 if (state
->resolve_uids
) {
203 user_str
= talloc_asprintf(tmp_ctx
, "%s", uidtoname(e
->uid
));
205 user_str
= talloc_asprintf(tmp_ctx
, "%u", (unsigned int)e
->uid
);
207 if (user_str
== NULL
) {
208 TALLOC_FREE(tmp_ctx
);
212 denymode_int
= map_share_mode_to_deny_mode(e
->share_access
,
214 switch (denymode_int
) {
216 denymode
= "DENY_NONE";
219 denymode
= "DENY_ALL";
222 denymode
= "DENY_DOS";
225 denymode
= "DENY_READ";
228 denymode
= "DENY_WRITE";
231 denymode
= "DENY_FCB";
234 denymode
= talloc_asprintf(tmp_ctx
,
237 if (denymode
== NULL
) {
238 TALLOC_FREE(tmp_ctx
);
242 "unknown-please report ! "
243 "e->share_access = 0x%x, "
244 "e->private_options = 0x%x\n",
245 (unsigned int)e
->share_access
,
246 (unsigned int)e
->private_options
);
250 filename
= talloc_asprintf(tmp_ctx
,
253 (d
->stream_name
!= NULL
) ? d
->stream_name
: "");
254 if (filename
== NULL
) {
255 TALLOC_FREE(tmp_ctx
);
258 if ((e
->access_mask
& (FILE_READ_DATA
|FILE_WRITE_DATA
))==
259 (FILE_READ_DATA
|FILE_WRITE_DATA
)) {
261 } else if (e
->access_mask
& FILE_WRITE_DATA
) {
267 if (e
->op_type
& BATCH_OPLOCK
) {
269 } else if (e
->op_type
& EXCLUSIVE_OPLOCK
) {
270 oplock
= "EXCLUSIVE";
271 } else if (e
->op_type
& LEVEL_II_OPLOCK
) {
273 } else if (e
->op_type
== LEASE_OPLOCK
) {
276 status
= leases_db_get(
280 &lstate
, /* current_state */
282 NULL
, /* breaking_to_requested */
283 NULL
, /* breaking_to_required */
284 NULL
, /* lease_version */
287 if (NT_STATUS_IS_OK(status
)) {
288 oplock
= talloc_asprintf(tmp_ctx
, "LEASE(%s%s%s)%s%s%s",
289 (lstate
& SMB2_LEASE_READ
)?"R":"",
290 (lstate
& SMB2_LEASE_WRITE
)?"W":"",
291 (lstate
& SMB2_LEASE_HANDLE
)?"H":"",
292 (lstate
& SMB2_LEASE_READ
)?"":" ",
293 (lstate
& SMB2_LEASE_WRITE
)?"":" ",
294 (lstate
& SMB2_LEASE_HANDLE
)?"":" ");
296 oplock
= "LEASE STATE UNKNOWN";
302 timestr
= time_to_asc((time_t)e
->time
.tv_sec
);
304 if (!state
->json_output
) {
305 print_share_mode_stdout(state
,
309 (unsigned int)e
->access_mask
,
316 print_share_mode_json(state
,
326 TALLOC_FREE(tmp_ctx
);
330 static void print_brl_stdout(struct traverse_state
*state
,
336 const char *sharepath
,
340 d_printf("Byte range locks:\n");
341 d_printf("Pid dev:inode R/W start size SharePath Name\n");
342 d_printf("--------------------------------------------------------------------------------\n");
344 state
->first
= false;
346 d_printf("%-10s %-15s %-4s %-9jd %-9jd %-24s %-24s\n",
347 pid
, id
, desc
, start
, size
, sharepath
, fname
);
350 static int prepare_brl(struct traverse_state
*state
)
352 if (!state
->json_output
) {
353 /* only print header line if there are locked files */
356 add_section_to_json(state
, "byte_range_locks");
361 static void print_brl(struct file_id id
,
362 struct server_id pid
,
363 enum brl_type lock_type
,
364 enum brl_flavour lock_flav
,
370 static const struct {
371 enum brl_type lock_type
;
378 const char *desc
="X";
379 const char *sharepath
= "";
381 struct share_mode_lock
*share_mode
;
382 struct server_id_buf tmp
;
383 struct file_id_buf ftmp
;
384 struct traverse_state
*state
= (struct traverse_state
*)private_data
;
386 share_mode
= fetch_share_mode_unlocked(NULL
, id
);
388 fname
= share_mode_filename(NULL
, share_mode
);
389 sharepath
= share_mode_servicepath(share_mode
);
391 fname
= talloc_strdup(NULL
, "");
397 for (i
=0;i
<ARRAY_SIZE(lock_types
);i
++) {
398 if (lock_type
== lock_types
[i
].lock_type
) {
399 desc
= lock_types
[i
].desc
;
403 if (!state
->json_output
) {
404 print_brl_stdout(state
,
405 server_id_str_buf(pid
, &tmp
),
406 file_id_str_buf(id
, &ftmp
),
413 print_brl_json(state
,
426 TALLOC_FREE(share_mode
);
429 static const char *session_dialect_str(uint16_t dialect
)
431 static fstring unknown_dialect
;
434 case SMB2_DIALECT_REVISION_000
:
436 case SMB2_DIALECT_REVISION_202
:
438 case SMB2_DIALECT_REVISION_210
:
440 case SMB2_DIALECT_REVISION_222
:
442 case SMB2_DIALECT_REVISION_224
:
444 case SMB3_DIALECT_REVISION_300
:
446 case SMB3_DIALECT_REVISION_302
:
448 case SMB3_DIALECT_REVISION_310
:
450 case SMB3_DIALECT_REVISION_311
:
454 fstr_sprintf(unknown_dialect
, "Unknown (0x%04x)", dialect
);
455 return unknown_dialect
;
458 static int traverse_connections_stdout(struct traverse_state
*state
,
459 const char *servicename
,
463 const char *encryption
,
466 d_printf("%-12s %-7s %-13s %-32s %-12s %-12s\n",
467 servicename
, server_id
, machine
, timestr
, encryption
, signing
);
472 static int prepare_connections(struct traverse_state
*state
)
474 if (!state
->json_output
) {
475 /* always print header line */
476 d_printf("\n%-12s %-7s %-13s %-32s %-12s %-12s\n", "Service", "pid", "Machine", "Connected at", "Encryption", "Signing");
477 d_printf("---------------------------------------------------------------------------------------------\n");
479 add_section_to_json(state
, "tcons");
484 static int traverse_connections(const struct connections_data
*crec
,
487 struct server_id_buf tmp
;
488 char *timestr
= NULL
;
490 const char *encryption
= "-";
491 enum crypto_degree encryption_degree
= CRYPTO_DEGREE_NONE
;
492 const char *signing
= "-";
493 enum crypto_degree signing_degree
= CRYPTO_DEGREE_NONE
;
494 struct traverse_state
*state
= (struct traverse_state
*)private_data
;
496 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
497 if (tmp_ctx
== NULL
) {
501 if (crec
->cnum
== TID_FIELD_INVALID
) {
502 TALLOC_FREE(tmp_ctx
);
507 (!process_exists(crec
->pid
) || !Ucrit_checkUid(crec
->uid
))) {
508 TALLOC_FREE(tmp_ctx
);
512 timestr
= timestring(tmp_ctx
, nt_time_to_unix(crec
->start
));
513 if (timestr
== NULL
) {
514 TALLOC_FREE(tmp_ctx
);
518 if (smbXsrv_is_encrypted(crec
->encryption_flags
)) {
519 switch (crec
->cipher
) {
520 case SMB_ENCRYPTION_GSSAPI
:
521 encryption
= "GSSAPI";
523 case SMB2_ENCRYPTION_AES128_CCM
:
524 encryption
= "AES-128-CCM";
526 case SMB2_ENCRYPTION_AES128_GCM
:
527 encryption
= "AES-128-GCM";
534 encryption_degree
= CRYPTO_DEGREE_FULL
;
537 if (smbXsrv_is_signed(crec
->signing_flags
)) {
538 switch (crec
->signing
) {
539 case SMB2_SIGNING_MD5_SMB1
:
540 signing
= "HMAC-MD5";
542 case SMB2_SIGNING_HMAC_SHA256
:
543 signing
= "HMAC-SHA256";
545 case SMB2_SIGNING_AES128_CMAC
:
546 signing
= "AES-128-CMAC";
548 case SMB2_SIGNING_AES128_GMAC
:
549 signing
= "AES-128-GMAC";
556 signing_degree
= CRYPTO_DEGREE_FULL
;
559 if (!state
->json_output
) {
560 result
= traverse_connections_stdout(state
,
562 server_id_str_buf(crec
->pid
, &tmp
),
568 result
= traverse_connections_json(state
,
576 TALLOC_FREE(timestr
);
577 TALLOC_FREE(tmp_ctx
);
582 static int traverse_sessionid_stdout(struct traverse_state
*state
,
585 char *machine_hostname
,
587 const char *encryption_cipher
,
588 enum crypto_degree encryption_degree
,
589 const char *signing_cipher
,
590 enum crypto_degree signing_degree
)
595 if (encryption_degree
== CRYPTO_DEGREE_FULL
) {
596 fstr_sprintf(encryption
, "%s", encryption_cipher
);
597 } else if (encryption_degree
== CRYPTO_DEGREE_PARTIAL
) {
598 fstr_sprintf(encryption
, "partial(%s)", encryption_cipher
);
600 fstr_sprintf(encryption
, "-");
602 if (signing_degree
== CRYPTO_DEGREE_FULL
) {
603 fstr_sprintf(signing
, "%s", signing_cipher
);
604 } else if (signing_degree
== CRYPTO_DEGREE_PARTIAL
) {
605 fstr_sprintf(signing
, "partial(%s)", signing_cipher
);
607 fstr_sprintf(signing
, "-");
610 d_printf("%-7s %-25s %-41s %-17s %-20s %-21s\n",
611 server_id
, uid_gid_str
, machine_hostname
, dialect
, encryption
,
617 static int prepare_sessionid(struct traverse_state
*state
)
619 if (!state
->json_output
) {
620 /* always print header line */
621 d_printf("\nSamba version %s\n",samba_version_string());
622 d_printf("%-7s %-12s %-12s %-41s %-17s %-20s %-21s\n", "PID", "Username", "Group", "Machine", "Protocol Version", "Encryption", "Signing");
623 d_printf("----------------------------------------------------------------------------------------------------------------------------------------\n");
625 add_section_to_json(state
, "sessions");
631 static int traverse_sessionid(const char *key
, struct sessionid
*session
,
637 struct server_id_buf tmp
;
638 char *machine_hostname
= NULL
;
640 const char *encryption
= "-";
641 enum crypto_degree encryption_degree
= CRYPTO_DEGREE_NONE
;
642 const char *signing
= "-";
643 enum crypto_degree signing_degree
= CRYPTO_DEGREE_NONE
;
644 struct traverse_state
*state
= (struct traverse_state
*)private_data
;
646 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
647 if (tmp_ctx
== NULL
) {
652 (!process_exists(session
->pid
) ||
653 !Ucrit_checkUid(session
->uid
))) {
654 TALLOC_FREE(tmp_ctx
);
658 Ucrit_addPid(session
->pid
);
661 fstr_sprintf(gid_str
, "%u", (unsigned int)session
->gid
);
662 fstr_sprintf(uid_str
, "%u", (unsigned int)session
->uid
);
663 fstr_sprintf(uid_gid_str
, "%-12u %-12u",
664 (unsigned int)session
->uid
,
665 (unsigned int)session
->gid
);
667 if (session
->uid
== -1 && session
->gid
== -1) {
669 * The session is not fully authenticated yet.
671 fstrcpy(uid_gid_str
, "(auth in progress)");
672 fstrcpy(gid_str
, "(auth in progress)");
673 fstrcpy(uid_str
, "(auth in progress)");
676 * In theory it should not happen that one of
677 * session->uid and session->gid is valid (ie != -1)
678 * while the other is not (ie = -1), so we a check for
679 * that case that bails out would be reasonable.
681 const char *uid_name
= "-1";
682 const char *gid_name
= "-1";
684 if (session
->uid
!= -1) {
685 uid_name
= uidtoname(session
->uid
);
686 if (uid_name
== NULL
) {
687 TALLOC_FREE(tmp_ctx
);
691 if (session
->gid
!= -1) {
692 gid_name
= gidtoname(session
->gid
);
693 if (gid_name
== NULL
) {
694 TALLOC_FREE(tmp_ctx
);
698 fstr_sprintf(gid_str
, "%s", gid_name
);
699 fstr_sprintf(uid_str
, "%s", uid_name
);
700 fstr_sprintf(uid_gid_str
, "%-12s %-12s",
705 machine_hostname
= talloc_asprintf(tmp_ctx
, "%s (%s)",
706 session
->remote_machine
,
708 if (machine_hostname
== NULL
) {
709 TALLOC_FREE(tmp_ctx
);
713 if (smbXsrv_is_encrypted(session
->encryption_flags
) ||
714 smbXsrv_is_partially_encrypted(session
->encryption_flags
)) {
715 switch (session
->cipher
) {
716 case SMB2_ENCRYPTION_AES128_CCM
:
717 encryption
= "AES-128-CCM";
719 case SMB2_ENCRYPTION_AES128_GCM
:
720 encryption
= "AES-128-GCM";
722 case SMB2_ENCRYPTION_AES256_CCM
:
723 encryption
= "AES-256-CCM";
725 case SMB2_ENCRYPTION_AES256_GCM
:
726 encryption
= "AES-256-GCM";
733 if (smbXsrv_is_encrypted(session
->encryption_flags
)) {
734 encryption_degree
= CRYPTO_DEGREE_FULL
;
735 } else if (smbXsrv_is_partially_encrypted(session
->encryption_flags
)) {
736 encryption_degree
= CRYPTO_DEGREE_PARTIAL
;
740 if (smbXsrv_is_signed(session
->signing_flags
) ||
741 smbXsrv_is_partially_signed(session
->signing_flags
)) {
742 switch (session
->signing
) {
743 case SMB2_SIGNING_MD5_SMB1
:
744 signing
= "HMAC-MD5";
746 case SMB2_SIGNING_HMAC_SHA256
:
747 signing
= "HMAC-SHA256";
749 case SMB2_SIGNING_AES128_CMAC
:
750 signing
= "AES-128-CMAC";
752 case SMB2_SIGNING_AES128_GMAC
:
753 signing
= "AES-128-GMAC";
760 if (smbXsrv_is_signed(session
->signing_flags
)) {
761 signing_degree
= CRYPTO_DEGREE_FULL
;
762 } else if (smbXsrv_is_partially_signed(session
->signing_flags
)) {
763 signing_degree
= CRYPTO_DEGREE_PARTIAL
;
768 if (!state
->json_output
) {
769 traverse_sessionid_stdout(state
,
770 server_id_str_buf(session
->pid
, &tmp
),
773 session_dialect_str(session
->connection_dialect
),
779 result
= traverse_sessionid_json(state
,
787 session_dialect_str(session
->connection_dialect
));
790 TALLOC_FREE(machine_hostname
);
791 TALLOC_FREE(tmp_ctx
);
797 static bool print_notify_rec_stdout(struct traverse_state
*state
,
801 unsigned subdir_filter
)
803 d_printf("%s\\%s\\%x\\%x\n", path
, server_id_str
,
804 filter
, subdir_filter
);
809 static int prepare_notify(struct traverse_state
*state
)
811 if (!state
->json_output
) {
812 /* don't print header line */
814 add_section_to_json(state
, "notifies");
819 static bool print_notify_rec(const char *path
, struct server_id server
,
820 const struct notify_instance
*instance
,
823 struct server_id_buf idbuf
;
824 struct traverse_state
*state
= (struct traverse_state
*)private_data
;
827 if (!state
->json_output
) {
828 result
= print_notify_rec_stdout(state
,
830 server_id_str_buf(server
, &idbuf
),
831 (unsigned)instance
->filter
,
832 (unsigned)instance
->subdir_filter
);
835 result
= print_notify_rec_json(state
,
845 OPT_RESOLVE_UIDS
= 1000,
848 int main(int argc
, const char *argv
[])
851 int profile_only
= 0;
852 bool show_processes
, show_locks
, show_shares
;
853 bool show_notify
= false;
854 poptContext pc
= NULL
;
855 struct traverse_state state
= {0};
856 struct poptOption long_options
[] = {
859 .longName
= "processes",
861 .argInfo
= POPT_ARG_NONE
,
864 .descrip
= "Show processes only",
867 .longName
= "verbose",
869 .argInfo
= POPT_ARG_NONE
,
872 .descrip
= "Be verbose",
877 .argInfo
= POPT_ARG_NONE
,
880 .descrip
= "Show locks only",
883 .longName
= "shares",
885 .argInfo
= POPT_ARG_NONE
,
888 .descrip
= "Show shares only",
891 .longName
= "notify",
893 .argInfo
= POPT_ARG_NONE
,
896 .descrip
= "Show notifies",
901 .argInfo
= POPT_ARG_STRING
,
904 .descrip
= "Switch to user",
909 .argInfo
= POPT_ARG_NONE
,
912 .descrip
= "Be brief",
915 .longName
= "profile",
917 .argInfo
= POPT_ARG_NONE
,
920 .descrip
= "Do profiling",
923 .longName
= "profile-rates",
925 .argInfo
= POPT_ARG_NONE
,
928 .descrip
= "Show call rates",
931 .longName
= "byterange",
933 .argInfo
= POPT_ARG_NONE
,
936 .descrip
= "Include byte range locks"
939 .longName
= "numeric",
941 .argInfo
= POPT_ARG_NONE
,
944 .descrip
= "Numeric uid/gid"
949 .argInfo
= POPT_ARG_NONE
,
952 .descrip
= "JSON output"
957 .argInfo
= POPT_ARG_NONE
,
960 .descrip
= "Skip checks if processes still exist"
963 .longName
= "resolve-uids",
965 .argInfo
= POPT_ARG_NONE
,
967 .val
= OPT_RESOLVE_UIDS
,
968 .descrip
= "Try to resolve UIDs to usernames"
974 TALLOC_CTX
*frame
= talloc_stackframe();
976 struct messaging_context
*msg_ctx
= NULL
;
981 state
.json_output
= false;
982 state
.resolve_uids
= false;
986 ok
= samba_cmdline_init(frame
,
987 SAMBA_CMDLINE_CONFIG_CLIENT
,
988 false /* require_smbconf */);
990 DBG_ERR("Failed to init cmdline parser!\n");
994 lp_set_cmdline("log level", "0");
996 pc
= samba_popt_get_context(getprogname(),
1000 POPT_CONTEXT_KEEP_FIRST
);
1002 DBG_ERR("Failed to setup popt context!\n");
1007 while ((c
= poptGetNextOpt(pc
)) != -1) {
1010 processes_only
= true;
1028 Ucrit_addUid(nametouid(poptGetOptArg(pc
)));
1038 numeric_only
= true;
1041 state
.json_output
= true;
1046 case OPT_RESOLVE_UIDS
:
1047 state
.resolve_uids
= true;
1049 case POPT_ERROR_BADOPT
:
1050 fprintf(stderr
, "\nInvalid option %s: %s\n\n",
1051 poptBadOption(pc
, 0), poptStrerror(c
));
1052 poptPrintUsage(pc
, stderr
, 0);
1060 state
.root_json
= json_new_object();
1061 add_general_information_to_json(&state
);
1062 #else /* HAVE_JANSSON */
1063 if (state
.json_output
) {
1064 fprintf(stderr
, "JSON support not available, please install lib Jansson\n");
1067 #endif /* HAVE_JANSSON */
1069 if (getuid() != geteuid()) {
1070 fprintf(stderr
, "smbstatus should not be run setuid\n");
1075 if (getuid() != 0) {
1076 fprintf(stderr
, "smbstatus only works as root!\n");
1081 /* setup the flags based on the possible combincations */
1083 show_processes
= !(shares_only
|| locks_only
|| profile_only
) || processes_only
;
1084 show_locks
= !(shares_only
|| processes_only
|| profile_only
) || locks_only
;
1085 show_shares
= !(processes_only
|| locks_only
|| profile_only
) || shares_only
;
1088 Ucrit_addUid( nametouid(username
) );
1090 if (verbose
&& !state
.json_output
) {
1091 d_printf("using configfile = %s\n", get_dyn_CONFIGFILE());
1094 msg_ctx
= cmdline_messaging_context(get_dyn_CONFIGFILE());
1095 if (msg_ctx
== NULL
) {
1096 fprintf(stderr
, "Could not initialize messaging, not root?\n");
1101 switch (profile_only
) {
1103 /* Dump profile data */
1104 ok
= status_profile_dump(verbose
, &state
);
1108 /* Continuously display rate-converted data */
1109 if (!state
.json_output
) {
1110 ok
= status_profile_rates(verbose
);
1113 fprintf(stderr
, "Call rates not available in a json output.\n");
1121 if ( show_processes
) {
1122 prepare_sessionid(&state
);
1123 sessionid_traverse_read(traverse_sessionid
, &state
);
1125 if (processes_only
) {
1130 if ( show_shares
) {
1134 prepare_connections(&state
);
1135 connections_forall_read(traverse_connections
, &state
);
1137 if (!state
.json_output
) {
1141 if ( shares_only
) {
1148 struct db_context
*db
;
1150 db_path
= lock_path(talloc_tos(), "locking.tdb");
1151 if (db_path
== NULL
) {
1152 fprintf(stderr
, "Out of memory - exiting\n");
1157 db
= db_open(NULL
, db_path
, 0,
1158 TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
, O_RDONLY
, 0,
1159 DBWRAP_LOCK_ORDER_1
, DBWRAP_FLAG_NONE
);
1162 fprintf(stderr
, "%s not initialised\n", db_path
);
1163 fprintf(stderr
, "This is normal if an SMB client has never "
1164 "connected to your server.\n");
1165 TALLOC_FREE(db_path
);
1169 TALLOC_FREE(db_path
);
1172 if (!locking_init_readonly()) {
1173 fprintf(stderr
, "Can't initialise locking module - exiting\n");
1178 prepare_share_mode(&state
);
1179 result
= share_entry_forall(print_share_mode
, &state
);
1181 if (result
== 0 && !state
.json_output
) {
1182 fprintf(stderr
, "No locked files\n");
1183 } else if (result
< 0 && !state
.json_output
) {
1184 fprintf(stderr
, "locked file list truncated\n");
1187 if (!state
.json_output
) {
1192 prepare_brl(&state
);
1193 brl_forall(print_brl
, &state
);
1200 prepare_notify(&state
);
1201 notify_walk(msg_ctx
, print_notify_rec
, &state
);
1205 cmdline_messaging_context_free();
1206 poptFreeContext(pc
);
1208 if (state
.json_output
) {
1209 d_printf("%s\n", json_to_string(frame
, &state
.root_json
));
1211 json_free(&state
.root_json
);
1212 #endif /* HAVE_JANSSON */