xref: /plan9/sys/src/cmd/aquarela/cifscmd.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1 #include "headers.h"
2 #include <bio.h>
3 
4 SmbClient *c;
5 Biobuf bin, bout;
6 static int verbose = 1;
7 
8 #define	SEP(c)	(((c)==' ')||((c)=='\t')||((c)=='\n'))
9 
10 typedef struct Slut {
11 	char *name;
12 	int val;
13 } Slut;
14 
15 static char *
tokenise(char * s,char ** start,char ** end)16 tokenise(char *s, char **start, char **end)
17 {
18 	char *to;
19 	Rune r;
20 	int n;
21 
22 	while(*s && SEP(*s))				/* skip leading white space */
23 		s++;
24 	to = *start = s;
25 	while(*s){
26 		n = chartorune(&r, s);
27 		if(SEP(r)){
28 			if(to != *start)		/* we have data */
29 				break;
30 			s += n;				/* null string - keep looking */
31 			while(*s && SEP(*s))
32 				s++;
33 			to = *start = s;
34 		}
35 		else if(r == '\''){
36 			s += n;				/* skip leading quote */
37 			while(*s){
38 				n = chartorune(&r, s);
39 				if(r == '\''){
40 					if(s[1] != '\'')
41 						break;
42 					s++;		/* embedded quote */
43 				}
44 				while (n--)
45 					*to++ = *s++;
46 			}
47 			if(!*s)				/* no trailing quote */
48 				break;
49 			s++;				/* skip trailing quote */
50 		}
51 		else  {
52 			while(n--)
53 				*to++ = *s++;
54 		}
55 	}
56 	*end = to;
57 	return s;
58 }
59 
60 static int
parse(char * s,char * fields[],int nfields)61 parse(char *s, char *fields[], int nfields)
62 {
63 	int c, argc;
64 	char *start, *end;
65 
66 	argc = 0;
67 	c = *s;
68 	while(c){
69 		s = tokenise(s, &start, &end);
70 		c = *s++;
71 		if(*start == 0)
72 			break;
73 		if(argc >= nfields-1)
74 			return -1;
75 		*end = 0;
76 		fields[argc++] = start;
77 	}
78 	fields[argc] = 0;
79 Bprint(&bout, "parse returns %d\n", argc);
80 	return argc;
81 }
82 
83 typedef struct {
84 	char *name;
85 	long (*f)(SmbClient *, int, char *[]);
86 	int connected;
87 	char *help;
88 } Cmd;
89 static Cmd cmd[];
90 
91 static long
cmdhelp(SmbClient *,int argc,char * argv[])92 cmdhelp(SmbClient *, int argc, char *argv[])
93 {
94 	Cmd *cp;
95 	char *p;
96 
97 	if(argc)
98 		p = argv[0];
99 	else
100 		p = 0;
101 	for (cp = cmd; cp->name; cp++) {
102 		if (p == 0 || strcmp(p, cp->name) == 0)
103 			Bprint(&bout, "%s\n", cp->help);
104 	}
105 	return 0;
106 }
107 
108 static Slut sharemodeslut[] = {
109 	{ "compatibility", SMB_OPEN_MODE_SHARE_COMPATIBILITY },
110 	{ "exclusive", SMB_OPEN_MODE_SHARE_EXCLUSIVE },
111 	{ "denywrite", SMB_OPEN_MODE_SHARE_DENY_WRITE },
112 	{ "denyread", SMB_OPEN_MODE_SHARE_DENY_READOREXEC },
113 	{ "denynone", SMB_OPEN_MODE_SHARE_DENY_NONE },
114 	{ 0 }
115 };
116 
117 static Slut openmodeslut[] = {
118 	{ "oread", OREAD },
119 	{ "owrite", OWRITE },
120 	{ "ordwr", ORDWR },
121 	{ "oexec", OEXEC },
122 	{ 0 }
123 };
124 
125 static int
slut(Slut * s,char * pat)126 slut(Slut *s, char *pat)
127 {
128 	while (s->name) {
129 		if (cistrcmp(s->name, pat) == 0)
130 			return s->val;
131 		s++;
132 	}
133 	Bprint(&bout, "%s unrecognised\n", pat);
134 	return -1;
135 }
136 
137 static long
cmdopen(SmbClient * c,int argc,char * argv[])138 cmdopen(SmbClient *c, int argc, char *argv[])
139 {
140 	char *errmsg;
141 	int sm, om;
142 	int rv;
143 	uchar errclass;
144 	ushort error;
145 	ushort fid, attr;
146 	ulong mtime, size;
147 	ushort accessallowed;
148 
149 	if (argc != 3) {
150 		Bprint(&bout, "wrong number of arguments\n");
151 		return -1;
152 	}
153 	sm = slut(sharemodeslut, argv[1]);
154 	if (sm < 0)
155 		return -1;
156 	om = slut(openmodeslut, argv[2]);
157 	if (om < 0)
158 		return -1;
159 	errmsg = nil;
160 	rv = smbclientopen(c, (sm << 3) | om, argv[0], &errclass, &error, &fid, &attr, &mtime, &size, &accessallowed, &errmsg);
161 	if (rv == 0) {
162 		if (errmsg) {
163 			print("local error %s\n", errmsg);
164 			free(errmsg);
165 			return -1;
166 		}
167 		return (errclass << 16) | error;
168 	}
169 	print("fid 0x%.4ux attr 0x%.4ux time %ld size %lud accessallowed %ud\n",
170 		fid, attr, mtime, size, accessallowed);
171 	return 0;
172 }
173 
174 static Cmd cmd[] = {
175 	{ "help",	cmdhelp,	0, "help" },
176 	{ "open", cmdopen, 1, "open name sharemode openmode" },
177 	{ 0, 0 },
178 };
179 
180 void
threadmain(int argc,char * argv[])181 threadmain(int argc, char *argv[])
182 {
183 	char *errmsg;
184 	int ac;
185 	char *ap, *av[256];
186 	Cmd *cp;
187 	long status;
188 
189 	if (argc > 3) {
190 		print("usage: cifscmd [to [share]]\n");
191 		exits("args");
192 	}
193 	smbglobalsguess(1);
194 	errmsg = nil;
195 
196 	if (Binit(&bin, 0, OREAD) == Beof || Binit(&bout, 1, OWRITE) == Beof) {
197 		fprint(2, "%s: can't init bio: %r\n", argv0);
198 		threadexits("Binit");
199 	}
200 
201 	if (argc > 1) {
202 		c = smbconnect(argv[1], argc == 3 ? argv[2] : nil, &errmsg);
203 		if (c == nil)
204 			fprint(2, "failed to connect: %s\n", errmsg);
205 	}
206 	while (ap = Brdline(&bin, '\n')) {
207 		ap[Blinelen(&bin) - 1] = 0;
208 		switch (ac = parse(ap, av, nelem(av))) {
209 		default:
210 			for (cp = cmd; cp->name; cp++) {
211 				if (strcmp(cp->name, av[0]) == 0)
212 					break;
213 			}
214 			if (cp->name == 0) {
215 				Bprint(&bout, "eh?\n");
216 				break;
217 			}
218 			if (c == 0 && cp->connected) {
219 				Bprint(&bout, "not currently connected\n");
220 				break;
221 			}
222 			if ((status = (*cp->f)(c, ac - 1, &av[1])) != -1) {
223 				if(verbose)
224 					Bprint(&bout, "ok %ld/%ld\n", status >> 16, status & 0xffff);
225 				break;
226 			}
227 			break;
228 
229 		case -1:
230 			Bprint(&bout, "eh?\n");
231 			break;
232 
233 		case 0:
234 			break;
235 		}
236 		Bflush(&bout);
237 	}
238 	threadexits(0);
239 }
240