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