Back to index

citadel  8.12
Classes | Defines | Functions | Variables
messages.c File Reference
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <limits.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <time.h>
#include <stdarg.h>
#include <libcitadel.h>
#include "citadel.h"
#include "citadel_ipc.h"
#include "citadel_decls.h"
#include "messages.h"
#include "commands.h"
#include "tuiconfig.h"
#include "rooms.h"
#include "snprintf.h"
#include "screen.h"

Go to the source code of this file.

Classes

struct  cittext

Defines

#define MAXWORDBUF   SIZ
#define NO_REPLY_TO   "nobody ... xxxxxx"

Functions

void stty_ctdl (int cmd)
int haschar (const char *st, int ch)
int file_checksum (char *filename)
void progress (CtdlIPC *ipc, unsigned long curr, unsigned long cmax)
void ka_sigcatch (int signum)
pid_t ka_wait (int *kstatus)
int ka_system (char *shc)
void add_newline (struct cittext *textlist)
void add_word (struct cittext *textlist, char *wordbuf)
void citedit (FILE *fp)
void free_parts (struct parts *p)
void mini_2047_decode (char *s)
int read_message (CtdlIPC *ipc, long num, int pagin, FILE *dest)
void replace_string (char *filename, long int startpos)
int client_make_message (CtdlIPC *ipc, char *filename, char *recipient, int is_anonymous, int format_type, int mode, char *subject, int subject_required)
void check_msg_arr_size (void)
void break_big_lines (char *msg)
int entmsg (CtdlIPC *ipc, int is_reply, int c, int masquerade)
void process_quote (void)
void list_urls (CtdlIPC *ipc)
int do_image_view (const char *filename)
void image_view (CtdlIPC *ipc, unsigned long msg)
void readmsgs (CtdlIPC *ipc, enum MessageList c, enum MessageDirection rdir, int q)
void edit_system_message (CtdlIPC *ipc, char *which_message)
char * load_message_from_file (FILE *src)

Variables

char reply_to [SIZ]
char reply_subject [SIZ]
char reply_references [SIZ]
char reply_inreplyto [SIZ]
unsigned long * msg_arr = NULL
int msg_arr_size = 0
int num_msgs
char room_name []
char tempdir []
unsigned room_flags
unsigned room_flags2
int entmsg_ok
long highest_msg_read
char temp []
char temp2 []
int screenwidth
int screenheight
long maxmsgnum
char is_mail
char is_aide
char is_room_aide
char fullname []
char axlevel
unsigned userflags
char sigcaught
char printcmd []
int rc_allow_attachments
int rc_display_message_numbers
int rc_force_mail_prompts
int editor_pid
CtdlIPCipc_for_signal_handlers
int num_urls = 0
char urls [MAXURLS][SIZ]
char imagecmd [SIZ]
int has_images = 0
struct partslast_message_parts = NULL

Class Documentation

struct cittext

Definition at line 66 of file messages.c.

Collaboration diagram for cittext:
Class Members
struct cittext * next
char text

Define Documentation

#define MAXWORDBUF   SIZ

Definition at line 58 of file messages.c.

#define NO_REPLY_TO   "nobody ... xxxxxx"

Definition at line 59 of file messages.c.


Function Documentation

void add_newline ( struct cittext textlist)

Definition at line 175 of file messages.c.

{
       struct cittext *ptr;

       ptr = textlist;
       while (ptr->next != NULL)
              ptr = ptr->next;

       while (ptr->text[strlen(ptr->text) - 1] == 32)
              ptr->text[strlen(ptr->text) - 1] = 0;
       /* strcat(ptr->text,"\n"); */

       ptr->next = (struct cittext *)
           malloc(sizeof(struct cittext));
       ptr = ptr->next;
       ptr->next = NULL;
       strcpy(ptr->text, "");
}

Here is the caller graph for this function:

void add_word ( struct cittext textlist,
char *  wordbuf 
)

Definition at line 198 of file messages.c.

{
       struct cittext *ptr;

       ptr = textlist;
       while (ptr->next != NULL)
              ptr = ptr->next;

       if (3 + strlen(ptr->text) + strlen(wordbuf) > screenwidth) {
              ptr->next = (struct cittext *)
                  malloc(sizeof(struct cittext));
              ptr = ptr->next;
              ptr->next = NULL;
              strcpy(ptr->text, "");
       }

       strcat(ptr->text, wordbuf);
       strcat(ptr->text, " ");
}

Here is the caller graph for this function:

void break_big_lines ( char *  msg)

Definition at line 1086 of file messages.c.

                                {
       char *ptr;
       char *break_here;

       if (msg == NULL) {
              return;
       }

       ptr = msg;
       while (strlen(ptr) > 1000) {
              break_here = strchr(&ptr[900], ' ');
              if ((break_here == NULL) || (break_here > &ptr[999])) {
                     break_here = &ptr[999];
              }
              *break_here = '\n';
              ptr = break_here++;
       }
}

Here is the caller graph for this function:

void check_msg_arr_size ( void  )

Definition at line 1073 of file messages.c.

                              {
       if ((num_msgs + 1) > msg_arr_size) {
              msg_arr_size += 512;
              msg_arr = realloc(msg_arr,
                     ((sizeof(long)) * msg_arr_size) );
       }
}
void citedit ( FILE *  fp)

Definition at line 222 of file messages.c.

{
       int a, prev, finished, b, last_space;
       int appending = 0;
       struct cittext *textlist = NULL;
       struct cittext *ptr;
       char wordbuf[MAXWORDBUF];
       int rv = 0;

       /* first, load the text into the buffer */
       fseek(fp, 0L, 0);
       textlist = (struct cittext *) malloc(sizeof(struct cittext));
       textlist->next = NULL;
       strcpy(textlist->text, "");

       strcpy(wordbuf, "");
       prev = (-1);
       while (a = getc(fp), a >= 0) {
              appending = 1;
              if ((a == 32) || (a == 9) || (a == 13) || (a == 10)) {
                     add_word(textlist, wordbuf);
                     strcpy(wordbuf, "");
                     if ((prev == 13) || (prev == 10)) {
                            add_word(textlist, "\n");
                            add_newline(textlist);
                            add_word(textlist, "");
                     }
              } else {
                     wordbuf[strlen(wordbuf) + 1] = 0;
                     wordbuf[strlen(wordbuf)] = a;
              }
              if (strlen(wordbuf) + 3 > screenwidth) {
                     add_word(textlist, wordbuf);
                     strcpy(wordbuf, "");
              }
              prev = a;
       }

       /* get text */
       finished = 0;
       prev = (appending ? 13 : (-1));
       strcpy(wordbuf, "");
       async_ka_start();
       do {
              a = inkey();
              if (a == 10)
                     a = 13;
              if (a == 9)
                     a = 32;
              if (a == 127)
                     a = 8;

              if ((a != 32) && (prev == 13)) {
                     add_word(textlist, "\n");
                     scr_printf(" ");
              }

              if ((a == 32) && (prev == 13)) {
                     add_word(textlist, "\n");
                     add_newline(textlist);
              }

              if (a == 8) {
                     if (!IsEmptyStr(wordbuf)) {
                            wordbuf[strlen(wordbuf) - 1] = 0;
                            scr_putc(8);
                            scr_putc(32);
                            scr_putc(8);
                     }
              } else if (a == 23) {
                     do {
                            wordbuf[strlen(wordbuf) - 1] = 0;
                            scr_putc(8);
                            scr_putc(32);
                            scr_putc(8);
                     } while (!IsEmptyStr(wordbuf) && wordbuf[strlen(wordbuf) - 1] != ' ');
              } else if (a == 13) {
                     scr_printf("\n");
                     if (IsEmptyStr(wordbuf))
                            finished = 1;
                     else {
                            for (b = 0; b < strlen(wordbuf); ++b)
                                   if (wordbuf[b] == 32) {
                                          wordbuf[b] = 0;
                                          add_word(textlist,
                                                  wordbuf);
                                          strcpy(wordbuf,
                                                 &wordbuf[b + 1]);
                                          b = 0;
                                   }
                            add_word(textlist, wordbuf);
                            strcpy(wordbuf, "");
                     }
              } else {
                     scr_putc(a);
                     wordbuf[strlen(wordbuf) + 1] = 0;
                     wordbuf[strlen(wordbuf)] = a;
              }
              if ((strlen(wordbuf) + 3) > screenwidth) {
                     last_space = (-1);
                     for (b = 0; b < strlen(wordbuf); ++b)
                            if (wordbuf[b] == 32)
                                   last_space = b;
                     if (last_space >= 0) {
                            for (b = 0; b < strlen(wordbuf); ++b)
                                   if (wordbuf[b] == 32) {
                                          wordbuf[b] = 0;
                                          add_word(textlist,
                                                  wordbuf);
                                          strcpy(wordbuf,
                                                 &wordbuf[b + 1]);
                                          b = 0;
                                   }
                            for (b = 0; b < strlen(wordbuf); ++b) {
                                   scr_putc(8);
                                   scr_putc(32);
                                   scr_putc(8);
                            }
                            scr_printf("\n%s", wordbuf);
                     } else {
                            add_word(textlist, wordbuf);
                            strcpy(wordbuf, "");
                            scr_printf("\n");
                     }
              }
              prev = a;
       } while (finished == 0);
       async_ka_end();

       /* write the buffer back to disk */
       fseek(fp, 0L, 0);
       for (ptr = textlist; ptr != NULL; ptr = ptr->next) {
              fprintf(fp, "%s", ptr->text);
       }
       putc(10, fp);
       fflush(fp);
       rv = ftruncate(fileno(fp), ftell(fp));
       if (rv < 0)
              scr_printf("failed to set message buffer: %s\n", strerror(errno));

       
       /* and deallocate the memory we used */
       while (textlist != NULL) {
              ptr = textlist->next;
              free(textlist);
              textlist = ptr;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int client_make_message ( CtdlIPC ipc,
char *  filename,
char *  recipient,
int  is_anonymous,
int  format_type,
int  mode,
char *  subject,
int  subject_required 
)

Definition at line 865 of file messages.c.

  {
       FILE *fp;
       int a, b, e_ex_code;
       long beg;
       char datestr[SIZ];
       char header[SIZ];
       int cksum = 0;

       if ( (mode == 2) && (IsEmptyStr(editor_path)) ) {
              scr_printf("*** No editor available; using built-in editor.\n");
              mode = 0;
       }

       fmt_date(datestr, sizeof datestr, time(NULL), 0);
       header[0] = 0;

       if (room_flags & QR_ANONONLY && !recipient) {
              snprintf(header, sizeof header, " ****");
       }
       else {
              snprintf(header, sizeof header,
                     " %s from %s",
                     datestr,
                     (is_anonymous ? "[anonymous]" : fullname)
                     );
              if (!IsEmptyStr(recipient)) {
                     size_t tmp = strlen(header);
                     snprintf(&header[tmp], sizeof header - tmp,
                            " to %s", recipient);
              }
       }
       scr_printf("%s\n", header);
       if (subject != NULL) if (!IsEmptyStr(subject)) {
              scr_printf("Subject: %s\n", subject);
       }
       
       if ( (subject_required) && (IsEmptyStr(subject)) ) {
              newprompt("Subject: ", subject, 70);
       }

       if (mode == 1) {
              scr_printf("(Press ctrl-d when finished)\n");
       }

       if (mode == 0) {
              fp = fopen(filename, "r");
              if (fp != NULL) {
                     fmout(screenwidth, fp, NULL, NULL, 0);
                     beg = ftell(fp);
                     if (beg < 0)
                            scr_printf("failed to get stream position %s\n", 
                                      strerror(errno));
                     fclose(fp);
              } else {
                     fp = fopen(filename, "w");
                     if (fp == NULL) {
                            scr_printf("*** Error opening temp file!\n    %s: %s\n",
                                   filename, strerror(errno)
                            );
                     return(1);
                     }
                     fclose(fp);
              }
       }

ME1:   switch (mode) {

       case 0:
              fp = fopen(filename, "r+");
              if (fp == NULL) {
                     scr_printf("*** Error opening temp file!\n    %s: %s\n",
                            filename, strerror(errno)
                     );
                     return(1);
              }
              citedit(fp);
              fclose(fp);
              goto MECR;

       case 1:
              fp = fopen(filename, "a");
              if (fp == NULL) {
                     scr_printf("*** Error opening temp file!\n"
                            "    %s: %s\n",
                            filename, strerror(errno));
                     return(1);
              }
              do {
                     a = inkey();
                     if (a == 255)
                            a = 32;
                     if (a == 13)
                            a = 10;
                     if (a != 4) {
                            putc(a, fp);
                            scr_putc(a);
                     }
                     if (a == 10)
                            scr_putc(10);
              } while (a != 4);
              fclose(fp);
              break;

       case 2:
       default:      /* allow 2+ modes */
              e_ex_code = 1;       /* start with a failed exit code */
              stty_ctdl(SB_RESTORE);
              editor_pid = fork();
              cksum = file_checksum(filename);
              if (editor_pid == 0) {
                     char tmp[SIZ];

                     chmod(filename, 0600);
                     snprintf(tmp, sizeof tmp, "WINDOW_TITLE=%s", header);
                     putenv(tmp);
                     execlp(editor_path, editor_path, filename, NULL);
                     exit(1);
              }
              if (editor_pid > 0)
                     do {
                            e_ex_code = 0;
                            b = ka_wait(&e_ex_code);
                     } while ((b != editor_pid) && (b >= 0));
              editor_pid = (-1);
              stty_ctdl(0);
              break;
       }

MECR:  if (mode >= 2) {
              if (file_checksum(filename) == cksum) {
                     scr_printf("*** Aborted message.\n");
                     e_ex_code = 1;
              }
              if (e_ex_code == 0) {
                     goto MEFIN;
              }
              goto MEABT2;
       }

       b = keymenu("Entry command (? for options)",
              "<A>bort|"
              "<C>ontinue|"
              "<S>ave message|"
              "<P>rint formatted|"
              "add s<U>bject|"
              "<R>eplace string|"
              "<H>old message"
       );

       if (b == 'a') goto MEABT;
       if (b == 'c') goto ME1;
       if (b == 's') goto MEFIN;
       if (b == 'p') {
              scr_printf(" %s from %s", datestr, fullname);
              if (!IsEmptyStr(recipient)) {
                     scr_printf(" to %s", recipient);
              }
              scr_printf("\n");
              if (subject != NULL) if (!IsEmptyStr(subject)) {
                     scr_printf("Subject: %s\n", subject);
              }
              fp = fopen(filename, "r");
              if (fp != NULL) {
                     fmout(screenwidth, fp, NULL, NULL, 0);
                     beg = ftell(fp);
                     if (beg < 0)
                            scr_printf("failed to get stream position %s\n", 
                                      strerror(errno));
                     fclose(fp);
              }
              goto MECR;
       }
       if (b == 'r') {
              replace_string(filename, 0L);
              goto MECR;
       }
       if (b == 'h') {
              return (2);
       }
       if (b == 'u') {
              if (subject != NULL) {
                     newprompt("Subject: ", subject, 70);
              }
              goto MECR;
       }

MEFIN: return (0);

MEABT: scr_printf("Are you sure? ");
       if (yesno() == 0) {
              goto ME1;
       }
MEABT2:       unlink(filename);
       return (2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int do_image_view ( const char *  filename)

Definition at line 1409 of file messages.c.

{
       char cmd[SIZ];
       pid_t childpid;

       snprintf(cmd, sizeof cmd, imagecmd, filename);
       childpid = fork();
       if (childpid < 0) {
              unlink(filename);
              return childpid;
       }

       if (childpid == 0) {
              int retcode;
              pid_t grandchildpid;

              grandchildpid = fork();
              if (grandchildpid < 0) {
                     return grandchildpid;
              }

              if (grandchildpid == 0) {
                     int nullfd;
                     int outfd = -1;
                     int errfd = -1;

                     nullfd = open("/dev/null", O_WRONLY);
                     if (nullfd > -1) {
                            dup2(1, outfd);
                            dup2(2, errfd);
                            dup2(nullfd, 1);
                            dup2(nullfd, 2);
                     }
                     retcode = system(cmd);
                     if (nullfd > -1) {
                            dup2(outfd, 1);
                            dup2(errfd, 2);
                            close(nullfd);
                     }
                     unlink(filename);
                     exit(retcode);
              }

              if (grandchildpid > 0) {
                     exit(0);
              }
       }

       if (childpid > 0) {
              int retcode;

              waitpid(childpid, &retcode, 0);
              return retcode;
       }
       
       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void edit_system_message ( CtdlIPC ipc,
char *  which_message 
)

Definition at line 1931 of file messages.c.

{
       char desc[SIZ];
       char read_cmd[SIZ];
       char write_cmd[SIZ];

       snprintf(desc, sizeof desc, "system message '%s'", which_message);
       snprintf(read_cmd, sizeof read_cmd, "MESG %s", which_message);
       snprintf(write_cmd, sizeof write_cmd, "EMSG %s", which_message);
       do_edit(ipc, desc, read_cmd, "NOOP", write_cmd);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int entmsg ( CtdlIPC ipc,
int  is_reply,
int  c,
int  masquerade 
)

Definition at line 1110 of file messages.c.

  {
       char buf[SIZ];
       int a, b;
       int need_recp = 0;
       int mode;
       long highmsg = 0L;
       FILE *fp;
       char subject[SIZ];
       struct ctdlipcmessage message;
       unsigned long *msgarr = NULL;
       int r;               /* IPC response code */
       int subject_required = 0;

       if (!entmsg_ok) {
              scr_printf("You may not enter messages in this type of room.\n");
              return(1);
       }

       if (c > 0) {
              mode = 1;
       }
       else {
              mode = 0;
       }

       strcpy(subject, "");

       /*
        * First, check to see if we have permission to enter a message in
        * this room.  The server will return an error code if we can't.
        */
       strcpy(message.recipient, "");
       strcpy(message.author, "");
       strcpy(message.subject, "");
       strcpy(message.references, "");
       message.text = "";          /* point to "", changes later */
       message.anonymous = 0;
       message.type = mode;

       if (masquerade) {
              newprompt("Display name for this message: ", message.author, 40);
       }

       if (is_reply) {

              if (!IsEmptyStr(reply_subject)) {
                     if (!strncasecmp(reply_subject,
                        "Re: ", 3)) {
                            strcpy(message.subject, reply_subject);
                     }
                     else {
                            snprintf(message.subject,
                                   sizeof message.subject,
                                   "Re: %s",
                                   reply_subject);
                     }
              }

              /* Trim down excessively long lists of thread references.  We eliminate the
               * second one in the list so that the thread root remains intact.
               */
              int rrtok = num_tokens(reply_references, '|');
              int rrlen = strlen(reply_references);
              if ( ((rrtok >= 3) && (rrlen > 900)) || (rrtok > 10) ) {
                     remove_token(reply_references, 1, '|');
              }

              snprintf(message.references, sizeof message.references, "%s%s%s",
                     reply_references,
                     (IsEmptyStr(reply_references) ? "" : "|"),
                     reply_inreplyto
              );
       }

       r = CtdlIPCPostMessage(ipc, 0, &subject_required, &message, buf);

       if (r / 100 != 2 && r / 10 != 57) {
              scr_printf("%s\n", buf);
              return (1);
       }

       /* Error code 570 is special.  It means that we CAN enter a message
        * in this room, but a recipient needs to be specified.
        */
       need_recp = 0;
       if (r / 10 == 57) {
              need_recp = 1;
       }

       /* If the user is a dumbass, tell them how to type. */
       if ((userflags & US_EXPERT) == 0) {
              formout(ipc, "entermsg");
       }

       /* Handle the selection of a recipient, if necessary. */
       strcpy(buf, "");
       if (need_recp == 1) {
              if (axlevel >= AxProbU) {
                     if (is_reply) {
                            strcpy(buf, reply_to);
                     } else {
                            newprompt("Enter recipient: ", buf, SIZ-100);
                            if (IsEmptyStr(buf)) {
                                   return (1);
                            }
                     }
              } else
                     strcpy(buf, "sysop");
       }
       strcpy(message.recipient, buf);

       if (room_flags & QR_ANONOPT) {
              scr_printf("Anonymous (Y/N)? ");
              if (yesno() == 1)
                     message.anonymous = 1;
       }

       /* If it's mail, we've got to check the validity of the recipient... */
       if (!IsEmptyStr(message.recipient)) {
              r = CtdlIPCPostMessage(ipc, 0, &subject_required,  &message, buf);
              if (r / 100 != 2) {
                     scr_printf("%s\n", buf);
                     return (1);
              }
       }

       /* Learn the number of the newest message in in the room, so we can
        * tell upon saving whether someone else has posted too.
        */
       num_msgs = 0;
       r = CtdlIPCGetMessages(ipc, LastMessages, 1, NULL, &msgarr, buf);
       if (r / 100 != 1) {
              scr_printf("%s\n", buf);
       } else {
              for (num_msgs = 0; msgarr[num_msgs]; num_msgs++)
                     ;
       }

       /* Now compose the message... */
       if (client_make_message(ipc, temp, message.recipient,
          message.anonymous, 0, c, message.subject, subject_required) != 0) {
           if (msgarr) free(msgarr);      
              return (2);
       }

       /* Reopen the temp file that was created, so we can send it */
       fp = fopen(temp, "r");

       if (!fp || !(message.text = load_message_from_file(fp))) {
              scr_printf("*** Internal error while trying to save message!\n"
                     "%s: %s\n",
                     temp, strerror(errno));
              unlink(temp);
              return(errno);
       }

       if (fp) fclose(fp);

       /* Break lines that are >1024 characters, otherwise the server
        * will truncate them.
        */
       break_big_lines(message.text);

       /* Transmit message to the server */
       r = CtdlIPCPostMessage(ipc, 1, NULL, &message, buf);
       if (r / 100 != 4) {
              scr_printf("%s\n", buf);
              return (1);
       }

       /* Yes, unlink it now, so it doesn't stick around if we crash */
       unlink(temp);

       if (num_msgs >= 1) highmsg = msgarr[num_msgs - 1];

       if (msgarr) free(msgarr);
       msgarr = NULL;
       r = CtdlIPCGetMessages(ipc, NewMessages, 0, NULL, &msgarr, buf);
       if (r / 100 != 1) {
              scr_printf("%s\n", buf);
       } else {
              for (num_msgs = 0; msgarr[num_msgs]; num_msgs++)
                     ;
       }

       /* get new highest message number in room to set lrp for goto... */
       maxmsgnum = msgarr[num_msgs - 1];

       /* now see if anyone else has posted in here */
       b = (-1);
       for (a = 0; a < num_msgs; ++a) {
              if (msgarr[a] > highmsg) {
                     ++b;
              }
       }
       if (msgarr) free(msgarr);
       msgarr = NULL;

       /* In the Mail> room, this algorithm always counts one message
        * higher than in public rooms, so we decrement it by one.
        */
       if (need_recp) {
              --b;
       }

       if (b == 1) {
              scr_printf("*** 1 additional message has been entered "
                     "in this room by another user.\n");
       }
       else if (b > 1) {
              scr_printf("*** %d additional messages have been entered "
                     "in this room by other users.\n", b);
       }
    free(message.text);

       return(0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int file_checksum ( char *  filename)

Definition at line 584 of file routines.c.

{
       int cksum = 0;
       int ch;
       FILE *fp;

       fp = fopen(filename,"r");
       if (fp == NULL) return(0);

       /* yes, this algorithm may allow cksum to overflow, but that's ok
        * as long as it overflows consistently, which it will.
        */
       while (ch=getc(fp), ch>=0) {
              cksum = (cksum + ch);
       }

       fclose(fp);
       return(cksum);
}

Here is the caller graph for this function:

void free_parts ( struct parts p)

Definition at line 375 of file messages.c.

{
       struct parts *a_part = p;

       while (a_part) {
              struct parts *q;

              q = a_part;
              a_part = a_part->next;
              free(q);
       }
}

Here is the caller graph for this function:

int haschar ( const char *  st,
int  ch 
)

Here is the caller graph for this function:

void image_view ( CtdlIPC ipc,
unsigned long  msg 
)

Definition at line 1471 of file messages.c.

{
       struct parts *ptr = last_message_parts;
       char part[SIZ];
       int found = 0;

       /* Run through available parts */
       for (ptr = last_message_parts; ptr; ptr = ptr->next) {
              if ((!strcasecmp(ptr->disposition, "attachment")
                 || !strcasecmp(ptr->disposition, "inline"))
                 && !strncmp(ptr->mimetype, "image/", 6)) {
                     found++;
                     if (found == 1) {
                            strcpy(part, ptr->number);
                     }
              }
       }

       while (found > 0) {
              if (found > 1)
                     strprompt("View which part (0 when done)", part, SIZ-1);
              found = -found;
              for (ptr = last_message_parts; ptr; ptr = ptr->next) {
                     if ((!strcasecmp(ptr->disposition, "attachment")
                        || !strcasecmp(ptr->disposition, "inline"))
                        && !strncmp(ptr->mimetype, "image/", 6)
                        && !strcasecmp(ptr->number, part)) {
                            char tmp[PATH_MAX];
                            char buf[SIZ];
                            void *file = NULL; /* The downloaded file */
                            int r;
       
                            /* view image */
                            found = -found;
                            r = CtdlIPCAttachmentDownload(ipc, msg, ptr->number, &file, progress, buf);
                            if (r / 100 != 2) {
                                   scr_printf("%s\n", buf);
                            } else {
                                   size_t len;
       
                                   len = (size_t)extract_long(buf, 0);
                                   progress(ipc, len, len);
                                   scr_flush();
                                   CtdlMakeTempFileName(tmp, sizeof tmp);
                                   strcat(tmp, ptr->filename);
                                   save_buffer(file, len, tmp);
                                   free(file);
                                   do_image_view(tmp);
                            }
                            break;
                     }
              }
              if (found == 1)
                     break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ka_sigcatch ( int  signum)

Definition at line 111 of file messages.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int ka_system ( char *  shc)

Definition at line 141 of file messages.c.

{
       pid_t childpid;
       pid_t waitpid;
       int retcode;

       childpid = fork();
       if (childpid < 0) {
              color(BRIGHT_RED);
              perror("Cannot fork");
              color(DIM_WHITE);
              return ((pid_t) childpid);
       }

       if (childpid == 0) {
              execlp("/bin/sh", "sh", "-c", shc, NULL);
              exit(127);
       }

       if (childpid > 0) {
              do {
                     waitpid = ka_wait(&retcode);
              } while (waitpid != childpid);
              return (retcode);
       }

       return (-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

pid_t ka_wait ( int *  kstatus)

Definition at line 122 of file messages.c.

{
       pid_t p;

       alarm(S_KEEPALIVE);
       signal(SIGALRM, ka_sigcatch);
       do {
              errno = 0;
              p = wait(kstatus);
       } while (errno == EINTR);
       signal(SIGALRM, SIG_IGN);
       alarm(0);
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void list_urls ( CtdlIPC ipc)

Definition at line 1380 of file messages.c.

{
       int i;
       char cmd[SIZ];
       int rv;

       if (num_urls == 0) {
              scr_printf("There were no URL's in the previous message.\n\n");
              return;
       }

       for (i = 0; i < num_urls; ++i) {
              scr_printf("%3d %s\n", i + 1, urls[i]);
       }

       if ((i = num_urls) != 1)
              i = intprompt("Display which one", 1, 1, num_urls);

       snprintf(cmd, sizeof cmd, rc_url_cmd, urls[i - 1]);
       rv = system(cmd);
       if (rv != 0) 
              scr_printf("failed to '%s' by %d\n", cmd, rv);
       scr_printf("\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* load_message_from_file ( FILE *  src)

Definition at line 1950 of file messages.c.

{
       size_t i;
       size_t got = 0;
       char *dest = NULL;

       fseek(src, 0, SEEK_END);
       i = ftell(src);
       rewind(src);

       dest = (char *)calloc(1, i + 1);
       if (!dest)
              return NULL;

       while (got < i) {
              size_t g;

              g = fread(dest + got, 1, i - got, src);
              got += g;
              if (g < i - got) {
                     /* Interrupted system call, keep going */
                     if (errno == EINTR)
                            continue;
                     /* At this point we have either EOF or error */
                     i = got;
                     break;
              }
              dest[i] = 0;
       }

       return dest;
}

Here is the caller graph for this function:

void mini_2047_decode ( char *  s)

Definition at line 393 of file messages.c.

                               {
       if (!s) return;

       char *qstart = strstr(s, "=?UTF-8?Q?");
       if (!qstart) return;

       char *qend = strstr(s, "?=");
       if (!qend) return;

       if (qend <= qstart) return;

       strcpy(qstart, &qstart[10]);
       qend -= 10;

       char *p = qstart;
       while (p < qend) {

              if (p[0] == '=') {

                     char ch[3];
                     ch[0] = p[1];
                     ch[1] = p[2];
                     ch[2] = p[3];
                     int c;
                     sscanf(ch, "%02x", &c);
                     p[0] = c;
                     strcpy(&p[1], &p[3]);
                     qend -= 2;
              }

              if (p[0] == '_') {
                     p[0] = ' ';
              }
              
              ++p;
       }

       strcpy(qend, &qend[2]);
}

Here is the caller graph for this function:

void process_quote ( void  )

Definition at line 1335 of file messages.c.

{
       FILE *qfile, *tfile;
       char buf[128];
       int line, qstart, qend;

       /* Unlink the second temp file as soon as it's opened, so it'll get
        * deleted even if the program dies
        */
       qfile = fopen(temp2, "r");
       unlink(temp2);

       /* Display the quotable text with line numbers added */
       line = 0;
       if (fgets(buf, 128, qfile) == NULL) {
              /* we're skipping a line here */
       }
       while (fgets(buf, 128, qfile) != NULL) {
              scr_printf("%3d %s", ++line, buf);
       }

       qstart = intprompt("Begin quoting at", 1, 1, line);
       qend = intprompt("  End quoting at", line, qstart, line);

       rewind(qfile);
       line = 0;
       if (fgets(buf, 128, qfile) == NULL) {
              /* we're skipping a line here */
       }
       tfile = fopen(temp, "w");
       while (fgets(buf, 128, qfile) != NULL) {
              if ((++line >= qstart) && (line <= qend))
                     fprintf(tfile, " >%s", buf);
       }
       fprintf(tfile, " \n");
       fclose(qfile);
       fclose(tfile);
       chmod(temp, 0666);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void progress ( CtdlIPC ipc,
unsigned long  curr,
unsigned long  cmax 
)

Definition at line 450 of file routines.c.

{
       static char dots[] =
              "**************************************************";
       char dots_printed[51];
       char fmt[42];
       unsigned long a;

       if (curr >= cmax) {
              scr_printf("\r%79s\r","");
       } else {
              /* a will be range 0-50 rather than 0-100 */
              a=(curr * 50) / cmax;
              sprintf(fmt, "[%%s%%%lds] %%3ld%%%% %%10ld/%%10ld\r", 50 - a);
              strncpy(dots_printed, dots, a);
              dots_printed[a] = 0;
              scr_printf(fmt, dots_printed, "",
                            curr * 100 / cmax, curr, cmax);
              scr_flush();
       }
}

Here is the caller graph for this function:

int read_message ( CtdlIPC ipc,
long  num,
int  pagin,
FILE *  dest 
)

Definition at line 436 of file messages.c.

{
       char buf[SIZ];
       char now[SIZ];
       int format_type = 0;
       int fr = 0;
       int nhdr = 0;
       struct ctdlipcmessage *message = NULL;
       int r;                      /* IPC response code */
       char *converted_text = NULL;
       char *lineptr;
       char *nextline;
       char *searchptr;
       int i;
       char ch;
       int linelen;
       int final_line_is_blank = 0;

       has_images = 0;

       sigcaught = 0;
       stty_ctdl(1);

       strcpy(reply_to, NO_REPLY_TO);
       strcpy(reply_subject, "");
       strcpy(reply_references, "");
       strcpy(reply_inreplyto, "");

       r = CtdlIPCGetSingleMessage(ipc, num, (pagin == READ_HEADER ? 1 : 0), 4, &message, buf);
       if (r / 100 != 1) {
              scr_printf("*** msg #%ld: %d %s\n", num, r, buf);
              stty_ctdl(0);
              free(message->text);
              free_parts(message->attachments);
              free(message);
              return (0);
       }

       if (dest) {
              fprintf(dest, "\n ");
       } else {
              scr_printf("\n");
              if (pagin != 2)
                     scr_printf(" ");
       }
       if (pagin == 1 && !dest) {
              color(BRIGHT_CYAN);
       }

       /* View headers only */
       if (pagin == 2) {
              scr_printf("nhdr=%s\nfrom=%s\ntype=%d\nmsgn=%s\n",
                            message->nhdr ? "yes" : "no",
                            message->author, message->type,
                            message->msgid);
              if (!IsEmptyStr(message->subject)) {
                     scr_printf("subj=%s\n", message->subject);
              }
              if (!IsEmptyStr(message->email)) {
                     scr_printf("rfca=%s\n", message->email);
              }
              scr_printf("hnod=%s\nroom=%s\nnode=%s\ntime=%s",
                            message->hnod, message->room,
                            message->node, 
                            asctime(localtime(&message->time)));
              if (!IsEmptyStr(message->recipient)) {
                     scr_printf("rcpt=%s\n", message->recipient);
              }
              if (message->attachments) {
                     struct parts *ptr;

                     for (ptr = message->attachments; ptr; ptr = ptr->next) {
                            scr_printf("part=%s|%s|%s|%s|%s|%ld\n",
                                   ptr->name, ptr->filename, ptr->number,
                                   ptr->disposition, ptr->mimetype,
                                   ptr->length
                            );
                     }
              }
              scr_printf("\n");
              stty_ctdl(0);
              free(message->text);
              free_parts(message->attachments);
              free(message);
              return (0);
       }

       if (rc_display_message_numbers) {
              if (dest) {
                     fprintf(dest, "[#%s] ", message->msgid);
              } else {
                     color(DIM_WHITE);
                     scr_printf("[");
                     color(BRIGHT_WHITE);
                     scr_printf("#%s", message->msgid);
                     color(DIM_WHITE);
                     scr_printf("] ");
              }
       }
       if (nhdr == 1 && !is_room_aide) {
              if (dest) {
                     fprintf(dest, " ****");
              } else {
                     scr_printf(" ****");
              }
       } else {
              fmt_date(now, sizeof now, message->time, 0);
              if (dest) {
                     fprintf(dest, "%s from %s ", now, message->author);
                     if (!IsEmptyStr(message->email)) {
                            fprintf(dest, "<%s> ", message->email);
                     }
              } else {
                     color(BRIGHT_CYAN);
                     scr_printf("%s ", now);
                     color(DIM_WHITE);
                     scr_printf("from ");
                     color(BRIGHT_CYAN);
                     scr_printf("%s ", message->author);
                     if (!IsEmptyStr(message->email)) {
                            color(DIM_WHITE);
                            scr_printf("<");
                            color(BRIGHT_BLUE);
                            scr_printf("%s", message->email);
                                   color(DIM_WHITE);
                            scr_printf("> ");
                     }
              }
              if (!IsEmptyStr(message->node)) {
                     if ((room_flags & QR_NETWORK)
                         || ((strcasecmp(message->node, ipc->ServInfo.nodename)
                          && (strcasecmp(message->node, ipc->ServInfo.fqdn))))) {
                            if (IsEmptyStr(message->email)) {
                                   if (dest) {
                                          fprintf(dest, "@%s ", message->node);
                                   } else {
                                          color(DIM_WHITE);
                                          scr_printf("@");
                                          color(BRIGHT_YELLOW);
                                          scr_printf("%s ", message->node);
                                   }
                            }
                     }
              }
              if (strcasecmp(message->hnod, ipc->ServInfo.humannode)
                  && (!IsEmptyStr(message->hnod)) && (IsEmptyStr(message->email))) {
                     if (dest) {
                            fprintf(dest, "(%s) ", message->hnod);
                     } else {
                            color(DIM_WHITE);
                            scr_printf("(");
                            color(BRIGHT_WHITE);
                            scr_printf("%s", message->hnod);
                            color(DIM_WHITE);
                            scr_printf(") ");
                     }
              }
              if (strcasecmp(message->room, room_name) && (IsEmptyStr(message->email))) {
                     if (dest) {
                            fprintf(dest, "in %s> ", message->room);
                     } else {
                            color(DIM_WHITE);
                            scr_printf("in ");
                            color(BRIGHT_MAGENTA);
                            scr_printf("%s> ", message->room);
                     }
              }
              if (!IsEmptyStr(message->recipient)) {
                     if (dest) {
                            fprintf(dest, "to %s ", message->recipient);
                     } else {
                            color(DIM_WHITE);
                            scr_printf("to ");
                            color(BRIGHT_CYAN);
                            scr_printf("%s ", message->recipient);
                     }
              }
       }
       
       if (dest) {
              fprintf(dest, "\n");
       } else {
              scr_printf("\n");
       }

       /* Set the reply-to address to an Internet e-mail address if possible
        */
       if ((message->email != NULL) && (!IsEmptyStr(message->email))) {
              if (!IsEmptyStr(message->author)) {
                     snprintf(reply_to, sizeof reply_to, "%s <%s>", message->author, message->email);
              }
              else {
                     safestrncpy(reply_to, message->email, sizeof reply_to);
              }
       }

       /* But if we can't do that, set it to a Citadel address.
        */
       if (!strcmp(reply_to, NO_REPLY_TO)) {
              snprintf(reply_to, sizeof(reply_to), "%s @ %s",
                      message->author, message->node);
       }

       if (message->msgid != NULL) {
              safestrncpy(reply_inreplyto, message->msgid, sizeof reply_inreplyto);
       }

       if (message->references != NULL) if (!IsEmptyStr(message->references)) {
              safestrncpy(reply_references, message->references, sizeof reply_references);
       }

       if (message->subject != NULL) {
              safestrncpy(reply_subject, message->subject, sizeof reply_subject);
              if (!IsEmptyStr(message->subject)) {
                     if (dest) {
                            fprintf(dest, "Subject: %s\n", message->subject);
                     } else {
                            color(DIM_WHITE);
                            scr_printf("Subject: ");
                            color(BRIGHT_CYAN);
                            mini_2047_decode(message->subject);
                            scr_printf("%s\n", message->subject);
                     }
              }
       }

       if (pagin == 1 && !dest) {
              color(BRIGHT_WHITE);
       }

       /******* end of header output, start of message text output *******/

       /*
        * Convert HTML to plain text, formatting for the actual width
        * of the client screen.
        */
       if (!strcasecmp(message->content_type, "text/html")) {
              converted_text = html_to_ascii(message->text, 0, screenwidth, 0);
              if (converted_text != NULL) {
                     free(message->text);
                     message->text = converted_text;
                     format_type = 1;
              }
       }

       /* Text/plain is a different type */
       if (!strcasecmp(message->content_type, "text/plain")) {
              format_type = 1;
       }

       /* Extract URL's */
       num_urls = 0; /* Start with a clean slate */
       searchptr = message->text;
       while ( (searchptr != NULL) && (num_urls < MAXURLS) ) {
              searchptr = strstr(searchptr, "http://");
              if (searchptr != NULL) {
                     safestrncpy(urls[num_urls], searchptr, sizeof(urls[num_urls]));
                     for (i = 0; i < strlen(urls[num_urls]); i++) {
                            ch = urls[num_urls][i];
                            if (ch == '>' || ch == '\"' || ch == ')' ||
                                ch == ' ' || ch == '\n') {
                                   urls[num_urls][i] = 0;
                                   break;
                            }
                     }
                     num_urls++;
                     ++searchptr;
              }
       }

       /*
        * Here we go
        */
       if (format_type == 0) {
              fr = fmout(screenwidth, NULL, message->text, dest, 1);
       } else {
              /* renderer for text/plain */

              lineptr = message->text;

              do {
                     nextline = strchr(lineptr, '\n');
                     if (nextline != NULL) {
                            *nextline = 0;
                            ++nextline;
                            if (*nextline == 0) nextline = NULL;
                     }

                     if (sigcaught == 0) {
                            linelen = strlen(lineptr);
                            if (linelen && (lineptr[linelen-1] == '\r')) {
                                   lineptr[--linelen] = 0;
                            }
                            if (dest) {
                                   fprintf(dest, "%s\n", lineptr);
                            } else {
                                   scr_printf("%s\n", lineptr);
                            }
                     }
                     if (lineptr[0] == 0) final_line_is_blank = 1;
                     else final_line_is_blank = 0;
                     lineptr = nextline;
              } while (nextline);
              fr = sigcaught;
       }
       if (!final_line_is_blank) {
              if (dest) {
                     fprintf(dest, "\n");
              }
              else {
                     scr_printf("\n");
                     fr = sigcaught;             
              }
       }

       /* Enumerate any attachments */
       if ( (pagin == 1) && (message->attachments) ) {
              struct parts *ptr;

              for (ptr = message->attachments; ptr; ptr = ptr->next) {
                     if ( (!strcasecmp(ptr->disposition, "attachment"))
                        || (!strcasecmp(ptr->disposition, "inline"))
                        || (!strcasecmp(ptr->disposition, ""))
                     ) {
                            if ( (strcasecmp(ptr->number, message->mime_chosen))
                               && (!IsEmptyStr(ptr->mimetype))
                            ) {
                                   color(DIM_WHITE);
                                   scr_printf("Part ");
                                   color(BRIGHT_MAGENTA);
                                   scr_printf("%s", ptr->number);
                                   color(DIM_WHITE);
                                   scr_printf(": ");
                                   color(BRIGHT_CYAN);
                                   scr_printf("%s", ptr->filename);
                                   color(DIM_WHITE);
                                   scr_printf(" (%s, %ld bytes)\n", ptr->mimetype, ptr->length);
                                   if (!strncmp(ptr->mimetype, "image/", 6)) {
                                          has_images++;
                                   }
                            }
                     }
              }
       }

       /* Save the attachments info for later */
       last_message_parts = message->attachments;

       /* Now we're done */
       free(message->text);
       free(message);

       if (pagin == 1 && !dest)
              color(DIM_WHITE);
       stty_ctdl(0);
       return (fr);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void readmsgs ( CtdlIPC ipc,
enum MessageList  c,
enum MessageDirection  rdir,
int  q 
)

Definition at line 1532 of file messages.c.

  {
       int a, e, f, g, start;
       int savedpos;
       int hold_sw = 0;
       char arcflag = 0;
       char quotflag = 0;
       int hold_color = 0;
       char prtfile[PATH_MAX];
       char pagin;
       char cmd[SIZ];
       char targ[ROOMNAMELEN];
       char filename[PATH_MAX];
       char save_to[PATH_MAX];
       void *attachment = NULL;    /* Downloaded attachment */
       FILE *dest = NULL;          /* Alternate destination other than screen */
       int r;                      /* IPC response code */
       static int att_seq = 0;            /* Attachment download sequence number */
       int rv = 0;                 /* silence the stupid warn_unused_result warnings */

       CtdlMakeTempFileName(prtfile, sizeof prtfile);

       if (msg_arr) {
              free(msg_arr);
              msg_arr = NULL;
       }
       r = CtdlIPCGetMessages(ipc, c, q, NULL, &msg_arr, cmd);
       if (r / 100 != 1) {
              scr_printf("%s\n", cmd);
       } else {
              for (num_msgs = 0; msg_arr[num_msgs]; num_msgs++)
                     ;
       }

       if (num_msgs == 0) { /* TODO look at this later */
              if (c == LastMessages) return;
              scr_printf("*** There are no ");
              if (c == NewMessages) scr_printf("new ");
              if (c == OldMessages) scr_printf("old ");
              scr_printf("messages in this room.\n");
              return;
       }

       /* this loop cycles through each message... */
       start = ((rdir == 1) ? 0 : (num_msgs - 1));
       for (a = start; ((a < num_msgs) && (a >= 0)); a = a + rdir) {
              while (msg_arr[a] == 0L) {
                     a = a + rdir;
                     if ((a == num_msgs) || (a == (-1)))
                            return;
              }

RAGAIN:              pagin = ((arcflag == 0)
                      && (quotflag == 0)
                      && (userflags & US_PAGINATOR)) ? 1 : 0;

              /* If we're doing a quote, set the screenwidth to 72 */
              if (quotflag) {
                     hold_sw = screenwidth;
                     screenwidth = 72;
              }

              /* If printing or archiving, set the screenwidth to 80 */
              if (arcflag) {
                     hold_sw = screenwidth;
                     screenwidth = 80;
              }

              /* clear parts list */
              free_parts(last_message_parts);
              last_message_parts = NULL;

              /* now read the message... */
              e = read_message(ipc, msg_arr[a], pagin, dest);

              /* ...and set the screenwidth back if we have to */
              if ((quotflag) || (arcflag)) {
                     screenwidth = hold_sw;
              }
RMSGREAD:
              highest_msg_read = msg_arr[a];
              if (quotflag) {
                     fclose(dest);
                     dest = NULL;
                     quotflag = 0;
                     enable_color = hold_color;
                     process_quote();
                     e = 'r';
                     goto DONE_QUOTING;
              }
              if (arcflag) {
                     fclose(dest);
                     dest = NULL;
                     arcflag = 0;
                     enable_color = hold_color;
                     f = fork();
                     if (f == 0) {
                            if (freopen(prtfile, "r", stdin) == NULL) {
                                   /* we probably should handle the error condition here */
                            }
                            stty_ctdl(SB_RESTORE);
                            ka_system(printcmd);
                            stty_ctdl(SB_NO_INTR);
                            unlink(prtfile);
                            exit(0);
                     }
                     if (f > 0)
                            do {
                                   g = wait(NULL);
                            } while ((g != f) && (g >= 0));
                     scr_printf("Message printed.\n");
              }
              if (e == SIGQUIT)
                     return;
              if (((userflags & US_NOPROMPT) || (e == SIGINT))
                     && (((room_flags & QR_MAILBOX) == 0)
                     || (rc_force_mail_prompts == 0))) {
                     e = 'n';
              } else {
                     color(DIM_WHITE);
                     scr_printf("(");
                     color(BRIGHT_WHITE);
                     scr_printf("%d", num_msgs - a - 1);
                     color(DIM_WHITE);
                     scr_printf(") ");

                     keyopt("<B>ack <A>gain <R>eply reply<Q>uoted <N>ext <S>top ");
                     if (rc_url_cmd[0] && num_urls)
                            keyopt("<U>RLview ");
                     if (has_images > 0 && !IsEmptyStr(imagecmd))
                            keyopt("<I>mages ");
                     keyopt("<?>help -> ");

                     do {
                            e = (inkey() & 127);
                            e = tolower(e);
/* return key same as <N> */ if (e == 10)
                                   e = 'n';
/* space key same as <N> */ if (e == 32)
                                   e = 'n';
/* del/move for aides only */
                                if (  (!is_room_aide)
                                   && ((room_flags & QR_MAILBOX) == 0)
                                   && ((room_flags2 & QR2_COLLABDEL) == 0)
                                   ) {
                                   if ((e == 'd') || (e == 'm'))
                                          e = 0;
                            }
/* print only if available */
                            if ((e == 'p') && (IsEmptyStr(printcmd)))
                                   e = 0;
/* can't file if not allowed */
                                if ((e == 'f')
                                   && (rc_allow_attachments == 0))
                                   e = 0;
/* link only if browser avail*/
                                if ((e == 'u')
                                   && (IsEmptyStr(rc_url_cmd)))
                                   e = 0;
                            if ((e == 'i')
                                   && (IsEmptyStr(imagecmd) || !has_images))
                                   e = 0;
                     } while ((e != 'a') && (e != 'n') && (e != 's')
                             && (e != 'd') && (e != 'm') && (e != 'p')
                             && (e != 'q') && (e != 'b') && (e != 'h')
                             && (e != 'r') && (e != 'f') && (e != '?')
                             && (e != 'u') && (e != 'c') && (e != 'y')
                             && (e != 'i') && (e != 'o') );
                     switch (e) {
                     case 's':
                            scr_printf("Stop");
                            break;
                     case 'a':
                            scr_printf("Again");
                            break;
                     case 'd':
                            scr_printf("Delete");
                            break;
                     case 'm':
                            scr_printf("Move");
                            break;
                     case 'c':
                            scr_printf("Copy");
                            break;
                     case 'n':
                            scr_printf("Next");
                            break;
                     case 'p':
                            scr_printf("Print");
                            break;
                     case 'q':
                            scr_printf("reply Quoted");
                            break;
                     case 'b':
                            scr_printf("Back");
                            break;
                     case 'h':
                            scr_printf("Header");
                            break;
                     case 'r':
                            scr_printf("Reply");
                            break;
                     case 'o':
                            scr_printf("Open attachments");
                            break;
                     case 'f':
                            scr_printf("File");
                            break;
                     case 'u':
                            scr_printf("URL's");
                            break;
                     case 'y':
                            scr_printf("mY next");
                            break;
                     case 'i':
                            break;
                     case '?':
                            scr_printf("? <help>");
                            break;
                     }
                     if (userflags & US_DISAPPEAR || e == 'i')
                            scr_printf("\r%79s\r", "");
                     else
                            scr_printf("\n");
              }
DONE_QUOTING: switch (e) {
              case '?':
                     scr_printf("Options available here:\n"
                            " ?  Help (prints this message)\n"
                            " S  Stop reading immediately\n"
                            " A  Again (repeats last message)\n"
                            " N  Next (continue with next message)\n"
                            " Y  My Next (continue with next message you authored)\n"
                            " B  Back (go back to previous message)\n");
                     if (  (is_room_aide)
                        || (room_flags & QR_MAILBOX)
                        || (room_flags2 & QR2_COLLABDEL)
                     ) {
                            scr_printf(" D  Delete this message\n"
                                   " M  Move message to another room\n");
                     }
                     scr_printf(" C  Copy message to another room\n");
                     if (!IsEmptyStr(printcmd))
                            scr_printf(" P  Print this message\n");
                     scr_printf(
                            " Q  Reply to this message, quoting portions of it\n"
                            " H  Headers (display message headers only)\n");
                     if (is_mail)
                            scr_printf(" R  Reply to this message\n");
                     if (rc_allow_attachments) {
                            scr_printf(" O  (Open attachments)\n");
                            scr_printf(" F  (save attachments to a File)\n");
                     }
                     if (!IsEmptyStr(rc_url_cmd))
                            scr_printf(" U  (list URL's for display)\n");
                     if (!IsEmptyStr(imagecmd) && has_images > 0)
                            scr_printf(" I  Image viewer\n");
                     scr_printf("\n");
                     goto RMSGREAD;
              case 'p':
                     scr_flush();
                     dest = fopen(prtfile, "w");
                     arcflag = 1;
                     hold_color = enable_color;
                     enable_color = 0;
                     goto RAGAIN;
              case 'q':
                     scr_flush();
                     dest = fopen(temp2, "w");
                     quotflag = 1;
                     hold_color = enable_color;
                     enable_color = 0;
                     goto RAGAIN;
              case 's':
                     return;
              case 'a':
                     goto RAGAIN;
              case 'b':
                     a = a - (rdir * 2);
                     break;
              case 'm':
              case 'c':
                     newprompt("Enter target room: ",
                              targ, ROOMNAMELEN - 1);
                     if (!IsEmptyStr(targ)) {
                            r = CtdlIPCMoveMessage(ipc, (e == 'c' ? 1 : 0),
                                                 msg_arr[a], targ, cmd);
                            scr_printf("%s\n", cmd);
                            if (r / 100 == 2)
                                   msg_arr[a] = 0L;
                     } else {
                            goto RMSGREAD;
                     }
                     if (r / 100 != 2)    /* r will be init'ed, FIXME */
                            goto RMSGREAD;       /* the logic here sucks */
                     break;
              case 'o':
              case 'f':
                     newprompt("Which section? ", filename, ((sizeof filename) - 1));
                     r = CtdlIPCAttachmentDownload(ipc, msg_arr[a],
                                   filename, &attachment, progress, cmd);
                     if (r / 100 != 2) {
                            scr_printf("%s\n", cmd);
                     } else {
                            extract_token(filename, cmd, 2, '|', sizeof filename);
                            /*
                             * Part 1 won't have a filename; use the
                             * subject of the message instead. IO
                             */
                            if (IsEmptyStr(filename)) {
                                   strcpy(filename, reply_subject);
                            }
                            if (e == 'o') {             /* open attachment */
                                   mkdir(tempdir, 0700);
                                   snprintf(save_to, sizeof save_to, "%s/%04x.%s",
                                          tempdir,
                                          ++att_seq,
                                          filename);
                                   save_buffer(attachment, extract_unsigned_long(cmd, 0), save_to);
                                   snprintf(cmd, sizeof cmd, rc_open_cmd, save_to);
                                   rv = system(cmd);
                                   if (rv != 0)
                                          scr_printf("failed to save %s Reason %d\n", cmd, rv);
                            }
                            else {               /* save attachment to disk */
                                   destination_directory(save_to, filename);
                                   save_buffer(attachment, extract_unsigned_long(cmd, 0), save_to);
                            }
                     }
                     if (attachment) {
                            free(attachment);
                            attachment = NULL;
                     }
                     goto RMSGREAD;
              case 'd':
                     scr_printf("*** Delete this message? ");
                     if (yesno() == 1) {
                            r = CtdlIPCDeleteMessage(ipc, msg_arr[a], cmd);
                            scr_printf("%s\n", cmd);
                            if (r / 100 == 2)
                                   msg_arr[a] = 0L;
                     } else {
                            goto RMSGREAD;
                     }
                     break;
              case 'h':
                     read_message(ipc, msg_arr[a], READ_HEADER, NULL);
                     goto RMSGREAD;
              case 'r':
                     savedpos = num_msgs;
                     entmsg(ipc, 1, ((userflags & US_EXTEDIT) ? 2 : 0), 0);
                     num_msgs = savedpos;
                     goto RMSGREAD;
              case 'u':
                     list_urls(ipc);
                     goto RMSGREAD;
              case 'i':
                     image_view(ipc, msg_arr[a]);
                     goto RMSGREAD;
           case 'y':
          { /* hack hack hack */
            /* find the next message by me, stay here if we find nothing */
            int finda;
            int lasta = a;
            for (finda = (a + rdir); ((finda < num_msgs) && (finda >= 0)); finda += rdir)
              {
              /* This is repetitively dumb, but that's what computers are for.
                 We have to load up messages until we find one by us */
              char buf[SIZ];
              int founda = 0;
              struct ctdlipcmessage *msg = NULL;
                
              /* read the header so we can get 'from=' */
              r = CtdlIPCGetSingleMessage(ipc, msg_arr[finda], 1, 0, &msg, buf);
              if (!strncasecmp(msg->author, fullname, sizeof(fullname))) {
                     a = lasta; /* meesa current */
                     founda = 1;
              }

              free(msg);

              if (founda)
                     break; /* for */
              lasta = finda; /* keep one behind or we skip on the reentrance to the for */
              } /* for */
          } /* case 'y' */
      } /* switch */
       }                    /* end for loop */
}                           /* end read routine */

Here is the call graph for this function:

Here is the caller graph for this function:

void replace_string ( char *  filename,
long int  startpos 
)

Definition at line 800 of file messages.c.

{
       char buf[512];
       char srch_str[128];
       char rplc_str[128];
       FILE *fp;
       int a;
       long rpos, wpos;
       char *ptr;
       int substitutions = 0;
       long msglen = 0L;
       int rv;

       newprompt("Enter test to be replaced: ", srch_str, (sizeof(srch_str)-1) );
       if (IsEmptyStr(srch_str)) {
              return;
       }

       newprompt("Enter text to replace it with: ", rplc_str, (sizeof(rplc_str)-1) );

       fp = fopen(filename, "r+");
       if (fp == NULL) {
              return;
       }

       wpos = startpos;
       fseek(fp, startpos, 0);
       strcpy(buf, "");
       while (a = getc(fp), a > 0) {
              ++msglen;
              buf[strlen(buf) + 1] = 0;
              buf[strlen(buf)] = a;
              if (strlen(buf) >= strlen(srch_str)) {
                     ptr = (&buf[strlen(buf) - strlen(srch_str)]);
                     if (!strncmp(ptr, srch_str, strlen(srch_str))) {
                            strcpy(ptr, rplc_str);
                            ++substitutions;
                     }
              }
              if (strlen(buf) > 384) {
                     rpos = ftell(fp);
                     fseek(fp, wpos, 0);
                     rv = fwrite((char *) buf, 128, 1, fp);
                     if (rv < 0) {
                            scr_printf("failed to replace string: %s\n", strerror(errno));
                            break; /*whoopsi! */
                     }
                     strcpy(buf, &buf[128]);
                     wpos = ftell(fp);
                     fseek(fp, rpos, 0);
              }
       }
       fseek(fp, wpos, 0);
       if (!IsEmptyStr(buf)) {
              rv = fwrite((char *) buf, strlen(buf), 1, fp);
       }
       wpos = ftell(fp);
       fclose(fp);
       rv = truncate(filename, wpos);
       scr_printf("<R>eplace made %d substitution(s).\n\n", substitutions);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void stty_ctdl ( int  cmd)

Definition at line 1163 of file commands.c.

{                           /* BSD version of stty_ctdl() */
       struct sgttyb live;
       static struct sgttyb saved_settings;
       static int last_cmd = 0;

       if (cmd == SB_LAST)
              cmd = last_cmd;
       else
              last_cmd = cmd;

       if ((cmd == 0) || (cmd == 1)) {
              gtty(0, &live);
              live.sg_flags |= CBREAK;
              live.sg_flags |= CRMOD;
              live.sg_flags |= NL1;
              live.sg_flags &= ~ECHO;
              if (cmd == 1)
                     live.sg_flags |= NOFLSH;
              stty(0, &live);
       }
       if (cmd == 2) {
              gtty(0, &saved_settings);
       }
       if (cmd == 3) {
              stty(0, &saved_settings);
       }
}

Variable Documentation

char axlevel

Definition at line 90 of file citadel.c.

Definition at line 80 of file citadel.c.

int entmsg_ok

Definition at line 84 of file citadel.c.

char fullname[]

Definition at line 81 of file citadel.c.

int has_images = 0

Definition at line 106 of file messages.c.

Definition at line 98 of file citadel.c.

char imagecmd[SIZ]

Definition at line 105 of file messages.c.

Definition at line 116 of file citadel.c.

char is_aide
char is_mail

Definition at line 89 of file citadel.c.

Definition at line 91 of file citadel.c.

struct parts* last_message_parts = NULL

Definition at line 107 of file messages.c.

long maxmsgnum

Definition at line 99 of file citadel.c.

unsigned long* msg_arr = NULL

Definition at line 76 of file messages.c.

int msg_arr_size = 0

Definition at line 77 of file messages.c.

int num_msgs

Definition at line 78 of file messages.c.

int num_urls = 0

Definition at line 103 of file messages.c.

char printcmd[]

Definition at line 79 of file citadel.c.

Definition at line 83 of file commands.c.

Definition at line 84 of file commands.c.

Definition at line 85 of file commands.c.

Definition at line 64 of file messages.c.

Definition at line 63 of file messages.c.

Definition at line 62 of file messages.c.

char reply_to[SIZ]

Definition at line 61 of file messages.c.

unsigned room_flags

Definition at line 82 of file citadel.c.

unsigned room_flags2

Definition at line 83 of file citadel.c.

char room_name[]

Definition at line 85 of file citadel.c.

Definition at line 42 of file screen.c.

Definition at line 43 of file screen.c.

char sigcaught

Definition at line 100 of file citadel.c.

char temp[]

Definition at line 76 of file citadel.c.

char temp2[]

Definition at line 77 of file citadel.c.

char tempdir[]

Definition at line 78 of file citadel.c.

char urls[MAXURLS][SIZ]

Definition at line 104 of file messages.c.

unsigned userflags

Definition at line 94 of file citadel.c.