diff options
| author | Richard M. Stallman | 1989-04-28 03:54:04 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1989-04-28 03:54:04 +0000 |
| commit | 237e001615155218965fc9ff98f0d3567a200cfa (patch) | |
| tree | fa1202d0ab3dcfbde92b20ed8f576c49cbc40368 /lib-src | |
| parent | 66f565252f793e2fd37bcb1ab0642c2037818c2f (diff) | |
| download | emacs-237e001615155218965fc9ff98f0d3567a200cfa.tar.gz emacs-237e001615155218965fc9ff98f0d3567a200cfa.zip | |
Initial revision
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/movemail.c | 642 |
1 files changed, 642 insertions, 0 deletions
diff --git a/lib-src/movemail.c b/lib-src/movemail.c new file mode 100644 index 00000000000..32e4039d519 --- /dev/null +++ b/lib-src/movemail.c | |||
| @@ -0,0 +1,642 @@ | |||
| 1 | /* movemail foo bar -- move file foo to file bar, | ||
| 2 | locking file foo the way /bin/mail respects. | ||
| 3 | Copyright (C) 1986 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 8 | but without any warranty. No author or distributor | ||
| 9 | accepts responsibility to anyone for the consequences of using it | ||
| 10 | or for whether it serves any particular purpose or works at all, | ||
| 11 | unless he says so in writing. | ||
| 12 | |||
| 13 | Everyone is granted permission to copy, modify and redistribute | ||
| 14 | GNU Emacs, but only under the conditions described in the | ||
| 15 | document "GNU Emacs copying permission notice". An exact copy | ||
| 16 | of the document is supposed to have been given to you along with | ||
| 17 | GNU Emacs so that you can know how you may redistribute it all. | ||
| 18 | It should be in a file named COPYING. Among other things, the | ||
| 19 | copyright notice and this notice must be preserved on all copies. */ | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Modified January, 1986 by Michael R. Gretzinger (Project Athena) | ||
| 23 | * | ||
| 24 | * Added POP (Post Office Protocol) service. When compiled -DPOP | ||
| 25 | * movemail will accept input filename arguments of the form | ||
| 26 | * "po:username". This will cause movemail to open a connection to | ||
| 27 | * a pop server running on $MAILHOST (environment variable). Movemail | ||
| 28 | * must be setuid to root in order to work with POP. | ||
| 29 | * | ||
| 30 | * New module: popmail.c | ||
| 31 | * Modified routines: | ||
| 32 | * main - added code within #ifdef MAIL_USE_POP; added setuid(getuid()) | ||
| 33 | * after POP code. | ||
| 34 | * New routines in movemail.c: | ||
| 35 | * get_errmsg - return pointer to system error message | ||
| 36 | * | ||
| 37 | */ | ||
| 38 | |||
| 39 | #include <sys/types.h> | ||
| 40 | #include <sys/stat.h> | ||
| 41 | #include <sys/file.h> | ||
| 42 | #include <errno.h> | ||
| 43 | #define NO_SHORTNAMES /* Tell config not to load remap.h */ | ||
| 44 | #include "../src/config.h" | ||
| 45 | |||
| 46 | #ifdef USG | ||
| 47 | #include <fcntl.h> | ||
| 48 | #include <unistd.h> | ||
| 49 | #endif /* USG */ | ||
| 50 | |||
| 51 | #ifdef XENIX | ||
| 52 | #include <sys/locking.h> | ||
| 53 | #endif | ||
| 54 | |||
| 55 | /* Cancel substitutions made by config.h for Emacs. */ | ||
| 56 | #undef open | ||
| 57 | #undef read | ||
| 58 | #undef write | ||
| 59 | #undef close | ||
| 60 | |||
| 61 | char *concat (); | ||
| 62 | extern int errno; | ||
| 63 | |||
| 64 | /* Nonzero means this is name of a lock file to delete on fatal error. */ | ||
| 65 | char *delete_lockname; | ||
| 66 | |||
| 67 | main (argc, argv) | ||
| 68 | int argc; | ||
| 69 | char **argv; | ||
| 70 | { | ||
| 71 | char *inname, *outname; | ||
| 72 | int indesc, outdesc; | ||
| 73 | char buf[1024]; | ||
| 74 | int nread; | ||
| 75 | |||
| 76 | #ifndef MAIL_USE_FLOCK | ||
| 77 | struct stat st; | ||
| 78 | long now; | ||
| 79 | int tem; | ||
| 80 | char *lockname, *p; | ||
| 81 | char tempname[40]; | ||
| 82 | int desc; | ||
| 83 | #endif /* not MAIL_USE_FLOCK */ | ||
| 84 | |||
| 85 | delete_lockname = 0; | ||
| 86 | |||
| 87 | if (argc < 3) | ||
| 88 | fatal ("two arguments required"); | ||
| 89 | |||
| 90 | inname = argv[1]; | ||
| 91 | outname = argv[2]; | ||
| 92 | |||
| 93 | /* Check access to input and output file. */ | ||
| 94 | if (access (inname, R_OK | W_OK) != 0) | ||
| 95 | pfatal_with_name (inname); | ||
| 96 | if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0) | ||
| 97 | pfatal_with_name (outname); | ||
| 98 | |||
| 99 | /* Also check that outname's directory is writeable to the real uid. */ | ||
| 100 | { | ||
| 101 | char *buf = (char *) malloc (strlen (outname) + 1); | ||
| 102 | char *p, q; | ||
| 103 | strcpy (buf, outname); | ||
| 104 | p = buf + strlen (buf); | ||
| 105 | while (p > buf && p[-1] != '/') | ||
| 106 | *--p = 0; | ||
| 107 | if (p == buf) | ||
| 108 | *p++ = '.'; | ||
| 109 | if (access (buf, W_OK) != 0) | ||
| 110 | pfatal_with_name (buf); | ||
| 111 | free (buf); | ||
| 112 | } | ||
| 113 | |||
| 114 | #ifdef MAIL_USE_POP | ||
| 115 | if (!bcmp (inname, "po:", 3)) | ||
| 116 | { | ||
| 117 | int status; char *user; | ||
| 118 | |||
| 119 | user = (char *) rindex (inname, ':') + 1; | ||
| 120 | status = popmail (user, outname); | ||
| 121 | exit (status); | ||
| 122 | } | ||
| 123 | |||
| 124 | setuid (getuid()); | ||
| 125 | #endif /* MAIL_USE_POP */ | ||
| 126 | |||
| 127 | #ifndef MAIL_USE_FLOCK | ||
| 128 | /* Use a lock file named /usr/spool/mail/$USER.lock: | ||
| 129 | If it exists, the mail file is locked. */ | ||
| 130 | lockname = concat (inname, ".lock", ""); | ||
| 131 | strcpy (tempname, inname); | ||
| 132 | p = tempname + strlen (tempname); | ||
| 133 | while (p != tempname && p[-1] != '/') | ||
| 134 | p--; | ||
| 135 | *p = 0; | ||
| 136 | strcpy (p, "EXXXXXX"); | ||
| 137 | mktemp (tempname); | ||
| 138 | (void) unlink (tempname); | ||
| 139 | |||
| 140 | while (1) | ||
| 141 | { | ||
| 142 | /* Create the lock file, but not under the lock file name. */ | ||
| 143 | /* Give up if cannot do that. */ | ||
| 144 | desc = open (tempname, O_WRONLY | O_CREAT, 0666); | ||
| 145 | if (desc < 0) | ||
| 146 | pfatal_with_name (concat ("temporary file \"", tempname, "\"")); | ||
| 147 | close (desc); | ||
| 148 | |||
| 149 | tem = link (tempname, lockname); | ||
| 150 | (void) unlink (tempname); | ||
| 151 | if (tem >= 0) | ||
| 152 | break; | ||
| 153 | sleep (1); | ||
| 154 | |||
| 155 | /* If lock file is a minute old, unlock it. */ | ||
| 156 | if (stat (lockname, &st) >= 0) | ||
| 157 | { | ||
| 158 | now = time (0); | ||
| 159 | if (st.st_ctime < now - 60) | ||
| 160 | (void) unlink (lockname); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | delete_lockname = lockname; | ||
| 165 | #endif /* not MAIL_USE_FLOCK */ | ||
| 166 | |||
| 167 | #ifdef MAIL_USE_FLOCK | ||
| 168 | indesc = open (inname, O_RDWR); | ||
| 169 | #else /* if not MAIL_USE_FLOCK */ | ||
| 170 | indesc = open (inname, O_RDONLY); | ||
| 171 | #endif /* not MAIL_USE_FLOCK */ | ||
| 172 | if (indesc < 0) | ||
| 173 | pfatal_with_name (inname); | ||
| 174 | |||
| 175 | #if defined(BSD) || defined(XENIX) | ||
| 176 | /* In case movemail is setuid to root, make sure the user can | ||
| 177 | read the output file. */ | ||
| 178 | /* This is desirable for all systems | ||
| 179 | but I don't want to assume all have the umask system call */ | ||
| 180 | umask (umask (0) & 0333); | ||
| 181 | #endif /* BSD or Xenix */ | ||
| 182 | outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666); | ||
| 183 | if (outdesc < 0) | ||
| 184 | pfatal_with_name (outname); | ||
| 185 | #ifdef MAIL_USE_FLOCK | ||
| 186 | #ifdef XENIX | ||
| 187 | if (locking (indesc, LK_RLCK, 0L) < 0) pfatal_with_name (inname); | ||
| 188 | #else | ||
| 189 | if (flock (indesc, LOCK_EX) < 0) pfatal_with_name (inname); | ||
| 190 | #endif | ||
| 191 | #endif /* MAIL_USE_FLOCK */ | ||
| 192 | |||
| 193 | while (1) | ||
| 194 | { | ||
| 195 | nread = read (indesc, buf, sizeof buf); | ||
| 196 | if (nread != write (outdesc, buf, nread)) | ||
| 197 | { | ||
| 198 | int saved_errno = errno; | ||
| 199 | (void) unlink (outname); | ||
| 200 | errno = saved_errno; | ||
| 201 | pfatal_with_name (outname); | ||
| 202 | } | ||
| 203 | if (nread < sizeof buf) | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | |||
| 207 | #ifdef BSD | ||
| 208 | fsync (outdesc); | ||
| 209 | #endif | ||
| 210 | |||
| 211 | /* Check to make sure no errors before we zap the inbox. */ | ||
| 212 | if (close (outdesc) != 0) | ||
| 213 | { | ||
| 214 | int saved_errno = errno; | ||
| 215 | (void) unlink (outname); | ||
| 216 | errno = saved_errno; | ||
| 217 | pfatal_with_name (outname); | ||
| 218 | } | ||
| 219 | |||
| 220 | #ifdef MAIL_USE_FLOCK | ||
| 221 | #if defined(STRIDE) || defined(XENIX) | ||
| 222 | /* Stride, xenix have file locking, but no ftruncate. This mess will do. */ | ||
| 223 | (void) close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666)); | ||
| 224 | #else | ||
| 225 | (void) ftruncate (indesc, 0L); | ||
| 226 | #endif /* STRIDE or XENIX */ | ||
| 227 | #endif /* MAIL_USE_FLOCK */ | ||
| 228 | close (indesc); | ||
| 229 | |||
| 230 | #ifndef MAIL_USE_FLOCK | ||
| 231 | /* Delete the input file; if we can't, at least get rid of its contents. */ | ||
| 232 | if (unlink (inname) < 0) | ||
| 233 | if (errno != ENOENT) | ||
| 234 | creat (inname, 0666); | ||
| 235 | (void) unlink (lockname); | ||
| 236 | #endif /* not MAIL_USE_FLOCK */ | ||
| 237 | exit (0); | ||
| 238 | } | ||
| 239 | |||
| 240 | /* Print error message and exit. */ | ||
| 241 | |||
| 242 | fatal (s1, s2) | ||
| 243 | char *s1, *s2; | ||
| 244 | { | ||
| 245 | if (delete_lockname) | ||
| 246 | unlink (delete_lockname); | ||
| 247 | error (s1, s2); | ||
| 248 | exit (1); | ||
| 249 | } | ||
| 250 | |||
| 251 | /* Print error message. `s1' is printf control string, `s2' is arg for it. */ | ||
| 252 | |||
| 253 | error (s1, s2) | ||
| 254 | char *s1, *s2; | ||
| 255 | { | ||
| 256 | printf ("movemail: "); | ||
| 257 | printf (s1, s2); | ||
| 258 | printf ("\n"); | ||
| 259 | } | ||
| 260 | |||
| 261 | pfatal_with_name (name) | ||
| 262 | char *name; | ||
| 263 | { | ||
| 264 | extern int errno, sys_nerr; | ||
| 265 | extern char *sys_errlist[]; | ||
| 266 | char *s; | ||
| 267 | |||
| 268 | if (errno < sys_nerr) | ||
| 269 | s = concat ("", sys_errlist[errno], " for %s"); | ||
| 270 | else | ||
| 271 | s = "cannot open %s"; | ||
| 272 | fatal (s, name); | ||
| 273 | } | ||
| 274 | |||
| 275 | /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ | ||
| 276 | |||
| 277 | char * | ||
| 278 | concat (s1, s2, s3) | ||
| 279 | char *s1, *s2, *s3; | ||
| 280 | { | ||
| 281 | int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); | ||
| 282 | char *result = (char *) xmalloc (len1 + len2 + len3 + 1); | ||
| 283 | |||
| 284 | strcpy (result, s1); | ||
| 285 | strcpy (result + len1, s2); | ||
| 286 | strcpy (result + len1 + len2, s3); | ||
| 287 | *(result + len1 + len2 + len3) = 0; | ||
| 288 | |||
| 289 | return result; | ||
| 290 | } | ||
| 291 | |||
| 292 | /* Like malloc but get fatal error if memory is exhausted. */ | ||
| 293 | |||
| 294 | int | ||
| 295 | xmalloc (size) | ||
| 296 | int size; | ||
| 297 | { | ||
| 298 | int result = malloc (size); | ||
| 299 | if (!result) | ||
| 300 | fatal ("virtual memory exhausted", 0); | ||
| 301 | return result; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* This is the guts of the interface to the Post Office Protocol. */ | ||
| 305 | |||
| 306 | #ifdef MAIL_USE_POP | ||
| 307 | |||
| 308 | #include <sys/socket.h> | ||
| 309 | #include <netinet/in.h> | ||
| 310 | #include <netdb.h> | ||
| 311 | #include <stdio.h> | ||
| 312 | |||
| 313 | #ifdef USG | ||
| 314 | #include <fcntl.h> | ||
| 315 | /* Cancel substitutions made by config.h for Emacs. */ | ||
| 316 | #undef open | ||
| 317 | #undef read | ||
| 318 | #undef write | ||
| 319 | #undef close | ||
| 320 | #endif /* USG */ | ||
| 321 | |||
| 322 | #define NOTOK (-1) | ||
| 323 | #define OK 0 | ||
| 324 | #define DONE 1 | ||
| 325 | |||
| 326 | char *progname; | ||
| 327 | FILE *sfi; | ||
| 328 | FILE *sfo; | ||
| 329 | char Errmsg[80]; | ||
| 330 | |||
| 331 | static int debug = 0; | ||
| 332 | |||
| 333 | popmail(user, outfile) | ||
| 334 | char *user; | ||
| 335 | char *outfile; | ||
| 336 | { | ||
| 337 | char *host; | ||
| 338 | int nmsgs, nbytes; | ||
| 339 | char response[128]; | ||
| 340 | register int i; | ||
| 341 | int mbfi; | ||
| 342 | FILE *mbf; | ||
| 343 | char *getenv(); | ||
| 344 | int mbx_write(); | ||
| 345 | char *get_errmsg(); | ||
| 346 | |||
| 347 | host = getenv("MAILHOST"); | ||
| 348 | if (host == NULL) { | ||
| 349 | fatal("no MAILHOST defined"); | ||
| 350 | } | ||
| 351 | |||
| 352 | if (pop_init(host) == NOTOK) { | ||
| 353 | error(Errmsg); | ||
| 354 | return(1); | ||
| 355 | } | ||
| 356 | |||
| 357 | if (getline(response, sizeof response, sfi) != OK) { | ||
| 358 | error(response); | ||
| 359 | return(1); | ||
| 360 | } | ||
| 361 | |||
| 362 | if (pop_command("USER %s", user) == NOTOK || | ||
| 363 | pop_command("RPOP %s", user) == NOTOK) { | ||
| 364 | error(Errmsg); | ||
| 365 | pop_command("QUIT"); | ||
| 366 | return(1); | ||
| 367 | } | ||
| 368 | |||
| 369 | if (pop_stat(&nmsgs, &nbytes) == NOTOK) { | ||
| 370 | error(Errmsg); | ||
| 371 | pop_command("QUIT"); | ||
| 372 | return(1); | ||
| 373 | } | ||
| 374 | |||
| 375 | if (!nmsgs) | ||
| 376 | { | ||
| 377 | pop_command("QUIT"); | ||
| 378 | return(0); | ||
| 379 | } | ||
| 380 | |||
| 381 | mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666); | ||
| 382 | if (mbfi < 0) | ||
| 383 | { | ||
| 384 | pop_command("QUIT"); | ||
| 385 | error("Error in open: %s, %s", get_errmsg(), outfile); | ||
| 386 | return(1); | ||
| 387 | } | ||
| 388 | fchown(mbfi, getuid(), -1); | ||
| 389 | |||
| 390 | if ((mbf = fdopen(mbfi, "w")) == NULL) | ||
| 391 | { | ||
| 392 | pop_command("QUIT"); | ||
| 393 | error("Error in fdopen: %s", get_errmsg()); | ||
| 394 | close(mbfi); | ||
| 395 | unlink(outfile); | ||
| 396 | return(1); | ||
| 397 | } | ||
| 398 | |||
| 399 | for (i = 1; i <= nmsgs; i++) { | ||
| 400 | mbx_delimit_begin(mbf); | ||
| 401 | if (pop_retr(i, mbx_write, mbf) != OK) { | ||
| 402 | error(Errmsg); | ||
| 403 | pop_command("QUIT"); | ||
| 404 | close(mbfi); | ||
| 405 | return(1); | ||
| 406 | } | ||
| 407 | mbx_delimit_end(mbf); | ||
| 408 | fflush(mbf); | ||
| 409 | } | ||
| 410 | |||
| 411 | for (i = 1; i <= nmsgs; i++) { | ||
| 412 | if (pop_command("DELE %d", i) == NOTOK) { | ||
| 413 | error(Errmsg); | ||
| 414 | pop_command("QUIT"); | ||
| 415 | close(mbfi); | ||
| 416 | return(1); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | pop_command("QUIT"); | ||
| 421 | close(mbfi); | ||
| 422 | return(0); | ||
| 423 | } | ||
| 424 | |||
| 425 | pop_init(host) | ||
| 426 | char *host; | ||
| 427 | { | ||
| 428 | register struct hostent *hp; | ||
| 429 | register struct servent *sp; | ||
| 430 | int lport = IPPORT_RESERVED - 1; | ||
| 431 | struct sockaddr_in sin; | ||
| 432 | register int s; | ||
| 433 | char *get_errmsg(); | ||
| 434 | |||
| 435 | hp = gethostbyname(host); | ||
| 436 | if (hp == NULL) { | ||
| 437 | sprintf(Errmsg, "MAILHOST unknown: %s", host); | ||
| 438 | return(NOTOK); | ||
| 439 | } | ||
| 440 | |||
| 441 | sp = getservbyname("pop", "tcp"); | ||
| 442 | if (sp == 0) { | ||
| 443 | strcpy(Errmsg, "tcp/pop: unknown service"); | ||
| 444 | return(NOTOK); | ||
| 445 | } | ||
| 446 | |||
| 447 | sin.sin_family = hp->h_addrtype; | ||
| 448 | bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); | ||
| 449 | sin.sin_port = sp->s_port; | ||
| 450 | s = rresvport(&lport); | ||
| 451 | if (s < 0) { | ||
| 452 | sprintf(Errmsg, "error creating socket: %s", get_errmsg()); | ||
| 453 | return(NOTOK); | ||
| 454 | } | ||
| 455 | |||
| 456 | if (connect(s, (char *)&sin, sizeof sin) < 0) { | ||
| 457 | sprintf(Errmsg, "error during connect: %s", get_errmsg()); | ||
| 458 | close(s); | ||
| 459 | return(NOTOK); | ||
| 460 | } | ||
| 461 | |||
| 462 | sfi = fdopen(s, "r"); | ||
| 463 | sfo = fdopen(s, "w"); | ||
| 464 | if (sfi == NULL || sfo == NULL) { | ||
| 465 | sprintf(Errmsg, "error in fdopen: %s", get_errmsg()); | ||
| 466 | close(s); | ||
| 467 | return(NOTOK); | ||
| 468 | } | ||
| 469 | |||
| 470 | return(OK); | ||
| 471 | } | ||
| 472 | |||
| 473 | pop_command(fmt, a, b, c, d) | ||
| 474 | char *fmt; | ||
| 475 | { | ||
| 476 | char buf[128]; | ||
| 477 | char errmsg[64]; | ||
| 478 | |||
| 479 | sprintf(buf, fmt, a, b, c, d); | ||
| 480 | |||
| 481 | if (debug) fprintf(stderr, "---> %s\n", buf); | ||
| 482 | if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK); | ||
| 483 | |||
| 484 | if (getline(buf, sizeof buf, sfi) != OK) { | ||
| 485 | strcpy(Errmsg, buf); | ||
| 486 | return(NOTOK); | ||
| 487 | } | ||
| 488 | |||
| 489 | if (debug) fprintf(stderr, "<--- %s\n", buf); | ||
| 490 | if (*buf != '+') { | ||
| 491 | strcpy(Errmsg, buf); | ||
| 492 | return(NOTOK); | ||
| 493 | } else { | ||
| 494 | return(OK); | ||
| 495 | } | ||
| 496 | } | ||
| 497 | |||
| 498 | |||
| 499 | pop_stat(nmsgs, nbytes) | ||
| 500 | int *nmsgs, *nbytes; | ||
| 501 | { | ||
| 502 | char buf[128]; | ||
| 503 | |||
| 504 | if (debug) fprintf(stderr, "---> STAT\n"); | ||
| 505 | if (putline("STAT", Errmsg, sfo) == NOTOK) return(NOTOK); | ||
| 506 | |||
| 507 | if (getline(buf, sizeof buf, sfi) != OK) { | ||
| 508 | strcpy(Errmsg, buf); | ||
| 509 | return(NOTOK); | ||
| 510 | } | ||
| 511 | |||
| 512 | if (debug) fprintf(stderr, "<--- %s\n", buf); | ||
| 513 | if (*buf != '+') { | ||
| 514 | strcpy(Errmsg, buf); | ||
| 515 | return(NOTOK); | ||
| 516 | } else { | ||
| 517 | sscanf(buf, "+OK %d %d", nmsgs, nbytes); | ||
| 518 | return(OK); | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | pop_retr(msgno, action, arg) | ||
| 523 | int (*action)(); | ||
| 524 | { | ||
| 525 | char buf[128]; | ||
| 526 | |||
| 527 | sprintf(buf, "RETR %d", msgno); | ||
| 528 | if (debug) fprintf(stderr, "%s\n", buf); | ||
| 529 | if (putline(buf, Errmsg, sfo) == NOTOK) return(NOTOK); | ||
| 530 | |||
| 531 | if (getline(buf, sizeof buf, sfi) != OK) { | ||
| 532 | strcpy(Errmsg, buf); | ||
| 533 | return(NOTOK); | ||
| 534 | } | ||
| 535 | |||
| 536 | while (1) { | ||
| 537 | switch (multiline(buf, sizeof buf, sfi)) { | ||
| 538 | case OK: | ||
| 539 | (*action)(buf, arg); | ||
| 540 | break; | ||
| 541 | case DONE: | ||
| 542 | return (OK); | ||
| 543 | case NOTOK: | ||
| 544 | strcpy(Errmsg, buf); | ||
| 545 | return (NOTOK); | ||
| 546 | } | ||
| 547 | } | ||
| 548 | } | ||
| 549 | |||
| 550 | getline(buf, n, f) | ||
| 551 | char *buf; | ||
| 552 | register int n; | ||
| 553 | FILE *f; | ||
| 554 | { | ||
| 555 | register char *p; | ||
| 556 | int c; | ||
| 557 | |||
| 558 | p = buf; | ||
| 559 | while (--n > 0 && (c = fgetc(f)) != EOF) | ||
| 560 | if ((*p++ = c) == '\n') break; | ||
| 561 | |||
| 562 | if (ferror(f)) { | ||
| 563 | strcpy(buf, "error on connection"); | ||
| 564 | return (NOTOK); | ||
| 565 | } | ||
| 566 | |||
| 567 | if (c == EOF && p == buf) { | ||
| 568 | strcpy(buf, "connection closed by foreign host"); | ||
| 569 | return (DONE); | ||
| 570 | } | ||
| 571 | |||
| 572 | *p = NULL; | ||
| 573 | if (*--p == '\n') *p = NULL; | ||
| 574 | if (*--p == '\r') *p = NULL; | ||
| 575 | return(OK); | ||
| 576 | } | ||
| 577 | |||
| 578 | multiline(buf, n, f) | ||
| 579 | char *buf; | ||
| 580 | register int n; | ||
| 581 | FILE *f; | ||
| 582 | { | ||
| 583 | if (getline(buf, n, f) != OK) return (NOTOK); | ||
| 584 | if (*buf == '.') { | ||
| 585 | if (*(buf+1) == NULL) { | ||
| 586 | return (DONE); | ||
| 587 | } else { | ||
| 588 | strcpy(buf, buf+1); | ||
| 589 | } | ||
| 590 | } | ||
| 591 | return(OK); | ||
| 592 | } | ||
| 593 | |||
| 594 | char * | ||
| 595 | get_errmsg() | ||
| 596 | { | ||
| 597 | extern int errno, sys_nerr; | ||
| 598 | extern char *sys_errlist[]; | ||
| 599 | char *s; | ||
| 600 | |||
| 601 | if (errno < sys_nerr) | ||
| 602 | s = sys_errlist[errno]; | ||
| 603 | else | ||
| 604 | s = "unknown error"; | ||
| 605 | return(s); | ||
| 606 | } | ||
| 607 | |||
| 608 | putline(buf, err, f) | ||
| 609 | char *buf; | ||
| 610 | char *err; | ||
| 611 | FILE *f; | ||
| 612 | { | ||
| 613 | fprintf(f, "%s\r\n", buf); | ||
| 614 | fflush(f); | ||
| 615 | if (ferror(f)) { | ||
| 616 | strcpy(err, "lost connection"); | ||
| 617 | return(NOTOK); | ||
| 618 | } | ||
| 619 | return(OK); | ||
| 620 | } | ||
| 621 | |||
| 622 | mbx_write(line, mbf) | ||
| 623 | char *line; | ||
| 624 | FILE *mbf; | ||
| 625 | { | ||
| 626 | fputs(line, mbf); | ||
| 627 | fputc(0x0a, mbf); | ||
| 628 | } | ||
| 629 | |||
| 630 | mbx_delimit_begin(mbf) | ||
| 631 | FILE *mbf; | ||
| 632 | { | ||
| 633 | fputs("\f\n0,unseen,,\n", mbf); | ||
| 634 | } | ||
| 635 | |||
| 636 | mbx_delimit_end(mbf) | ||
| 637 | FILE *mbf; | ||
| 638 | { | ||
| 639 | putc('\037', mbf); | ||
| 640 | } | ||
| 641 | |||
| 642 | #endif /* MAIL_USE_POP */ | ||