xref: /plan9-contrib/sys/src/cmd/cifs/fs.c (revision 912e5f5442636b48aaa52937edbb904e279d1987)
1671dfc47SDavid du Colombier #include <u.h>
2671dfc47SDavid du Colombier #include <libc.h>
3671dfc47SDavid du Colombier #include <auth.h>
4671dfc47SDavid du Colombier #include <fcall.h>
5671dfc47SDavid du Colombier #include <thread.h>
6671dfc47SDavid du Colombier #include <9p.h>
7671dfc47SDavid du Colombier #include "cifs.h"
8671dfc47SDavid du Colombier 
9671dfc47SDavid du Colombier static char *period(long sec);
10671dfc47SDavid du Colombier 
11671dfc47SDavid du Colombier int
shareinfo(Fmt * f)12671dfc47SDavid du Colombier shareinfo(Fmt *f)
13671dfc47SDavid du Colombier {
14671dfc47SDavid du Colombier 	int i, j, n;
15671dfc47SDavid du Colombier 	char *type;
16671dfc47SDavid du Colombier 	Shareinfo2 si2;
17671dfc47SDavid du Colombier 	Share *sp, *sip;
18671dfc47SDavid du Colombier 
19671dfc47SDavid du Colombier 	if((n = RAPshareenum(Sess, &Ipc, &sip)) < 1){
20671dfc47SDavid du Colombier 		fmtprint(f, "can't enumerate shares: %r\n");
21671dfc47SDavid du Colombier 		return 0;
22671dfc47SDavid du Colombier 	}
23671dfc47SDavid du Colombier 
24671dfc47SDavid du Colombier 	for(i = 0; i < n; i++){
25671dfc47SDavid du Colombier 		fmtprint(f, "%-13q ", sip[i].name);
26671dfc47SDavid du Colombier 
27671dfc47SDavid du Colombier 		sp = &sip[i];
28671dfc47SDavid du Colombier 		for(j = 0; j < Nshares; j++)
29671dfc47SDavid du Colombier 			if(strcmp(Shares[j].name, sip[i].name) == 0){
30671dfc47SDavid du Colombier 				sp = &Shares[j];
31671dfc47SDavid du Colombier 				break;
32671dfc47SDavid du Colombier 			}
33*912e5f54SDavid du Colombier 		if(j >= Nshares)
34671dfc47SDavid du Colombier 			sp->tid = Ipc.tid;
35671dfc47SDavid du Colombier 
36671dfc47SDavid du Colombier 		if(RAPshareinfo(Sess, sp, sp->name, &si2) != -1){
37671dfc47SDavid du Colombier 			switch(si2.type){
38671dfc47SDavid du Colombier 			case STYPE_DISKTREE:	type = "disk"; break;
39671dfc47SDavid du Colombier 			case STYPE_PRINTQ:	type = "printq"; break;
40671dfc47SDavid du Colombier 			case STYPE_DEVICE:	type = "device"; break;
41671dfc47SDavid du Colombier 			case STYPE_IPC:		type = "ipc"; break;
42671dfc47SDavid du Colombier 			case STYPE_SPECIAL:	type = "special"; break;
43671dfc47SDavid du Colombier 			case STYPE_TEMP:	type = "temp"; break;
44671dfc47SDavid du Colombier 			default:		type = "unknown"; break;
45671dfc47SDavid du Colombier 			}
46671dfc47SDavid du Colombier 
47*912e5f54SDavid du Colombier 			fmtprint(f, "%-8s %5d/%-5d %s", type,
48*912e5f54SDavid du Colombier 				si2.activeusrs, si2.maxusrs, si2.comment);
49671dfc47SDavid du Colombier 			free(si2.name);
50671dfc47SDavid du Colombier 			free(si2.comment);
51671dfc47SDavid du Colombier 			free(si2.path);
52671dfc47SDavid du Colombier 			free(si2.passwd);
53671dfc47SDavid du Colombier 		}
54671dfc47SDavid du Colombier 		fmtprint(f, "\n");
55671dfc47SDavid du Colombier 
56671dfc47SDavid du Colombier 	}
57671dfc47SDavid du Colombier 	free(sip);
58671dfc47SDavid du Colombier 	return 0;
59671dfc47SDavid du Colombier }
60671dfc47SDavid du Colombier 
61671dfc47SDavid du Colombier int
openfileinfo(Fmt * f)62671dfc47SDavid du Colombier openfileinfo(Fmt *f)
63671dfc47SDavid du Colombier {
64671dfc47SDavid du Colombier 	int got,  i;
65671dfc47SDavid du Colombier 	Fileinfo *fi;
66671dfc47SDavid du Colombier 
67671dfc47SDavid du Colombier 	fi = nil;
68671dfc47SDavid du Colombier 	if((got = RAPFileenum2(Sess, &Ipc, "", "", &fi)) == -1){
69*912e5f54SDavid du Colombier 		fmtprint(f, "RAPfileenum: %r\n");
70671dfc47SDavid du Colombier 		return 0;
71671dfc47SDavid du Colombier 	}
72671dfc47SDavid du Colombier 
73671dfc47SDavid du Colombier 	for(i = 0; i < got; i++){
74*912e5f54SDavid du Colombier 		fmtprint(f, "%c%c%c %-4d %-24q %q ",
75*912e5f54SDavid du Colombier 			(fi[i].perms & 1)? 'r': '-',
76*912e5f54SDavid du Colombier 			(fi[i].perms & 2)? 'w': '-',
77*912e5f54SDavid du Colombier 			(fi[i].perms & 4)? 'c': '-',
78671dfc47SDavid du Colombier 			fi[i].locks, fi[i].user, fi[i].path);
79671dfc47SDavid du Colombier 		free(fi[i].path);
80671dfc47SDavid du Colombier 		free(fi[i].user);
81671dfc47SDavid du Colombier 	}
82671dfc47SDavid du Colombier 	free(fi);
83671dfc47SDavid du Colombier 	return 0;
84671dfc47SDavid du Colombier }
85671dfc47SDavid du Colombier 
86671dfc47SDavid du Colombier int
conninfo(Fmt * f)87671dfc47SDavid du Colombier conninfo(Fmt *f)
88671dfc47SDavid du Colombier {
89671dfc47SDavid du Colombier 	int i;
90671dfc47SDavid du Colombier 	typedef struct {
91671dfc47SDavid du Colombier 		int	val;
92671dfc47SDavid du Colombier 		char	*name;
93671dfc47SDavid du Colombier 	} Tab;
94671dfc47SDavid du Colombier 	static Tab captab[] = {
95671dfc47SDavid du Colombier 		{ 1,		"raw-mode" },
96671dfc47SDavid du Colombier 		{ 2,		"mpx-mode" },
97671dfc47SDavid du Colombier 		{ 4,		"unicode" },
98671dfc47SDavid du Colombier 		{ 8,		"large-files" },
99671dfc47SDavid du Colombier 		{ 0x10,		"NT-smbs" },
100671dfc47SDavid du Colombier 		{ 0x20,		"rpc-remote-APIs" },
101671dfc47SDavid du Colombier 		{ 0x40,		"status32" },
102671dfc47SDavid du Colombier 		{ 0x80,		"l2-oplocks" },
103671dfc47SDavid du Colombier 		{ 0x100,	"lock-read" },
104671dfc47SDavid du Colombier 		{ 0x200,	"NT-find" },
105671dfc47SDavid du Colombier 		{ 0x1000,	"Dfs" },
106671dfc47SDavid du Colombier 		{ 0x2000,	"info-passthru" },
107671dfc47SDavid du Colombier 		{ 0x4000,	"large-readx" },
108671dfc47SDavid du Colombier 		{ 0x8000,	"large-writex" },
109671dfc47SDavid du Colombier 		{ 0x800000,	"Unix" },
110671dfc47SDavid du Colombier 		{ 0x20000000,	"bulk-transfer" },
111671dfc47SDavid du Colombier 		{ 0x40000000,	"compressed" },
112671dfc47SDavid du Colombier 		{ 0x80000000,	"extended-security" },
113671dfc47SDavid du Colombier 	};
114671dfc47SDavid du Colombier 	static Tab sectab[] = {
115671dfc47SDavid du Colombier 		{ 1,		"user-auth" },
116671dfc47SDavid du Colombier 		{ 2,		"challange-response" },
117671dfc47SDavid du Colombier 		{ 4,		"signing-available" },
118671dfc47SDavid du Colombier 		{ 8,		"signing-required" },
119671dfc47SDavid du Colombier 	};
120671dfc47SDavid du Colombier 
121671dfc47SDavid du Colombier 	fmtprint(f, "%q %q %q %q %+ldsec %dmtu %s\n",
122671dfc47SDavid du Colombier 		Sess->auth->user, Sess->cname,
123671dfc47SDavid du Colombier 		Sess->auth->windom, Sess->remos,
124671dfc47SDavid du Colombier 		Sess->slip, Sess->mtu, Sess->isguest? "as guest": "");
125671dfc47SDavid du Colombier 
126671dfc47SDavid du Colombier 	fmtprint(f, "caps: ");
127671dfc47SDavid du Colombier 	for(i = 0; i < nelem(captab); i++)
128671dfc47SDavid du Colombier 		if(Sess->caps & captab[i].val)
129671dfc47SDavid du Colombier 			fmtprint(f, "%s ", captab[i].name);
130671dfc47SDavid du Colombier 	fmtprint(f, "\n");
131671dfc47SDavid du Colombier 
132671dfc47SDavid du Colombier 	fmtprint(f, "security: ");
133671dfc47SDavid du Colombier 	for(i = 0; i < nelem(sectab); i++)
134671dfc47SDavid du Colombier 		if(Sess->secmode & sectab[i].val)
135671dfc47SDavid du Colombier 			fmtprint(f, "%s ", sectab[i].name);
136671dfc47SDavid du Colombier 	fmtprint(f, "\n");
137671dfc47SDavid du Colombier 
138671dfc47SDavid du Colombier 	if(Sess->nbt)
139671dfc47SDavid du Colombier 		fmtprint(f, "transport: cifs over netbios\n");
140671dfc47SDavid du Colombier 	else
141671dfc47SDavid du Colombier 		fmtprint(f, "transport: cifs\n");
142671dfc47SDavid du Colombier 	return 0;
143671dfc47SDavid du Colombier }
144671dfc47SDavid du Colombier 
145671dfc47SDavid du Colombier int
sessioninfo(Fmt * f)146671dfc47SDavid du Colombier sessioninfo(Fmt *f)
147671dfc47SDavid du Colombier {
148671dfc47SDavid du Colombier 	int got,  i;
149671dfc47SDavid du Colombier 	Sessinfo *si;
150671dfc47SDavid du Colombier 
151671dfc47SDavid du Colombier 	si = nil;
152671dfc47SDavid du Colombier 	if((got = RAPsessionenum(Sess, &Ipc, &si)) == -1){
153671dfc47SDavid du Colombier 		fmtprint(f, "RAPsessionenum: %r\n");
154671dfc47SDavid du Colombier 		return 0;
155671dfc47SDavid du Colombier 	}
156671dfc47SDavid du Colombier 
157671dfc47SDavid du Colombier 	for(i = 0; i < got; i++){
158671dfc47SDavid du Colombier 		fmtprint(f, "%-24q %-24q ", si[i].user, si[i].wrkstn);
159671dfc47SDavid du Colombier 		fmtprint(f, "%12s ", period(si[i].sesstime));
160671dfc47SDavid du Colombier 		fmtprint(f, "%12s\n", period(si[i].idletime));
161671dfc47SDavid du Colombier 		free(si[i].wrkstn);
162671dfc47SDavid du Colombier 		free(si[i].user);
163671dfc47SDavid du Colombier 	}
164671dfc47SDavid du Colombier 	free(si);
165671dfc47SDavid du Colombier 	return 0;
166671dfc47SDavid du Colombier }
167671dfc47SDavid du Colombier 
168671dfc47SDavid du Colombier /*
169671dfc47SDavid du Colombier  * We request the domain referral for "" which gives the
170671dfc47SDavid du Colombier  * list of all the trusted domains in the clients forest, and
171671dfc47SDavid du Colombier  * other trusted forests.
172671dfc47SDavid du Colombier  *
173671dfc47SDavid du Colombier  * We then sumbit each of these names in turn which gives the
174671dfc47SDavid du Colombier  * names of the domain controllers for that domain.
175671dfc47SDavid du Colombier  *
176671dfc47SDavid du Colombier  * We get a DNS domain name for each domain controller as well as a
177671dfc47SDavid du Colombier  * netbios name.  I THINK I am correct in saying that a name
178671dfc47SDavid du Colombier  * containing a dot ('.') must be a DNS name, as the NetBios
179671dfc47SDavid du Colombier  * name munging cannot encode one.  Thus names which contain no
180671dfc47SDavid du Colombier  * dots must be netbios names.
181*912e5f54SDavid du Colombier  *
182671dfc47SDavid du Colombier  */
183671dfc47SDavid du Colombier static void
dfsredir(Fmt * f,char * path,int depth)184671dfc47SDavid du Colombier dfsredir(Fmt *f, char *path, int depth)
185671dfc47SDavid du Colombier {
186671dfc47SDavid du Colombier 	Refer *re, retab[128];
187671dfc47SDavid du Colombier 	int n, used, flags;
188671dfc47SDavid du Colombier 
189671dfc47SDavid du Colombier 	n = T2getdfsreferral(Sess, &Ipc, path, &flags, &used, retab, nelem(retab));
190671dfc47SDavid du Colombier 	if(n == -1)
191671dfc47SDavid du Colombier 		return;
192671dfc47SDavid du Colombier 	for(re = retab; re < retab+n; re++){
193671dfc47SDavid du Colombier 		if(strcmp(path, re->path) != 0)
194671dfc47SDavid du Colombier 			dfsredir(f, re->path, depth+1);
195671dfc47SDavid du Colombier 		else
196671dfc47SDavid du Colombier 			fmtprint(f, "%-32q %q\n", re->path, re->addr);
197*912e5f54SDavid du Colombier 
198671dfc47SDavid du Colombier 		free(re->addr);
199671dfc47SDavid du Colombier 		free(re->path);
200671dfc47SDavid du Colombier 	}
201671dfc47SDavid du Colombier }
202671dfc47SDavid du Colombier 
203671dfc47SDavid du Colombier int
dfsrootinfo(Fmt * f)204671dfc47SDavid du Colombier dfsrootinfo(Fmt *f)
205671dfc47SDavid du Colombier {
206671dfc47SDavid du Colombier 	dfsredir(f, "", 0);
207671dfc47SDavid du Colombier 	return 0;
208671dfc47SDavid du Colombier }
209671dfc47SDavid du Colombier 
210671dfc47SDavid du Colombier 
211671dfc47SDavid du Colombier int
userinfo(Fmt * f)212671dfc47SDavid du Colombier userinfo(Fmt *f)
213671dfc47SDavid du Colombier {
214671dfc47SDavid du Colombier 	int got, i;
215671dfc47SDavid du Colombier 	Namelist *nl;
216671dfc47SDavid du Colombier 	Userinfo ui;
217671dfc47SDavid du Colombier 
218671dfc47SDavid du Colombier 	nl = nil;
219671dfc47SDavid du Colombier 	if((got = RAPuserenum2(Sess, &Ipc, &nl)) == -1)
220671dfc47SDavid du Colombier 		if((got = RAPuserenum(Sess, &Ipc, &nl)) == -1){
221671dfc47SDavid du Colombier 			fmtprint(f, "RAPuserenum: %r\n");
222671dfc47SDavid du Colombier 			return 0;
223671dfc47SDavid du Colombier 		}
224671dfc47SDavid du Colombier 
225671dfc47SDavid du Colombier 	for(i = 0; i < got; i++){
226671dfc47SDavid du Colombier 		fmtprint(f, "%-24q ", nl[i].name);
227671dfc47SDavid du Colombier 
228671dfc47SDavid du Colombier 		if(RAPuserinfo(Sess, &Ipc, nl[i].name, &ui) != -1){
229671dfc47SDavid du Colombier 			fmtprint(f, "%-48q %q", ui.fullname, ui.comment);
230671dfc47SDavid du Colombier 			free(ui.user);
231671dfc47SDavid du Colombier 			free(ui.comment);
232671dfc47SDavid du Colombier 			free(ui.fullname);
233671dfc47SDavid du Colombier 			free(ui.user_comment);
234671dfc47SDavid du Colombier 		}
235671dfc47SDavid du Colombier 		free(nl[i].name);
236671dfc47SDavid du Colombier 		fmtprint(f, "\n");
237671dfc47SDavid du Colombier 	}
238671dfc47SDavid du Colombier 	free(nl);
239671dfc47SDavid du Colombier 	return 0;
240671dfc47SDavid du Colombier }
241671dfc47SDavid du Colombier 
242671dfc47SDavid du Colombier int
groupinfo(Fmt * f)243671dfc47SDavid du Colombier groupinfo(Fmt *f)
244671dfc47SDavid du Colombier {
245671dfc47SDavid du Colombier 	int got1, got2, i, j;
246671dfc47SDavid du Colombier 	Namelist *grps, *usrs;
247671dfc47SDavid du Colombier 
248671dfc47SDavid du Colombier 	grps = nil;
249671dfc47SDavid du Colombier 	if((got1 = RAPgroupenum(Sess, &Ipc, &grps)) == -1){
250671dfc47SDavid du Colombier 		fmtprint(f, "RAPgroupenum: %r\n");
251671dfc47SDavid du Colombier 		return 0;
252671dfc47SDavid du Colombier 	}
253671dfc47SDavid du Colombier 
254671dfc47SDavid du Colombier 	for(i = 0; i < got1; i++){
255671dfc47SDavid du Colombier 		fmtprint(f, "%q ", grps[i].name);
256671dfc47SDavid du Colombier 		usrs = nil;
257671dfc47SDavid du Colombier 		if((got2 = RAPgroupusers(Sess, &Ipc, grps[i].name, &usrs)) != -1){
258671dfc47SDavid du Colombier 			for(j = 0; j < got2; j++){
259671dfc47SDavid du Colombier 				fmtprint(f, "%q ", usrs[j].name);
260671dfc47SDavid du Colombier 				free(usrs[j].name);
261671dfc47SDavid du Colombier 			}
262671dfc47SDavid du Colombier 			free(usrs);
263671dfc47SDavid du Colombier 		}
264671dfc47SDavid du Colombier 		free(grps[i].name);
265671dfc47SDavid du Colombier 		fmtprint(f, "\n");
266671dfc47SDavid du Colombier 	}
267671dfc47SDavid du Colombier 	free(grps);
268671dfc47SDavid du Colombier 	return 0;
269671dfc47SDavid du Colombier }
270671dfc47SDavid du Colombier 
271671dfc47SDavid du Colombier static int
nodelist(Fmt * f,int type)272671dfc47SDavid du Colombier nodelist(Fmt *f, int type)
273671dfc47SDavid du Colombier {
274671dfc47SDavid du Colombier 	int more, got, i, j;
275671dfc47SDavid du Colombier 	Serverinfo *si;
276671dfc47SDavid du Colombier 	static char *types[] = {
277671dfc47SDavid du Colombier 		[0]	"workstation",
278671dfc47SDavid du Colombier 		[1]	"server",
279671dfc47SDavid du Colombier 		[2]	"SQL server",
280671dfc47SDavid du Colombier 		[3]	"DC",
281671dfc47SDavid du Colombier 		[4]	"backup DC",
282671dfc47SDavid du Colombier 		[5]	"time source",
283671dfc47SDavid du Colombier 		[6]	"Apple server",
284671dfc47SDavid du Colombier 		[7]	"Novell server",
285671dfc47SDavid du Colombier 		[8]	"domain member",
286671dfc47SDavid du Colombier 		[9]	"printer server",
287671dfc47SDavid du Colombier 		[10]	"dial-up server",
288671dfc47SDavid du Colombier 		[11]	"Unix",
289671dfc47SDavid du Colombier 		[12]	"NT",
290671dfc47SDavid du Colombier 		[13]	"WFW",
291671dfc47SDavid du Colombier 		[14]	"MFPN (?)",
292671dfc47SDavid du Colombier 		[15]	"NT server",
293671dfc47SDavid du Colombier 		[16]	"potential browser",
294671dfc47SDavid du Colombier 		[17]	"backup browser",
295671dfc47SDavid du Colombier 		[18]	"LMB",
296671dfc47SDavid du Colombier 		[19]	"DMB",
297671dfc47SDavid du Colombier 		[20]	"OSF Unix",
298671dfc47SDavid du Colombier 		[21]	"VMS",
299671dfc47SDavid du Colombier 		[22]	"Win95",
300671dfc47SDavid du Colombier 		[23]	"DFS",
301671dfc47SDavid du Colombier 		[24]	"NT cluster",
302671dfc47SDavid du Colombier 		[25]	"Terminal server",
303671dfc47SDavid du Colombier 		[26]	"[26]",
304671dfc47SDavid du Colombier 		[27]	"[27]",
305671dfc47SDavid du Colombier 		[28]	"IBM DSS",
306671dfc47SDavid du Colombier 	};
307671dfc47SDavid du Colombier 
308671dfc47SDavid du Colombier 	si = nil;
309671dfc47SDavid du Colombier 	if((got = RAPServerenum2(Sess, &Ipc, Sess->auth->windom, type, &more,
310671dfc47SDavid du Colombier 	    &si)) == -1){
311671dfc47SDavid du Colombier 		fmtprint(f, "RAPServerenum2: %r\n");
312671dfc47SDavid du Colombier 		return 0;
313671dfc47SDavid du Colombier 	}
314671dfc47SDavid du Colombier 	if(more)
315671dfc47SDavid du Colombier 		if((got = RAPServerenum3(Sess, &Ipc, Sess->auth->windom, type,
316671dfc47SDavid du Colombier 		    got-1, si)) == -1){
317671dfc47SDavid du Colombier 			fmtprint(f, "RAPServerenum3: %r\n");
318671dfc47SDavid du Colombier 			return 0;
319671dfc47SDavid du Colombier 		}
320671dfc47SDavid du Colombier 
321671dfc47SDavid du Colombier 	for(i = 0; i < got; i++){
322671dfc47SDavid du Colombier 		fmtprint(f, "%-16q %-16q ", si[i].name, si[i].comment);
323671dfc47SDavid du Colombier 		if(type != LIST_DOMAINS_ONLY){
324671dfc47SDavid du Colombier 			fmtprint(f, "v%d.%d ", si[i].major, si[i].minor);
325671dfc47SDavid du Colombier 			for(j = 0; j < nelem(types); j++)
326671dfc47SDavid du Colombier 				if(si[i].type & (1 << j) && types[j])
327671dfc47SDavid du Colombier 					fmtprint(f, "%s,", types[j]);
328671dfc47SDavid du Colombier 		}
329671dfc47SDavid du Colombier 		fmtprint(f, "\n");
330671dfc47SDavid du Colombier 		free(si[i].name);
331671dfc47SDavid du Colombier 		free(si[i].comment);
332671dfc47SDavid du Colombier 	}
333671dfc47SDavid du Colombier 	free(si);
334671dfc47SDavid du Colombier 	return 0;
335671dfc47SDavid du Colombier }
336671dfc47SDavid du Colombier 
337671dfc47SDavid du Colombier int
domaininfo(Fmt * f)338671dfc47SDavid du Colombier domaininfo(Fmt *f)
339671dfc47SDavid du Colombier {
340671dfc47SDavid du Colombier 	return nodelist(f, LIST_DOMAINS_ONLY);
341671dfc47SDavid du Colombier }
342671dfc47SDavid du Colombier 
343671dfc47SDavid du Colombier int
workstationinfo(Fmt * f)344671dfc47SDavid du Colombier workstationinfo(Fmt *f)
345671dfc47SDavid du Colombier {
346671dfc47SDavid du Colombier 	return nodelist(f, ALL_LEARNT_IN_DOMAIN);
347671dfc47SDavid du Colombier }
348671dfc47SDavid du Colombier 
349671dfc47SDavid du Colombier static char *
period(long sec)350671dfc47SDavid du Colombier period(long sec)
351671dfc47SDavid du Colombier {
352671dfc47SDavid du Colombier 	int days, hrs, min;
353671dfc47SDavid du Colombier 	static char when[32];
354671dfc47SDavid du Colombier 
355671dfc47SDavid du Colombier 	days = sec  / (60L * 60L * 24L);
356671dfc47SDavid du Colombier 	sec -= days * (60L * 60L * 24L);
357671dfc47SDavid du Colombier 	hrs  = sec / (60L * 60L);
358671dfc47SDavid du Colombier 	sec -= hrs * (60L * 60L);
359671dfc47SDavid du Colombier 	min  = sec / 60L;
360671dfc47SDavid du Colombier 	sec -= min * 60L;
361671dfc47SDavid du Colombier 	if(days)
362671dfc47SDavid du Colombier 		snprint(when, sizeof(when), "%d %d:%d:%ld ", days, hrs, min, sec);
363671dfc47SDavid du Colombier 	else
364671dfc47SDavid du Colombier 		snprint(when, sizeof(when), "%d:%d:%ld ", hrs, min, sec);
365671dfc47SDavid du Colombier 	return when;
366671dfc47SDavid du Colombier }
367