1/* 2 Samba Unix/Linux SMB client library 3 net status command -- possible replacement for smbstatus 4 Copyright (C) 2003 Volker Lendecke (vl@samba.org) 5 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. 10 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. 15 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/>. */ 18 19#include "includes.h" 20#include "utils/net.h" 21 22int net_status_usage(struct net_context *c, int argc, const char **argv) 23{ 24 d_printf(_(" net status sessions [parseable] " 25 "Show list of open sessions\n")); 26 d_printf(_(" net status shares [parseable] " 27 "Show list of open shares\n")); 28 return -1; 29} 30 31static int show_session(struct db_record *rec, void *private_data) 32{ 33 bool *parseable = (bool *)private_data; 34 struct sessionid sessionid; 35 36 if (rec->value.dsize != sizeof(sessionid)) 37 return 0; 38 39 memcpy(&sessionid, rec->value.dptr, sizeof(sessionid)); 40 41 if (!process_exists(sessionid.pid)) { 42 return 0; 43 } 44 45 if (*parseable) { 46 d_printf("%s\\%s\\%s\\%s\\%s\n", 47 procid_str_static(&sessionid.pid), uidtoname(sessionid.uid), 48 gidtoname(sessionid.gid), 49 sessionid.remote_machine, sessionid.hostname); 50 } else { 51 d_printf("%7s %-12s %-12s %-12s (%s)\n", 52 procid_str_static(&sessionid.pid), uidtoname(sessionid.uid), 53 gidtoname(sessionid.gid), 54 sessionid.remote_machine, sessionid.hostname); 55 } 56 57 return 0; 58} 59 60static int net_status_sessions(struct net_context *c, int argc, const char **argv) 61{ 62 struct db_context *db; 63 bool parseable; 64 65 if (c->display_usage) { 66 d_printf( "%s\n" 67 "net status sessions [parseable]\n" 68 " %s\n", 69 _("Usage:"), 70 _("Display open user sessions.\n" 71 " If parseable is specified, output is machine-" 72 "readable.")); 73 return 0; 74 } 75 76 if (argc == 0) { 77 parseable = false; 78 } else if ((argc == 1) && strequal(argv[0], "parseable")) { 79 parseable = true; 80 } else { 81 return net_status_usage(c, argc, argv); 82 } 83 84 if (!parseable) { 85 d_printf(_("PID Username Group Machine" 86 " \n" 87 "-------------------------------------------" 88 "------------------------\n")); 89 } 90 91 db = db_open(NULL, lock_path("sessionid.tdb"), 0, 92 TDB_CLEAR_IF_FIRST, O_RDONLY, 0644); 93 if (db == NULL) { 94 d_fprintf(stderr, _("%s not initialised\n"), 95 lock_path("sessionid.tdb")); 96 return -1; 97 } 98 99 db->traverse_read(db, show_session, &parseable); 100 TALLOC_FREE(db); 101 102 return 0; 103} 104 105static int show_share(struct db_record *rec, 106 const struct connections_key *key, 107 const struct connections_data *crec, 108 void *state) 109{ 110 if (crec->cnum == -1) 111 return 0; 112 113 if (!process_exists(crec->pid)) { 114 return 0; 115 } 116 117 d_printf("%-10.10s %s %-12s %s", 118 crec->servicename, procid_str_static(&crec->pid), 119 crec->machine, 120 time_to_asc(crec->start)); 121 122 return 0; 123} 124 125struct sessionids { 126 int num_entries; 127 struct sessionid *entries; 128}; 129 130static int collect_pid(struct db_record *rec, void *private_data) 131{ 132 struct sessionids *ids = (struct sessionids *)private_data; 133 struct sessionid sessionid; 134 135 if (rec->value.dsize != sizeof(sessionid)) 136 return 0; 137 138 memcpy(&sessionid, rec->value.dptr, sizeof(sessionid)); 139 140 if (!process_exists(sessionid.pid)) 141 return 0; 142 143 ids->num_entries += 1; 144 ids->entries = SMB_REALLOC_ARRAY(ids->entries, struct sessionid, ids->num_entries); 145 if (!ids->entries) { 146 ids->num_entries = 0; 147 return 0; 148 } 149 ids->entries[ids->num_entries-1] = sessionid; 150 151 return 0; 152} 153 154static int show_share_parseable(struct db_record *rec, 155 const struct connections_key *key, 156 const struct connections_data *crec, 157 void *state) 158{ 159 struct sessionids *ids = (struct sessionids *)state; 160 int i; 161 bool guest = true; 162 163 if (crec->cnum == -1) 164 return 0; 165 166 if (!process_exists(crec->pid)) { 167 return 0; 168 } 169 170 for (i=0; i<ids->num_entries; i++) { 171 struct server_id id = ids->entries[i].pid; 172 if (procid_equal(&id, &crec->pid)) { 173 guest = false; 174 break; 175 } 176 } 177 178 d_printf("%s\\%s\\%s\\%s\\%s\\%s\\%s", 179 crec->servicename,procid_str_static(&crec->pid), 180 guest ? "" : uidtoname(ids->entries[i].uid), 181 guest ? "" : gidtoname(ids->entries[i].gid), 182 crec->machine, 183 guest ? "" : ids->entries[i].hostname, 184 time_to_asc(crec->start)); 185 186 return 0; 187} 188 189static int net_status_shares_parseable(struct net_context *c, int argc, const char **argv) 190{ 191 struct sessionids ids; 192 struct db_context *db; 193 194 ids.num_entries = 0; 195 ids.entries = NULL; 196 197 db = db_open(NULL, lock_path("sessionid.tdb"), 0, 198 TDB_CLEAR_IF_FIRST, O_RDONLY, 0644); 199 if (db == NULL) { 200 d_fprintf(stderr, _("%s not initialised\n"), 201 lock_path("sessionid.tdb")); 202 return -1; 203 } 204 205 db->traverse_read(db, collect_pid, &ids); 206 TALLOC_FREE(db); 207 208 connections_forall(show_share_parseable, &ids); 209 210 SAFE_FREE(ids.entries); 211 212 return 0; 213} 214 215static int net_status_shares(struct net_context *c, int argc, const char **argv) 216{ 217 if (c->display_usage) { 218 d_printf( "%s\n" 219 "net status shares [parseable]\n" 220 " %s\n", 221 _("Usage:"), 222 _("Display open user shares.\n" 223 " If parseable is specified, output is machine-" 224 "readable.")); 225 return 0; 226 } 227 228 if (argc == 0) { 229 230 d_printf(_("\nService pid machine " 231 "Connected at\n" 232 "-------------------------------------" 233 "------------------\n")); 234 235 connections_forall(show_share, NULL); 236 237 return 0; 238 } 239 240 if ((argc != 1) || !strequal(argv[0], "parseable")) { 241 return net_status_usage(c, argc, argv); 242 } 243 244 return net_status_shares_parseable(c, argc, argv); 245} 246 247int net_status(struct net_context *c, int argc, const char **argv) 248{ 249 struct functable func[] = { 250 { 251 "sessions", 252 net_status_sessions, 253 NET_TRANSPORT_LOCAL, 254 N_("Show list of open sessions"), 255 N_("net status sessions [parseable]\n" 256 " If parseable is specified, output is presented " 257 "in a machine-parseable fashion.") 258 }, 259 { 260 "shares", 261 net_status_shares, 262 NET_TRANSPORT_LOCAL, 263 N_("Show list of open shares"), 264 N_("net status shares [parseable]\n" 265 " If parseable is specified, output is presented " 266 "in a machine-parseable fashion.") 267 }, 268 {NULL, NULL, 0, NULL, NULL} 269 }; 270 return net_run_function(c, argc, argv, "net status", func); 271} 272