* Client protocol synchronization check during exit from chat.
[citadel.git] / citadel / client_chat.c
1 /*
2  * Citadel/UX
3  *
4  * client_chat.c  --  front end for chat mode
5  *                    (the "single process" version - no more fork() anymore)
6  *
7  * $Id$
8  *
9  */
10
11 #include "sysdep.h"
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <stdio.h>
15 #include <fcntl.h>
16 #include <ctype.h>
17 #include <string.h>
18 #include <signal.h>
19 #include <errno.h>
20 #include <sys/time.h>
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #include <stdarg.h>
26 #include "citadel.h"
27 #include "client_chat.h"
28 #include "commands.h"
29 #include "routines.h"
30 #include "ipc.h"
31 #include "citadel_decls.h"
32 #include "tools.h"
33 #ifndef HAVE_SNPRINTF
34 #include "snprintf.h"
35 #endif
36
37 #define MIN(a, b) ((a) < (b) ? (a) : (b))
38
39 extern struct CtdlServInfo serv_info;
40 extern char temp[];
41 void citedit(FILE *fp, long int base_pos);
42 void getline(char *, int);
43
44 void chatmode(void) {
45         char wbuf[256];
46         char buf[256];
47         char c_user[256];
48         char c_text[256];
49         char c_room[256];
50         char last_user[256];
51         int send_complete_line;
52         int recv_complete_line;
53         char ch;
54         int a,pos;
55         
56         fd_set rfds;
57         struct timeval tv;
58         int retval;
59
60         serv_puts("CHAT");
61         serv_gets(buf);
62         if (buf[0]!='8') {
63                 printf("%s\n",&buf[4]);
64                 return;
65                 }
66
67         printf("Entering chat mode (type /quit to exit, /help for other cmds)\n");
68         set_keepalives(KA_CHAT);
69
70         strcpy(buf,"");
71         strcpy(wbuf,"");
72         color(BRIGHT_YELLOW);
73         printf("> ");
74         send_complete_line = 0;
75         recv_complete_line = 0;
76
77         while(1) {
78             fflush(stdout);
79             FD_ZERO(&rfds);
80             FD_SET(0,&rfds);
81             FD_SET(getsockfd(),&rfds);
82             tv.tv_sec = S_KEEPALIVE;
83             tv.tv_usec = 0;
84             retval = select(getsockfd()+1, &rfds, NULL, NULL, &tv);
85
86             if (FD_ISSET(getsockfd(), &rfds)) {
87                 ch = serv_getc();
88                 if (ch == 10) {
89                         recv_complete_line = 1;
90                         goto RCL; /* ugly, but we've gotta get out! */
91                         }
92                 else {
93                         buf[strlen(buf) + 1] = 0;
94                         buf[strlen(buf)] = ch;
95                         }
96                 goto RCL;
97                 }
98
99             if (FD_ISSET(0, &rfds)) {
100                 ch = inkey();
101                 if ((ch == 10) || (ch == 13)) {
102                         send_complete_line = 1;
103                         }
104                 else if ((ch == 8) || (ch == 127)) {
105                         if (strlen(wbuf) > 0) {
106                                 wbuf[strlen(wbuf)-1] = 0;
107                                 printf("%c %c",8,8);
108                                 }
109                         }
110                 else {
111                         putc(ch,stdout);
112                         wbuf[strlen(wbuf) + 1] = 0;
113                         wbuf[strlen(wbuf)] = ch;
114                         }
115                 }
116
117
118         /* if the user hit return, send the line */
119 RCL:        if (send_complete_line) {
120                 serv_puts(wbuf);
121                 strcpy(wbuf,"");
122                 send_complete_line = 0;
123                 }
124
125         /* if it's time to word wrap, send a partial line */
126             if ( strlen(wbuf) >= (77-strlen(fullname)) ) {
127                 pos = 0;
128                 for (a=0; a<strlen(wbuf); ++a) {
129                         if (wbuf[a] == 32) pos = a;
130                         }
131                 if (pos == 0) {
132                         serv_puts(wbuf);
133                         strcpy(wbuf, "");
134                         send_complete_line = 0;
135                         }
136                 else {
137                         wbuf[pos] = 0;
138                         serv_puts(wbuf);
139                         strcpy(wbuf,&wbuf[pos+1]);
140                         }
141                 }
142
143             if (recv_complete_line) {   
144                 printf("\r%79s\r","");
145                 if (!strcmp(buf,"000")) {
146                         color(BRIGHT_WHITE);
147                         printf("Exiting chat mode\n");
148
149                         fflush(stdout);
150                         set_keepalives(KA_YES);
151
152
153                         /* Some users complained about the client and server
154                          * losing protocol synchronization when exiting chat.
155                          * This little dialog forces everything to be
156                          * hunky-dory.
157                          */
158                         serv_puts("ECHO __ExitingChat__");
159                         do {
160                                 serv_gets(buf);
161                         } while (strcmp(buf, "200 __ExitingChat__"));
162
163
164                         return;
165                         }
166                 if (num_parms(buf)>=2) {
167                         extract(c_user,buf,0);
168                         extract(c_text,buf,1);
169                         if (num_parms(buf)>2)
170                         {
171                            extract(c_room,buf,2);
172                            printf("Got room %s\n", c_room);
173                         }
174                            
175                         if (strucmp(c_text,"NOOP")) {
176                                 if (!strcmp(c_user, fullname)) {
177                                         color(BRIGHT_YELLOW);
178                                         }
179                                 else if (!strcmp(c_user,":")) {
180                                         color(BRIGHT_RED);
181                                         }
182                                 else {
183                                         color(BRIGHT_GREEN);
184                                         }
185                                 if (strcmp(c_user,last_user)) {
186                                         snprintf(buf,sizeof buf,"%s: %s",c_user,c_text);
187                                         }
188                                 else {
189                                         size_t i = MIN(sizeof buf - 1,
190                                                        strlen(c_user) + 2);
191
192                                         memset(buf, ' ', i);
193                                         safestrncpy(&buf[i], c_text,
194                                                     sizeof buf - i);
195                                         }
196                                 while (strlen(buf)<79) strcat(buf," ");
197                                 if (strcmp(c_user,last_user)) {
198                                         printf("\r%79s\n","");
199                                         strcpy(last_user,c_user);
200                                         }
201                                 printf("\r%s\n",buf);
202                                 fflush(stdout);
203                                 }
204                         }
205                 color(BRIGHT_YELLOW);
206                 printf("> %s",wbuf);
207                 recv_complete_line = 0;
208                 strcpy(buf,"");
209                 }
210             }
211         }
212
213 /*
214  * send an express message
215  */
216 void page_user() {
217         static char last_paged[32] = "";
218         char buf[256], touser[256], msg[256];
219         FILE *pagefp;
220
221         strcpy(touser, last_paged);
222         strprompt("Page who", touser, 30);
223
224         /* old server -- use inline paging */
225         if (serv_info.serv_paging_level == 0) {
226                 newprompt("Message:  ", msg, 69);
227                 snprintf(buf,sizeof buf,"SEXP %s|%s",touser,msg);
228                 serv_puts(buf);
229                 serv_gets(buf);
230                 if (!strncmp(buf, "200", 3)) {
231                         strcpy(last_paged, touser);
232                         }
233                 printf("%s\n", &buf[4]);
234                 return;
235         }
236
237         /* new server -- use extended paging */ 
238         else if (serv_info.serv_paging_level >= 1) {
239                 snprintf(buf, sizeof buf, "SEXP %s||", touser);
240                 serv_puts(buf);
241                 serv_gets(buf);
242                 if (buf[0] != '2') {
243                         printf("%s\n", &buf[4]);
244                         return;
245                         }
246
247                 printf("Type message to send.  Enter a blank line when finished.\n");
248                 pagefp = fopen(temp, "w+");
249                 unlink(temp);
250                 citedit(pagefp, 0L);
251                 fseek(pagefp, 0L, SEEK_END);
252                 if ( ftell(pagefp) > 2)  {
253                         rewind(pagefp);
254                         snprintf(buf, sizeof buf, "SEXP %s|-", touser);
255                         serv_puts(buf);
256                         serv_gets(buf);
257                         if (buf[0]=='4') {
258                                 strcpy(last_paged, touser);
259                                 while (fgets(buf, 256, pagefp) != NULL) {
260                                         buf[strlen(buf)-1] = 0;
261                                         serv_puts(buf);
262                                         }
263                                 fclose(pagefp);
264                                 serv_puts("000");
265                                 printf("Message sent.\n");
266                         }
267                         else {
268                                 printf("%s\n", &buf[4]);
269                         }
270                 } 
271                 else {
272                         printf("No message sent.\n");
273                 }
274         }
275 }
276
277
278