[12454] | 1 | |
---|
| 2 | /* |
---|
| 3 | * inc.c -- incorporate messages from a maildrop into a folder |
---|
| 4 | * |
---|
[14162] | 5 | * $Id: inc.c,v 1.5 2000-01-07 04:43:58 rbasch Exp $ |
---|
[12454] | 6 | */ |
---|
| 7 | |
---|
| 8 | #ifdef MAILGROUP |
---|
| 9 | /* Revised: Sat Apr 14 17:08:17 PDT 1990 (marvit@hplabs) |
---|
| 10 | * Added hpux hacks to set and reset gid to be "mail" as needed. The reset |
---|
| 11 | * is necessary so inc'ed mail is the group of the inc'er, rather than |
---|
| 12 | * "mail". We setgid to egid only when [un]locking the mail file. This |
---|
| 13 | * is also a major security precaution which will not be explained here. |
---|
| 14 | * |
---|
| 15 | * Fri Feb 7 16:04:57 PST 1992 John Romine <bug-mh@ics.uci.edu> |
---|
| 16 | * NB: I'm not 100% sure that this setgid stuff is secure even now. |
---|
| 17 | */ |
---|
| 18 | #endif |
---|
| 19 | |
---|
| 20 | #include <h/mh.h> |
---|
| 21 | #include <fcntl.h> |
---|
| 22 | |
---|
| 23 | #ifdef POP |
---|
| 24 | # include <h/dropsbr.h> |
---|
| 25 | # include <h/popsbr.h> |
---|
| 26 | #endif |
---|
| 27 | |
---|
| 28 | #ifdef HESIOD |
---|
| 29 | # include <hesiod.h> |
---|
| 30 | #endif |
---|
| 31 | |
---|
| 32 | #include <h/fmt_scan.h> |
---|
| 33 | #include <h/scansbr.h> |
---|
| 34 | #include <h/signals.h> |
---|
| 35 | #include <zotnet/tws/tws.h> |
---|
| 36 | #include <zotnet/mts/mts.h> |
---|
| 37 | #include <errno.h> |
---|
| 38 | #include <signal.h> |
---|
| 39 | |
---|
| 40 | #ifndef POP |
---|
| 41 | # define POPminc(a) (a) |
---|
| 42 | #else |
---|
| 43 | # define POPminc(a) 0 |
---|
| 44 | #endif |
---|
| 45 | |
---|
| 46 | #ifndef RPOP |
---|
| 47 | # define RPOPminc(a) (a) |
---|
| 48 | #else |
---|
| 49 | # define RPOPminc(a) 0 |
---|
| 50 | #endif |
---|
| 51 | |
---|
| 52 | #ifndef APOP |
---|
| 53 | # define APOPminc(a) (a) |
---|
| 54 | #else |
---|
| 55 | # define APOPminc(a) 0 |
---|
| 56 | #endif |
---|
| 57 | |
---|
| 58 | static struct swit switches[] = { |
---|
| 59 | #define AUDSW 0 |
---|
| 60 | { "audit audit-file", 0 }, |
---|
| 61 | #define NAUDSW 1 |
---|
| 62 | { "noaudit", 0 }, |
---|
| 63 | #define CHGSW 2 |
---|
| 64 | { "changecur", 0 }, |
---|
| 65 | #define NCHGSW 3 |
---|
| 66 | { "nochangecur", 0 }, |
---|
| 67 | #define FILESW 4 |
---|
| 68 | { "file name", 0 }, |
---|
| 69 | #define FORMSW 5 |
---|
| 70 | { "form formatfile", 0 }, |
---|
| 71 | #define FMTSW 6 |
---|
| 72 | { "format string", 5 }, |
---|
| 73 | #define HOSTSW 7 |
---|
| 74 | { "host hostname", POPminc (-4) }, |
---|
| 75 | #define USERSW 8 |
---|
| 76 | { "user username", POPminc (-4) }, |
---|
| 77 | #define PACKSW 9 |
---|
| 78 | { "pack file", POPminc (-4) }, |
---|
| 79 | #define NPACKSW 10 |
---|
| 80 | { "nopack", POPminc (-6) }, |
---|
| 81 | #define APOPSW 11 |
---|
| 82 | { "apop", APOPminc (-4) }, |
---|
| 83 | #define NAPOPSW 12 |
---|
| 84 | { "noapop", APOPminc (-6) }, |
---|
| 85 | #define RPOPSW 13 |
---|
| 86 | { "rpop", RPOPminc (-4) }, |
---|
| 87 | #define NRPOPSW 14 |
---|
| 88 | { "norpop", RPOPminc (-6) }, |
---|
| 89 | #define SILSW 15 |
---|
| 90 | { "silent", 0 }, |
---|
| 91 | #define NSILSW 16 |
---|
| 92 | { "nosilent", 0 }, |
---|
| 93 | #define TRNCSW 17 |
---|
| 94 | { "truncate", 0 }, |
---|
| 95 | #define NTRNCSW 18 |
---|
| 96 | { "notruncate", 0 }, |
---|
| 97 | #define WIDTHSW 19 |
---|
| 98 | { "width columns", 0 }, |
---|
| 99 | #define VERSIONSW 20 |
---|
| 100 | { "version", 0 }, |
---|
| 101 | #define HELPSW 21 |
---|
| 102 | { "help", 4 }, |
---|
| 103 | #define SNOOPSW 22 |
---|
| 104 | { "snoop", -5 }, |
---|
| 105 | { NULL, 0 } |
---|
| 106 | }; |
---|
| 107 | |
---|
| 108 | extern int errno; |
---|
| 109 | |
---|
| 110 | /* |
---|
| 111 | * flags for the mail source |
---|
| 112 | */ |
---|
| 113 | #define INC_FILE 0 |
---|
| 114 | #define INC_POP 1 |
---|
| 115 | |
---|
| 116 | static int inc_type; |
---|
| 117 | static int snoop = 0; |
---|
| 118 | |
---|
| 119 | #ifdef POP |
---|
| 120 | extern char response[]; |
---|
| 121 | |
---|
| 122 | static char *packfile = NULL; |
---|
| 123 | static int size; |
---|
| 124 | static long pos; |
---|
| 125 | static long start; |
---|
| 126 | static long stop; |
---|
| 127 | |
---|
| 128 | static int mbx_style = MMDF_FORMAT; |
---|
| 129 | static int pd = NOTOK; |
---|
| 130 | static FILE *pf = NULL; |
---|
| 131 | #endif /* POP */ |
---|
| 132 | |
---|
| 133 | |
---|
| 134 | /* |
---|
| 135 | * For setting and returning to "mail" gid |
---|
| 136 | */ |
---|
| 137 | #ifdef MAILGROUP |
---|
| 138 | static int return_gid; |
---|
| 139 | #endif |
---|
| 140 | |
---|
| 141 | /* |
---|
| 142 | * prototypes |
---|
| 143 | */ |
---|
| 144 | char *map_name(char *); |
---|
| 145 | |
---|
| 146 | #ifdef POP |
---|
| 147 | void done(int); |
---|
| 148 | static int pop_action(char *); |
---|
| 149 | static int pop_pack(char *); |
---|
| 150 | static int map_count(void); |
---|
| 151 | #endif |
---|
| 152 | |
---|
| 153 | |
---|
| 154 | int |
---|
| 155 | main (int argc, char **argv) |
---|
| 156 | { |
---|
| 157 | int chgflag = 1, trnflag = 1; |
---|
| 158 | int noisy = 1, width = 0, locked = 0; |
---|
| 159 | int rpop, i, hghnum, msgnum; |
---|
| 160 | char *cp, *maildir, *folder = NULL; |
---|
| 161 | char *format = NULL, *form = NULL; |
---|
| 162 | char *newmail, *host = NULL, *user = NULL; |
---|
| 163 | char *audfile = NULL, *from = NULL; |
---|
| 164 | char buf[BUFSIZ], **argp, *nfs, **arguments; |
---|
| 165 | struct msgs *mp; |
---|
| 166 | struct stat st, s1; |
---|
| 167 | FILE *in, *aud = NULL; |
---|
| 168 | |
---|
| 169 | #ifdef POP |
---|
| 170 | int nmsgs, nbytes, p = 0; |
---|
| 171 | char *pass = NULL; |
---|
| 172 | #endif |
---|
| 173 | |
---|
| 174 | #ifdef MHE |
---|
| 175 | FILE *mhe = NULL; |
---|
| 176 | #endif |
---|
| 177 | |
---|
| 178 | #ifdef HESIOD |
---|
| 179 | struct hes_postoffice *po; |
---|
| 180 | char *tmphost; |
---|
| 181 | #endif |
---|
| 182 | |
---|
| 183 | #ifdef LOCALE |
---|
| 184 | setlocale(LC_ALL, ""); |
---|
| 185 | #endif |
---|
| 186 | invo_name = r1bindex (argv[0], '/'); |
---|
| 187 | |
---|
| 188 | /* read user profile/context */ |
---|
| 189 | context_read(); |
---|
| 190 | |
---|
| 191 | mts_init (invo_name); |
---|
| 192 | arguments = getarguments (invo_name, argc, argv, 1); |
---|
| 193 | argp = arguments; |
---|
| 194 | |
---|
| 195 | #ifdef POP |
---|
| 196 | # ifdef HESIOD |
---|
| 197 | /* |
---|
| 198 | * Scheme is: |
---|
| 199 | * use MAILHOST environment variable if present, |
---|
| 200 | * else try Hesiod. |
---|
| 201 | * If that fails, use the default (if any) |
---|
| 202 | * provided by mts.conf in mts_init() |
---|
| 203 | */ |
---|
| 204 | if ((tmphost = getenv("MAILHOST")) != NULL) |
---|
| 205 | pophost = tmphost; |
---|
| 206 | else if ((po = hes_getmailhost(getusername())) != NULL && |
---|
| 207 | strcmp(po->po_type, "POP") == 0) |
---|
| 208 | pophost = po->po_host; |
---|
| 209 | # endif /* HESIOD */ |
---|
| 210 | /* |
---|
| 211 | * If there is a valid "pophost" entry in mts.conf, |
---|
| 212 | * then use it as the default host. |
---|
| 213 | */ |
---|
| 214 | if (pophost && *pophost) |
---|
| 215 | host = pophost; |
---|
| 216 | |
---|
| 217 | if ((cp = getenv ("MHPOPDEBUG")) && *cp) |
---|
| 218 | snoop++; |
---|
| 219 | #endif /* POP */ |
---|
| 220 | |
---|
| 221 | #ifdef KPOP |
---|
| 222 | rpop = 1; |
---|
| 223 | #else |
---|
| 224 | rpop = 0; |
---|
| 225 | #endif |
---|
| 226 | |
---|
| 227 | while ((cp = *argp++)) { |
---|
| 228 | if (*cp == '-') { |
---|
| 229 | switch (smatch (++cp, switches)) { |
---|
| 230 | case AMBIGSW: |
---|
| 231 | ambigsw (cp, switches); |
---|
| 232 | done (1); |
---|
| 233 | case UNKWNSW: |
---|
| 234 | adios (NULL, "-%s unknown", cp); |
---|
| 235 | |
---|
| 236 | case HELPSW: |
---|
| 237 | snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name); |
---|
| 238 | print_help (buf, switches, 1); |
---|
| 239 | done (1); |
---|
| 240 | case VERSIONSW: |
---|
| 241 | print_version(invo_name); |
---|
| 242 | done (1); |
---|
| 243 | |
---|
| 244 | case AUDSW: |
---|
| 245 | if (!(cp = *argp++) || *cp == '-') |
---|
| 246 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 247 | audfile = getcpy (m_maildir (cp)); |
---|
| 248 | continue; |
---|
| 249 | case NAUDSW: |
---|
| 250 | audfile = NULL; |
---|
| 251 | continue; |
---|
| 252 | |
---|
| 253 | case CHGSW: |
---|
| 254 | chgflag++; |
---|
| 255 | continue; |
---|
| 256 | case NCHGSW: |
---|
| 257 | chgflag = 0; |
---|
| 258 | continue; |
---|
| 259 | |
---|
| 260 | /* |
---|
| 261 | * The flag `trnflag' has the value: |
---|
| 262 | * |
---|
| 263 | * 2 if -truncate is given |
---|
| 264 | * 1 by default (truncating is default) |
---|
| 265 | * 0 if -notruncate is given |
---|
| 266 | */ |
---|
| 267 | case TRNCSW: |
---|
| 268 | trnflag = 2; |
---|
| 269 | continue; |
---|
| 270 | case NTRNCSW: |
---|
| 271 | trnflag = 0; |
---|
| 272 | continue; |
---|
| 273 | |
---|
| 274 | case FILESW: |
---|
| 275 | if (!(cp = *argp++) || *cp == '-') |
---|
| 276 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 277 | from = path (cp, TFILE); |
---|
| 278 | |
---|
| 279 | /* |
---|
| 280 | * If the truncate file is in default state, |
---|
| 281 | * change to not truncate. |
---|
| 282 | */ |
---|
| 283 | if (trnflag == 1) |
---|
| 284 | trnflag = 0; |
---|
| 285 | continue; |
---|
| 286 | |
---|
| 287 | case SILSW: |
---|
| 288 | noisy = 0; |
---|
| 289 | continue; |
---|
| 290 | case NSILSW: |
---|
| 291 | noisy++; |
---|
| 292 | continue; |
---|
| 293 | |
---|
| 294 | case FORMSW: |
---|
| 295 | if (!(form = *argp++) || *form == '-') |
---|
| 296 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 297 | format = NULL; |
---|
| 298 | continue; |
---|
| 299 | case FMTSW: |
---|
| 300 | if (!(format = *argp++) || *format == '-') |
---|
| 301 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 302 | form = NULL; |
---|
| 303 | continue; |
---|
| 304 | |
---|
| 305 | case WIDTHSW: |
---|
| 306 | if (!(cp = *argp++) || *cp == '-') |
---|
| 307 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 308 | width = atoi (cp); |
---|
| 309 | continue; |
---|
| 310 | |
---|
| 311 | case HOSTSW: |
---|
| 312 | if (!(host = *argp++) || *host == '-') |
---|
| 313 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 314 | continue; |
---|
| 315 | case USERSW: |
---|
| 316 | if (!(user = *argp++) || *user == '-') |
---|
| 317 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 318 | continue; |
---|
| 319 | |
---|
| 320 | case PACKSW: |
---|
| 321 | #ifndef POP |
---|
| 322 | if (!(cp = *argp++) || *cp == '-') |
---|
| 323 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 324 | #else /* POP */ |
---|
| 325 | if (!(packfile = *argp++) || *packfile == '-') |
---|
| 326 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
| 327 | #endif /* POP */ |
---|
| 328 | continue; |
---|
| 329 | case NPACKSW: |
---|
| 330 | #ifdef POP |
---|
| 331 | packfile = NULL; |
---|
| 332 | #endif /* POP */ |
---|
| 333 | continue; |
---|
| 334 | |
---|
| 335 | case APOPSW: |
---|
| 336 | rpop = -1; |
---|
| 337 | continue; |
---|
| 338 | case NAPOPSW: |
---|
| 339 | rpop = 0; |
---|
| 340 | continue; |
---|
| 341 | |
---|
| 342 | case RPOPSW: |
---|
| 343 | rpop = 1; |
---|
| 344 | continue; |
---|
| 345 | case NRPOPSW: |
---|
| 346 | rpop = 0; |
---|
| 347 | continue; |
---|
| 348 | |
---|
| 349 | case SNOOPSW: |
---|
| 350 | snoop++; |
---|
| 351 | continue; |
---|
| 352 | } |
---|
| 353 | } |
---|
| 354 | if (*cp == '+' || *cp == '@') { |
---|
| 355 | if (folder) |
---|
| 356 | adios (NULL, "only one folder at a time!"); |
---|
| 357 | else |
---|
| 358 | folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); |
---|
| 359 | } else { |
---|
| 360 | adios (NULL, "usage: %s [+folder] [switches]", invo_name); |
---|
| 361 | } |
---|
| 362 | } |
---|
| 363 | |
---|
| 364 | #ifdef MAILGROUP |
---|
| 365 | return_gid = getegid(); /* Save effective gid, assuming we'll use it */ |
---|
| 366 | setgid(getgid()); /* Turn off extraordinary privileges */ |
---|
| 367 | #endif /* MAILGROUP */ |
---|
| 368 | |
---|
| 369 | #ifdef POP |
---|
| 370 | if (host && !*host) |
---|
| 371 | host = NULL; |
---|
| 372 | if (from || !host || rpop <= 0) |
---|
| 373 | setuid (getuid ()); |
---|
| 374 | #endif /* POP */ |
---|
| 375 | |
---|
| 376 | /* |
---|
| 377 | * Where are we getting the new mail? |
---|
| 378 | */ |
---|
[12487] | 379 | if (from || getenv("MAILDROP")) |
---|
[12454] | 380 | inc_type = INC_FILE; |
---|
| 381 | #ifdef POP |
---|
| 382 | else if (host) |
---|
| 383 | inc_type = INC_POP; |
---|
| 384 | #endif |
---|
| 385 | else |
---|
| 386 | inc_type = INC_FILE; |
---|
| 387 | |
---|
| 388 | #ifdef POP |
---|
| 389 | /* |
---|
| 390 | * Are we getting the mail from |
---|
| 391 | * a POP server? |
---|
| 392 | */ |
---|
| 393 | if (inc_type == INC_POP) { |
---|
| 394 | if (user == NULL) |
---|
| 395 | user = getusername (); |
---|
| 396 | if (rpop > 0) |
---|
| 397 | pass = getusername (); |
---|
| 398 | else |
---|
| 399 | ruserpass (host, &user, &pass); |
---|
| 400 | |
---|
| 401 | /* |
---|
| 402 | * initialize POP connection |
---|
| 403 | */ |
---|
| 404 | if (pop_init (host, user, pass, snoop, rpop) == NOTOK) |
---|
| 405 | adios (NULL, "%s", response); |
---|
| 406 | |
---|
| 407 | /* Check if there are any messages */ |
---|
| 408 | if (pop_stat (&nmsgs, &nbytes) == NOTOK) |
---|
| 409 | adios (NULL, "%s", response); |
---|
| 410 | |
---|
| 411 | if (rpop > 0) |
---|
| 412 | setuid (getuid ()); |
---|
| 413 | if (nmsgs == 0) { |
---|
| 414 | pop_quit(); |
---|
| 415 | adios (NULL, "no mail to incorporate"); |
---|
| 416 | } |
---|
| 417 | } |
---|
| 418 | #endif /* POP */ |
---|
| 419 | |
---|
| 420 | /* |
---|
| 421 | * We will get the mail from a file |
---|
| 422 | * (typically the standard maildrop) |
---|
| 423 | */ |
---|
| 424 | |
---|
| 425 | if (inc_type == INC_FILE) { |
---|
| 426 | if (from) |
---|
| 427 | newmail = from; |
---|
| 428 | else if ((newmail = getenv ("MAILDROP")) && *newmail) |
---|
| 429 | newmail = m_mailpath (newmail); |
---|
| 430 | else if ((newmail = context_find ("maildrop")) && *newmail) |
---|
| 431 | newmail = m_mailpath (newmail); |
---|
| 432 | else { |
---|
| 433 | newmail = concat (MAILDIR, "/", MAILFIL, NULL); |
---|
| 434 | } |
---|
| 435 | if (stat (newmail, &s1) == NOTOK || s1.st_size == 0) |
---|
| 436 | adios (NULL, "no mail to incorporate"); |
---|
| 437 | } |
---|
| 438 | |
---|
| 439 | #ifdef POP |
---|
| 440 | /* skip the folder setup */ |
---|
| 441 | if ((inc_type == INC_POP) && packfile) |
---|
| 442 | goto go_to_it; |
---|
| 443 | #endif /* POP */ |
---|
| 444 | |
---|
| 445 | if (!context_find ("path")) |
---|
| 446 | free (path ("./", TFOLDER)); |
---|
| 447 | if (!folder) |
---|
| 448 | folder = getfolder (0); |
---|
| 449 | maildir = m_maildir (folder); |
---|
| 450 | |
---|
| 451 | if (stat (maildir, &st) == NOTOK) { |
---|
| 452 | if (errno != ENOENT) |
---|
| 453 | adios (maildir, "error on folder"); |
---|
| 454 | cp = concat ("Create folder \"", maildir, "\"? ", NULL); |
---|
| 455 | if (noisy && !getanswer (cp)) |
---|
| 456 | done (1); |
---|
| 457 | free (cp); |
---|
| 458 | if (!makedir (maildir)) |
---|
| 459 | adios (NULL, "unable to create folder %s", maildir); |
---|
| 460 | } |
---|
| 461 | |
---|
| 462 | if (chdir (maildir) == NOTOK) |
---|
| 463 | adios (maildir, "unable to change directory to"); |
---|
| 464 | |
---|
| 465 | /* read folder and create message structure */ |
---|
| 466 | if (!(mp = folder_read (folder))) |
---|
| 467 | adios (NULL, "unable to read folder %s", folder); |
---|
| 468 | |
---|
| 469 | #ifdef POP |
---|
| 470 | go_to_it: |
---|
| 471 | #endif /* POP */ |
---|
| 472 | |
---|
| 473 | if (inc_type == INC_FILE) { |
---|
| 474 | if (access (newmail, W_OK) != NOTOK) { |
---|
| 475 | locked++; |
---|
| 476 | if (trnflag) { |
---|
| 477 | SIGNAL (SIGHUP, SIG_IGN); |
---|
| 478 | SIGNAL (SIGINT, SIG_IGN); |
---|
| 479 | SIGNAL (SIGQUIT, SIG_IGN); |
---|
| 480 | SIGNAL (SIGTERM, SIG_IGN); |
---|
| 481 | } |
---|
| 482 | |
---|
| 483 | #ifdef MAILGROUP |
---|
| 484 | setgid(return_gid); /* Reset gid to lock mail file */ |
---|
| 485 | #endif /* MAILGROUP */ |
---|
| 486 | |
---|
| 487 | /* lock and fopen the mail spool */ |
---|
| 488 | if ((in = lkfopen (newmail, "r")) == NULL) |
---|
| 489 | adios (NULL, "unable to lock and fopen %s", newmail); |
---|
| 490 | |
---|
| 491 | #ifdef MAILGROUP |
---|
| 492 | setgid(getgid()); /* Return us to normal privileges */ |
---|
| 493 | #endif /* MAILGROUP */ |
---|
| 494 | fstat (fileno(in), &s1); |
---|
| 495 | } else { |
---|
| 496 | trnflag = 0; |
---|
| 497 | if ((in = fopen (newmail, "r")) == NULL) |
---|
| 498 | adios (newmail, "unable to read"); |
---|
| 499 | } |
---|
| 500 | } |
---|
| 501 | |
---|
| 502 | #ifdef MAILGROUP |
---|
| 503 | setgid(getgid()); /* Return us to normal privileges */ |
---|
| 504 | #endif /* MAILGROUP */ |
---|
| 505 | |
---|
| 506 | if (audfile) { |
---|
| 507 | if ((i = stat (audfile, &st)) == NOTOK) |
---|
| 508 | advise (NULL, "Creating Receive-Audit: %s", audfile); |
---|
| 509 | if ((aud = fopen (audfile, "a")) == NULL) |
---|
| 510 | adios (audfile, "unable to append to"); |
---|
| 511 | else if (i == NOTOK) |
---|
| 512 | chmod (audfile, m_gmprot ()); |
---|
| 513 | |
---|
| 514 | #ifdef POP |
---|
| 515 | fprintf (aud, from ? "<<inc>> %s -ms %s\n" |
---|
| 516 | : host ? "<<inc>> %s -host %s -user %s%s\n" |
---|
| 517 | : "<<inc>> %s\n", |
---|
| 518 | dtimenow (0), from ? from : host, user, |
---|
| 519 | rpop < 0 ? " -apop" : rpop > 0 ? " -rpop" : ""); |
---|
| 520 | #else /* POP */ |
---|
| 521 | fprintf (aud, from ? "<<inc>> %s -ms %s\n" : "<<inc>> %s\n", |
---|
| 522 | dtimenow (0), from); |
---|
| 523 | #endif /* POP */ |
---|
| 524 | } |
---|
| 525 | |
---|
| 526 | #ifdef MHE |
---|
| 527 | if (context_find ("mhe")) { |
---|
| 528 | cp = concat (maildir, "/++", NULL); |
---|
| 529 | i = stat (cp, &st); |
---|
| 530 | if ((mhe = fopen (cp, "a")) == NULL) |
---|
| 531 | admonish (cp, "unable to append to"); |
---|
| 532 | else |
---|
| 533 | if (i == NOTOK) |
---|
| 534 | chmod (cp, m_gmprot ()); |
---|
| 535 | free (cp); |
---|
| 536 | } |
---|
| 537 | #endif /* MHE */ |
---|
| 538 | |
---|
| 539 | /* Get new format string */ |
---|
| 540 | nfs = new_fs (form, format, FORMAT); |
---|
| 541 | |
---|
| 542 | if (noisy) { |
---|
| 543 | printf ("Incorporating new mail into %s...\n\n", folder); |
---|
| 544 | fflush (stdout); |
---|
| 545 | } |
---|
| 546 | |
---|
| 547 | #ifdef POP |
---|
| 548 | /* |
---|
| 549 | * Get the mail from a POP server |
---|
| 550 | */ |
---|
| 551 | if (inc_type == INC_POP) { |
---|
| 552 | if (packfile) { |
---|
| 553 | packfile = path (packfile, TFILE); |
---|
| 554 | if (stat (packfile, &st) == NOTOK) { |
---|
| 555 | if (errno != ENOENT) |
---|
| 556 | adios (packfile, "error on file"); |
---|
| 557 | cp = concat ("Create file \"", packfile, "\"? ", NULL); |
---|
| 558 | if (noisy && !getanswer (cp)) |
---|
| 559 | done (1); |
---|
| 560 | free (cp); |
---|
| 561 | } |
---|
| 562 | msgnum = map_count (); |
---|
| 563 | if ((pd = mbx_open (packfile, mbx_style, getuid(), getgid(), m_gmprot())) |
---|
| 564 | == NOTOK) |
---|
| 565 | adios (packfile, "unable to open"); |
---|
| 566 | if ((pf = fdopen (pd, "w+")) == NULL) |
---|
| 567 | adios (NULL, "unable to fdopen %s", packfile); |
---|
| 568 | } else { |
---|
| 569 | hghnum = msgnum = mp->hghmsg; |
---|
| 570 | /* |
---|
| 571 | * Check if we have enough message space for all the new |
---|
| 572 | * messages. If not, then realloc the folder and add enough |
---|
| 573 | * space for all new messages plus 10 additional slots. |
---|
| 574 | */ |
---|
| 575 | if (mp->hghmsg + nmsgs >= mp->hghoff |
---|
| 576 | && !(mp = folder_realloc (mp, mp->lowoff, mp->hghmsg + nmsgs + 10))) |
---|
| 577 | adios (NULL, "unable to allocate folder storage"); |
---|
| 578 | } |
---|
| 579 | |
---|
| 580 | for (i = 1; i <= nmsgs; i++) { |
---|
| 581 | msgnum++; |
---|
| 582 | if (packfile) { |
---|
| 583 | fseek (pf, 0L, SEEK_CUR); |
---|
| 584 | pos = ftell (pf); |
---|
| 585 | size = 0; |
---|
| 586 | fwrite (mmdlm1, 1, strlen (mmdlm1), pf); |
---|
| 587 | start = ftell (pf); |
---|
| 588 | |
---|
| 589 | if (pop_retr (i, pop_pack) == NOTOK) |
---|
| 590 | adios (NULL, "%s", response); |
---|
| 591 | |
---|
| 592 | fseek (pf, 0L, SEEK_CUR); |
---|
| 593 | stop = ftell (pf); |
---|
| 594 | if (fflush (pf)) |
---|
| 595 | adios (packfile, "write error on"); |
---|
| 596 | fseek (pf, start, SEEK_SET); |
---|
| 597 | } else { |
---|
| 598 | cp = getcpy (m_name (msgnum)); |
---|
| 599 | if ((pf = fopen (cp, "w+")) == NULL) |
---|
| 600 | adios (cp, "unable to write"); |
---|
| 601 | chmod (cp, m_gmprot ()); |
---|
| 602 | start = stop = 0L; |
---|
| 603 | |
---|
| 604 | if (pop_retr (i, pop_action) == NOTOK) |
---|
| 605 | adios (NULL, "%s", response); |
---|
| 606 | |
---|
| 607 | if (fflush (pf)) |
---|
| 608 | adios (cp, "write error on"); |
---|
| 609 | fseek (pf, 0L, SEEK_SET); |
---|
| 610 | } |
---|
| 611 | switch (p = scan (pf, msgnum, 0, nfs, width, |
---|
| 612 | packfile ? 0 : msgnum == mp->hghmsg + 1 && chgflag, |
---|
| 613 | 1, NULL, stop - start, noisy)) { |
---|
| 614 | case SCNEOF: |
---|
| 615 | printf ("%*d empty\n", DMAXFOLDER, msgnum); |
---|
| 616 | break; |
---|
| 617 | |
---|
| 618 | case SCNFAT: |
---|
| 619 | trnflag = 0; |
---|
| 620 | noisy++; |
---|
| 621 | /* advise (cp, "unable to read"); already advised */ |
---|
| 622 | /* fall thru */ |
---|
| 623 | |
---|
| 624 | case SCNERR: |
---|
| 625 | case SCNNUM: |
---|
| 626 | break; |
---|
| 627 | |
---|
| 628 | case SCNMSG: |
---|
| 629 | case SCNENC: |
---|
| 630 | default: |
---|
| 631 | if (aud) |
---|
| 632 | fputs (scanl, aud); |
---|
| 633 | # ifdef MHE |
---|
| 634 | if (mhe) |
---|
| 635 | fputs (scanl, mhe); |
---|
| 636 | # endif /* MHE */ |
---|
| 637 | if (noisy) |
---|
| 638 | fflush (stdout); |
---|
| 639 | if (!packfile) { |
---|
| 640 | clear_msg_flags (mp, msgnum); |
---|
| 641 | set_exists (mp, msgnum); |
---|
| 642 | set_unseen (mp, msgnum); |
---|
| 643 | mp->msgflags |= SEQMOD; |
---|
| 644 | } |
---|
| 645 | break; |
---|
| 646 | } |
---|
| 647 | if (packfile) { |
---|
| 648 | fseek (pf, stop, SEEK_SET); |
---|
| 649 | fwrite (mmdlm2, 1, strlen (mmdlm2), pf); |
---|
| 650 | if (fflush (pf) || ferror (pf)) { |
---|
| 651 | int e = errno; |
---|
| 652 | pop_quit (); |
---|
| 653 | errno = e; |
---|
| 654 | adios (packfile, "write error on"); |
---|
| 655 | } |
---|
| 656 | map_write (packfile, pd, 0, 0L, start, stop, pos, size, noisy); |
---|
| 657 | } else { |
---|
| 658 | if (ferror(pf) || fclose (pf)) { |
---|
| 659 | int e = errno; |
---|
| 660 | unlink (cp); |
---|
| 661 | pop_quit (); |
---|
| 662 | errno = e; |
---|
| 663 | adios (cp, "write error on"); |
---|
| 664 | } |
---|
| 665 | free (cp); |
---|
| 666 | } |
---|
| 667 | |
---|
| 668 | if (trnflag && pop_dele (i) == NOTOK) |
---|
| 669 | adios (NULL, "%s", response); |
---|
| 670 | } |
---|
| 671 | |
---|
| 672 | if (pop_quit () == NOTOK) |
---|
| 673 | adios (NULL, "%s", response); |
---|
| 674 | if (packfile) { |
---|
[14162] | 675 | if (mbx_close (packfile, pd) == NOTOK) |
---|
| 676 | adios (packfile, "error writing to file"); |
---|
[12454] | 677 | pd = NOTOK; |
---|
| 678 | } |
---|
[13963] | 679 | |
---|
| 680 | if (p < 0) |
---|
| 681 | adios (NULL, "failed"); |
---|
[12454] | 682 | } |
---|
| 683 | #endif /* POP */ |
---|
| 684 | |
---|
| 685 | /* |
---|
| 686 | * Get the mail from file (usually mail spool) |
---|
| 687 | */ |
---|
| 688 | if (inc_type == INC_FILE) { |
---|
| 689 | m_unknown (in); /* the MAGIC invocation... */ |
---|
| 690 | hghnum = msgnum = mp->hghmsg; |
---|
| 691 | for (i = 0;;) { |
---|
| 692 | /* |
---|
| 693 | * Check if we need to allocate more space for message status. |
---|
| 694 | * If so, then add space for an additional 100 messages. |
---|
| 695 | */ |
---|
| 696 | if (msgnum >= mp->hghoff |
---|
| 697 | && !(mp = folder_realloc (mp, mp->lowoff, mp->hghoff + 100))) { |
---|
| 698 | advise (NULL, "unable to allocate folder storage"); |
---|
| 699 | i = NOTOK; |
---|
| 700 | break; |
---|
| 701 | } |
---|
| 702 | |
---|
| 703 | #if 0 |
---|
| 704 | /* copy file from spool to tmp file */ |
---|
| 705 | tmpfilenam = m_scratch ("", invo_name); |
---|
| 706 | if ((fd = creat (tmpfilenam, m_gmprot ())) == NOTOK) |
---|
| 707 | adios (tmpfilenam, "unable to create"); |
---|
| 708 | chmod (tmpfilenam, m_gmprot ()); |
---|
| 709 | if (!(in2 = fdopen (fd, "r+"))) |
---|
| 710 | adios (tmpfilenam, "unable to access"); |
---|
| 711 | cpymsg (in, in2); |
---|
| 712 | |
---|
| 713 | /* link message into folder */ |
---|
| 714 | newmsg = folder_addmsg(mp, tmpfilenam); |
---|
| 715 | #endif |
---|
| 716 | |
---|
| 717 | /* create scanline for new message */ |
---|
| 718 | switch (i = scan (in, msgnum + 1, msgnum + 1, nfs, width, |
---|
| 719 | msgnum == hghnum && chgflag, 1, NULL, 0L, noisy)) { |
---|
| 720 | case SCNFAT: |
---|
| 721 | case SCNEOF: |
---|
| 722 | break; |
---|
| 723 | |
---|
| 724 | case SCNERR: |
---|
| 725 | if (aud) |
---|
| 726 | fputs ("inc aborted!\n", aud); |
---|
| 727 | advise (NULL, "aborted!"); /* doesn't clean up locks! */ |
---|
| 728 | break; |
---|
| 729 | |
---|
| 730 | case SCNNUM: |
---|
| 731 | advise (NULL, "BUG in %s, number out of range", invo_name); |
---|
| 732 | break; |
---|
| 733 | |
---|
| 734 | default: |
---|
| 735 | advise (NULL, "BUG in %s, scan() botch (%d)", invo_name, i); |
---|
| 736 | break; |
---|
| 737 | |
---|
| 738 | case SCNMSG: |
---|
| 739 | case SCNENC: |
---|
| 740 | if (aud) |
---|
| 741 | fputs (scanl, aud); |
---|
| 742 | #ifdef MHE |
---|
| 743 | if (mhe) |
---|
| 744 | fputs (scanl, mhe); |
---|
| 745 | #endif /* MHE */ |
---|
| 746 | if (noisy) |
---|
| 747 | fflush (stdout); |
---|
| 748 | |
---|
| 749 | msgnum++; |
---|
| 750 | mp->hghmsg++; |
---|
| 751 | clear_msg_flags (mp, msgnum); |
---|
| 752 | set_exists (mp, msgnum); |
---|
| 753 | set_unseen (mp, msgnum); |
---|
| 754 | mp->msgflags |= SEQMOD; |
---|
| 755 | continue; |
---|
| 756 | } |
---|
| 757 | break; |
---|
| 758 | } |
---|
| 759 | |
---|
[13963] | 760 | if (i < 0) { /* error */ |
---|
| 761 | if (locked) { |
---|
[12454] | 762 | #ifdef MAILGROUP |
---|
[13963] | 763 | /* Be sure we can unlock mail file */ |
---|
| 764 | setgid(return_gid); |
---|
[12454] | 765 | #endif /* MAILGROUP */ |
---|
| 766 | |
---|
[13963] | 767 | lkfclose (in, newmail); |
---|
[12454] | 768 | |
---|
| 769 | #ifdef MAILGROUP |
---|
[13963] | 770 | /* And then return us to normal privileges */ |
---|
| 771 | setgid(getgid()); |
---|
[12454] | 772 | #endif /* MAILGROUP */ |
---|
[13963] | 773 | } else { |
---|
| 774 | fclose (in); |
---|
| 775 | } |
---|
| 776 | adios (NULL, "failed"); |
---|
[12454] | 777 | } |
---|
| 778 | } |
---|
| 779 | |
---|
| 780 | if (aud) |
---|
| 781 | fclose (aud); |
---|
| 782 | |
---|
| 783 | #ifdef MHE |
---|
| 784 | if (mhe) |
---|
| 785 | fclose (mhe); |
---|
| 786 | #endif /* MHE */ |
---|
| 787 | |
---|
| 788 | if (noisy) |
---|
| 789 | fflush (stdout); |
---|
| 790 | |
---|
| 791 | #ifdef POP |
---|
| 792 | if ((inc_type == INC_POP) && packfile) |
---|
| 793 | done (0); |
---|
| 794 | #endif /* POP */ |
---|
| 795 | |
---|
| 796 | /* |
---|
| 797 | * truncate file we are incorporating from |
---|
| 798 | */ |
---|
| 799 | if (inc_type == INC_FILE) { |
---|
| 800 | if (trnflag) { |
---|
| 801 | if (stat (newmail, &st) != NOTOK && s1.st_mtime != st.st_mtime) |
---|
| 802 | advise (NULL, "new messages have arrived!\007"); |
---|
| 803 | else { |
---|
| 804 | if ((i = creat (newmail, 0600)) != NOTOK) |
---|
| 805 | close (i); |
---|
| 806 | else |
---|
| 807 | admonish (newmail, "error zero'ing"); |
---|
| 808 | unlink(map_name(newmail)); |
---|
| 809 | } |
---|
| 810 | } else { |
---|
| 811 | if (noisy) |
---|
| 812 | printf ("%s not zero'd\n", newmail); |
---|
| 813 | } |
---|
| 814 | } |
---|
| 815 | |
---|
| 816 | if (msgnum == hghnum) { |
---|
| 817 | admonish (NULL, "no messages incorporated"); |
---|
| 818 | } else { |
---|
| 819 | context_replace (pfolder, folder); /* update current folder */ |
---|
| 820 | if (chgflag) |
---|
| 821 | mp->curmsg = hghnum + 1; |
---|
| 822 | mp->hghmsg = msgnum; |
---|
| 823 | if (mp->lowmsg == 0) |
---|
| 824 | mp->lowmsg = 1; |
---|
| 825 | if (chgflag) /* sigh... */ |
---|
| 826 | seq_setcur (mp, mp->curmsg); |
---|
| 827 | } |
---|
| 828 | |
---|
| 829 | /* |
---|
| 830 | * unlock the mail spool |
---|
| 831 | */ |
---|
| 832 | if (inc_type == INC_FILE) { |
---|
| 833 | if (locked) { |
---|
| 834 | #ifdef MAILGROUP |
---|
| 835 | setgid(return_gid); /* Be sure we can unlock mail file */ |
---|
| 836 | #endif /* MAILGROUP */ |
---|
| 837 | |
---|
| 838 | lkfclose (in, newmail); |
---|
| 839 | |
---|
| 840 | #ifdef MAILGROUP |
---|
| 841 | setgid(getgid()); /* And then return us to normal privileges */ |
---|
| 842 | #endif /* MAILGROUP */ |
---|
| 843 | } else { |
---|
| 844 | fclose (in); |
---|
| 845 | } |
---|
| 846 | } |
---|
| 847 | |
---|
| 848 | seq_setunseen (mp, 0); /* set the Unseen-Sequence */ |
---|
| 849 | seq_save (mp); /* synchronize sequences */ |
---|
| 850 | context_save (); /* save the context file */ |
---|
| 851 | done (0); |
---|
| 852 | } |
---|
| 853 | |
---|
| 854 | |
---|
| 855 | #if 0 |
---|
| 856 | |
---|
| 857 | /* |
---|
| 858 | * Copy message message from spool into |
---|
| 859 | * temporary file. Massage the "From " line |
---|
| 860 | * while copying. |
---|
| 861 | */ |
---|
| 862 | |
---|
| 863 | cpymsg (FILE *in, FILE *out) |
---|
| 864 | { |
---|
| 865 | int state; |
---|
| 866 | char *tmpbuf, name[NAMESZ]; |
---|
| 867 | |
---|
| 868 | for (;;) { |
---|
| 869 | state = m_getfld (state, name, tmpbuf, rlwidth, in); |
---|
| 870 | switch (state) { |
---|
| 871 | case FLD: |
---|
| 872 | case FLDPLUS: |
---|
| 873 | break; |
---|
| 874 | case BODY: |
---|
| 875 | break; |
---|
| 876 | case LENERR: |
---|
| 877 | case FMTERR: |
---|
| 878 | break; |
---|
| 879 | case FILEEOF: |
---|
| 880 | break; |
---|
| 881 | default: |
---|
| 882 | } |
---|
| 883 | } |
---|
| 884 | } |
---|
| 885 | #endif /* if 0 */ |
---|
| 886 | |
---|
| 887 | |
---|
| 888 | #ifdef POP |
---|
| 889 | void |
---|
| 890 | done (int status) |
---|
| 891 | { |
---|
| 892 | if (packfile && pd != NOTOK) |
---|
| 893 | mbx_close (packfile, pd); |
---|
| 894 | |
---|
| 895 | exit (status); |
---|
| 896 | } |
---|
| 897 | |
---|
| 898 | static int |
---|
| 899 | pop_action (char *s) |
---|
| 900 | { |
---|
| 901 | fprintf (pf, "%s\n", s); |
---|
| 902 | stop += strlen (s) + 1; |
---|
| 903 | } |
---|
| 904 | |
---|
| 905 | static int |
---|
| 906 | pop_pack (char *s) |
---|
| 907 | { |
---|
| 908 | int j; |
---|
| 909 | char buffer[BUFSIZ]; |
---|
| 910 | |
---|
| 911 | snprintf (buffer, sizeof(buffer), "%s\n", s); |
---|
| 912 | for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++) |
---|
| 913 | continue; |
---|
| 914 | for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++) |
---|
| 915 | continue; |
---|
| 916 | fputs (buffer, pf); |
---|
| 917 | size += strlen (buffer) + 1; |
---|
| 918 | } |
---|
| 919 | |
---|
| 920 | static int |
---|
| 921 | map_count (void) |
---|
| 922 | { |
---|
| 923 | int md; |
---|
| 924 | char *cp; |
---|
| 925 | struct drop d; |
---|
| 926 | struct stat st; |
---|
| 927 | |
---|
| 928 | if (stat (packfile, &st) == NOTOK) |
---|
| 929 | return 0; |
---|
| 930 | if ((md = open (cp = map_name (packfile), O_RDONLY)) == NOTOK |
---|
| 931 | || map_chk (cp, md, &d, (long) st.st_size, 1)) { |
---|
| 932 | if (md != NOTOK) |
---|
| 933 | close (md); |
---|
| 934 | return 0; |
---|
| 935 | } |
---|
| 936 | close (md); |
---|
| 937 | return (d.d_id); |
---|
| 938 | } |
---|
| 939 | #endif /* POP */ |
---|