/* * cmdui.c - simple network user interface for ezxd * * Copyright (c) 2007 Daniel Ribeiro * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "ezxd.h" extern int eval_cmd(unsigned int, char *, struct sb *); int cmdui_setup_socket () { struct sockaddr_in addr; int ret = -1; #ifdef DEBUG char *error; #endif if ((sfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { error("socket() failed"); goto end; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(7100); if (bind(sfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { error("bind() failed"); goto end; } if (listen(sfd, 0) < 0) { error("listen() failed"); goto end; } return 0; end: dbg("failed to setup cmd_ui socket (%s)\n", error); return ret; } int cmdui_new_connection(int s) { int c, r; #ifdef DEBUG char *error; #endif if ((r = accept(s, NULL, 0)) < 0) goto end; for (c=0;cinp = NULL; clients[c]->outp = NULL; clients[c]->fd = r; memset(clients[c]->outb, 0, sizeof(clients[c]->outb)); memset(clients[c]->inb, 0, sizeof(clients[c]->inb)); dbg ("new connection at sock %d\n", r); return 0; close: close(r); end: return -1; } static int cmdui_close_connection(int s) { int c; for (c=0;cfd == s)) break; if (c == MAX_CLIENTS) return -1; dbg("closing sock %d\n", s); shutdown(s, SHUT_RDWR); close(s); free(clients[c]); clients[c] = NULL; return 0; } int cmdui_read_cmd (struct sb *client) { int l, s = sizeof(client->inb); char *sep; if (!client->inp) client->inp = client->inb; l = read(client->fd, client->inp, s-(client->inp-client->inb)); if (l < 1) { cmdui_close_connection(client->fd); return -1; } client->inp += l; while (client->inp && (sep = strstr(client->inb, "\r")) != NULL) { sep[0] = 0; sep++; dbg("evaluating: '%s'\n", client->inb); if (sep[0] == '\n') sep++; eval_cmd(0, client->inb, client); if(client->inp == sep) client->inp = NULL; else { memmove(client->inb, sep, client->inp-sep); client->inp = client->inb + (client->inp-sep); client->inp[0] = 0; } } /* prevent buffer overflow condition */ if (client->inp == (client->inb+s)) { cmdui_close_connection(client->fd); return -1; } return 0; } int cmdui_real_write(struct sb *client) { int l, s = strlen(client->outb); if (!client->outp) client->outp = client->outb; l = write (client->fd, client->outp, s-(client->outp-client->outb)); if (l < 1) { cmdui_close_connection(client->fd); return -1; } if (l == (s-(client->outp-client->outb))) { client->outb[0] = 0; client->outp = NULL; } else client->outp += l; return 0; } int cmdui_write(struct sb *client, char *str) { int s = strlen(str)+1; int l = strlen(client->outb); if ((s+l) > sizeof(client->outb)) return -1; memmove(client->outb+l, str, s); return 0; }