wmii/cmd/wmiir2.c

244 lines
5.3 KiB
C

/*
* (C)opyright MMIV-MMV Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../libixp2/ixp.h"
#include <cext.h>
typedef struct {
char *name;
int (*cmd) (char **argv);
int min_argc;
} Command;
static int xcreate(char **argv);
static int xread(char **argv);
static int xwrite(char **argv);
static int xremove(char **argv);
static Command cmds[] = {
{"create", xcreate, 2},
{"read", xread, 1},
{"write", xwrite, 2},
{"remove", xremove, 1},
{0, 0}
};
static IXPClient c = { 0 };
static char *version[] = {
"wmir - window manager improved remote - " VERSION "\n"
" (C)opyright MMIV-MMV Anselm R. Garbe\n", 0
};
static void usage()
{
fprintf(stderr, "%s",
"usage: wmir [-s <socket file>] [-v] <command> <args> [...]\n"
" -s socket file (default: $WMIR_SOCKET)\n"
" -f read commands from stdin\n"
" -v version info\n"
"commands:\n"
" create <file> <content> -- creates file\n"
" read <file/directory> -- reads file/directory contents\n"
" write <file> <content> -- writes content to a file\n"
" remove <file/directory> -- removes file\n");
exit(1);
}
static u32 write_data(u32 fid, u8 * data, u32 count)
{
u32 len, i, runs = count / c.fcall.iounit;
for (i = 0; i <= runs; i++) {
/* write */
len = count - (i * c.fcall.iounit);
if (len > c.fcall.iounit)
len = c.fcall.iounit;
if (ixp_client_write
(&c, fid, i * c.fcall.iounit, len,
&data[i * c.fcall.iounit]) != count) {
fprintf(stderr, "wmir: cannot write file: %s\n", c.errstr);
return 0;
}
}
return count;
}
static int xcreate(char **argv)
{
u32 fid;
char *p = strrchr(argv[0], '/');
fid = c.root_fid << 2;
/* walk to bottom-most directory */
*p = 0;
if (!ixp_client_walk(&c, fid, argv[0])) {
fprintf(stderr, "wmir: cannot walk to %s: %s\n", argv[0],
c.errstr);
return 1;
}
/* create */
p++;
if (!ixp_client_create(&c, fid, p, (u32) 0xff, IXP_OWRITE)) {
fprintf(stderr, "wmir: cannot create file: %s\n", c.errstr);
return 1;
}
write_data(fid, (u8 *) argv[1], strlen(argv[1]));
return !ixp_client_close(&c, fid);
}
static int xwrite(char **argv)
{
/* open */
u32 fid = c.root_fid << 2;
if (!ixp_client_open(&c, fid, argv[0], IXP_OWRITE)) {
fprintf(stderr, "wmir: cannot open file: %s\n", c.errstr);
return 1;
}
write_data(fid, (u8 *) argv[1], strlen(argv[1]));
return !ixp_client_close(&c, fid);
}
static void print_directory(void *result, u32 msize)
{
void *p = result;
static Stat stat, zerostat = { 0 };
u32 len = 0;
do {
p = ixp_dec_stat(p, &stat);
len += stat.size + sizeof(u16);
if (stat.qid.type == IXP_QTDIR)
fprintf(stdout, "%s/\n", stat.name);
else
fprintf(stdout, "%s\n", stat.name);
stat = zerostat;
}
while (len < msize);
}
static int xread(char **argv)
{
u32 count, fid = c.root_fid << 2;
int is_directory = FALSE;
static u8 result[IXP_MAX_MSG];
/* open */
if (!ixp_client_open(&c, fid, argv[0], IXP_OREAD)) {
fprintf(stderr, "wmir: cannot open file: %s\n", c.errstr);
return 1;
}
is_directory = !c.fcall.nwqid || (c.fcall.qid.type == IXP_QTDIR);
/* read */
if (!(count = ixp_client_read(&c, fid, 0, result, IXP_MAX_MSG))
&& c.errstr) {
fprintf(stderr, "wmir: cannot read file: %s\n", c.errstr);
return 1;
}
if (count) {
if (is_directory)
print_directory(result, count);
else {
u32 i;
for (i = 0; i < count; i++)
putchar(result[i]);
}
}
return !ixp_client_close(&c, fid);
}
static int xremove(char **argv)
{
u32 fid;
/* remove */
fid = c.root_fid << 2;
if (!ixp_client_remove(&c, fid, argv[0])) {
fprintf(stderr, "wmir: cannot remove file: %s\n", c.errstr);
return 1;
}
return 0;
}
static int perform_cmd(int argc, char **argv)
{
int i;
for (i = 0; cmds[i].name; i++)
if (!strncmp(cmds[i].name, argv[0], strlen(cmds[i].name))) {
if (cmds[i].min_argc <= argc)
return cmds[i].cmd(&argv[1]);
else
usage();
}
/* bogus command */
return 1;
}
int main(int argc, char *argv[])
{
int i = 0, ret, read_stdin = 0;
char line[4096];
char *sockfile = getenv("WMIR_SOCKET");
/* command line args */
if (argc > 1) {
for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
switch (argv[i][1]) {
case 'v':
fprintf(stderr, "%s", version[0]);
exit(0);
break;
case 's':
if (i + 1 < argc)
sockfile = argv[++i];
else
usage();
break;
case 'f':
read_stdin = 1;
break;
default:
usage();
break;
}
}
}
if ((argc <= 1) || (!read_stdin && (i + 1) >= argc)) {
fprintf(stderr, "%s", "wmir: arguments: ");
for (i = 1; i < argc; i++)
fprintf(stderr, "%s, ", argv[i]);
fprintf(stderr, "%s", "\n");
usage();
}
if (!sockfile) {
fprintf(stderr, "%s",
"wmir: error: WMIR_SOCKET environment not set\n");
usage();
}
/* open socket */
if (!ixp_client_init(&c, sockfile)) {
fprintf(stderr, "wmir: %s\n", c.errstr);
exit(1);
}
/* wether perform directly or read from stdin */
if (read_stdin) {
char *_argv[3];
int _argc;
while (fgets(line, 4096, stdin))
if ((_argc = cext_tokenize(_argv, 3, line, ' '))) {
if ((ret = perform_cmd(_argc, _argv)))
break;
}
} else
ret = perform_cmd(argc - (i + 1), &argv[i]);
/* close socket */
ixp_client_deinit(&c);
return ret;
}