Mercurial > hg > RemoteEditor > vim7
view src/reditor.c @ 30:bf9fabc0ae84 almost-works
*** empty log message ***
author | kono |
---|---|
date | Tue, 28 Oct 2008 01:42:44 +0900 |
parents | ef6d2a18d7c2 |
children | 8d4ffb7c9f4e |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <unistd.h> #include <errno.h> #include "vim.h" #include "reditor.h" /* Global variables of Vim */ #include "globals.h" /* Wrapper for Vim */ static void e_msg_wrp(char *msg); static void free_wrp(void *p); static BUFTYPE* make_new_buf_wrp(char *name); static void free_buf_wrp(BUFTYPE *buf); static BUFTYPE* find_buf_by_name_wrp(char *name); static void open_buffer_memline_wrp(BUFTYPE *buf); static BUFTYPE* get_curbuf_wrp(); static BUFTYPE* set_curbuf_wrp(BUFTYPE *buf); static char* get_memline_wrp(BUFTYPE *buf, long lnum); static int append_memline_wrp(long lnum, char *text); static int delete_memline_wrp(long lnum); static void update_screen_now_wrp(); static char *get_fullpath_wrp(BUFTYPE *buf); /* Wrapper END */ static rep_T* get_rep(); static int rep_connect(char *host); static void rep_free(void *obj); static BUFTYPE* get_buf_by_name(char *name); static Session* init_session(Session *sn); static Session* make_session(char *name, BUFTYPE *buf); static void free_session(Session *sn); static void free_session_list(Session *head); static Session* set_cursession(Session *sn); static Session* find_session_by_buf(BUFTYPE *buf); // static Session* find_session_by_name(char *name); static char* get_fullpath(Session *session); static Session * get_waiting_session(int sid, char *text) ; static void set_waiting_session(Session *session); static int writen(int fd, char *textbuf, unsigned int len); static rep_cmd* make_cmd(unsigned int cmd, unsigned int sid, unsigned int eid, unsigned int seq, unsigned int lnum, unsigned int length, char *text); static void forwardCommand(rep_T *rep, rep_cmd *command); static void set_cmd_seq( rep_cmd *command, unsigned int cmd, unsigned int seq); static int free_cmd(rep_cmd *cmd); static int free_cmdlist(rep_cmdlist *cmdlist); static void add_cmd_to_list(rep_cmdlist *cmdlist, rep_cmd *cmd); static unsigned int get_header(char *buf,int offset); static int set_header(unsigned int num, char *pkt, int offset); static int rep_exe_cmd(rep_cmd *command); static int rep_exe_pktlist(rep_cmdlist *cmdlist); static int rep_recv_cmds(int fd, rep_cmdlist *txtcmdlist); static int rep_send_cmds(int fd, rep_cmdlist *cmdlist); static int rep_send_cmd( int fd, rep_cmd *cur); /* g_rep has an all information of Remote Editor */ static rep_T g_rep; int lock_editor = 0; /* * Wrapper for vim */ /* エラーメッセージ出力 */ static void e_msg_wrp(msg) char * msg; { EMSG(msg); } /* 通常のメッセージを出力 */ void puts_msg_wrp(msg) char * msg; { MSG_PUTS(msg); } static void free_wrp(p) void *p; { vim_free(p); return; } /* 空の新しいバッファを取得 */ static BUFTYPE * make_new_buf_wrp(name) char * name; { return buflist_new((char_u*)name, NULL, 0, BLN_LISTED); } static void free_buf_wrp(buf) BUFTYPE *buf; { close_buffer(NULL, buf, DOBUF_DEL); return; } /* 名前からバッファへのポインタを取得 */ static BUFTYPE * find_buf_by_name_wrp(name) char * name; { char *sfname = NULL; // sfname is used name's address BUFTYPE *buf = NULL; //??? fname_expand(buf, (char_u**)&name, (char_u**)&sfname); buf = buflist_findname((char_u*)name); free_wrp(name); return buf; } static void open_buffer_memline_wrp(buf) BUFTYPE *buf; { BUFTYPE *oldbuf; oldbuf = curbuf; curbuf = buf; open_buffer(FALSE, NULL); curbuf = oldbuf; return; } /* 現在編集中のバッファへのポインタを取得 */ extern BUFTYPE *curbuf; static BUFTYPE * get_curbuf_wrp() { return curbuf; } /* buf を編集対象にする。 *それまで編集対象だったバッファへのポインタを返す */ static BUFTYPE * set_curbuf_wrp(buf) BUFTYPE *buf; { BUFTYPE *cb; if (buf == NULL) return NULL; cb = get_curbuf_wrp(); set_curbuf(buf,DOBUF_GOTO); return cb; } /* 指定した行番号の行のテキスト(文字列)のポインタを取得 */ static char * get_memline_wrp(buf, lnum) BUFTYPE *buf; // buf is curbuf long lnum; { return (char*)ml_get_buf(buf, lnum, FALSE); } /* 編集中のバッファの行の挿入 */ static int append_memline_wrp(lnum, text) long lnum; char *text; { int r; int permit; rep_T *rep; rep = get_rep(); permit = rep->permit; rep->permit = FALSE; r = ml_append(lnum, (char_u*)text, strlen(text)+1, FALSE); appended_lines_mark(lnum,1); rep->permit = permit; return r; } /* 編集中のバッファの行数を返す */ long get_bufmaxline_wrp(buf) BUFTYPE *buf; { return buf->b_ml.ml_line_count; } /* 編集中のバッファの行の削除 */ static int delete_memline_wrp(lnum) long lnum; { int r; int permit; rep_T *rep; rep = get_rep(); permit = rep->permit; rep->permit = FALSE; int maxline = get_bufmaxline_wrp(get_curbuf_wrp()); if (lnum+1>maxline) return 0; r = ml_delete(lnum+1, FALSE); deleted_lines_mark(lnum+1,1); rep->permit = permit; return r; } /* バッファの編集後の後処理 */ static void update_screen_now_wrp() { check_cursor(); update_screen(CLEAR); return; } /* get full path of buffer */ static char * get_fullpath_wrp(buf) BUFTYPE *buf; { return (char*)buf->b_ffname; } /* Wrapper END */ static void puts_sys_err() { char *err = strerror(errno); char *errmsg = (char*)alloca(strlen(err)+50); sprintf(errmsg, "rep>> %d:%s", errno, err); e_msg_wrp(errmsg); return; } static rep_T* get_rep() { return(&g_rep); } int rep_permit() { return(g_rep.permit); } int rep_session_permit() { return(g_rep.permit && g_rep.cursession && g_rep.cursession->permit); } void rep_start_create_cmds() { if (g_rep.cursession) { g_rep.cursession->permit = TRUE; } return; } void rep_stop_create_cmds() { if (g_rep.cursession) { g_rep.cursession->permit = FALSE; } return; } int rep_init() { /* * g_rep is global variable and it is zero cleared. */ char def_hostname[] = "localhost"; // 現在編集対象のバッファはセッションに加える? g_rep.shead = NULL; g_rep.cursession = NULL; g_rep.servername = NULL; g_rep.waiting_session = NULL; g_rep.smfd = -1; g_rep.eid = 0; g_rep.seqno = 0; g_rep.prevSeq = 0; g_rep.syncMode = 0; g_rep.permit = FALSE; #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 255 #endif g_rep.hostname = (char *)malloc(HOST_NAME_MAX); if (gethostname(g_rep.hostname, sizeof(g_rep.hostname)) < 0) { strncpy(g_rep.hostname, def_hostname, sizeof(def_hostname)+1); } g_rep.nop = make_cmd(REPCMD_NOP, 0, 0, 0, 0, 0, ""); return TRUE; } static char default_host[] = "localhost"; static int rep_connect(host) char *host; /* "hostname:portnumber" */ { int sock; struct hostent *hp; struct sockaddr_in sin; char *tmp; int port; if (host == NULL || *host == '\n') { host = default_host; port = REP_PORT; } else { if ((tmp = strchr(host, ':')) == NULL ) { return(-1); } *tmp = '\0'; tmp++; port = atol(tmp); } if ((hp = gethostbyname(host)) == NULL) { e_msg_wrp("rep_open: gethostbyname: ERROR"); return(-1); } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { e_msg_wrp("rep_open: socket : ERROR"); return(-1); } bzero(&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port); bcopy(hp->h_addr, &sin.sin_addr, hp->h_length); if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) { e_msg_wrp("rep_open: connect: ERROR"); return(-1); } return(sock); } static BUFTYPE * get_buf_by_name(name) char *name; { BUFTYPE *buf; if ((buf = find_buf_by_name_wrp(name)) == NULL) { buf = make_new_buf_wrp(name); } if (buf && (buf->b_ml.ml_mfp == NULL)) { open_buffer_memline_wrp(buf); } return buf; } /* About Session */ static Session * init_session(sn) Session *sn; { sn->next = NULL; sn->buf = NULL; sn->sname = NULL; sn->new_cmdlist.head = NULL; sn->new_cmdlist.num = 0; sn->sent_cmdlist.head = NULL; sn->sent_cmdlist.num = 0; sn->sid = 0; sn->permit = FALSE; sn->prevline = -1; sn->del_cmd = 0; return sn; } /* * Make a new session. * if buf is NULL, buffer is found or made new one. */ static Session * make_session(name, buf) char *name; BUFTYPE *buf; { Session *s; char *sname; int namelen = strlen(name)+1; s = (Session*)malloc(sizeof(Session)); if (s == NULL) { return(NULL); } if ((sname = (char*)malloc(namelen)) == NULL) { return NULL; } strncpy(sname,name,namelen); init_session(s); if (buf == NULL) buf = get_buf_by_name(sname); s->buf = buf; s->sname = sname; return s; } static void free_session(sn) Session *sn; { free_cmdlist(&sn->new_cmdlist); free_cmdlist(&sn->sent_cmdlist); free_buf_wrp(sn->buf); if (sn->sname) rep_free(sn->sname); init_session(sn); rep_free(sn); return; } static void free_session_list(head) Session *head; { Session *next; for (; head; head=next) { next = head->next; head->next = NULL; free_session(head); } return; } static Session * get_waiting_session(int sid, char *text) { rep_T *rep = get_rep(); Session *session = rep->waiting_session; if (session==NULL) return session; rep->waiting_session = session->next; session->sid = sid; if (text!=0) { // set session name to the buffer update_screen_now_wrp(); } return session; } static Session* set_cursession(sn) Session *sn; { BUFTYPE *oldbuf = NULL; Session *oldsn; rep_T *rep = get_rep(); if (sn) oldbuf = set_curbuf_wrp(sn->buf); rep->cursession = sn; oldsn = find_session_by_buf(oldbuf); return oldsn; } static Session* find_session_by_id(id) unsigned int id; { Session *cursn = NULL; rep_T *rep = get_rep(); for (cursn = rep->shead; cursn; cursn = cursn->next) { if (cursn->sid == id) { return cursn; } } return NULL; } static Session* find_session_by_buf(buf) BUFTYPE *buf; { Session *cursn = NULL; rep_T *rep = get_rep(); if (buf == NULL) return NULL; for (cursn = rep->shead; cursn; cursn = cursn->next) { if (cursn->buf == buf) break; } return cursn; } /* static Session* find_session_by_name(name) char *name; { BUFTYPE *buf; buf = find_buf_by_name_wrp(name); return find_session_by_buf(buf); } */ static char* get_fullpath(session) Session *session; { BUFTYPE *buf; if (session == NULL) { buf = get_curbuf_wrp(); } else { buf = session->buf; } return get_fullpath_wrp(buf); } static Session * append_session(Session *s1,Session *s2) { Session *s3=s1; if (s1==NULL) return s2; while(s1->next) s1 = s1->next; s1->next = s2; return s3; } static void set_waiting_session(Session *session) { rep_T *rep = get_rep(); rep->waiting_session = append_session(rep->waiting_session,session); } /* End Session */ static int rep_join_put(int cmd) { int sock; rep_T *rep; rep = get_rep(); if ((sock = rep_connect(NULL)) < 0) { return FALSE; } if (rep->smfd > 0) { close(rep->smfd); } rep->smfd = sock; rep->permit = TRUE; /* get current buffer name */ char *sname; if ((sname = get_fullpath(rep->cursession)) == NULL) { sname =NO_NAME; /* the buffer has not name */ } BUFTYPE *buf = get_curbuf_wrp(); Session *session = make_session(sname,buf); set_waiting_session(session); rep_cmd *command = make_cmd(cmd, 0, rep->eid, rep->seqno++, 0, 0, ""); forwardCommand(rep, command); free_cmd(command); return TRUE; } int rep_join() { return rep_join_put(SMCMD_JOIN); } int rep_put() { return rep_join_put(SMCMD_PUT); } int rep_remove() { rep_T *rep = get_rep(); rep_cmd *cmd; Session *sn = rep->cursession; if (rep->smfd < 0) { /* session does not exist */ EMSG("Session does not exist."); return FALSE; } cmd = make_cmd(REPCMD_CLOSE, sn->sid, rep->eid, rep->seqno, 0, 0, ""); forwardCommand(rep,cmd); free_cmd(cmd); return TRUE; } /* Session End */ static void rep_free(obj) void *obj; { if (obj) vim_free(obj); return; } static int writen(sock, pkt, len) int sock; char *pkt; unsigned int len; { int offset; int written; if (len == 0) return 0; for (offset=0, written=0; offset<len; offset += written) { if ((written = write(sock, pkt + offset, len - offset)) < 0) { puts_sys_err(); return written; } } return offset; } static int readn(sock, pkt, len) int sock; char *pkt; unsigned int len; { unsigned int r; unsigned int offset; if (len == 0) return 0; for (offset=0, r=0; offset<len; offset += r) { if ((r = read(sock, pkt + offset, len - offset)) < 0) { puts_sys_err(); return r; } else if (r==0) return 0; } return offset; } static void make_packet(command, cmd, sid, eid, seq, lnum, len, text) rep_cmd *command; unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; unsigned int len; char * text; { char *packet = &command->pkt[0]; set_header(cmd, packet, REP_CMD_OFFSET); set_header(sid, packet, REP_SID_OFFSET); set_header(eid, packet, REP_EID_OFFSET); set_header(seq, packet, REP_SEQNUM_OFFSET); set_header(lnum, packet, REP_LNUM_OFFSET); set_header(len, packet, REP_T_SIZE_OFFSET); if (text && len>0) { memcpy(packet+REP_TEXT_OFFSET, text, len); } return; } static rep_cmd* make_cmd(cmd, sid, eid, seq, lnum, length, text) unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; unsigned int length; char *text; { rep_cmd *cmd_p; cmd_p = (rep_cmd*)malloc(sizeof(rep_cmd)+REP_HEADER_SIZE+length); if (cmd_p == NULL) return(NULL); cmd_p->next = NULL; cmd_p->cmd = cmd; cmd_p->sid = sid; cmd_p->eid = eid; cmd_p->seq = seq; cmd_p->len = length; cmd_p->lnum = lnum; make_packet(cmd_p, cmd, sid, eid, seq, lnum, length, text); return(cmd_p); } static void set_cmd_seq(cmd_p,cmd,seq) rep_cmd *cmd_p; unsigned int cmd; unsigned int seq; { char *packet = &cmd_p->pkt[0]; cmd_p->seq = seq; cmd_p->cmd = cmd; set_header(cmd, packet, REP_CMD_OFFSET); set_header(seq, packet, REP_SEQNUM_OFFSET); } static int free_cmd(cmd) rep_cmd *cmd; { if (cmd == NULL) return(FALSE); rep_free(cmd); return(TRUE); } static int free_cmdlist(cmdlist) rep_cmdlist *cmdlist; { rep_cmd *cur; rep_cmd *next; if (cmdlist->head==NULL) return(FALSE); for (cur=cmdlist->head; cur; cur=next) { next=cur->next; free_cmd(cur); } cmdlist->head = NULL; cmdlist->num = 0; return(TRUE); } static void add_cmd_to_list(cmdlist, cmd) rep_cmdlist *cmdlist; rep_cmd *cmd; { rep_cmd *p; int count = 0; for (p=cmd; p; p=p->next) count++; if (cmdlist->head) { for (p = cmdlist->head; p->next; p = p->next); p->next = cmd; } else { cmdlist->head = cmd; } cmdlist->num += count; return; } /* Before any line changes, keep the lines as DELETE_LINE_CMD. xtr==0 ml_replace xtr==1 ml_append xtr==-1 ml_delete */ void rep_prevline_flush(int lnum, int xtr) { BUFTYPE *cbuf; Session *cursn; rep_cmd *cmd; rep_T *rep = get_rep(); cursn = rep->cursession; if (cursn == NULL) return; // バッファが変更された場合には rep->cursession も合わす if ((cbuf = get_curbuf_wrp()) != cursn->buf) { cursn = find_session_by_buf(cbuf); if (cursn == NULL) return; rep->cursession = cursn; } if(cursn->prevline!=lnum&&xtr!=0) { if (cursn->del_cmd) { // Cancel delete cmd rep_free(cursn->del_cmd); cursn->del_cmd = 0; } } cursn->prevline=lnum; if (xtr<0) { // ml_delete case char *text = get_memline_wrp(cursn->buf, lnum); unsigned int length = strlen(text); cmd = make_cmd(REPCMD_DELETE, cursn->sid, rep->eid, rep->seqno++, cursn->prevline-1, length, text); rep_send_cmd(rep->smfd,cmd); rep_free(cmd); if (cursn->del_cmd) { // Cancel delete cmd rep_free(cursn->del_cmd); cursn->del_cmd = 0; } } else if (xtr==0) { // ml_replace case if (cursn->del_cmd) return; // already line saved do nothing char *text = get_memline_wrp(cursn->buf, lnum); unsigned int length = strlen(text); cursn->del_cmd = make_cmd(REPCMD_DELETE, cursn->sid, rep->eid, rep->seqno++, cursn->prevline-1, length, text); } else { // ml_append case // do nothing } } /* * channged_common から呼ばれて、変更をREP commandに直して * 送信する。 */ void rep_register(lnum, lnume, xtra) unsigned int lnum; unsigned int lnume; int xtra; { int i; BUFTYPE *cbuf; Session *cursn; rep_cmd *cmd; rep_T *rep = get_rep(); if ((cursn = rep->cursession) == NULL) return ; // バッファが変更された場合には rep->cursession も合わす if ((cbuf = get_curbuf_wrp()) != cursn->buf) { cursn = find_session_by_buf(cbuf); if (cursn == NULL) return ; rep->cursession = cursn; } if (xtra<0) { // delete case, the command was sent, do nothing cursn->prevline=-1; } else if (xtra>0) { // append case for(i=lnum;i<lnum+xtra;i++) { char *text = get_memline_wrp(cursn->buf, i); unsigned int length = strlen(text); // make INSERT_CMD for insert or changed lines if any cmd = make_cmd(REPCMD_INSERT, cursn->sid, rep->eid, rep->seqno++, i-1, length, text); rep_send_cmd(rep->smfd,cmd); free_cmd(cmd); } cursn->prevline=-1; } else if (xtra==0) { // replace case // send saved DELETE command if (cursn->del_cmd!=0) { cmd = cursn->del_cmd; rep_send_cmd(rep->smfd,cmd); rep_free(cmd); cmd=0; cursn->del_cmd = 0; } else { // first insert case? } cursn->prevline = lnum; // send saved new line as INSERT command char *text = get_memline_wrp(cursn->buf, lnum); unsigned int length = strlen(text); cmd = make_cmd(REPCMD_INSERT, cursn->sid, rep->eid, rep->seqno++, cursn->prevline-1, length,text); rep_send_cmd(rep->smfd,cmd); // reuse cmd // save current line for next replace set_cmd_seq(cmd,REPCMD_DELETE,rep->seqno++); cursn->del_cmd = cmd; } } static int set_header(data, pkt, offset) unsigned int data; char *pkt; int offset; { int *ipkt; int ndata = htonl(data); ipkt = (int*)pkt; ipkt[offset/4] = ndata; return(TRUE); } static unsigned int get_header(pkt, offset) char *pkt; int offset; { int *ipkt; int data; unsigned int header; ipkt = (int *)pkt; data = ipkt[offset/4]; header = (unsigned int)ntohl(data); return(header); } /* REP command packet flow Own change CMD ------> session manager session manager <--- CMD command return <------ MERGE_START (block user input) <------ Merge fix from session manager CMD ------> session manager return same command as ack <------ MERGE_END command return (enable user input) session manager <--- CMD incomming external command NOP ------> session manager if we have sent any command CMD ------> session manager return same command as ack */ static void forwardCommand(rep_T *rep, rep_cmd *command) { int fd = rep->smfd; writen(fd,command->pkt,command->len+REP_HEADER_SIZE); } static void incrementSeq(rep_T *rep) { rep->seqno++; } static void addNop(int sid, rep_T *rep) { int fd = rep->smfd; char *packet = &rep->nop->pkt[0]; if (rep->prevSeq==rep->seqno) { set_header(sid, packet, REP_SID_OFFSET); set_header(rep->eid, packet, REP_EID_OFFSET); set_header(rep->seqno, packet, REP_SEQNUM_OFFSET); rep->prevSeq = rep->seqno; incrementSeq(rep); writen(fd,rep->nop->pkt,rep->nop->len+REP_HEADER_SIZE); } } static int rep_exe_cmd(command) rep_cmd *command; { char *text = command->pkt+REP_TEXT_OFFSET; int eid = command->eid; rep_T *rep = get_rep(); Session *session; session = find_session_by_id(command->sid); switch (command->cmd) { case SMCMD_JOIN_ACK: { session = get_waiting_session(command->sid,text); set_cursession(session); rep_start_create_cmds(); rep->eid = command->eid; char *msg = alloca(150); sprintf(msg,"joined eid=%d sid=%d",rep->eid,session->sid); e_msg_wrp(msg); rep->prevSeq = rep->seqno; } break; case SMCMD_PUT_ACK: { /* Enter Session */ session = get_waiting_session(command->sid,text); /* set session to cursession */ set_cursession(session); rep_start_create_cmds(); rep->eid = command->eid; char *msg = alloca(150); sprintf(msg,"put eid=%d sid=%d",rep->eid,session->sid); e_msg_wrp(msg); rep->prevSeq = rep->seqno; } break; case REPCMD_INSERT: append_memline_wrp(command->lnum, text); if (eid!=MERGE_EID) addNop(command->sid, rep); forwardCommand(rep,command); if (eid!=MERGE_EID) update_screen_now_wrp(); break; case REPCMD_DELETE: delete_memline_wrp(command->lnum); if (eid!=MERGE_EID) update_screen_now_wrp(); case REPCMD_NOP: if (eid!=MERGE_EID) addNop(command->sid, rep); forwardCommand(rep,command); break; case SMCMD_SYNC: rep->syncMode = 1; set_cmd_seq(command,SMCMD_SYNC_ACK,rep->seqno++); forwardCommand(rep,command); break; case SMCMD_QUIT: forwardCommand(rep,command); break; case SMCMD_START_MERGE: lock_editor = 1; set_cmd_seq(command,SMCMD_START_MERGE_ACK,rep->seqno++); forwardCommand(rep,command); break; case SMCMD_END_MERGE: lock_editor = 0; rep->prevSeq = rep->seqno; update_screen_now_wrp(); default: break; } free_cmd(command); return(TRUE); } /* execute command list based cmd packet */ static int rep_exe_pktlist(cmdlist) rep_cmdlist *cmdlist; { rep_cmd *repcmd; if ((cmdlist == NULL) || (cmdlist->head == NULL)) { return(FALSE); } for (repcmd = cmdlist->head; repcmd; repcmd = repcmd->next) { rep_exe_cmd(repcmd); } return(TRUE); } static int rep_recv_cmds(fd, txtcmdlist) int fd; rep_cmdlist *txtcmdlist; { unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; unsigned int textsize; rep_cmd *cmd_p ; char *text; char *header; if (fd < 0) { return(FALSE); } if ((cmd_p = (rep_cmd *)malloc(sizeof(rep_cmd)+128)) == NULL) return FALSE; text = &cmd_p->pkt[REP_TEXT_OFFSET]; header = &cmd_p->pkt[0]; /* read header part */ if (readn(fd, header, REP_HEADER_SIZE) <= 0) { puts_sys_err(); return(FALSE); } cmd = get_header(header, REP_CMD_OFFSET); sid = get_header(header, REP_SID_OFFSET); eid = get_header(header, REP_EID_OFFSET); seq = get_header(header, REP_SEQNUM_OFFSET); lnum = get_header(header, REP_LNUM_OFFSET); textsize = get_header(header, REP_T_SIZE_OFFSET); if ((cmd_p = (rep_cmd *)realloc(cmd_p,sizeof(rep_cmd)+textsize)) == NULL) return FALSE; if (textsize > 0) { /* read text part */ if (readn(fd, text, textsize) <= 0) { puts_sys_err(); rep_free(cmd_p); return(FALSE); } text[textsize] = 0; } cmd_p->next = NULL; cmd_p->cmd = cmd; cmd_p->sid = sid; cmd_p->eid = eid; cmd_p->seq = seq; cmd_p->len = textsize; cmd_p->lnum = lnum; add_cmd_to_list(txtcmdlist, cmd_p); return(TRUE); } void rep_send_cur_cmdlist() { rep_T *rep_p = get_rep(); rep_send_cmds(rep_p->smfd,&(rep_p->cursession->new_cmdlist)); free_cmdlist(&rep_p->cursession->sent_cmdlist); rep_p->cursession->sent_cmdlist.head = rep_p->cursession->new_cmdlist.head; rep_p->cursession->sent_cmdlist.num = rep_p->cursession->new_cmdlist.num; rep_p->cursession->new_cmdlist.head = NULL; rep_p->cursession->new_cmdlist.num = 0; return; } static int rep_send_cmd(fd,cur) int fd; rep_cmd *cur; { return writen(fd,cur->pkt,cur->len+REP_HEADER_SIZE ); } static int rep_send_cmds(fd,cmdlist) int fd; rep_cmdlist *cmdlist; { rep_cmd *cur; if ((fd<0) || (cmdlist == NULL)) { return(FALSE); } if ((cmdlist->head == NULL) || (cmdlist->num == 0)) { return(TRUE); } for (cur = cmdlist->head; cur; cur = cur->next) { if (writen(fd,cur->pkt,cur->len+REP_HEADER_SIZE)==FALSE) { return(FALSE); } } return(TRUE); } int rep_fd_check(fd, rfds_p, efds_p) int fd; // input from keyboard or something... fd_set *rfds_p; // readable fds fd_set *efds_p; // include a error fd { rep_T *rep_p; rep_cmdlist txtcmdlist = {NULL,0}; rep_p = get_rep(); if ((rep_p->smfd > 0) && (FD_ISSET(rep_p->smfd, rfds_p))) { if (rep_recv_cmds(rep_p->smfd, &(txtcmdlist)) == FALSE) { close(rep_p->smfd); rep_p->smfd = -1; } else { rep_exe_pktlist(&txtcmdlist); } } if (FD_ISSET(fd, rfds_p) || FD_ISSET(fd, efds_p)) { return(TRUE); } return FALSE; } int rep_fd_set(rfds_p, efds_p, max_fds) fd_set *rfds_p; fd_set *efds_p; int max_fds; { rep_T *rep_p; rep_p = get_rep(); if (rep_p->smfd > 0) { FD_SET(rep_p->smfd,rfds_p); FD_SET(rep_p->smfd,efds_p); if(max_fds < rep_p->smfd){ max_fds = rep_p->smfd; } } return(max_fds); } void rep_close(int i) { rep_T *rep_p; rep_p = get_rep(); // What should I do? rep_end(); } /* * read などで待つ場合に、この関数で REP 関連のデータをチェックする * 指定した fd ( read で読みこむ) から入力があるとぬける。 */ int rep_select(fd) int fd; { fd_set rfds_p; fd_set efds_p; int sk; int max_fds = MAX_FDS; struct timeval zerotime; zerotime.tv_sec = 0; zerotime.tv_usec = 0; if (fd < 0) return FALSE; for(;;) { /* select の中で modify されてるので、初期化 */ // struct timeval tv; // tv.tv_sec = 0; // tv.tv_usec = 100000; FD_ZERO(&rfds_p); FD_ZERO(&efds_p); FD_SET(fd,&rfds_p); max_fds = rep_fd_set(&rfds_p, &efds_p, max_fds); if ((sk = select(max_fds+1, &rfds_p, NULL, &efds_p, NULL)) < 0) { if (errno == EBADF){ int i; for(i = 0;i < max_fds;i++){ fd_set suspect; FD_ZERO(&suspect); if (FD_ISSET(i, &rfds_p)){ FD_SET(i, &suspect); if (select(max_fds, &suspect, NULL, NULL, &zerotime) == FAIL){ FD_CLR(i, &rfds_p); rep_close(i); // we have to something to prevent to write to this // port... return(TRUE); } FD_CLR(i, &suspect); } } } else { e_msg_wrp("rep_select(): ERROR"); return(FALSE); } } if ( rep_fd_check(fd, &rfds_p, &efds_p)) return TRUE; // fd に入力があったので抜ける } } void rep_end() { rep_T *rep_p; rep_p = get_rep(); if (rep_p->shead) free_session_list(rep_p->shead); // cursession is freed if (rep_p->servername) free_wrp(rep_p->servername); if (rep_p->smfd > 0) close(rep_p->smfd); set_curbuf_wrp(rep_p->scratch_buf); rep_init(); } extern void pcmd(cmd_p) rep_cmd *cmd_p; { int i; fprintf(stderr,"cmd=%04x",cmd_p->cmd ); fprintf(stderr,"sid=%08x", cmd_p->sid); fprintf(stderr,"eid=%08x", cmd_p->eid); fprintf(stderr,"seq=%08x", cmd_p->seq); fprintf(stderr,"lineno=%08x", cmd_p->lnum); fprintf(stderr,"sz=%08x", cmd_p->len); fprintf(stderr,"\n"); for(i=0;i<cmd_p->len+REP_HEADER_SIZE;i++) { fprintf(stderr,"%02x ", cmd_p->pkt[i]); } fprintf(stderr,"\n"); } /* end */