3aad45f43a42a2fd0c632ef52a70c7e1a05cd661
[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 #include "rooms.h"
34 #include "messages.h"
35 #ifndef HAVE_SNPRINTF
36 #include "snprintf.h"
37 #endif
38
39 #define MIN(a, b) ((a) < (b) ? (a) : (b))
40
41 extern struct CtdlServInfo serv_info;
42 extern char temp[];
43 void getline(char *, int);
44
45 void chatmode(void) {
46         char wbuf[256];
47         char buf[256];
48         char c_user[256];
49         char c_text[256];
50         char c_room[256];
51         char last_user[256];
52         int send_complete_line;
53         int recv_complete_line;
54         char ch;
55         int a,pos;
56         
57         fd_set rfds;
58         struct timeval tv;
59         int retval;
60
61         serv_puts("CHAT");
62         serv_gets(buf);
63         if (buf[0]!='8') {
64                 printf("%s\n",&buf[4]);
65                 return;
66                 }
67
68         printf("Entering chat mode (type /quit to exit, /help for other cmds)\n");
69         set_keepalives(KA_CHAT);
70
71         strcpy(buf,"");
72         strcpy(wbuf,"");
73         color(BRIGHT_YELLOW);
74         printf("> ");
75         send_complete_line = 0;
76         recv_complete_line = 0;
77
78         while(1) {
79             fflush(stdout);
80             FD_ZERO(&rfds);
81             FD_SET(0,&rfds);
82             FD_SET(getsockfd(),&rfds);
83             tv.tv_sec = S_KEEPALIVE;
84             tv.tv_usec = 0;
85             retval = select(getsockfd()+1, &rfds, NULL, NULL, &tv);
86
87             if (FD_ISSET(getsockfd(), &rfds)) {
88                 ch = serv_getc();
89                 if (ch == 10) {
90                         recv_complete_line = 1;
91                         goto RCL; /* ugly, but we've gotta get out! */
92                         }
93                 else {
94                         buf[strlen(buf) + 1] = 0;
95                         buf[strlen(buf)] = ch;
96                         }
97                 goto RCL;
98                 }
99
100             if (FD_ISSET(0, &rfds)) {
101                 ch = inkey();
102                 if ((ch == 10) || (ch == 13)) {
103                         send_complete_line = 1;
104                         }
105                 else if ((ch == 8) || (ch == 127)) {
106                         if (strlen(wbuf) > 0) {
107                                 wbuf[strlen(wbuf)-1] = 0;
108                                 printf("%c %c",8,8);
109                                 }
110                         }
111                 else {
112                         putc(ch,stdout);
113                         wbuf[strlen(wbuf) + 1] = 0;
114                         wbuf[strlen(wbuf)] = ch;
115                         }
116                 }
117
118
119         /* if the user hit return, send the line */
120 RCL:        if (send_complete_line) {
121                 serv_puts(wbuf);
122                 strcpy(wbuf,"");
123                 send_complete_line = 0;
124                 }
125
126         /* if it's time to word wrap, send a partial line */
127             if ( strlen(wbuf) >= (77-strlen(fullname)) ) {
128                 pos = 0;
129                 for (a=0; a<strlen(wbuf); ++a) {
130                         if (wbuf[a] == 32) pos = a;
131                         }
132                 if (pos == 0) {
133                         serv_puts(wbuf);
134                         strcpy(wbuf, "");
135                         send_complete_line = 0;
136                         }
137                 else {
138                         wbuf[pos] = 0;
139                         serv_puts(wbuf);
140                         strcpy(wbuf,&wbuf[pos+1]);
141                         }
142                 }
143
144             if (recv_complete_line) {   
145                 printf("\r%79s\r","");
146                 if (!strcmp(buf,"000")) {
147                         color(BRIGHT_WHITE);
148                         printf("Exiting chat mode\n");
149
150                         fflush(stdout);
151                         set_keepalives(KA_YES);
152
153
154                         /* Some users complained about the client and server
155                          * losing protocol synchronization when exiting chat.
156                          * This little dialog forces everything to be
157                          * hunky-dory.
158                          */
159                         serv_puts("ECHO __ExitingChat__");
160                         do {
161                                 serv_gets(buf);
162                         } while (strcmp(buf, "200 __ExitingChat__"));
163
164
165                         return;
166                         }
167                 if (num_parms(buf)>=2) {
168                         extract(c_user,buf,0);
169                         extract(c_text,buf,1);
170                         if (num_parms(buf)>2)
171                         {
172                            extract(c_room,buf,2);
173                            printf("Got room %s\n", c_room);
174                         }
175                            
176                         if (strcasecmp(c_text,"NOOP")) {
177                                 if (!strcmp(c_user, fullname)) {
178                                         color(BRIGHT_YELLOW);
179                                         }
180                                 else if (!strcmp(c_user,":")) {
181                                         color(BRIGHT_RED);
182                                         }
183                                 else {
184                                         color(BRIGHT_GREEN);
185                                         }
186                                 if (strcmp(c_user,last_user)) {
187                                         snprintf(buf,sizeof buf,"%s: %s",c_user,c_text);
188                                         }
189                                 else {
190                                         size_t i = MIN(sizeof buf - 1,
191                                                        strlen(c_user) + 2);
192
193                                         memset(buf, ' ', i);
194                                         safestrncpy(&buf[i], c_text,
195                                                     sizeof buf - i);
196                                         }
197                                 while (strlen(buf)<79) strcat(buf," ");
198                                 if (strcmp(c_user,last_user)) {
199                                         printf("\r%79s\n","");
200                                         strcpy(last_user,c_user);
201                                         }
202                                 printf("\r%s\n",buf);
203                                 fflush(stdout);
204                                 }
205                         }
206                 color(BRIGHT_YELLOW);
207                 printf("> %s",wbuf);
208                 recv_complete_line = 0;
209                 strcpy(buf,"");
210                 }
211             }
212         }
213
214 /*
215  * send an express message
216  */
217 void page_user() {
218         static char last_paged[32] = "";
219         char buf[256], touser[256], msg[256];
220         FILE *pagefp;
221
222         strcpy(touser, last_paged);
223         strprompt("Page who", touser, 30);
224
225         /* old server -- use inline paging */
226         if (serv_info.serv_paging_level == 0) {
227                 newprompt("Message:  ", msg, 69);
228                 snprintf(buf,sizeof buf,"SEXP %s|%s",touser,msg);
229                 serv_puts(buf);
230                 serv_gets(buf);
231                 if (!strncmp(buf, "200", 3)) {
232                         strcpy(last_paged, touser);
233                         }
234                 printf("%s\n", &buf[4]);
235                 return;
236         }
237
238         /* new server -- use extended paging */ 
239         else if (serv_info.serv_paging_level >= 1) {
240                 snprintf(buf, sizeof buf, "SEXP %s||", touser);
241                 serv_puts(buf);
242                 serv_gets(buf);
243                 if (buf[0] != '2') {
244                         printf("%s\n", &buf[4]);
245                         return;
246                         }
247
248                 if ( make_message(temp, touser, 0, 0, 0) != 0 ) {
249                         printf("No message sent.\n");
250                         return;
251                 }
252
253                 pagefp = fopen(temp, "r");
254                 unlink(temp);
255                 snprintf(buf, sizeof buf, "SEXP %s|-", touser);
256                 serv_puts(buf);
257                 serv_gets(buf);
258                 if (buf[0]=='4') {
259                         strcpy(last_paged, touser);
260                         while (fgets(buf, 256, pagefp) != NULL) {
261                                 buf[strlen(buf)-1] = 0;
262                                 serv_puts(buf);
263                                 }
264                         fclose(pagefp);
265                         serv_puts("000");
266                         printf("Message sent.\n");
267                 }
268                 else {
269                         printf("%s\n", &buf[4]);
270                 }
271         }
272 }
273
274
275
276
277 void quiet_mode(void) {
278         int qstate;
279         char buf[256];
280
281         serv_puts("DEXP 2");
282         serv_gets(buf);
283         if (buf[0]!='2') {
284                 printf("%s\n", &buf[4]);
285                 return;
286         }
287         qstate = atoi(&buf[4]);
288         if (qstate == 0) qstate = 1;
289         else qstate = 0;
290         sprintf(buf, "DEXP %d", qstate);
291         serv_puts(buf);
292         serv_gets(buf);
293         if (buf[0]!='2') {
294                 printf("%s\n", &buf[4]);
295                 return;
296         }
297         qstate = atoi(&buf[4]);
298         if (qstate) {
299                 printf("Quiet mode enabled (no other users may page you)\n");
300         }
301         else {
302                 printf("Quiet mode disabled (other users may page you)\n");
303         }
304 }