dmc

dynamic mail client
git clone git://git.suckless.org/dmc
Log | Files | Refs | README | LICENSE

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 }