aboutsummaryrefslogtreecommitdiff
path: root/unsaver.c
diff options
context:
space:
mode:
Diffstat (limited to 'unsaver.c')
-rw-r--r--unsaver.c110
1 files changed, 79 insertions, 31 deletions
diff --git a/unsaver.c b/unsaver.c
index eceb4d3..a612ff2 100644
--- a/unsaver.c
+++ b/unsaver.c
@@ -47,16 +47,16 @@ typedef enum {
/* user options */
int interval = DEFAULT_INTERVAL; /* -i (always in millisec) */
-int debug = 0; /* -D */
+int debug = 0; /* -d */
int keycode = -1; /* -k */
int button = -1; /* -b */
-char *event_dir = EVENTDIR; /* -d */
+const char *event_dir = EVENTDIR; /* joydev args can change this */
char *js_node_name = JSNODE; /* -j */
int autodiscover = 1; /* cleared if user supplies joydev args */
fake_mode_t fake_mode = fm_auto_keycode; /* -k, -b, -m */
char *c_command = NULL; /* -c, -x */
-int monitor_joysticks = 1; /* -F */
-int monitor_fullscreen = 0; /* -f, -F */
+int monitor_joysticks = 1; /* -f clears this */
+int monitor_fullscreen = 1; /* -j clears this */
/* joystick stuff */
char *joynames[MAX_STICKS + 1];
@@ -77,8 +77,8 @@ struct inotify_event *inotify_ev = (struct inotify_event *)inotify_buf;
/* not going to include pages of usage info duplicating the man page */
void usage(void) {
printf(PROJ " v" VERSION " by B. Watson, WTFPL\n");
- printf("Usage: %s [-i interval] [-b button | -k keycode] [-j name]\n", self);
- printf(" [-d dir] [-D] [joystick [...]]\n");
+ printf("Usage: %s [-i interval] [-m | -b button | -k keycode | -c command | -x]\n", self);
+ printf(" [-j | -f ] [-d] [inputdir] [joystick [...]]\n");
printf("Built-in defaults: MAX_STICKS=%d, -d " EVENTDIR ", -j " JSNODE "\n", MAX_STICKS);
printf("See man page for details\n");
exit(0);
@@ -206,6 +206,39 @@ void send_fake_x_event(void) {
}
}
+/* wrapper for open(2), does an ioctl to make sure the thing it just
+ opened really is a joystick. also warns on 'permission denied'. */
+int js_open(const char *path, int mode) {
+ int fd, res, ver;
+
+ fd = open(path, mode);
+
+ if(fd < 0 && errno == EACCES)
+ fprintf(stderr, "%s: warning: %s exists, but: %s\n",
+ self, path, strerror(errno));
+
+ if(fd > -1) {
+ res = ioctl(fd, JSIOCGVERSION, &ver);
+
+ if(res < 0) {
+ if(errno == ENOTTY || errno == EINVAL) {
+ fprintf(stderr, "%s: file %s is not a joystick\n", self, path);
+ exit(1);
+ } else {
+ fprintf(stderr, "%s: %s: %s\n", self, path, strerror(errno));
+ exit(1);
+ }
+ }
+
+ /* don't really need this much detail:
+ if(debug)
+ fprintf(stderr, "joystick driver version 0x%x\n", ver);
+ */
+ }
+
+ return fd;
+}
+
void open_joysticks(void) {
int fdcount, i;
struct js_event e;
@@ -214,7 +247,7 @@ void open_joysticks(void) {
for(i = 0; i < last_joyname; i++) {
int synthev = 0;
if(joyfds[i] > -1) close(joyfds[i]);
- joyfds[i] = open(joynames[i], O_RDONLY | O_NONBLOCK);
+ joyfds[i] = js_open(joynames[i], O_RDONLY | O_NONBLOCK);
if(joyfds[i] > -1) {
fdcount++;
while( (read(joyfds[i], &e, sizeof(e)) > 0) && (e.type & JS_EVENT_INIT) )
@@ -389,7 +422,7 @@ void set_exe_name(const char *argv0) {
if(p[0] == '/' && p[1]) self = p + 1;
}
-char *make_joystick_name(int js) {
+char *joy_num_to_name(int js) {
static char buf[PATH_MAX + 1];
sprintf(buf, "%s/%s%d", event_dir, js_node_name, js);
return buf;
@@ -407,7 +440,7 @@ void add_joystick_name(const char *name) {
}
if(*name >= '0' && *name <= '9') {
- add_joystick_name(make_joystick_name(atoi(name)));
+ add_joystick_name(joy_num_to_name(atoi(name)));
return;
}
@@ -415,16 +448,30 @@ void add_joystick_name(const char *name) {
die(strerror(errno));
if(debug)
- fprintf(stderr, "added device name %d: %s\n", last_joyname, name);
+ fprintf(stderr, "added device %d: %s\n", last_joyname, joynames[last_joyname]);
last_joyname++;
}
+void add_joystick_num(char *arg) {
+ int i;
+ char *end;
+
+ i = strtol(arg, &end, 0);
+
+ if(end == arg || *end || i < 0) {
+ fprintf(stderr, "%s: invalid joystick number: %s\n", self, arg);
+ exit(1);
+ }
+
+ add_joystick_name(joy_num_to_name(i));
+}
+
void populate_joynames(void) {
int i;
for(i = 0; i < MAX_STICKS; i++) {
- add_joystick_name(make_joystick_name(i));
+ add_joystick_name(joy_num_to_name(i));
}
}
@@ -474,7 +521,7 @@ void parse_args(int argc, char **argv) {
while(++argv, --argc) {
if(argv[0][0] != '-') {
/* no dash, treat as a joystick device */
- add_joystick_name(*argv);
+ add_joystick_num(*argv);
autodiscover = 0;
} else {
if(argv[0][1] && argv[0][2])
@@ -516,22 +563,6 @@ void parse_args(int argc, char **argv) {
die("-i requires a positive integer argument in milliseconds");
break;
case 'd':
- if(nextarg) {
- event_dir = nextarg;
- argv++, argc--;
- } else {
- die("-d requires a directory argument");
- }
- break;
- case 'j':
- if(nextarg) {
- js_node_name = nextarg;
- argv++, argc--;
- } else {
- die("-j requires a string argument");
- }
- break;
- case 'D':
debug = 1;
break;
case 'c':
@@ -547,10 +578,11 @@ void parse_args(int argc, char **argv) {
set_fake_mode(fm_cmd);
c_command = X_COMMAND;
break;
- case 'F':
- monitor_joysticks = 0; /* and fall thru */
case 'f':
- monitor_fullscreen = 1;
+ monitor_joysticks = 0;
+ break;
+ case 'j':
+ monitor_fullscreen = 0;
break;
default:
die("unrecognized argument, try --help");
@@ -558,6 +590,9 @@ void parse_args(int argc, char **argv) {
}
}
}
+
+ if(!monitor_joysticks && !monitor_fullscreen)
+ die("nothing to monitor (can't use -f and -j together)");
}
/* make ourselves a daemon, double-fork technique.
@@ -731,9 +766,22 @@ void print_banner() {
self, VERSION, m, interval);
}
+void read_env_vars(void) {
+ char *tmp;
+
+ if( (tmp = getenv("UNSAVER_JS_DIR")) )
+ event_dir = tmp;
+
+ if( (tmp = getenv("UNSAVER_JS_NODE")) )
+ js_node_name = tmp;
+
+}
+
int main(int argc, char **argv) {
set_exe_name(argv[0]);
+ read_env_vars();
+
parse_args(argc, argv);
print_banner();