Mercurial > hg > RemoteEditor > vim7
view src/reditor.c @ 12:f0f9a028aa7c
*** empty log message ***
author | shinobu |
---|---|
date | Sat, 30 Aug 2008 21:30:44 +0900 |
parents | bb64d8561b7b |
children | 1e44fe6dcfaa |
line wrap: on
line source
#include <stdio.h> #include <strings.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 e_msg2_wrp(char *msg1, char *msg2); static void puts_msg_wrpt(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 int replace_memline_wrp(long lnum, char *text); static void update_screen_now_wrp(); static void update_screen_later_wrp(BUFTYPE *buf); static long get_bufmaxline_wrp(BUFTYPE* buf); static char* getstr_input_wrp(char *msg); static char *get_fullpath_wrp(BUFTYPE *buf); static char *get_shortname_wrp(BUFTYPE *buf); /* Wrapper END */ static rep_T* get_rep(); static int del_ignored_cmd(rep_cmdlist *cmdlist); static int translate(rep_cmdlist *userlist, rep_cmdlist *tokenlist); static void set_header_to_pkt(rep_cmdlist *cmdlist); static int rep_get_listened_fd(); static int set_hostnamebysock(int sock, char *hostname, int maxlen); static int rep_accept(); static int rep_connect(char *host); static void* rep_alloc(int size); 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 void register_session(Session *sn); static Session* set_cursession(Session *sn); static Session* find_session_by_buf(BUFTYPE *buf); static Session* find_session_by_name(char *name); static int set_session_info(char *dest_sinfo, char *sname, char *hostname, int port); static char* get_fullpath(Session *session); static char* get_shortname(Session *session); static int make_local_slineup(Session *slineup, char *hostname, Session *my_sessions); static int get_slineup_from_sm(char *servername, Session *slineup, char *hostname, Session *my_sessions); static char* get_sname_by_snum(int snum); static int writen(int fd, char *textbuf, unsigned int len); static char* make_packet(unsigned int cmd, unsigned int sid, unsigned int eid, unsigned int seq, unsigned int lnum, char *text); static char* make_open_packet(char *file_name); static rep_cmd* make_cmd(unsigned int cmd, unsigned int sid, unsigned int eid, unsigned int seq, unsigned int lnum, char *text); 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 int add_pkt_to_list(rep_cmdlist *cmdlist, char *pkt); static void check_line_change(Session *sn, unsigned int lnum); 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(unsigned int cmd, unsigned int sid, unsigned int eid, unsigned int seq, unsigned int lnum, unsigned int textsize, char *text); static int rep_exe_pkt(char *pkt); static int rep_exe_pktlist(rep_cmdlist *cmdlist); static int rep_exe_cmdlist(rep_cmdlist *cmdlist); static int rep_recv_cmds(int fd, rep_cmdlist *smcmdlist,rep_cmdlist *txtcmdlist); static int rep_send_cmds(int fd, rep_cmdlist *cmdlist); static int session_fd_check(Session *sn, fd_set *rfds_p, fd_set *efds_p); static int session_fd_set(Session *sn, fd_set *rfds_p, fd_set *efds_p, int max_fds); static int append_newline_sep_text(Session *sn, char *text); /* g_rep has an all information of Remote Editor */ rep_T g_rep; /* * Wrapper for vim */ /* エラーメッセージ出力 */ static void e_msg_wrp(msg) char * msg; { EMSG(msg); } static void e_msg2_wrp(msg1, msg2) char * msg1; char * msg2; { EMSG2(msg1,msg2); } /* 通常のメッセージを出力 */ static 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; BUFTYPE *orgbuf; /* make a full file name. name is changed to absolute path. * name's address is assigned to sfname. */ 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 = set_curbuf_wrp(buf); set_curbuf_wrp(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 ml_get(lnum); return (char*)ml_get_buf(buf, lnum, FALSE); } /* 編集中のバッファの行の挿入 */ /* "text" does NOT need to be allocated */ 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-1, (char_u*)text, strlen(text)+1, FALSE); appended_lines_mark(lnum-1,1); rep->permit = permit; return r; } /* 編集中のバッファの行の削除 */ static int delete_memline_wrp(lnum) long lnum; { int r; int permit; rep_T *rep; rep = get_rep(); permit = rep->permit; rep->permit = FALSE; r = ml_delete(lnum, FALSE); deleted_lines_mark(lnum,1); rep->permit = permit; return r; } /* 編集中のバッファの行の置換 */ static int replace_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_replace(lnum, (char_u*)text, TRUE); rep->permit = permit; return r; } /* バッファの編集後の後処理 */ static void update_screen_now_wrp() { check_cursor(); update_screen(CLEAR); return; } static void update_screen_later_wrp(buf) BUFTYPE *buf; { check_cursor(); return redraw_buf_later(buf, CLEAR); } /* 編集中のバッファの行数を返す */ static long get_bufmaxline_wrp(buf) BUFTYPE *buf; { return buf->b_ml.ml_line_count; } /* XXX もう使わないので消す予定 */ /* ユーザに文字列を入力させる */ static char * getstr_input_wrp(msg) char *msg; // 入力時のメッセージ { char *cmdline; /* 受け取る文字列は使用後 vim_free() する */ // cmdline = (char*)getcmdline_prompt('@', (char_u*)msg, 0); cmdline = NULL; return cmdline; } /* get full path of buffer */ static char * get_fullpath_wrp(buf) BUFTYPE *buf; { return (char*)buf->b_ffname; } /* get short name of buffer */ static char * get_shortname_wrp(buf) BUFTYPE *buf; { return (char*)buf->b_sfname; } /* Wrapper END */ static void puts_sys_err() { char errmsg[50]; sprintf(errmsg, "rep>> %d:%s", errno, strerror(errno)); 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; //make_session(); g_rep.slineup = NULL; g_rep.cursession = NULL; g_rep.servername = NULL; g_rep.waiting_session_name = NULL; g_rep.smfd = -1; g_rep.eid = 0; g_rep.seqno = 0; g_rep.permit = FALSE; if (gethostname(g_rep.hostname, sizeof(g_rep.hostname)) < 0) { strncpy(g_rep.hostname, def_hostname, sizeof(def_hostname)+1); } return(TRUE); } /* * cmdlistを辿り、statメンバが REP_IGNORE であるREPコマンドを削除する。 */ static int del_ignored_cmd(cmdlist) rep_cmdlist *cmdlist; { rep_cmd *curcmd; rep_cmd *next; for (;(cmdlist->head) && (cmdlist->head->stat == REP_IGNORE); cmdlist->head=next) { next = cmdlist->head->next; free_cmd(cmdlist->head); } if (cmdlist->head == NULL) return(TRUE); for (curcmd=cmdlist->head; curcmd->next;) { next = curcmd->next->next; if (curcmd->next->stat == REP_IGNORE) { free_cmd(curcmd->next); curcmd->next = next; cmdlist->num--; } else { curcmd = curcmd->next; } } return(TRUE); } /***** translate(UserList, ToknList) ***** 入力はトークンとユーザ入力からのREPコマンドのリストで、 それらを比較・変換して、二つのREPコマンドリストを生成する。 ------------- UserList ->| | -> UserList' | translate | ToknList ->| | -> ToknList' ------------- Session ID が異なるときは、可換なので、何もしない。 ToknList + UserList' をトークンとして次のリモートエディタに渡し、 ToknList' は自分のバッファに反映させる。 比較時に行番号が重なったときの処理は以下の表。 なるべくテキストが残るようにしている。 x\y は、TOKEN を x, USER を y するという意味。 0 -- なにもしない +1 -- 行番号を +1 i -- コマンド id を 'i' にする。 X -- コマンドを削除(無視に)する。 USER | i | r | d ---|-------------------- T i | 0\+1 | 0\+1 | 0\+1 O ---|-------------------- K r | +1\0 | 0\X | i\X E ---|-------------------- N d | +1\0 | X\i | X\X 無視にされた(stat に REP_IGNORE が入っている)REPコマンドは、 全ての比較が終了したときにリストから削除される。 */ static int translate(userlist, tokenlist) /* userのREPコマンドリスト, tokenのREPコマンドリスト */ rep_cmdlist *userlist; rep_cmdlist *tokenlist; { rep_cmd *usercmd; rep_cmd *tokencmd; rep_cmd *unext; rep_cmd *tnext; rep_cmd *h_pricmd; // high priority command rep_cmd *l_pricmd; // low priority command for (usercmd=userlist->head; usercmd; usercmd=unext) { unext = usercmd->next; /* 削除される(予定)のREPコマンドの比較は無視 */ if (usercmd->stat == REP_IGNORE) continue; for (tokencmd=tokenlist->head; tokencmd; tokencmd=tnext) { tnext=tokencmd->next; /* 削除される(予定)のREPコマンドの比較は無視 */ if (tokencmd->stat == REP_IGNORE) continue; /* XXX 消してもいい??*/ if ( tokencmd->cmd != REP_INSERT_CMD && tokencmd->cmd != REP_DELETE_LINE_CMD && tokencmd->cmd != REP_REPLACE_CMD) { tokencmd->stat = REP_IGNORE; continue; } if (usercmd->stat == REP_IGNORE) break; if ( usercmd->cmd != REP_INSERT_CMD && usercmd->cmd != REP_DELETE_LINE_CMD && usercmd->cmd != REP_REPLACE_CMD) { usercmd->stat = REP_IGNORE; break; } if (usercmd->sid != tokencmd->sid) { // session id が違う場合は何しない continue; } if (usercmd->lnum < tokencmd->lnum) { /* UsersLineNumber < TokensLineNumber */ if (usercmd->cmd == REP_INSERT_CMD) { tokencmd->lnum++; } else if (usercmd->cmd == REP_DELETE_LINE_CMD) { tokencmd->lnum--; } } else if (usercmd->lnum > tokencmd->lnum) { /* UsersLineNumber > TokensLineNumber */ if (tokencmd->cmd == REP_INSERT_CMD) { usercmd->lnum++; } else if (tokencmd->cmd == REP_DELETE_LINE_CMD) { usercmd->lnum--; } } else if (usercmd->lnum == tokencmd->lnum) { /* UsersLineNumber == TokensLineNumber */ #if 0 /* * 行番号が重なるとREPコマンドの競合が起こるので、 * どちらかが譲らないといけない。 * uid が小さい方を優先(h_pricmdに)し、 * uid が大きい方(l_pricmd)を変更する。 */ if (usercmd->eid < tokencmd->eid) { h_pricmd = usercmd; l_pricmd = tokencmd; } else { h_pricmd = tokencmd; l_pricmd = usercmd; } #else /* 無条件に、自分の方が優先 */ h_pricmd = usercmd; l_pricmd = tokencmd; #endif if (h_pricmd->cmd == REP_INSERT_CMD) { l_pricmd->lnum++; } else if (h_pricmd->cmd == REP_REPLACE_CMD) { if (l_pricmd->cmd == REP_INSERT_CMD) { h_pricmd->lnum++; } else if (l_pricmd->cmd == REP_REPLACE_CMD) { /* h_pricmd が優先され,l_pricmd は削除(無視に)する */ l_pricmd->stat = REP_IGNORE; } else if (l_pricmd->cmd == REP_DELETE_LINE_CMD) { /* * l_pricmd 側ではすでにdeleteされているので、 * h_pricmd を REP_REPLACE_CMD -> REP_INSERT_CMD へ変更。 */ h_pricmd->cmd = REP_INSERT_CMD; l_pricmd->stat = REP_IGNORE; } } else if (h_pricmd->cmd == REP_DELETE_LINE_CMD) { if (l_pricmd->cmd == REP_INSERT_CMD) { h_pricmd->lnum++; } else if (l_pricmd->cmd == REP_REPLACE_CMD) { /* * h_pricmd 側ではすでにdeleteされているので、 * l_pricmd 側を REP_REPLACE_CMD -> REP_INSERT_CMD へ変更。 */ l_pricmd->cmd = REP_INSERT_CMD; h_pricmd->stat= REP_IGNORE; } else if (l_pricmd->cmd == REP_DELETE_LINE_CMD) { /* * 相手と削除する行が重なるので、 * 両方のコマンドを無視にする。 * 相手先ではすでにこの行は削除されている。 */ h_pricmd->stat = REP_IGNORE; l_pricmd->stat = REP_IGNORE; break; } else { } } else { } } } } return(TRUE); } static void set_header_to_pkt(cmdlist) rep_cmdlist *cmdlist; { rep_cmd *curcmd; for (curcmd=cmdlist->head; curcmd; curcmd=curcmd->next) { set_header(curcmd->cmd, curcmd->pkt, REP_CMD_OFFSET); set_header(curcmd->sid, curcmd->pkt, REP_SID_OFFSET); set_header(curcmd->eid, curcmd->pkt, REP_EID_OFFSET); set_header(curcmd->seq, curcmd->pkt, REP_SEQNUM_OFFSET); set_header(curcmd->len, curcmd->pkt, REP_T_SIZE_OFFSET); set_header(curcmd->lnum, curcmd->pkt, REP_LNUM_OFFSET); } return; } static int rep_get_listened_fd() { int sock; int value; struct sockaddr_in addr; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { e_msg_wrp("socket(): ERROR"); return(-1); } /* Allow other programs to bind to the socket */ value = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0) { e_msg_wrp("setsockopt() REUSEADDR failed"); exit(1); } bzero((char*)&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(REP_PORT); if ((bind(sock, (struct sockaddr*)&addr, sizeof(addr))) == -1) { e_msg_wrp("bind(): ERROR"); return(-1); } if ((listen(sock, SOCK_MAX)) < 0) { e_msg_wrp("listen(): ERROR"); return(-1); } return(sock); } static int set_hostnamebysock(sock,hostname,maxlen) int sock; char *hostname; int maxlen; { int sinlen; struct sockaddr_in sin; struct hostent *host; int namelen; sinlen = sizeof sin; if (getpeername(sock, (struct sockaddr *) &sin, (socklen_t *)&sinlen) < 0){ return(FALSE); } if ((host = gethostbyaddr((char *) &sin.sin_addr, sizeof(sin.sin_addr), AF_INET)) == NULL){ return(FALSE); } namelen = strlen(host->h_name); if (namelen > maxlen) { e_msg_wrp("host name is too long."); return(FALSE); } strncpy(hostname,host->h_name,namelen); hostname[namelen] = '\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; 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*)rep_alloc(sizeof(Session)); if (s == NULL) { return(NULL); } if ((sname = (char*)rep_alloc(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 void register_session(sn) Session *sn; { rep_T *rep; rep = get_rep(); sn->next = rep->shead; rep->shead = sn; return; } static Session* set_cursession(sn) Session *sn; { BUFTYPE *oldbuf; 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(); if (rep->slineup && rep->slineup->sid == id) { return rep->slineup; } 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; if(rep->slineup->buf == buf) return rep->slineup; 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); } int rep_input_reg_session() // input own session(s) { char *sname; while (1) { // retrun value (sname) is allocated. sname = getstr_input_wrp("Session to offer = "); if (sname == NULL) return FALSE; if (*sname=='\0') { // input pert is finished free_wrp(sname); break; } register_session(make_session(sname, NULL)); free_wrp(sname); } update_screen_now_wrp(); /* ウィンドウを再描画 */ return TRUE; } static int set_session_info(dest_sinfo, sname, hostname, port) char *dest_sinfo; char *sname; char *hostname; int port; { int size; size = sprintf(dest_sinfo, "%s:%d:%s",hostname, port, sname); dest_sinfo[size] = '\0'; return 0; } 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 char* get_shortname(session) Session *session; { return get_shortname_wrp(session->buf); } /* End Session */ #define SINFO_MAX 255 /* * 自身が提供するセッションのみをセッションリストに書き出す * あらかじめセッションリストのバッファを編集対象のバッファに *指定しておく(set_curbuf_wrp(slineup)しておく) */ static int make_local_slineup(slineup, hostname, my_sessions) Session *slineup; char *hostname; Session *my_sessions; { Session *s; BUFTYPE *oldcurbuf; char sinfo[SINFO_MAX]; if (my_sessions == NULL) return FALSE; for (; my_sessions; my_sessions=my_sessions->next) { set_session_info(sinfo, my_sessions->sname, hostname, REP_PORT); /* 現在の編集対象のバッファ curbuf に対して書き込みを行なう */ append_memline_wrp(1, sinfo); } return TRUE; } /* * セッションマネージャからセッションリストを取得 * あらかじめセッションリストのバッファを編集対象のバッファに *指定しておく(set_curbuf_wrp(buf)しておく) */ static int get_slineup_from_sm(servername, slineup, hostname, my_sessions) char *servername; Session *slineup; char *hostname; Session *my_sessions; // linked list { return TRUE; } char * rep_input_param(msg, err_msg) char *msg; char *err_msg; { char *input_string; if ((input_string = getstr_input_wrp(msg)) == NULL) { return NULL; } if (*input_string == '\0') { if (err_msg) { puts_msg_wrp(err_msg); } free_wrp(input_string); return NULL; } return input_string; } int rep_join() { int sock; rep_T *rep; rep_cmdlist cmdlist = {NULL,0}; rep = get_rep(); /* if (server == NULL) { return FALSE; } */ if ((sock = rep_connect(NULL)) < 0) { return FALSE; } if (rep->smfd > 0) { close(rep->smfd); } rep->smfd = sock; rep->permit = TRUE; add_cmd_to_list(&cmdlist, make_cmd(REP_JOIN_CMD, 0, rep->eid, rep->seqno++, 0, "bufname")); rep_send_cmds(sock, &cmdlist); free_cmdlist(&cmdlist); return TRUE; } int rep_select_command(session_no) char *session_no; { rep_T *rep = get_rep(); rep_cmdlist cmdlist = {NULL, 0}; int sid; if (rep->smfd < 0 || session_no == NULL) { return FALSE; } if (rep->waiting_session_name) { rep_free(rep->waiting_session_name); } sid = atol(session_no); if ((rep->waiting_session_name = get_sname_by_snum(sid)) == NULL) { e_msg_wrp("Session Selection is false."); return FALSE; } add_cmd_to_list(&cmdlist, make_cmd(REP_SELECT_CMD, sid, rep->eid, rep->seqno++, 0, session_no)); rep_send_cmds(rep->smfd, &cmdlist); free_cmdlist(&cmdlist); return TRUE; } int rep_put(sname) char *sname; { int sock; rep_T *rep = get_rep(); rep_cmdlist cmdlist = {NULL, 0}; int len; Session *sn; if ((sock = rep_connect(NULL)) < 0) { return FALSE; } if (rep->smfd > 0) { close(rep->smfd); } rep->smfd = sock; rep->permit = TRUE; if (sname == NULL) { /* get current buffer name */ if ((sname = get_fullpath(rep->cursession)) == NULL) { sname = NO_NAME; /* the buffer has not name */ } } /* if (find_session_by_name(sname) == NULL) { sn = make_session(sname, get_buf_by_name(sname)); register_session(sn); } */ if (rep->waiting_session_name) { rep_free(rep->waiting_session_name); } len = strlen(sname) +1; rep->waiting_session_name = (char *)rep_alloc(len); memcpy(rep->waiting_session_name, sname, len); add_cmd_to_list(&cmdlist, make_cmd(REP_PUT_CMD, 0, rep->eid, rep->seqno++, 0, sname)); rep_send_cmds(rep->smfd, &cmdlist); free_cmdlist(&cmdlist); return TRUE; } int rep_remove() { rep_T *rep = get_rep(); rep_cmd *cmd; rep_cmdlist cmdlist = {NULL, 0}; Session *sn = rep->cursession; if (rep->smfd < 0) { /* session does not exist */ EMSG("Session does not exist."); return FALSE; } cmd = make_cmd(REP_DEREGISTER_CMD, sn->sid, rep->eid, rep->seqno, 0, NULL); add_cmd_to_list(&cmdlist, cmd); rep_send_cmds(rep->smfd, &cmdlist); free_cmdlist(&cmdlist); return TRUE; } static int rep_make_slineup() { BUFTYPE buf; // BUFTYPE *oldcurbuf; Session *oldsn; rep_T *rep; rep = get_rep(); if (rep->slineup) { free_session(rep->slineup); } rep->slineup = make_session(SLINEUP_NAME, make_new_buf_wrp(SLINEUP_NAME)); oldsn = set_cursession(rep->slineup); /* セッション一覧リストを作成 */ if ((get_slineup_from_sm(rep->servername, rep->slineup, rep->hostname, rep->shead) == FALSE)) { make_local_slineup(rep->slineup, rep->hostname, rep->shead); } update_screen_now_wrp(); /* ウィンドウを再描画 */ return TRUE; } static int enter_session(session_name) char *session_name; { return TRUE; } /* Session End */ static void * rep_alloc(size) int size; /* byte */ { void *allocated; if ((allocated = malloc(size)) == NULL) { e_msg_wrp("no memory!"); } return allocated; } static void rep_free(obj) void *obj; { if (obj) 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; } } return offset; } static char* make_packet(cmd, sid, eid, seq, lnum, text) unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; char * text; { char *packet; unsigned int len = 0; if (text) len += strlen(text);// + 1; /* for include '\0' */ if ((packet = (char *)rep_alloc(REP_HEADER_SIZE+len)) == NULL) { return(NULL); } 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) { memcpy(packet+REP_TEXT_OFFSET, text, len); } return(packet); } static rep_cmd* make_cmd(cmd, sid, eid, seq, lnum, text) unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; char *text; { rep_cmd *cmd_p; char *pkt; unsigned int length = 0; pkt = make_packet(cmd, sid, eid, seq, lnum, text); if (pkt == NULL) { e_msg_wrp("make_cmd: no memory: ERROR"); return(NULL); } cmd_p = (rep_cmd*)rep_alloc(sizeof(rep_cmd)); if (cmd_p == NULL) { e_msg_wrp("make_cmd: no memory: ERROR"); return(NULL); } if (text) { length = strlen(text); //+1; // include '\0' } 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; cmd_p->stat = REP_AVAIL; cmd_p->pkt = pkt; return(cmd_p); } static int free_cmd(cmd) rep_cmd *cmd; { if (cmd == NULL) return(FALSE); if (cmd->pkt) { rep_free(cmd->pkt); cmd->pkt=NULL; } rep_free(cmd); cmd = 0; 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; } static int add_pkt_to_list(cmdlist, pkt) /* pkt is allocated */ rep_cmdlist *cmdlist; char *pkt; { rep_cmd *cmd_p; if (pkt == NULL) return(FALSE); cmd_p = (rep_cmd*)rep_alloc(sizeof(rep_cmd)); if (cmd_p == NULL) { e_msg_wrp("add_pkt_to_list: no memory: ERROR"); return(FALSE); } cmd_p->next = NULL; cmd_p->cmd = get_header(pkt, REP_CMD_OFFSET); cmd_p->sid = get_header(pkt, REP_SID_OFFSET); cmd_p->eid = get_header(pkt, REP_EID_OFFSET); cmd_p->seq = get_header(pkt, REP_SEQNUM_OFFSET); cmd_p->lnum = get_header(pkt, REP_LNUM_OFFSET); cmd_p->stat = REP_AVAIL; cmd_p->len = strlen(pkt)+1 - REP_HEADER_SIZE; cmd_p->pkt = pkt; add_cmd_to_list(cmdlist, cmd_p); return(TRUE); } void rep_prevline_flush() { BUFTYPE *cbuf; Session *cursn; rep_cmd *cmd; rep_T *rep = get_rep(); char *text; cursn = rep->cursession; if ((cursn == NULL) || (cursn->prevline == -1)) return; // バッファが変更された場合には rep->cursession も合わす if ((cbuf = get_curbuf_wrp()) != cursn->buf) { cursn = find_session_by_buf(cbuf); if (cursn == NULL) return; rep->cursession = cursn; } text = get_memline_wrp(cursn->buf, cursn->prevline); //cmd = make_cmd(REP_REPLACE_CMD, cursn->sid, rep->eid, rep->seqno++, cursn->prevline, text); // TODO : 変更前のテキストを UNDO バッファから取得する cmd = make_cmd(REP_DELETE_CMD, cursn->sid, rep->eid, rep->seqno++, cursn->prevline, prev_text); cmd->next = make_cmd(REP_INSERT_CMD, cursn->sid, rep->eid, rep->seqno++, cursn->prevline, text); add_cmd_to_list(&(cursn->new_cmdlist), cmd); if (cursn->sent_cmdlist.num == 0) { // 自トークンを送信してない場合 rep_send_cur_cmdlist(); } cursn->prevline = -1; } static void check_line_change(sn, lnum) Session *sn; unsigned int lnum; { rep_cmd *cmd; rep_T *rep = get_rep(); if (sn->prevline == lnum) { return; } if (sn->prevline == -1) { sn->prevline = lnum; return; } cmd = make_cmd(REP_REPLACE_CMD, sn->sid, rep->eid, rep->seqno++, sn->prevline, get_memline_wrp(sn->buf, sn->prevline)); add_cmd_to_list(&(sn->new_cmdlist), cmd); sn->prevline = lnum; return; } int 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 FALSE; // バッファが変更された場合には rep->cursession も合わす if ((cbuf = get_curbuf_wrp()) != cursn->buf) { cursn = find_session_by_buf(cbuf); if (cursn == NULL) return FALSE; rep->cursession = cursn; } if (xtra == 0) { for (i = 0; lnume-lnum > i; i++) { check_line_change(cursn,lnum+i); } } else if (xtra > 0) { if (lnum != lnume) { /* 行の途中から改行 */ cmd = make_cmd( REP_REPLACE_CMD, cursn->sid, rep->eid, rep->seqno++, lnum, get_memline_wrp(cursn->buf, lnum)); add_cmd_to_list(&(cursn->new_cmdlist), cmd); lnum++; } for (i = 0; xtra > 0; i++, xtra--) { cmd = make_cmd( REP_INSERT_CMD, cursn->sid, rep->eid, rep->seqno++, lnum+i, get_memline_wrp(cursn->buf, lnum+i)); add_cmd_to_list(&(cursn->new_cmdlist), cmd); } } else { /* xtra < 0 */ xtra = -xtra; for (; xtra > 0; xtra--) { cmd = make_cmd(REP_DELETE_LINE_CMD, cursn->sid, rep->eid, rep->seqno++, lnum, NULL); add_cmd_to_list(&(cursn->new_cmdlist), cmd); } } if (cursn->sent_cmdlist.num == 0) { rep_send_cur_cmdlist(); } return(lnume - lnum); } 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); } static int rep_exe_cmd(cmd, sid, eid, seq, lnum, textsize, text) unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; unsigned int textsize; char *text; { char h_name[50]; rep_cmdlist tmplist = {NULL, 0}; rep_cmd *repcmd; BUFTYPE *buf; rep_T *rep = get_rep(); Session *session; unsigned int buflenmax; session = find_session_by_id(sid); /*XXX 無理矢理 */ if (textsize == 0) { text = NULL; } switch (cmd) { case REP_JOIN_ACK: /* show session lineup */ if (rep->slineup) { free_session(rep->slineup); } rep->slineup = make_session(SLINEUP_NAME, make_new_buf_wrp(SLINEUP_NAME)); append_newline_sep_text(rep->slineup, text); set_cursession(rep->slineup); update_screen_now_wrp(); if (rep->eid == 0) { rep->eid = eid; } break; /* case REP_SELECT_ACK: // text is error message. means occur ERROR in session manager if (text) { e_msg_wrp(text); return FALSE; } // DON'T wait session from session manager if (! rep->waiting_session_name) { return FALSE; } session = make_session(rep->waiting_session_name, make_new_buf_wrp(rep->waiting_session_name)); session->sid = sid; register_session(session); rep_free(rep->waiting_session_name); rep->waiting_session_name = NULL; set_cursession(session); rep_start_create_cmds(); // get window size // send read command break; case REP_REGISTER_ACK: */ case REP_PUT_ACK: /* Enter Session */ if (text) { // text is error message. e_msg_wrp(text); return FALSE; } /* Use wating_session_name for assign session id */ if ((session = find_session_by_name(rep->waiting_session_name)) == NULL) { if (rep->waiting_session_name) { rep_free(rep->waiting_session_name); rep->waiting_session_name = NULL; } return FALSE; } session->sid = sid; /* set session to cursession */ set_cursession(session); rep_start_create_cmds(); break; /* case REP_DEREGISTER_CMD: case REP_DEREGISTER_ACK: case REP_QUIT_CMD: case REP_QUIT_ACK: case REP_GET_CMD: case REP_GET_ACK: break; case REP_OPEN_CMD: // REP_OPEN_CMD is handled in list part. (may be upper function) break; case REP_OPEN_ACK: case REP_CLOSE_CMD: break; case REP_CLOSE_ACK: break; case REP_READ_CMD: break; case REP_READ_ACK: break; case REP_READ_FIN: break; // buffer edit commands // session's buffer is set to current buffer */ case REP_INSERT_CMD: append_memline_wrp(lnum, text); break; case REP_DELETE_LINE_CMD: delete_memline_wrp(lnum); break; /* case REP_REPLACE_CMD: if (lnum > get_bufmaxline_wrp(session->buf)) { append_memline_wrp(lnum, text); } replace_memline_wrp(lnum, text); // text was allocated break; */ default: break; } free_cmdlist(&(tmplist)); return(TRUE); } static int rep_exe_pkt(pkt) char *pkt; { unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; unsigned int len; char *text; cmd = get_header(pkt, REP_CMD_OFFSET); sid = get_header(pkt, REP_SID_OFFSET); eid = get_header(pkt, REP_EID_OFFSET); seq = get_header(pkt, REP_SEQNUM_OFFSET); lnum = get_header(pkt, REP_LNUM_OFFSET); len = get_header(pkt, REP_T_SIZE_OFFSET); text = pkt + REP_TEXT_OFFSET; rep_exe_cmd(cmd, sid, eid, seq, lnum, len, text); return(TRUE); } /* execute command list based cmd packet */ static int rep_exe_pktlist(cmdlist) rep_cmdlist *cmdlist; { rep_cmd *repcmd; BUFTYPE *orgbuf; char *sname; if ((cmdlist == NULL) || (cmdlist->head == NULL)) { return(FALSE); } for (repcmd = cmdlist->head; repcmd; repcmd = repcmd->next) { if (repcmd->stat == REP_AVAIL) { rep_exe_pkt(repcmd->pkt); } } return(TRUE); } /* execute command list based cmd structure */ /* sn must be already exists */ static int rep_exe_cmdlist(cmdlist) rep_cmdlist *cmdlist; { rep_cmd *cmd; BUFTYPE *orgbuf; unsigned short uid; if ((cmdlist == NULL) || (cmdlist->head == NULL)) { return(FALSE); } for (cmd = cmdlist->head; cmd; cmd = cmd->next) { if (cmd->stat == REP_AVAIL) { rep_exe_cmd(cmd->cmd, cmd->sid, cmd->eid, cmd->seq, cmd->lnum, cmd->len, cmd->pkt + REP_TEXT_OFFSET); } } return(TRUE); } static int rep_recv_cmds(fd, smcmdlist, txtcmdlist) int fd; rep_cmdlist *smcmdlist; rep_cmdlist *txtcmdlist; { unsigned int cmd; unsigned int sid; unsigned int eid; unsigned int seq; unsigned int lnum; unsigned int textsize; char header[REP_HEADER_SIZE]; char *text = NULL; int retval; if (fd < 0) { return(FALSE); } /* 一定時間読み取るようにしたい */ /* 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 (textsize > 0) { if ((text = (char*)rep_alloc(textsize)) == NULL) { return(FALSE); } /* read text part */ if (readn(fd, text, textsize) < 0) { puts_sys_err(); rep_free(text); return(FALSE); } } if (cmd == REP_INSERT_CMD || cmd == REP_DELETE_LINE_CMD || cmd == REP_REPLACE_CMD) { add_cmd_to_list(txtcmdlist, make_cmd(cmd, sid, eid, seq, lnum, text)); } else { add_cmd_to_list(smcmdlist, make_cmd(cmd, sid, eid, seq, lnum, text)); } 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_cmds(fd,cmdlist) int fd; rep_cmdlist *cmdlist; { rep_cmd *cur; unsigned int nlen; 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) < 0) { return(FALSE); } } return(TRUE); } /* static int session_fd_check(sn, rfds_p, efds_p) Session *sn; fd_set *rfds_p; fd_set *efds_p; { rep_cmdlist smcmdlist = {NULL,0}; rep_cmdlist txtcmdlist = {NULL,0}; if (sn == NULL) return FALSE; if (sn->smfd > 0) { if (FD_ISSET(sn->smfd, efds_p)) { if (sn->rfd != sn->sfd) close(sn->rfd); sn->rfd = -1; // 再接続処理をしたい return FALSE; } else if (FD_ISSET(sn->rfd, rfds_p)) { if (rep_recv_cmds(sn->rfd, &(smcmdlist), &(txtcmdlist)) == FALSE) { if (sn->rfd != sn->sfd) close(sn->rfd); sn->rfd = -1; return(FALSE); } if ((cmdlist.head) && (cmdlist.head->uid == 99)) { // 単方向コマンド rep_exe_cmdlist(sn, sn->rfd, &(cmdlist)); free_cmdlist(&(cmdlist)); } else if ((cmdlist.head) && (cmdlist.head->uid == sn->uid)) { // 自分のコマンド free_cmdlist(&cmdlist); if (rep_send_cmds(sn->sfd, &(sn->new_cmdlist)) == FALSE) { if (sn->rfd != sn->sfd) close(sn->sfd); sn->sfd = -1; return FALSE; } sn->sent_cmdlist.head = sn->new_cmdlist.head; sn->sent_cmdlist.num = sn->new_cmdlist.num; sn->new_cmdlist.head = NULL; sn->new_cmdlist.num = 0; } else { // リングに流すコマンド // 受け取ったトークンとユーザからのREPコマンドを比較・マージする // 既に送信した REPコマンド列 と比較 translate(&(sn->sent_cmdlist), &(cmdlist)); del_ignored_cmd(&(cmdlist)); set_header_to_pkt(&(cmdlist)); if (rep_send_cmds(sn->sfd, &(cmdlist)) == FALSE) { if (sn->rfd != sn->sfd) close(sn->sfd); sn->sfd = -1; free_cmdlist(&(cmdlist)); return FALSE; } // 新規に追加された REPコマンド列 との比較 translate(&(sn->new_cmdlist), &(cmdlist)); del_ignored_cmd(&(cmdlist)); set_header_to_pkt(&(sn->new_cmdlist)); // 変換したトークンREPコマンドを自分のバッファに反映する。 //各パケットにはその変換は反映されていない. rep_exe_cmdlist(sn, sn->rfd, &(cmdlist)); free_cmdlist(&(cmdlist)); } } } if (sn->sfd > 0) { if (FD_ISSET(sn->sfd, efds_p)) { if (sn->rfd != sn->sfd) close(sn->sfd); sn->sfd = -1; // 再接続処理をしたい return FALSE; } else if (FD_ISSET(sn->sfd, rfds_p)) { // from send client if (rep_recv_cmds(sn->sfd, &cmdlist) == FALSE) { if (sn->rfd != sn->sfd) close(sn->sfd); sn->sfd = -1; return(FALSE); } rep_exe_cmdlist(sn, sn->sfd, &cmdlist); free_cmdlist(&cmdlist); } } } */ 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 { int newfd; rep_T *rep_p; rep_cmdlist smcmdlist = {NULL,0}; rep_cmdlist txtcmdlist = {NULL,0}; Session *sn; /* input from keyboard is most important. * reditor has nothing to do */ if (FD_ISSET(fd, rfds_p) || FD_ISSET(fd, efds_p)) { return(TRUE); } rep_p = get_rep(); if ((rep_p->smfd > 0) && (FD_ISSET(rep_p->smfd, rfds_p))) { /* we don't need this? // 受け取ったトークンとユーザからのREPコマンドを比較・マージする // 既に送信した REPコマンド列 と比較 translate(&(sn->sent_cmdlist), &(cmdlist)); del_ignored_cmd(&(cmdlist)); set_header_to_pkt(&(cmdlist)); */ if (rep_recv_cmds(rep_p->smfd, &(smcmdlist), &(txtcmdlist)) == FALSE) { close(rep_p->smfd); rep_p->smfd = -1; return FALSE; } /* Session ごとに行う↓*/ /* for(sn = rep_p->shead; sn ; sn = sn->next) { translate( &sn->new_cmdlist , &txtcmdlist); } */ del_ignored_cmd(&txtcmdlist); rep_exe_pktlist(&txtcmdlist); if (rep_send_cmds(rep_p->smfd, &(txtcmdlist)) == FALSE) { close(sn->smfd); sn->smfd = -1; free_cmdlist(&(txtcmdlist)); return FALSE; } free_cmdlist(&(txtcmdlist)); rep_exe_pktlist( &smcmdlist); free_cmdlist(&(smcmdlist)); return TRUE; } rep_exe_pktlist( &smcmdlist); free_cmdlist(&(smcmdlist)); /* session_fd_check(rep_p->slineup, rfds_p, efds_p); for (sn=rep_p->shead; sn; sn=sn->next) { session_fd_check(sn, rfds_p, efds_p); } */ } /* static int session_fd_set(sn, rfds_p, efds_p, max_fds) Session *sn; fd_set *rfds_p; fd_set *efds_p; int max_fds; { if (sn == NULL) return max_fds; if (sn->rfd > 0) { FD_SET(sn->rfd, rfds_p); FD_SET(sn->rfd, efds_p); if (max_fds < sn->rfd) { max_fds = sn->rfd; } } if (sn->sfd > 0) { FD_SET(sn->sfd, rfds_p); FD_SET(sn->sfd, efds_p); if (max_fds < sn->sfd) { max_fds = sn->sfd; } } return max_fds; } */ 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; Session *sn; int i; 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; } } /* max_fds = session_fd_set(rep_p->slineup, rfds_p, efds_p, max_fds); for (sn=rep_p->shead; sn; sn=sn->next) { max_fds = session_fd_set(sn, rfds_p, efds_p, max_fds); } */ return(max_fds); } /* * 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 tv; if (fd < 0) return(FALSE); while (1) { /* select の中で modify されてるので、初期化 */ 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, &tv)) < 0) { e_msg_wrp("rep_select(): ERROR"); return(FALSE); } rep_fd_check(fd, &rfds_p, &efds_p); return(TRUE); } } 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->slineup) free_session(rep_p->slineup); 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(); } /* append newline separated text to session buf */ static int append_newline_sep_text(sn, text) Session *sn; char *text; { char *str; char *cur; // BUFTYPE *oldbuf; Session *oldsn; /* *"append_memline()" is available "curbuf" only * thus, we must set buffer to "curbuf" */ oldsn = set_cursession(sn); for (str = cur = text; cur && *cur ; str = cur) { cur = strchr(str, '\n'); if (cur) { *cur = '\0'; cur++; } append_memline_wrp(1, str); } set_cursession(oldsn); return TRUE; } /* return value (file name) is allocated */ static char * get_sname_by_snum(snum) int snum; { char *tmp, *text, *sname; int i, len; int maxlnum; rep_T *rep = get_rep(); maxlnum = get_bufmaxline_wrp(rep->slineup->buf); for (i = 1; i <= maxlnum; i++) { // text is "filename:hostname:sessionnumber" text = get_memline_wrp(rep->slineup->buf, i); // get ':' separated last parameter (session number) if ((tmp = strrchr(text, ':')) == NULL) { return NULL; } tmp++; if (snum == atol(tmp)) { // get ':' separated first parameter (filename) tmp = strchr(text, ':'); len = tmp - text; if ((sname = (char *)rep_alloc(len+1)) == NULL){ e_msg_wrp("no memory!"); return NULL; } memcpy(sname, text, len); sname[len] = '\0'; return sname; } } return NULL; }