imap4.c (4925B)
1 /* dmc - dynamic mail client 2 * See LICENSE file for copyright and license details. 3 */ 4 5 #include <poll.h> 6 #include <fcntl.h> 7 #include <stdio.h> 8 #include <string.h> 9 #include <stdlib.h> 10 #include <signal.h> 11 #include <unistd.h> 12 #include <sys/stat.h> 13 #include <sys/types.h> 14 #include "sock.c" 15 16 #if 0 17 cd list.thelist 18 * 3395 EXISTS -> 19 * 0 RECENT -> number of new messages 20 #endif 21 22 #define STRSZ 4095 23 static char cmd[STRSZ], word[STRSZ]; 24 static char *dir; 25 static int ctr = 1; 26 27 /* TODO clean this ugly code */ 28 static char *getword() { 29 char *p = NULL; 30 char *str = word; 31 *word = 0; 32 reread: 33 fscanf (stdin, "%255s", str); 34 if (feof (stdin)) 35 *str = '\0'; 36 else { 37 if (str == word) { 38 if (*word=='"') { 39 strcpy (word, word+1); 40 p = strchr (word, '"'); 41 if (!p) { 42 str = word + strlen (word); 43 *str = ' '; 44 str++; 45 *str = 0; 46 goto reread; 47 } else *p = 0; 48 } 49 } else { 50 p = strchr (str, '"'); 51 if (!p) { 52 *str = ' '; 53 str++; 54 *str = 0; 55 goto reread; 56 } else *p = 0; 57 } 58 } 59 return word; 60 } 61 62 static int waitreply(int catmode) { 63 char *ptr; 64 int lock = 1; 65 int line = 0; 66 int reply = -1; 67 char res[1024]; 68 69 ftruncate (2, 0); 70 lseek (2, 0, SEEK_SET); 71 word[0] = res[0] = '\0'; 72 while (lock || sock_ready ()) { 73 lock = 0; 74 memset (word, 0, sizeof (word)); 75 if (sock_read (word, sizeof (word)-1) <1) 76 break; 77 if (line++ == 0) { 78 ptr = strchr (word, ' '); 79 if (ptr) { 80 if (!memcmp (ptr+1, "OK", 2)) 81 reply = 1; 82 else 83 if (!memcmp (ptr+1, "FETCH", 5)) 84 reply = 1; 85 else 86 if (!memcmp (ptr+1, "NO", 2)) 87 reply = 0; 88 else // TODO: Do 'BAD' should be -1 ? 89 if (!memcmp (ptr+1, "BAD", 3)) 90 reply = 0; 91 else reply = -1; 92 } else reply = -1; 93 94 ptr = strstr (word, "\r\n"); 95 if (!ptr) 96 ptr = strchr (word, '\n'); 97 if (ptr) { 98 char oldptr = *ptr; 99 *ptr = '\0'; 100 snprintf (res, sizeof (res), "### %s %d \"%s\"\n", cmd, reply, word); 101 *ptr = oldptr; 102 if (catmode) { 103 if (oldptr=='\r') 104 strcpy (word, ptr+2); 105 else strcpy (word, ptr+1); 106 if (reply != 0) 107 lock = 1; 108 } 109 } 110 } else if (catmode) { 111 ptr = strstr (word, "\r\n)"); 112 if (ptr == NULL) 113 ptr = strstr (word, "\n)"); 114 if (ptr) { 115 ptr[0] = '\n'; 116 ptr[1] = 0; 117 lock = 0; 118 } else lock = 1; 119 } 120 write (2, word, strlen (word)); 121 } 122 write (1, res, strlen (res)); 123 return reply; 124 } 125 126 #if 0 127 LIST - list all folders 128 LSUB - list all subscribed folders 129 SUBSCRIBE - subcribe a folder 130 CHECK - ??? 131 CLOSE - commit the delete stuff (maybe must be done after rm) 132 EXPUNGE - permanent remove of deltec 133 RECENT - show the number of recent messages 134 #endif 135 static int doword(char *word) { 136 int ret = 1; 137 strcpy (cmd, word); 138 if (*word == '\0') { 139 /* Do nothing */ 140 } else 141 if (!strcmp (word, "exit")) { 142 sock_printf ("%d LOGOUT\n", ctr++); 143 waitreply (0); 144 ret = 0; 145 } else 146 if (!strcmp (word, "help") || !strcmp (word, "?")) { 147 fprintf (stderr, "Use: login exit find cd pwd ls cat head rm rmdir mkdir mvdir\n"); 148 } else 149 if (!strcmp (word, "pwd")) { 150 fprintf (stderr, "%s\n", dir); 151 } else 152 if (!strcmp (word, "cd")) { 153 free(dir); 154 dir = strdup (getword ()); 155 if (!strcmp (dir, "\"\"")) 156 *dir = 0; 157 sock_printf ("%d SELECT \"%s\"\n", ctr++, dir); 158 waitreply (0); 159 } else 160 if (!strcmp (word, "find")) { 161 sock_printf ("%d SEARCH TEXT \"%s\"\n", ctr++, getword ()); 162 waitreply (0); 163 } else 164 if (!strcmp (word, "ls")) { 165 sock_printf ("%d LIST \"%s\" *\n", ctr++, dir); 166 waitreply (0); 167 } else 168 if (!strcmp (word, "cat")) { 169 sock_printf ("%d FETCH %d body[]\n", ctr++, atoi (getword ())); 170 waitreply (1); 171 } else 172 if (!strcmp (word, "head")) { 173 sock_printf ("%d FETCH %d body[header]\n", ctr++, atoi (getword ())); 174 waitreply (1); 175 } else 176 if (!strcmp (word, "mvdir")) { 177 sock_printf ("%d RENAME %s %s\n", 178 ctr++, getword (), getword ()); 179 } else 180 if (!strcmp (word, "mkdir")) { 181 sock_printf ("%d CREATE \"%s\"\n", ctr++, getword ()); 182 } else 183 if (!strcmp (word, "rm")) { 184 sock_printf ("%d DELE %d\n", ctr++, atoi (getword ())); 185 waitreply (0); 186 } else 187 if (!strcmp (word, "rmdir")) { 188 sock_printf ("%d DELETE \"%s\"\n", ctr++, getword ()); 189 waitreply (0); 190 } else 191 if (!strcmp (word, "login")) { 192 char *user = strdup (getword ()); 193 char *pass = strdup (getword ()); 194 sock_printf ("%d LOGIN \"%s\" \"%s\"\n", ctr++, user, pass); 195 free (user); 196 free (pass); 197 waitreply (0); 198 } else { 199 sock_printf ("%d NOOP\n", ctr++); 200 waitreply (0); 201 } 202 return ret; 203 } 204 205 int main (int argc, char **argv) { 206 int ssl = 0, ret = 0; 207 if (argc>2) { 208 if (argc>3) 209 ssl = (*argv[3]=='1'); 210 if (sock_connect (argv[1], atoi (argv[2]), ssl) >= 0) { 211 ret = 0; 212 *cmd = 0; 213 atexit (sock_close); 214 waitreply (0); 215 dir = strdup (""); 216 while (doword (getword ())); 217 } else printf ("Cannot connect to %s %d\n", argv[1], atoi (argv[2])); 218 } else printf ("Usage: dmc-imap4 host port 2> body > fifo < input\n"); 219 return ret; 220 }