3 * More client-side support functions.
4 * Unlike routines.c, some of these DO use global variables.
10 #include <sys/types.h>
18 #if TIME_WITH_SYS_TIME
19 # include <sys/time.h>
23 # include <sys/time.h>
33 #include <libcitadel.h>
36 #include "citadel_ipc.h"
37 #include "citadel_decls.h"
38 #include "routines2.h"
47 /* work around solaris include files */
53 extern char tempdir
[];
54 extern char *axdefs
[8];
55 extern long highest_msg_read
;
56 extern long maxmsgnum
;
57 extern unsigned room_flags
;
58 extern int screenwidth
;
62 int eopen(char *name, int mode)
65 ret = open(name, mode);
67 err_printf("Cannot open file '%s', mode=%d, errno=%d\n",
76 int room_prompt(unsigned int qrflags
)
77 { /* return proper room prompt character */
80 if (qrflags
& QR_DIRECTORY
)
82 if ((a
== ']') && (qrflags
& QR_NETWORK
))
84 if ((a
== '>') && (qrflags
& QR_NETWORK
))
89 void entregis(CtdlIPC
*ipc
)
90 { /* register with name and address */
106 int r
; /* IPC response code */
111 strcpy(tmpstate
, "");
113 strcpy(tmpphone
, "");
114 strcpy(tmpemail
, "");
115 strcpy(tmpcountry
, "");
117 r
= CtdlIPCGetUserRegistration(ipc
, NULL
, ®
, buf
);
121 while (reg
&& !IsEmptyStr(reg
)) {
123 extract_token(buf
, reg
, 0, '\n', sizeof buf
);
124 remove_token(reg
, 0, '\n');
127 safestrncpy(tmpname
, buf
, sizeof tmpname
);
129 safestrncpy(tmpaddr
, buf
, sizeof tmpaddr
);
131 safestrncpy(tmpcity
, buf
, sizeof tmpcity
);
133 safestrncpy(tmpstate
, buf
, sizeof tmpstate
);
135 safestrncpy(tmpzip
, buf
, sizeof tmpzip
);
137 safestrncpy(tmpphone
, buf
, sizeof tmpphone
);
139 safestrncpy(tmpemail
, buf
, sizeof tmpemail
);
141 safestrncpy(tmpcountry
, buf
, sizeof tmpcountry
);
145 strprompt("REAL name", tmpname
, 29);
146 strprompt("Address", tmpaddr
, 24);
147 strprompt("City/town", tmpcity
, 14);
148 strprompt("State/province", tmpstate
, 2);
149 strprompt("ZIP/Postal Code", tmpzip
, 10);
150 strprompt("Country", tmpcountry
, 31);
151 strprompt("Telephone number", tmpphone
, 14);
155 safestrncpy(holdemail
, tmpemail
, sizeof holdemail
);
156 strprompt("Email address", tmpemail
, 31);
157 r
= CtdlIPCDirectoryLookup(ipc
, tmpemail
, buf
);
159 extract_token(diruser
, buf
, 0, '@', sizeof diruser
);
160 extract_token(dirnode
, buf
, 1, '@', sizeof dirnode
);
163 if ((strcasecmp(diruser
, fullname
))
164 || (strcasecmp(dirnode
, ipc
->ServInfo
.nodename
))) {
166 "\nYou can't use %s as your address.\n",
169 "It is already in use by %s @ %s.\n",
172 safestrncpy(tmpemail
, holdemail
, sizeof tmpemail
);
177 /* now send the registration info back to the server */
178 reg
= (char *)realloc(reg
, SIZ
);
180 sprintf(reg
, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
181 tmpname
, tmpaddr
, tmpcity
, tmpstate
,
182 tmpzip
, tmpphone
, tmpemail
, tmpcountry
);
183 r
= CtdlIPCSetRegistration(ipc
, reg
, buf
);
185 scr_printf("%s\n", buf
);
191 void updatels(CtdlIPC
*ipc
)
192 { /* make all messages old in current room */
194 int r
; /* IPC response code */
196 if (rc_alt_semantics
) {
197 if (maxmsgnum
== 0 && highest_msg_read
== 0) {
200 r
= CtdlIPCSetLastRead(ipc
, (maxmsgnum
> highest_msg_read
) ?
201 maxmsgnum
: highest_msg_read
, buf
);
203 r
= CtdlIPCSetLastRead(ipc
, (maxmsgnum
> highest_msg_read
) ?
204 maxmsgnum
: highest_msg_read
, buf
);
205 /* r = CtdlIPCSetLastRead(ipc, maxmsgnum, buf); */
206 /* This is a quick-and-dirty fix to all msgs becoming new in Mail>.
207 * It will need to be rethought when messages.c is rewritten.
211 scr_printf("%s\n", buf
);
215 * only make messages old in this room that have been read
217 void updatelsa(CtdlIPC
*ipc
)
220 int r
; /* IPC response code */
222 r
= CtdlIPCSetLastRead(ipc
, highest_msg_read
, buf
);
224 scr_printf("%s\n", &buf
[4]);
229 * client-based uploads (for users with their own clientware)
231 void cli_upload(CtdlIPC
*ipc
)
237 int r
; /* IPC response code */
241 if ((room_flags
& QR_UPLOAD
) == 0) {
242 scr_printf("*** You cannot upload to this room.\n");
245 newprompt("File to be uploaded: ", flnm
, 55);
246 fd
= open(flnm
, O_RDONLY
);
248 scr_printf("Cannot open '%s': %s\n", flnm
, strerror(errno
));
251 scr_printf("Enter a description of this file:\n");
252 newprompt(": ", desc
, 75);
254 /* Keep generating filenames in hope of finding a unique one */
257 /* basename of filename */
259 if (haschar(tbuf
, '/'))
260 extract_token(tbuf
, flnm
,
261 num_tokens(tbuf
, '/') - 1,
264 /* filename.1, filename.2, etc */
266 sprintf(&tbuf
[strlen(tbuf
)], ".%d", a
);
269 r
= CtdlIPCFileUpload(ipc
, tbuf
, desc
, flnm
, progress
, buf
);
270 if (r
/ 100 == 5 || r
< 0)
271 scr_printf("%s\n", buf
);
276 if (a
> 0) scr_printf("Saved as '%s'\n", tbuf
);
281 * Function used for various image upload commands
283 void cli_image_upload(CtdlIPC
*ipc
, char *keyname
)
289 /* Can we upload this image? */
290 r
= CtdlIPCImageUpload(ipc
, 0, NULL
, keyname
, NULL
, buf
);
292 err_printf("%s\n", buf
);
295 newprompt("Image file to be uploaded: ", flnm
, 55);
296 r
= CtdlIPCImageUpload(ipc
, 1, flnm
, keyname
, progress
, buf
);
298 err_printf("%s\n", buf
);
300 err_printf("Cannot upload '%s': %s\n", flnm
, strerror(errno
));
302 /* else upload succeeded */
307 * protocol-based uploads (Xmodem, Ymodem, Zmodem)
309 void upload(CtdlIPC
*ipc
, int c
)
310 { /* c = upload mode */
320 if ((room_flags
& QR_UPLOAD
) == 0) {
321 scr_printf("*** You cannot upload to this room.\n");
324 /* we don't need a filename when receiving batch y/z modem */
325 if ((c
== 2) || (c
== 3))
328 newprompt("Enter filename: ", flnm
, 15);
330 for (a
= 0; !IsEmptyStr(&flnm
[a
]); ++a
)
331 if ((flnm
[a
] == '/') || (flnm
[a
] == '\\') || (flnm
[a
] == '>')
332 || (flnm
[a
] == '?') || (flnm
[a
] == '*')
333 || (flnm
[a
] == ';') || (flnm
[a
] == '&'))
336 /* create a temporary directory... */
337 if (mkdir(tempdir
, 0700) != 0) {
338 scr_printf("*** Could not create temporary directory %s: %s\n",
339 tempdir
, strerror(errno
));
342 /* now do the transfer ... in a separate process */
349 scr_printf("Receiving %s - press Ctrl-D to end.\n", flnm
);
350 fp
= fopen(flnm
, "w");
366 execlp("rx", "rx", flnm
, NULL
);
371 execlp("rb", "rb", NULL
);
376 execlp("rz", "rz", NULL
);
382 } while ((b
!= xfer_pid
) && (b
!= (-1)));
387 scr_printf("\r*** Transfer unsuccessful.\n");
391 scr_printf("\r*** Transfer successful.\n");
392 snprintf(buf
, sizeof buf
, "cd %s; ls", tempdir
);
393 lsfp
= popen(buf
, "r");
395 while (fgets(flnm
, sizeof flnm
, lsfp
) != NULL
) {
396 flnm
[strlen(flnm
) - 1] = 0; /* chop newline */
397 snprintf(buf
, sizeof buf
,
398 "Enter a short description of '%s':\n: ",
400 newprompt(buf
, desc
, 150);
401 snprintf(buf
, sizeof buf
, "%s/%s", tempdir
, flnm
);
402 r
= CtdlIPCFileUpload(ipc
, flnm
, desc
, buf
, progress
, tbuf
);
403 scr_printf("%s\n", tbuf
);
411 * validate a user (returns 0 for successful validation, nonzero if quitting)
413 int val_user(CtdlIPC
*ipc
, char *user
, int do_validate
)
421 int r
; /* IPC response code */
424 r
= CtdlIPCGetUserRegistration(ipc
, user
, &resp
, cmd
);
428 extract_token(buf
, resp
, 0, '\n', sizeof buf
);
429 remove_token(resp
, 0, '\n');
432 scr_printf("User #%s - %s ", buf
, cmd
);
434 scr_printf("PW: %s\n", (IsEmptyStr(buf
) ? "<NOT SET>" : "<SET>") );
436 scr_printf("%s\n", buf
);
438 scr_printf("%s\n", buf
);
440 scr_printf("%s, ", buf
);
442 scr_printf("%s ", buf
);
444 scr_printf("%s\n", buf
);
446 scr_printf("%s\n", buf
);
450 scr_printf("%s\n", buf
);
452 scr_printf("%s\n", buf
);
453 } while (!IsEmptyStr(resp
));
455 /* TODODRW: discrepancy here. Parts of the code refer to axdefs[7] as the highest
456 * but most of it limits it to axdefs[6].
457 * Webcit limits to 6 as does the code here but there are 7 in axdefs.h
459 scr_printf("Current access level: %d (%s)\n", ax
, axdefs
[ax
]);
461 scr_printf("%s\n%s\n", user
, &cmd
[4]);
463 if (resp
) free(resp
);
466 /* now set the access level */
468 sprintf(answer
, "%d", ax
);
469 strprompt("New access level (? for help, q to quit)",
471 if ((answer
[0] >= '0') && (answer
[0] <= '6')) {
473 r
= CtdlIPCValidateUser(ipc
, user
, ax
, cmd
);
475 scr_printf("%s\n\n", cmd
);
478 if (tolower(answer
[0]) == 'q') {
479 scr_printf("*** Aborted.\n\n");
482 if (answer
[0] == '?') {
483 scr_printf("Available access levels:\n");
484 for (a
=0; a
<7; ++a
) {
485 scr_printf("%d - %s\n",
495 void validate(CtdlIPC
*ipc
)
496 { /* validate new users */
500 int r
; /* IPC response code */
503 r
= CtdlIPCNextUnvalidatedUser(ipc
, cmd
);
507 scr_printf("%s\n", cmd
);
509 extract_token(buf
, cmd
, 0, '|', sizeof buf
);
510 if (val_user(ipc
, buf
, 1) != 0) finished
= 1;
512 } while (finished
== 0);
520 stty_ctdl(SB_RESTORE
);
523 signal(SIGINT
, SIG_DFL
);
524 signal(SIGQUIT
, SIG_DFL
);
525 execlp(getenv("SHELL"), getenv("SHELL"), NULL
);
526 err_printf("Could not open a shell: %s\n", strerror(errno
));
531 } while ((a
!= b
) && (a
!= (-1)));
537 * <.A>ide <F>ile <D>elete command
539 void deletefile(CtdlIPC
*ipc
)
544 newprompt("Filename: ", filename
, 31);
545 if (IsEmptyStr(filename
))
547 CtdlIPCDeleteFile(ipc
, filename
, buf
);
548 err_printf("%s\n", buf
);
553 * <.A>ide <F>ile <M>ove command
555 void movefile(CtdlIPC
*ipc
)
558 char newroom
[ROOMNAMELEN
];
561 newprompt("Filename: ", filename
, 63);
562 if (IsEmptyStr(filename
))
564 newprompt("Enter target room: ", newroom
, ROOMNAMELEN
- 1);
565 CtdlIPCMoveFile(ipc
, filename
, newroom
, buf
);
566 err_printf("%s\n", buf
);
571 * list of users who have filled out a bio
573 void list_bio(CtdlIPC
*ipc
)
578 int r
; /* IPC response code */
580 r
= CtdlIPCListUsersWithBios(ipc
, &resp
, buf
);
582 pprintf("%s\n", buf
);
585 while (resp
&& !IsEmptyStr(resp
)) {
586 extract_token(buf
, resp
, 0, '\n', sizeof buf
);
587 remove_token(resp
, 0, '\n');
588 if ((pos
+ strlen(buf
) + 5) > screenwidth
) {
592 pprintf("%s, ", buf
);
593 pos
= pos
+ strlen(buf
) + 2;
595 pprintf("%c%c \n\n", 8, 8);
596 if (resp
) free(resp
);
603 void read_bio(CtdlIPC
*ipc
)
608 int r
; /* IPC response code */
611 newprompt("Read bio for who ('?' for list) : ", who
, 25);
613 if (!strcmp(who
, "?"))
615 } while (!strcmp(who
, "?"));
617 r
= CtdlIPCGetBio(ipc
, who
, &resp
, buf
);
619 pprintf("%s\n", buf
);
622 while (!IsEmptyStr(resp
)) {
623 extract_token(buf
, resp
, 0, '\n', sizeof buf
);
624 remove_token(resp
, 0, '\n');
625 pprintf("%s\n", buf
);
627 if (resp
) free(resp
);