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