Exemple #1
0
/*
 * make_add - stick a single add onto the queue
 */
static void 
make_add(int modifier, KeySym keysym)
{
    union op *uop;
    struct op_addmodifier *opam;

    uop = AllocStruct (union op);
    if (!uop) {
	badmsg ("attempt to allocate %ld byte addmodifier opcode",
		(long) sizeof (struct op_addmodifier));
	return;
    }
    opam = &uop->addmodifier;

    opam->type = doAddModifier;
    opam->modifier = modifier;
    opam->count = 1;
    opam->keysyms = (KeySym *) malloc (sizeof (KeySym));
    if (!opam->keysyms) {
	badmsg ("attempt to allocate %ld byte KeySym", (long) sizeof (KeySym));
	free ((char *) opam);
	return;
    }
    opam->keysyms[0] = keysym;

    add_to_work_queue (uop);
    return;
}
Exemple #2
0
/*
 * make_remove - stick a single remove onto the queue
 */
static void 
make_remove(int modifier, KeyCode keycode)
{
    union op *uop;
    struct op_removemodifier *oprm;

    uop = AllocStruct (union op);
    if (!uop) {
	badmsg ("attempt to allocate %ld byte removemodifier opcode",
		(long) sizeof (struct op_removemodifier));
	return;
    }
    oprm = &uop->removemodifier;

    oprm->type = doRemoveModifier;
    oprm->modifier = modifier;
    oprm->count = 1;
    oprm->keycodes = (KeyCode *) malloc (sizeof (KeyCode));
    if (!oprm->keycodes) {
	badmsg ("attempt to allocate %ld byte KeyCode",
		(long) sizeof (KeyCode));
	free ((char *) oprm);
	return;
    }
    oprm->keycodes[0] = keycode;

    add_to_work_queue (uop);
    return;
}
Exemple #3
0
static void 
do_add(char *line, int len)
{
    int n;
    int modifier;
    KeySym *kslist;
    union op *uop;
    struct op_addmodifier *opam;

    if (len < 6 || !line || *line == '\0') {  /* Lock=a minimum */
	badmsg0 ("add modifier input line");
	return;
    }

    n = skip_chars (line, len);
    if (n < 1) {
	badmsg ("add modifier name %s", line);
	return;
    }

    modifier = parse_modifier (line, n);
    if (modifier < 0) {
	badmsgn ("add modifier name '%s', not allowed", line, n);
	return;
    }

    line += n, len -= n;
    n = skip_until_char (line, len, '=');
    if (n < 0) {
	badmsg0 ("add modifier = keysym");
	return;
    }

    n++;				/* skip = */
    n += skip_space (line+n, len-n);
    line += n, len -= n;

    if (get_keysym_list (line, len, &n, &kslist) < 0)
	return;
    if (n == 0) {
	badmsg0 ("add modifier keysym list (empty)");
	return;
    }

    uop = AllocStruct (union op);
    if (!uop) {
	badmsg ("attempt to allocate %ld byte addmodifier opcode",
		(long) sizeof (struct op_addmodifier));
	return;
    }
    opam = &uop->addmodifier;

    opam->type = doAddModifier;
    opam->modifier = modifier;
    opam->count = n;
    opam->keysyms = kslist;

    add_to_work_queue (uop);
}
Exemple #4
0
static int
authtisfn(Conn *c)
{
	int fd, n;
	char *chal, resp[256];
	Msg *m;

	if(!c->interactive)
		return -1;

	debug(DBG_AUTH, "try TIS\n");
	sendmsg(allocmsg(c, SSH_CMSG_AUTH_TIS, 0));

	m = recvmsg(c, -1);
	switch(m->type){
	default:
		badmsg(m, SSH_SMSG_AUTH_TIS_CHALLENGE);
	case SSH_SMSG_FAILURE:
		free(m);
		return -1;
	case SSH_SMSG_AUTH_TIS_CHALLENGE:
		break;
	}

	chal = getstring(m);
	free(m);

	if((fd = open("/dev/cons", ORDWR)) < 0)
		error("can't open console");

	fprint(fd, "TIS Authentication\n%s", chal);
	n = read(fd, resp, sizeof resp-1);
	if(n < 0)
		resp[0] = '\0';
	else
		resp[n] = '\0';

	if(resp[0] == 0 || resp[0] == '\n')
		return -1;

	m = allocmsg(c, SSH_CMSG_AUTH_TIS_RESPONSE, 4+strlen(resp));
	putstring(m, resp);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	default:
		badmsg(m, 0);
	case SSH_SMSG_SUCCESS:
		free(m);
		return 0;
	case SSH_SMSG_FAILURE:
		free(m);
		return -1;
	}
}
Exemple #5
0
void 
handle_line(char *line,		/* string to parse */
	    int len)		/* length of line */
{
    int n;
    struct dt *dtp;

    n = skip_chars (line, len);
    if (n < 0) {
	badmsg ("input line '%s'", line);
	return;
    }

    for (dtp = dispatch_table; dtp->command != NULL; dtp++) {
	if (n == dtp->length &&
	    strncmp (line, dtp->command, dtp->length) == 0) {

	    n += skip_space (line+n, len-n);
	    line += n, len -= n;

	    (*(dtp->proc)) (line, len);
	    return;
	}
    }

    fprintf (stderr, "%s:  unknown command on line %s:%d\n",
	     ProgramName, inputFilename, lineno+1);
    parse_errors++;
}
Exemple #6
0
static int
authpasswordfn(Conn *c)
{
	Msg *m;
	UserPasswd *up;

	up = auth_getuserpasswd(c->interactive ? auth_getkey : nil, "proto=pass service=ssh server=%q user=%q", c->host, c->user);
	if(up == nil){
		debug(DBG_AUTH, "getuserpasswd returned nothing (interactive=%d)\n", c->interactive);
		return -1;
	}

	debug(DBG_AUTH, "try using password from factotum\n");
	m = allocmsg(c, SSH_CMSG_AUTH_PASSWORD, 4+strlen(up->passwd));
	putstring(m, up->passwd);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	default:
		badmsg(m, 0);
	case SSH_SMSG_SUCCESS:
		free(m);
		return 0;
	case SSH_SMSG_FAILURE:
		free(m);
		return -1;
	}
}
Exemple #7
0
static int
authuser(Conn *c)
{
	int i;
	Msg *m;

	m = allocmsg(c, SSH_CMSG_USER, 4+strlen(c->user));
	putstring(m, c->user);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	case SSH_SMSG_SUCCESS:
		free(m);
		return 0;
	case SSH_SMSG_FAILURE:
		free(m);
		break;
	default:
		badmsg(m, 0);
	}

	for(i=0; i<c->nokauth; i++){
		debug(DBG_AUTH, "authmask %#lux, consider %s (%#x)\n",
			c->authmask, c->okauth[i]->name, 1<<c->okauth[i]->id);
		if(c->authmask & (1<<c->okauth[i]->id))
			if((*c->okauth[i]->fn)(c) == 0)
				return 0;
	}

	debug(DBG_AUTH, "no auth methods worked; (authmask=%#lux)\n", c->authmask);
	return -1;
}
Exemple #8
0
int
startagent(Conn *c)
{
	int ret;
	Msg *m;

	m = allocmsg(c, SSH_CMSG_AGENT_REQUEST_FORWARDING, 0);
	sendmsg(m);

	m = recvmsg(c, -1);
	switch(m->type){
	case SSH_SMSG_SUCCESS:
		debug(DBG_AUTH, "agent allocated\n");
		ret = 0;
		break;
	case SSH_SMSG_FAILURE:
		debug(DBG_AUTH, "agent failed to allocate\n");
		ret = -1;
		break;
	default:
		badmsg(m, 0);
		ret = -1;
		break;
	}
	free(m);
	return ret;
}
Exemple #9
0
static void 
do_keysym(char *line, int len)
{
    int n;
    KeyCode *keycodes;
    KeySym keysym;
    char *tmpname;

    if (len < 3 || !line || *line == '\0') {  /* a=b minimum */
	badmsg0 ("keysym input line");
	return;
    }

    n = skip_chars (line, len);
    if (n < 1) {
	badmsg0 ("target keysym name");
	return;
    }
    if (!parse_keysym(line, n, &tmpname, &keysym)) {
	badmsg ("keysym target key symbol '%s'", tmpname);
	return;
    }

    keycodes = KeysymToKeycodes (dpy, keysym, &n);
    if (n == 0) {
	badmsg ("keysym target keysym '%s', no corresponding keycodes",
		tmpname);
	return;
    }
    if (verbose) {
	int i;
	printf ("! Keysym %s (0x%lx) corresponds to keycode(s)",
		tmpname, (long) keysym);
	for (i = 0; i < n; i++)
	    printf (" 0x%x", keycodes[i]);
	printf("\n");
    }

    finish_keycodes (line, len, keycodes, n);
}
Exemple #10
0
static void
authsrvuser(Conn *c)
{
	int i;
	char *ns, *user;
	AuthInfo *ai;
	Msg *m;

	m = recvmsg(c, SSH_CMSG_USER);
	user = getstring(m);
	c->user = emalloc(strlen(user)+1);
	strcpy(c->user, user);
	free(m);

	ai = authusername(c);
	while(ai == nil){
		/*
		 * clumsy: if the client aborted the auth_tis early
		 * we don't send a new failure.  we check this by
		 * looking at c->unget, which is only used in that
		 * case.
		 */
		if(c->unget != nil)
			goto skipfailure;
		sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
	skipfailure:
		m = recvmsg(c, -1);
		for(i=0; i<c->nokauthsrv; i++)
			if(c->okauthsrv[i]->firstmsg == m->type){
				ai = (*c->okauthsrv[i]->fn)(c, m);
				break;
			}
		if(i==c->nokauthsrv)
			badmsg(m, 0);
	}
	sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));

	if(noworld(ai->cuid))
		ns = "/lib/namespace.noworld";
	else
		ns = nil;
	if(auth_chuid(ai, ns) < 0){
		sshlog("auth_chuid to %s: %r", ai->cuid);
		sysfatal("auth_chuid: %r");
	}
	sshlog("logged in as %s", ai->cuid);
	auth_freeAI(ai);
}
Exemple #11
0
static void 
finish_keycodes(const char *line, int len, KeyCode *keycodes, int count)
{
    int n;
    KeySym *kslist;
    union op *uop;
    struct op_keycode *opk;
   
    n = skip_until_char (line, len, '=');
    line += n, len -= n;
    
    if (len < 1 || *line != '=') {	/* = minimum */
	badmsg0 ("keycode command (missing keysym list),");
	return;
    }
    line++, len--;			/* skip past the = */

    n = skip_space (line, len);
    line += n, len -= n;

    /* allow empty list */
    if (get_keysym_list (line, len, &n, &kslist) < 0)
	return;

    while (--count >= 0) {
	uop = AllocStruct (union op);
	if (!uop) {
	    badmsg ("attempt to allocate a %ld byte keycode opcode",
		    (long) sizeof (struct op_keycode));
	    return;
	}
	opk = &uop->keycode;

	opk->type = doKeycode;
	opk->target_keycode = keycodes[count];
	opk->count = n;
	opk->keysyms = kslist;

	add_to_work_queue (uop);
    }

#ifdef later
    /* make sure we handle any special keys */
    check_special_keys (keycode, n, kslist);
#endif
}
Exemple #12
0
static void 
do_clear(char *line, int len)
{
    int n;
    int modifier;
    union op *uop;
    struct op_clearmodifier *opcm;

    if (len < 4 || !line || *line == '\0') {  /* Lock minimum */
	badmsg0 ("clear modifier input line");
	return;
    }

    n = skip_chars (line, len);

    modifier = parse_modifier (line, n);
    if (modifier < 0) {
	badmsgn ("clear modifier name '%s'", line, n);
	return;
    }
    n += skip_space (line+n, len-n);
    if (n != len) {
	badmsgn ("extra argument '%s' to clear modifier", line+n, len-n);
	/* okay to continue */
    }

    uop = AllocStruct (union op);
    if (!uop) {
	badmsg ("attempt to allocate %ld byte clearmodifier opcode",
		(long) sizeof (struct op_clearmodifier));
	return;
    }
    opcm = &uop->clearmodifier;

    opcm->type = doClearModifier;
    opcm->modifier = modifier;

    add_to_work_queue (uop);
}
Exemple #13
0
void
requestpty(Conn *c)
{
	char *term;
	int nrow, ncol, width, height;
	Msg *m;

	m = allocmsg(c, SSH_CMSG_REQUEST_PTY, 1024);
	if((term = getenv("TERM")) == nil)
		term = "9term";
	putstring(m, term);

	readgeom(&nrow, &ncol, &width, &height);
	putlong(m, nrow);	/* characters */
	putlong(m, ncol);
	putlong(m, width);	/* pixels */
	putlong(m, height);

	if(rawhack)
		putbytes(m, rawptyopt, sizeof rawptyopt);
	else
		putbytes(m, ptyopt, sizeof ptyopt);

	sendmsg(m);

	m = recvmsg(c, 0);
	switch(m->type){
	case SSH_SMSG_SUCCESS:
		debug(DBG_IO, "PTY allocated\n");
		break;
	case SSH_SMSG_FAILURE:
		debug(DBG_IO, "PTY allocation failed\n");
		break;
	default:
		badmsg(m, 0);
	}
	free(m);
}
Exemple #14
0
static int 
get_keysym_list(const char *line, int len, int *np, KeySym **kslistp)
{
    int havesofar, maxcanhave;
    KeySym *keysymlist;

    *np = 0;
    *kslistp = NULL;

    if (len == 0) return (0);		/* empty list */

    havesofar = 0;
    maxcanhave = 4;			/* most lists are small */
    keysymlist = (KeySym *) malloc (maxcanhave * sizeof (KeySym));
    if (!keysymlist) {
	badmsg ("attempt to allocate %ld byte initial keysymlist",
		(long) (maxcanhave * sizeof (KeySym)));
	return (-1);
    }

    while (len > 0) {
	KeySym keysym;
	int n;
	char *tmpname;
	Bool ok;

	n = skip_space (line, len);
	line += n, len -= n;

	n = skip_chars (line, len);
	if (n < 0) {
	    badmsg0 ("keysym name list");
	    free(keysymlist);
	    return (-1);
	}

	ok = parse_keysym (line, n, &tmpname, &keysym);
	line += n, len -= n;
	if (!ok) {
	    badmsg ("keysym name '%s' in keysym list", tmpname);
	    /* do NOT return here, look for others */
	    continue;
	}

	/*
	 * Do NOT test to see if the keysym translates to a keycode or you
	 * won't be able to assign new ones....
	 */

	/* grow the list bigger if necessary */
	if (havesofar >= maxcanhave) {
	    KeySym *origkeysymlist = keysymlist;
	    maxcanhave *= 2;
	    keysymlist = (KeySym *) realloc (keysymlist,
					     maxcanhave * sizeof (KeySym));
	    if (!keysymlist) {
		badmsg ("attempt to grow keysym list to %ld bytes",
			(long) (maxcanhave * sizeof (KeySym)));
		free(origkeysymlist);
		return (-1);
	    }
	}

	/* and add it to the list */
	keysymlist[havesofar++] = keysym;
    }

    *kslistp = keysymlist;
    *np = havesofar;
    return (0);
}
Exemple #15
0
static int
authrsafn(Conn *c)
{
	uint8_t chalbuf[32+SESSIDLEN], response[MD5dlen];
	char *s, *p;
	int afd, ret;
	AuthRpc *rpc;
	Msg *m;
	mpint *chal, *decr, *unpad, *mod;

	debug(DBG_AUTH, "rsa!\n");

	if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0){
		debug(DBG_AUTH, "open /mnt/factotum/rpc: %r\n");
		return -1;
	}
	if((rpc = auth_allocrpc(afd)) == nil){
		debug(DBG_AUTH, "auth_allocrpc: %r\n");
		close(afd);
		return -1;
	}
	s = "proto=rsa role=client";
	if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){
		debug(DBG_AUTH, "auth_rpc start %s failed: %r\n", s);
		auth_freerpc(rpc);
		close(afd);
		return -1;
	}

	ret = -1;
	debug(DBG_AUTH, "trying factotum rsa keys\n");
	while(auth_rpc(rpc, "read", nil, 0) == ARok){
		debug(DBG_AUTH, "try %s\n", (char*)rpc->arg);
		mod = strtomp(rpc->arg, nil, 16, nil);
		m = allocmsg(c, SSH_CMSG_AUTH_RSA, 16+(mpsignif(mod)+7/8));
		putmpint(m, mod);
		sendmsg(m);
		mpfree(mod);
		m = recvmsg(c, -1);
		switch(m->type){
		case SSH_SMSG_FAILURE:
			debug(DBG_AUTH, "\tnot accepted %s\n",
			      (char*)rpc->arg);
			free(m);
			continue;
		default:
			badmsg(m, 0);
		case SSH_SMSG_AUTH_RSA_CHALLENGE:
			break;
		}
		chal = getmpint(m);
		debug(DBG_AUTH, "\tgot challenge %B\n", chal);
		free(m);
		p = mptoa(chal, 16, nil, 0);
		mpfree(chal);
		if(p == nil){
			debug(DBG_AUTH, "\tmptoa failed: %r\n");
			unpad = mpnew(0);
			goto Keepgoing;
		}
		if(auth_rpc(rpc, "write", p, strlen(p)) != ARok){
			debug(DBG_AUTH, "\tauth_rpc write failed: %r\n");
			free(p);
			unpad = mpnew(0);	/* it will fail, we'll go round again */
			goto Keepgoing;
		}
		free(p);
		if(auth_rpc(rpc, "read", nil, 0) != ARok){
			debug(DBG_AUTH, "\tauth_rpc read failed: %r\n");
			unpad = mpnew(0);
			goto Keepgoing;
		}
		decr = strtomp(rpc->arg, nil, 16, nil);
		debug(DBG_AUTH, "\tdecrypted %B\n", decr);
		unpad = rsaunpad(decr);
		debug(DBG_AUTH, "\tunpadded %B\n", unpad);
		mpfree(decr);
	Keepgoing:
		mptoberjust(unpad, chalbuf, 32);
		mpfree(unpad);
		debug(DBG_AUTH, "\trjusted %.*H\n", 32, chalbuf);
		memmove(chalbuf+32, c->sessid, SESSIDLEN);
		debug(DBG_AUTH, "\tappend sesskey %.*H\n", 32, chalbuf);
		md5(chalbuf, 32+SESSIDLEN, response, nil);
		m = allocmsg(c, SSH_CMSG_AUTH_RSA_RESPONSE, MD5dlen);
		putbytes(m, response, MD5dlen);
		sendmsg(m);

		m = recvmsg(c, -1);
		switch(m->type){
		case SSH_SMSG_FAILURE:
			free(m);
			continue;
		default:
			badmsg(m, 0);
		case SSH_SMSG_SUCCESS:
			break;
		}
		ret = 0;
		break;
	}
	auth_freerpc(rpc);
	close(afd);
	return ret;
}
Exemple #16
0
void
fromnet(Conn *c)
{
	int infd, kidpid, n;
	char *cmd;
	Msg *m;

	infd = kidpid = -1;
	for(;;){
		m = recvmsg(c, -1);
		if(m == nil)
			exits(nil);
		switch(m->type){
		default:
			//badmsg(m, 0);
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
			break;

		case SSH_MSG_DISCONNECT:
			sysfatal("client disconnected");

		case SSH_CMSG_REQUEST_PTY:
			sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
			break;

		case SSH_CMSG_X11_REQUEST_FORWARDING:
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
			break;

		case SSH_CMSG_MAX_PACKET_SIZE:
			maxmsg = getlong(m);
			sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
			break;

		case SSH_CMSG_REQUEST_COMPRESSION:
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
			break;

		case SSH_CMSG_EXEC_SHELL:
			startcmd(c, nil, &kidpid, &infd);
			goto InteractiveMode;

		case SSH_CMSG_EXEC_CMD:
			cmd = getstring(m);
			startcmd(c, cmd, &kidpid, &infd);
			goto InteractiveMode;
		}
		free(m);
	}

InteractiveMode:
	for(;;){
		free(m);
		m = recvmsg(c, -1);
		if(m == nil)
			exits(nil);
		switch(m->type){
		default:
			badmsg(m, 0);

		case SSH_MSG_DISCONNECT:
			postnote(PNGROUP, kidpid, "hangup");
			sysfatal("client disconnected");

		case SSH_CMSG_STDIN_DATA:
			if(infd != 0){
				n = getlong(m);
				write(infd, getbytes(m, n), n);
			}
			break;

		case SSH_CMSG_EOF:
			close(infd);
			infd = -1;
			break;

		case SSH_CMSG_EXIT_CONFIRMATION:
			/* sent by some clients as dying breath */
			exits(nil);
	
		case SSH_CMSG_WINDOW_SIZE:
			/* we don't care */
			break;
		}
	}
}
Exemple #17
0
void
fromnet(Conn *c)
{
	int fd, len;
	char *s, *es, *r, *w;
	uint32_t ex;
	char buf[64];
	Msg *m;

	for(;;){
		m = recvmsg(c, -1);
		if(m == nil)
			break;
		switch(m->type){
		default:
			badmsg(m, 0);

		case SSH_SMSG_EXITSTATUS:
			ex = getlong(m);
			if(ex==0)
				exits(0);
			sprint(buf, "%lu", ex);
			exits(buf);

		case SSH_MSG_DISCONNECT:
			s = getstring(m);
			error("disconnect: %s", s);

		/*
		 * If we ever add reverse port forwarding, we'll have to
		 * revisit this.  It assumes that the agent connections are
		 * the only ones.
		 */
		case SSH_SMSG_AGENT_OPEN:
			if(!forwardagent)
				error("server tried to use agent forwarding");
			handleagentopen(m);
			break;
		case SSH_MSG_CHANNEL_INPUT_EOF:
			if(!forwardagent)
				error("server tried to use agent forwarding");
			handleagentieof(m);
			break;
		case SSH_MSG_CHANNEL_OUTPUT_CLOSED:
			if(!forwardagent)
				error("server tried to use agent forwarding");
			handleagentoclose(m);
			break;
		case SSH_MSG_CHANNEL_DATA:
			if(!forwardagent)
				error("server tried to use agent forwarding");
			handleagentmsg(m);
			break;

		case SSH_SMSG_STDOUT_DATA:
			fd = outfd;
			goto Dataout;
		case SSH_SMSG_STDERR_DATA:
			fd = 2;
			goto Dataout;
		Dataout:
			len = getlong(m);
			s = (char*)getbytes(m, len);
			if(crstrip){
				es = s+len;
				for(r=w=s; r<es; r++)
					if(*r != '\r')
						*w++ = *r;
				len = w-s;
			}
			write(fd, s, len);
			break;
		}
		free(m);
	}
}		
Exemple #18
0
static void 
do_pointer(char *line, int len)
{
    int n;
    int i;
    unsigned long val;
    union op *uop;
    struct op_pointer *opp;
    unsigned char buttons[MAXBUTTONCODES];
    int nbuttons;
    char *strval;
    Bool ok;

    if (len < 2 || !line || *line == '\0') {  /* =1 minimum */
	badmsg0 ("buttons input line");
	return;
    }

    nbuttons = XGetPointerMapping (dpy, buttons, MAXBUTTONCODES);

    n = skip_space (line, len);
    line += n, len -= n;

    if (line[0] != '=') {
	badmsg0 ("buttons pointer code list, missing equal sign");
	return;
    }

    line++, len--;			/* skip = */
    n = skip_space (line, len);
    line += n, len -= n;

    i = 0;
    if (len < 7 || strncasecmp (line, "default", 7) != 0) {
	while (len > 0) {
	    n = skip_space (line, len);
	    line += n, len -= n;
	    if (line[0] == '\0') break;
	    n = skip_word (line, len);
	    if (n < 1) {
		badmsg ("skip of word in buttons line:  %s", line);
		return;
	    }
	    strval = copy_to_scratch(line, n);
	    ok = parse_number (strval, &val);
	    if (!ok || val >= MAXBUTTONCODES) {
		badmsg ("value %s given for buttons list", strval);
		return;
	    }
	    buttons[i++] = (unsigned char) val;
	    line += n, len -= n;
	}
    }
    
    if (i > 0 && i != nbuttons) {
	fprintf (stderr, "Warning: Only changing the first %d of %d buttons.\n",
		 i, nbuttons);
	i = nbuttons;
    }

    uop = AllocStruct (union op);
    if (!uop) {
	badmsg ("attempt to allocate a %ld byte pointer opcode",
		(long) sizeof (struct op_pointer));
	return;
    }
    opp = &uop->pointer;

    opp->type = doPointer;
    opp->count = i;
    for (i = 0; i < opp->count; i++) {
	opp->button_codes[i] = buttons[i];
    }

    add_to_work_queue (uop);
}
Exemple #19
0
static void 
do_remove(char *line, int len)
{
    int n;
    int nc;
    int i;
    int tot;
    int modifier;
    KeySym *kslist;
    KeyCode *kclist;
    union op *uop;
    struct op_removemodifier *oprm;

    if (len < 6 || !line || *line == '\0') {  /* Lock=a minimum */
	badmsg0 ("remove modifier input line");
	return;
    }

    n = skip_chars (line, len);
    if (n < 1) {
	badmsg ("remove modifier name %s", line);
	return;
    }

    modifier = parse_modifier (line, n);
    if (modifier < 0) {
	badmsgn ("remove modifier name '%s', not allowed", line, n);
	return;
    }

    line += n, len -= n;
    n = skip_until_char (line, len, '=');
    if (n < 0) {
	badmsg0 ("remove modifier = keysym");
	return;
    }

    n++;
    n += skip_space (line+n, len-n);
    line += n, len -= n;

    if (get_keysym_list (line, len, &n, &kslist) < 0)
	return;
    if (n == 0) {
	badmsg0 ("remove modifier keysym list (empty)");
	return;
    }

    /*
     * unlike the add command, we have to now evaluate the keysyms
     */

    kclist = (KeyCode *) malloc (n * sizeof (KeyCode));
    if (!kclist) {
	badmsg ("attempt to allocate %ld byte keycode list",
		(long) (n * sizeof (KeyCode)));
	free ((char *) kslist);
	return;
    }

    tot = n;
    nc = 0;
    for (i = 0; i < n; i++) {
        int num_kcs;
	KeyCode *kcs;
	kcs = KeysymToKeycodes (dpy, kslist[i], &num_kcs);
	if (num_kcs == 0) {
	    char *tmpname = XKeysymToString (kslist[i]);
	    badmsg ("keysym in remove modifier list '%s', no corresponding keycodes",
		    tmpname ? tmpname : "?");
	    continue;
	}
	if (verbose) {
	    int j;
	    char *tmpname = XKeysymToString (kslist[i]);
	    printf ("! Keysym %s (0x%lx) corresponds to keycode(s)", 
		    tmpname ? tmpname : "?", (long) kslist[i]);
	    for (j = 0; j < num_kcs; j++)
		printf(" 0x%x", kcs[j]);
	    printf("\n");
	}
	if (nc + num_kcs > tot) {
	    tot = nc + num_kcs;
	    kclist = (KeyCode *)realloc((char *)kclist, tot * sizeof(KeyCode));
	    if (!kclist) {
		badmsg ("attempt to allocate %ld byte keycode list",
			(long) (tot * sizeof (KeyCode)));
		free ((char *) kslist);
		return;
	    }
	}
	while (--num_kcs >= 0)
	    kclist[nc++] = *kcs++;		/* okay, add it to list */
    }

    free ((char *) kslist);		/* all done with it */

    uop = AllocStruct (union op);
    if (!uop) {
	badmsg ("attempt to allocate %ld byte removemodifier opcode",
		(long) sizeof (struct op_removemodifier));
	return;
    }
    oprm = &uop->removemodifier;

    oprm->type = doRemoveModifier;
    oprm->modifier = modifier;
    oprm->count = nc;
    oprm->keycodes = kclist;

    add_to_work_queue (uop);
}