added gentoo ebuilds
[libmixp.git] / cmd / ixpc.c
blob15a2ae490d94f297dba673b1699b56d5bc8f606f
1 /* Copyright ©2007 Kris Maglione <fbsdaemon@gmail.com>
2 * See LICENSE file for license details.
3 */
4 #define IXP_NO_P9_
5 #define IXP_P9_STRUCTS
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include <9p-mixp/mixp.h>
12 #include <9p-mixp/err.h>
13 #include <9p-mixp/stat.h>
14 #include <9p-mixp/convert.h>
16 /* Temporary */
17 #define fatal(...) ixp_eprint("ixpc: fatal: " __VA_ARGS__); \
19 char *argv0;
20 #define ARGBEGIN int _argi=0, _argtmp=0, _inargv=0; char *_argv=NULL; \
21 if(!argv0)argv0=ARGF(); _inargv=1; \
22 while(argc && argv[0][0] == '-') { \
23 _argi=1; _argv=*argv++; argc--; \
24 while(_argv[_argi]) switch(_argv[_argi++])
25 #define ARGEND }_inargv=0;USED(_argtmp);USED(_argv);USED(_argi)
26 #define ARGF() ((_inargv && _argv[_argi]) ? \
27 (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \
28 : ((argc > 0) ? (argc--, *argv++) : ((char*)0)))
29 #define EARGF(f) ((_inargv && _argv[_argi]) ? \
30 (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \
31 : ((argc > 0) ? (argc--, *argv++) : ((f), (char*)0)))
32 #define USED(x) if(x){}else
33 #define SET(x) ((x)=0)
35 static MIXP_CLIENT *client;
37 static void
38 usage() {
39 fprintf(stderr,
40 "usage: %1$s [-a <address>] {create | read | ls [-ld] | remove | write} <file>\n"
41 " %1$s [-a <address>] xwrite <file> <data>\n"
42 " %1$s -v\n", argv0);
43 exit(1);
46 /* Utility Functions */
47 static void
48 write_data(MIXP_CFID *fid, char *name) {
49 void *buf;
50 unsigned int len;
52 buf = malloc(fid->iounit);;
53 do {
54 len = read(0, buf, fid->iounit);
55 if(len >= 0 && mixp_write(fid, buf, len) != len)
56 fatal("cannot write file '%s': %s\n", name, mixp_errbuf());
57 } while(len > 0);
59 free(buf);
62 static int
63 comp_stat(const void *s1, const void *s2) {
64 MIXP_STAT *st1, *st2;
66 st1 = (MIXP_STAT*)s1;
67 st2 = (MIXP_STAT*)s2;
68 return strcmp(st1->name, st2->name);
71 static void
72 setrwx(long m, char *s) {
73 static char *modes[] = {
74 "---", "--x", "-w-",
75 "-wx", "r--", "r-x",
76 "rw-", "rwx",
78 strncpy(s, modes[m], 3);
81 static char *
82 str_of_mode(unsigned int mode) {
83 static char buf[16];
85 buf[0]='-';
86 if(mode & P9_DMDIR)
87 buf[0]='d';
88 buf[1]='-';
89 setrwx((mode >> 6) & 7, &buf[2]);
90 setrwx((mode >> 3) & 7, &buf[5]);
91 setrwx((mode >> 0) & 7, &buf[8]);
92 buf[11] = 0;
93 return buf;
96 static char *
97 str_of_time(unsigned int val) {
98 static char buf[32];
99 time_t tv = val;
101 ctime_r(&tv, buf);
102 buf[strlen(buf) - 1] = '\0';
103 return buf;
106 static void
107 print_stat(MIXP_STAT *s, int details) {
108 if(details)
109 fprintf(stdout, "%s %s %s %5llu %s %s\n", str_of_mode(s->mode),
110 s->uid, s->gid, s->length, str_of_time(s->mtime), s->name);
111 else {
112 if((s->mode&P9_DMDIR) && strcmp(s->name, "/"))
113 fprintf(stdout, "%s/\n", s->name);
114 else
115 fprintf(stdout, "%s\n", s->name);
119 /* Service Functions */
120 static int
121 xwrite(int argc, char *argv[]) {
122 MIXP_CFID *fid;
123 char *file;
125 ARGBEGIN{
126 default:
127 usage();
128 }ARGEND;
130 file = EARGF(usage());
131 fid = mixp_open(client, file, P9_OWRITE);
132 if(fid == NULL)
133 fatal("Can't open file '%s': %s\n", file, mixp_errbuf());
135 write_data(fid, file);
136 return 0;
139 static int
140 xawrite(int argc, char *argv[]) {
141 MIXP_CFID *fid;
142 char *file, *buf, *arg;
143 int nbuf, mbuf, len;
145 ARGBEGIN{
146 default:
147 usage();
148 }ARGEND;
150 file = EARGF(usage());
151 fid = mixp_open(client, file, P9_OWRITE);
152 if(fid == NULL)
153 fatal("Can't open file '%s': %s\n", file, mixp_errbuf());
155 nbuf = 0;
156 mbuf = 128;
157 buf = malloc(mbuf);
158 while(argc) {
159 arg = ARGF();
160 len = strlen(arg);
161 if(nbuf + len > mbuf) {
162 mbuf <<= 1;
163 buf = ixp_erealloc(buf, mbuf);
165 memcpy(buf+nbuf, arg, len);
166 nbuf += len;
167 if(argc)
168 buf[nbuf++] = ' ';
171 if(mixp_write(fid, buf, nbuf) == -1)
172 fatal("cannot write file '%s': %s\n", file, mixp_errbuf());
173 return 0;
176 static int
177 xcreate(int argc, char *argv[]) {
178 MIXP_CFID *fid;
179 char *file;
181 ARGBEGIN{
182 default:
183 usage();
184 }ARGEND;
186 file = EARGF(usage());
187 fid = mixp_create(client, file, 0777, P9_OWRITE);
188 if(fid == NULL)
189 fatal("Can't create file '%s': %s\n", file, mixp_errbuf());
191 if((fid->qid.type&P9_DMDIR) == 0)
192 write_data(fid, file);
194 return 0;
197 static int
198 xremove(int argc, char *argv[]) {
199 char *file;
201 ARGBEGIN{
202 default:
203 usage();
204 }ARGEND;
206 file = EARGF(usage());
207 if(mixp_remove(client, file) == 0)
208 fatal("Can't remove file '%s': %s\n", file, mixp_errbuf());
209 return 0;
212 static int
213 xread(int argc, char *argv[]) {
214 MIXP_CFID *fid;
215 char *file, *buf;
216 int count;
218 ARGBEGIN{
219 default:
220 usage();
221 }ARGEND;
223 file = EARGF(usage());
224 fid = mixp_open(client, file, P9_OREAD);
225 if(fid == NULL)
226 fatal("Can't open file '%s': %s\n", file, mixp_errbuf());
228 buf = malloc(fid->iounit);
229 while((count = mixp_read(fid, buf, fid->iounit)) > 0)
230 write(1, buf, count);
232 if(count == -1)
233 fatal("cannot read file/directory '%s': %s\n", file, mixp_errbuf());
235 return 0;
238 static int
239 xls(int argc, char *argv[]) {
240 MIXP_MESSAGE m;
241 MIXP_STAT *stat;
242 MIXP_CFID *fid;
243 char *file, *buf;
244 int lflag, dflag, count, nstat, mstat, i;
246 lflag = dflag = 0;
248 ARGBEGIN{
249 case 'l':
250 lflag++;
251 break;
252 case 'd':
253 dflag++;
254 break;
255 default:
256 usage();
257 }ARGEND;
259 file = EARGF(usage());
261 stat = mixp_stat(client, file);
262 if(stat == NULL)
263 fatal("cannot stat file '%s': %s\n", file, mixp_errbuf());
265 if(dflag || (stat->mode&P9_DMDIR) == 0) {
266 print_stat(stat, lflag);
267 mixp_stat_free(stat);
268 return 0;
270 mixp_stat_free(stat);
272 fid = mixp_open(client, file, P9_OREAD);
273 if(fid == NULL)
274 fatal("Can't open file '%s': %s\n", file, mixp_errbuf());
276 nstat = 0;
277 mstat = 16;
278 stat = malloc(sizeof(*stat) * mstat);
279 buf = malloc(fid->iounit);
280 while((count = mixp_read(fid, buf, fid->iounit)) > 0) {
281 m = mixp_message(buf, count, MsgUnpack);
282 while(m.pos < m.end) {
283 if(nstat == mstat) {
284 mstat <<= 1;
285 stat = ixp_erealloc(stat, sizeof(*stat) * mstat);
287 mixp_pstat(&m, &stat[nstat++]);
291 qsort(stat, nstat, sizeof(*stat), comp_stat);
292 for(i = 0; i < nstat; i++) {
293 print_stat(&stat[i], lflag);
294 mixp_stat_free(&stat[i]);
296 free(stat);
298 if(count == -1)
299 fatal("cannot read directory '%s': %s\n", file, mixp_errbuf());
300 return 0;
303 typedef struct exectab exectab;
304 struct exectab {
305 char *cmd;
306 int (*fn)(int, char**);
307 } etab[] = {
308 {"write", xwrite},
309 {"xwrite", xawrite},
310 {"read", xread},
311 {"create", xcreate},
312 {"remove", xremove},
313 {"ls", xls},
314 {0, 0}
318 main(int argc, char *argv[]) {
319 char *cmd, *address;
320 exectab *tab;
321 int ret;
323 address = getenv("IXP_ADDRESS");
325 ARGBEGIN{
326 case 'v':
327 printf("%s-" VERSION ", (C) 2007 Kris Maglione, 2008 Enrico Weigelt <weigelt@metux.de>\n", argv0);
328 exit(0);
329 case 'd':
330 mixp_dump = 1;
331 break;
332 case 'a':
333 address = EARGF(usage());
334 break;
335 default:
336 usage();
337 }ARGEND;
339 cmd = EARGF(usage());
341 if(!address)
342 fatal("$IXP_ADDRESS not set\n");
344 MIXP_SERVER_ADDRESS* addr = mixp_srv_addr_parse(address);
345 if (!addr)
346 fatal("Could not parse address\n");
348 // printf("addr.hostname=\"%s\"\n", addr->hostname);
349 // printf("addr.port=\"%d\"\n", addr->port);
350 // printf("addr.path=\"%s\"\n", addr->path);
351 // printf("addr.proto=\"%d\"\n", addr->proto);
353 client = mixp_mount_addr(addr);
355 if (!client)
356 fatal("Could not mount: %s\n", mixp_errbuf());
358 for(tab = etab; tab->cmd; tab++)
359 if(strcmp(cmd, tab->cmd) == 0) break;
360 if(tab->cmd == 0)
361 usage();
363 ret = tab->fn(argc, argv);
365 mixp_unmount(client);
366 return ret;