home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i076: ELM mail syste, release 2.3, Part17/26
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: be6ab14a 542cdba5 7368fbd2 f3129d3b
-
- Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
- Posting-number: Volume 22, Issue 76
- Archive-name: elm2.3/part17
-
- ---- Cut Here and unpack ----
- #!/bin/sh
- # this is part 17 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file src/leavembox.c continued
- #
- CurArch=17
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file src/leavembox.c"
- sed 's/^X//' << 'SHAR_EOF' >> src/leavembox.c
- X */
- X
- X for (num_chgd_status = 0, i = 0; i < message_count; i++)
- X if(headers[i]->status_chgd == TRUE)
- X num_chgd_status++;
- X
- X if(!to_delete && !to_store && !num_chgd_status && !resyncing) {
- X dprint(3, (debugfile, "Folder keep as is!\n"));
- X error("Folder unchanged.");
- X return(0);
- X }
- X
- X /** we have to check to see what the sorting order was...so that
- X the order in which we write messages is the same as the order
- X of the messages originally.
- X We only need to do this if there are any messages to be
- X written out (either to keep or to store). **/
- X
- X if ((to_keep || to_store ) && sortby != MAILBOX_ORDER) {
- X last_sortby = sortby;
- X sortby = MAILBOX_ORDER;
- X sort_mailbox(message_count, FALSE);
- X sortby = last_sortby;
- X }
- X
- X /* Formulate message as to number of keeps, stores, and deletes.
- X * This is only complex so that the message is good English.
- X */
- X if (to_keep > 0) {
- X if (to_store > 0) {
- X if (to_delete > 0)
- X sprintf(buffer,
- X "[Keeping %d message%s, storing %d, and deleting %d.]",
- X to_keep, plural(to_keep), to_store, to_delete);
- X else
- X sprintf(buffer, "[Keeping %d message%s and storing %d.]",
- X to_keep, plural(to_keep), to_store);
- X } else {
- X if (to_delete > 0)
- X sprintf(buffer, "[Keeping %d message%s and deleting %d.]",
- X to_keep, plural(to_keep), to_delete);
- X else
- X sprintf(buffer, "[Keeping %s.]",
- X to_keep > 1 ? "all messages" : "message");
- X }
- X } else if (to_store > 0) {
- X if (to_delete > 0)
- X sprintf(buffer, "[Storing %d message%s and deleting %d.]",
- X to_store, plural(to_store), to_delete);
- X else
- X sprintf(buffer, "[Storing %s.]",
- X to_store > 1? "all messages" : "message");
- X
- X } else {
- X if (to_delete > 0)
- X sprintf(buffer, "[Deleting all messages.]");
- X else
- X buffer[0] = '\0';
- X }
- X /* NOTE: don't use variable "buffer" till message is output later */
- X
- X /** next, let's lock the file up and make one last size check **/
- X
- X if (folder_type == SPOOL)
- X lock(OUTGOING);
- X
- X if (mailfile_size != bytes(cur_folder)) {
- X unlock();
- X error("New mail has just arrived. Resynchronizing...");
- X return(-1);
- X }
- X
- X /* Everything's GO - so ouput that user message and go to it. */
- X
- X dprint(2, (debugfile, "Action: %s\n", buffer));
- X error(buffer);
- X
- X /* Store messages slated for storage in received mail folder */
- X if (to_store > 0) {
- X if ((errno = can_open(recvd_mail, "a"))) {
- X error1(
- X "Permission to append to %s denied! Leaving folder intact.\n",
- X recvd_mail);
- X dprint(1, (debugfile,
- X "Error: Permission to append to folder %s denied!! (%s)\n",
- X recvd_mail, "leavembox"));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X unlock();
- X return(0);
- X }
- X if ((temp = fopen(recvd_mail,"a")) == NULL) {
- X unlock();
- X dprint(1, (debugfile, "Error: could not append to file %s\n",
- X recvd_mail));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X sprintf(buffer, "Could not append to folder %s!", recvd_mail);
- X Centerline(LINES-1, buffer);
- X emergency_exit();
- X }
- X dprint(2, (debugfile, "Storing message%s ", plural(to_store)));
- X for (i = 0; i < message_count; i++) {
- X if(headers[i]->exit_disposition == STORE) {
- X current = i+1;
- X dprint(2, (debugfile, "#%d, ", current));
- X copy_message("", temp, FALSE, FALSE, TRUE, FALSE);
- X }
- X }
- X fclose(temp);
- X dprint(2, (debugfile, "\n\n"));
- X chown(recvd_mail, userid, groupid);
- X }
- X
- X /* If there are any messages to keep, first copy them to a
- X * temp file, then remove original and copy whole temp file over.
- X */
- X if (to_keep > 0) {
- X sprintf(temp_keep_file, "%s%s%d", temp_dir, temp_file, getpid());
- X if ((errno = can_open(temp_keep_file, "w"))) {
- X error1(
- X"Permission to create temp file %s for writing denied! Leaving folder intact.",
- X temp_keep_file);
- X dprint(1, (debugfile,
- X "Error: Permission to create temp file %s denied!! (%s)\n",
- X temp_keep_file, "leavembox"));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X unlock();
- X return(0);
- X }
- X if ((temp = fopen(temp_keep_file,"w")) == NULL) {
- X unlock();
- X dprint(1, (debugfile, "Error: could not create file %s\n",
- X temp_keep_file));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X sprintf(buffer, "Could not create temp file %s!", temp_keep_file);
- X Centerline(LINES-1, buffer);
- X emergency_exit();
- X }
- X dprint(2, (debugfile, "Copying to temp file message%s to be kept ",
- X plural(to_keep)));
- X for (i = 0; i < message_count; i++) {
- X if(headers[i]->exit_disposition == KEEP) {
- X current = i+1;
- X dprint(2, (debugfile, "#%d, ", current));
- X copy_message("", temp, FALSE, FALSE, TRUE, FALSE);
- X }
- X }
- X if ( fclose(temp) == EOF ) {
- X Write_to_screen("\n\rClose failed on temp keep file in leavembox\n\r", 0);
- X perror(temp_keep_file);
- X dprint(2, (debugfile, "\n\rfclose err on temp_keep_file - leavembox\n\r"));
- X rm_temps_exit();
- X }
- X dprint(2, (debugfile, "\n\n"));
- X
- X } else if (folder_type == NON_SPOOL && !keep_empty_files) {
- X
- X /* i.e. if no messages were to be kept and this is not a spool
- X * folder and we aren't keeping empty non-spool folders,
- X * simply remove the old original folder and that's it!
- X */
- X (void)unlink(cur_folder);
- X return(1);
- X }
- X
- X /* Otherwise we have some work left to do! */
- X
- X /* Get original permissions and access time of the original
- X * mail folder before we remove it.
- X */
- X if(save_file_stats(cur_folder) != 0) {
- X error1("Problems saving permissions of folder %s!", cur_folder);
- X sleep(2);
- X }
- X
- X if (stat(cur_folder, &buf) != 0) {
- X dprint(1, (debugfile, "Error: errno %s attempting to stat file %s\n",
- X error_name(errno), cur_folder));
- X error3("Error %s (%s) on stat(%s).", error_name(errno),
- X error_description(errno), cur_folder);
- X }
- X
- X /* Close and remove the original folder.
- X * However, if we are going to copy a temp file of kept messages
- X * to it, and this is a locked (spool) mailbox, we need to keep
- X * it locked during this process. Unfortunately,
- X * if we did our LOCK_BY_FLOCK, unlinking the original will kill the
- X * lock, so we have to resort to copying the temp file to the original
- X * file while keeping the original open.
- X * Also, if the file has a link count > 1, then it has links, so to
- X * prevent destroying the links, we do a copy back, even though its
- X * slower.
- X */
- X
- X fclose(mailfile);
- X
- X if(to_keep) {
- X#ifdef LOCK_BY_FLOCK
- X need_to_copy = (folder_type == SPOOL ? TRUE : FALSE);
- X#else
- X need_to_copy = FALSE;
- X#endif
- X if (buf.st_nlink > 1)
- X need_to_copy = TRUE;
- X
- X if(!need_to_copy) {
- X unlink(cur_folder);
- X if (link(temp_keep_file, cur_folder) != 0) {
- X if(errno == EXDEV || errno == EEXIST) {
- X /* oops - can't link across file systems - use copy instead */
- X need_to_copy = TRUE;
- X } else {
- X dprint(1, (debugfile, "link(%s, %s) failed (leavembox)\n",
- X temp_keep_file, cur_folder));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X error2("Link failed! %s - %s.", error_name(errno),
- X error_description(errno));
- X unlock();
- X emergency_exit();
- X }
- X }
- X }
- X
- X if(need_to_copy) {
- X
- X if (copy(temp_keep_file, cur_folder) != 0) {
- X
- X /* copy to cur_folder failed - try to copy to special file */
- X dprint(1, (debugfile, "leavembox: copy(%s, %s) failed;",
- X temp_keep_file, cur_folder));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X error("Couldn't modify folder!");
- X sleep(1);
- X sprintf(cur_folder,"%s/%s", home, unedited_mail);
- X if (copy(temp_keep_file, cur_folder) != 0) {
- X
- X /* couldn't copy to special file either */
- X dprint(1, (debugfile,
- X "leavembox: couldn't copy to %s either!! Help;",
- X cur_folder));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X error("Can't copy mailbox, system trouble!!!");
- X unlock();
- X emergency_exit();
- X } else {
- X dprint(1, (debugfile,
- X "\nWoah! Confused - Saved mail in %s (leavembox)\n",
- X cur_folder));
- X error1("Saved mail in %s.", cur_folder);
- X sleep(1);
- X }
- X }
- X }
- X
- X /* link or copy complete - remove temp keep file */
- X unlink(temp_keep_file);
- X
- X } else if(folder_type == SPOOL || keep_empty_files) {
- X
- X /* if this is an empty spool file, or if this is an empty non spool
- X * file and we keep empty non spool files (we always keep empty
- X * spool files), create an empty file */
- X
- X if(folder_type == NON_SPOOL)
- X error1("Keeping empty folder '%s'.", cur_folder);
- X temp = fopen(cur_folder, "w");
- X fclose(temp);
- X }
- X
- X /* restore permissions and access times of folder */
- X
- X if(restore_file_stats(cur_folder) != 1) {
- X error1("Problems restoring permissions of folder %s!", cur_folder);
- X sleep(2);
- X }
- X
- X#ifdef BSD
- X utime_buffer[0] = buf.st_atime;
- X utime_buffer[1] = buf.st_mtime;
- X#else
- X utime_buffer.actime = buf.st_atime;
- X utime_buffer.modtime= buf.st_mtime;
- X#endif
- X
- X#ifdef BSD
- X if (utime(cur_folder, utime_buffer) != 0) {
- X#else
- X if (utime(cur_folder, &utime_buffer) != 0) {
- X#endif
- X dprint(1, (debugfile,
- X "Error: encountered error doing utime (leavmbox)\n"));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X error2("Error %s trying to change file %s access time.",
- X error_name(errno), cur_folder);
- X }
- X
- X
- X mailfile_size = bytes(cur_folder);
- X unlock(); /* remove the lock on the file ASAP! */
- X
- X return(1);
- X}
- X
- Xstatic int lock_state = OFF;
- X
- Xstatic char lock_name[SLEN];
- X
- Xchar *
- Xmk_lockname(file_to_lock)
- Xchar *file_to_lock;
- X{
- X /** Create the proper name of the lock file for file_to_lock,
- X which is presumed to be a spool file full path (see
- X get_folder_type()), and put it in the static area lock_name.
- X Return lock_name for informational purposes.
- X **/
- X
- X#ifdef XENIX
- X /* lock is /tmp/[basename of file_to_lock].mlk */
- X sprintf(lock_name, "/tmp/%.10s.mlk", rindex(file_to_lock, '/')+1);
- X#else
- X /* lock is [file_to_lock].lock */
- X sprintf(lock_name, "%s.lock", file_to_lock);
- X#endif
- X return(lock_name);
- X}
- X
- X
- Xstatic int flock_fd, /* file descriptor for flocking mailbox itself */
- X create_fd; /* file descriptor for creating lock file */
- X
- Xlock(direction)
- Xint direction;
- X{
- X /** Create lock file to ensure that we don't get any mail
- X while altering the folder contents!
- X If it already exists sit and spin until
- X either the lock file is removed...indicating new mail
- X or
- X we have iterated MAX_ATTEMPTS times, in which case we
- X either fail or remove it and make our own (determined
- X by if REMOVE_AT_LAST is defined in header file
- X
- X If direction == INCOMING then DON'T remove the lock file
- X on the way out! (It'd mess up whatever created it!).
- X
- X But if that succeeds and if we are also locking by flock(),
- X follow a similar algorithm. Now if we can't lock by flock(),
- X we DO need to remove the lock file, since if we got this far,
- X we DID create it, not another process.
- X **/
- X
- X register int create_iteration = 0,
- X flock_iteration = 0;
- X char pid_buffer[SHORT];
- X
- X#ifndef LOCK_FLOCK_ONLY /* { LOCK_FLOCK_ONLY */
- X /* formulate lock file name */
- X mk_lockname(cur_folder);
- X
- X#ifdef PIDCHECK
- X /** first, try to read the lock file, and if possible, check the pid.
- X If we can validate that the pid is no longer active, then remove
- X the lock file.
- X **/
- X if((create_fd=open(lock_name,O_RDONLY)) != -1) {
- X if (read(create_fd, pid_buffer, SHORT) > 0) {
- X create_iteration = atoi(pid_buffer);
- X if (create_iteration) {
- X if (kill(create_iteration, 0)) {
- X close(create_fd);
- X if (unlink(lock_name) != 0) {
- X dprint(1, (debugfile,
- X "Error %s (%s)\n\ttrying to unlink file %s (%s)\n",
- X error_name(errno), error_description(errno), lock_name, "lock"));
- X PutLine1(LINES, 0,
- X "\n\rCouldn't remove the current lock file %s\n\r", lock_name);
- X PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
- X error_description(errno));
- X if (direction == INCOMING)
- X leave();
- X else
- X emergency_exit();
- X }
- X }
- X }
- X }
- X create_iteration = 0;
- X }
- X#endif
- X
- X /* try to assert create lock file MAX_ATTEMPTS times */
- X do {
- X
- X errno = 0;
- X if((create_fd=open(lock_name,O_WRONLY | O_CREAT | O_EXCL,0444)) != -1)
- X break;
- X else {
- X if(errno != EEXIST) {
- X /* Creation of lock failed NOT because it already exists!!! */
- X
- X if (direction == OUTGOING) {
- X dprint(1, (debugfile,
- X "Error encountered attempting to create lock %s\n", lock_name));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X MoveCursor(LINES, 0);
- X printf(
- X "\n\rError encountered while attempting to create lock file %s;\n\r",
- X lock_name);
- X printf("** %s - %s.**\n\r\n\r",
- X error_name(errno), error_description(errno));
- X } else { /* incoming - permission denied in the middle? Odd. */
- X dprint(1, (debugfile,
- X "Can't create lock file: creat(%s) raises error %s (lock)\n",
- X lock_name, error_name(errno)));
- X error1(
- X "Can't create lock file! Need write permission in \"%s\".\n\r",
- X mailhome);
- X }
- X leave();
- X }
- X }
- X dprint(2, (debugfile,"File '%s' already exists! Waiting...(lock)\n",
- X lock_name));
- X error1(
- X "Waiting to read mailbox while mail is being received: attempt #%d",
- X create_iteration);
- X sleep(5);
- X } while (create_iteration++ < MAX_ATTEMPTS);
- X clear_error();
- X
- X if(errno != 0) {
- X
- X /* we weren't able to create the lock file */
- X
- X#ifdef REMOVE_AT_LAST
- X
- X /** time to waste the lock file! Must be there in error! **/
- X dprint(2, (debugfile,
- X "Warning: I'm giving up waiting - removing lock file(lock)\n"));
- X if (direction == INCOMING)
- X PutLine0(LINES, 0,"\nTimed out - removing current lock file...");
- X else
- X error("Throwing away the current lock file!");
- X
- X if (unlink(lock_name) != 0) {
- X dprint(1, (debugfile,
- X "Error %s (%s)\n\ttrying to unlink file %s (%s)\n",
- X error_name(errno), error_description(errno), lock_name, "lock"));
- X PutLine1(LINES, 0,
- X "\n\rCouldn't remove the current lock file %s\n\r", lock_name);
- X PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
- X error_description(errno));
- X if (direction == INCOMING)
- X leave();
- X else
- X emergency_exit();
- X }
- X
- X /* we've removed the bad lock, let's try to assert lock once more */
- X if((create_fd=open(lock_name,O_WRONLY | O_CREAT | O_EXCL,0444)) == -1){
- X
- X /* still can't lock it - just give up */
- X dprint(1, (debugfile,
- X "Error encountered attempting to create lock %s\n", lock_name));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X MoveCursor(LINES, 0);
- X printf(
- X "\n\rError encountered while attempting to create lock file %s;\n\r",
- X lock_name);
- X printf("** %s - %s.**\n\r\n\r", error_name(errno),
- X error_description(errno));
- X leave();
- X }
- X#else
- X /* Okay...we die and leave, not updating the mailfile mbox or
- X any of those! */
- X
- X if (direction == INCOMING) {
- X PutLine1(LINES, 0, "\n\r\n\rGiving up after %d iterations.\n\r",
- X create_iteration);
- X PutLine0(LINES, 0,
- X "\n\rPlease try to read your mail again in a few minutes.\n\r\n\r");
- X dprint(1, (debugfile,
- X "Warning: bailing out after %d iterations...(lock)\n",
- X create_iteration));
- X leave_locked(0);
- X } else {
- X dprint(1, (debugfile,
- X "Warning: after %d iterations, timed out! (lock)\n",
- X create_iteration));
- X leave(error("Timed out on locking mailbox. Leaving program."));
- X }
- X#endif
- X }
- X
- X /* If we're here we successfully created the lock file */
- X dprint(5,
- X (debugfile, "Lock %s %s for file %s on.\n", lock_name,
- X (direction == INCOMING ? "incoming" : "outgoing"), cur_folder));
- X
- X /* Place the pid of Elm into the lock file for SVR3.2 and its ilk */
- X sprintf(pid_buffer, "%d", getpid());
- X write(create_fd, pid_buffer, strlen(pid_buffer));
- X
- X (void)close(create_fd);
- X#endif /* } LOCK_FLOCK_ONLY */
- X
- X#ifdef LOCK_BY_FLOCK
- X /* Now we also need to lock the file with flock(2) */
- X
- X /* Open mail file separately for locking */
- X if((flock_fd = open(cur_folder, O_RDONLY)) < 0) {
- X dprint(1, (debugfile,
- X "Error encountered attempting to reopen %s for lock\n", cur_folder));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X MoveCursor(LINES, 0);
- X printf(
- X "\n\rError encountered while attempting to reopen mailbox %s for lock;\n\r",
- X cur_folder);
- X printf("** %s - %s.**\n\r\n\r", error_name(errno),
- X error_description(errno));
- X (void)unlink(lock_name);
- X leave();
- X }
- X
- X /* try to assert lock MAX_ATTEMPTS times */
- X do {
- X
- X errno = 0;
- X if(flock(flock_fd, LOCK_NB | LOCK_EX) != -1)
- X break;
- X else {
- X if(errno != EWOULDBLOCK && errno != EAGAIN) {
- X
- X /* Creation of lock failed NOT because it already exists!!! */
- X
- X dprint(1, (debugfile,
- X "Error encountered attempting to flock %s\n", cur_folder));
- X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
- X error_description(errno)));
- X MoveCursor(LINES, 0);
- X printf(
- X "\n\rError encountered while attempting to flock mailbox %s;\n\r",
- X cur_folder);
- X printf("** %s - %s.**\n\r\n\r", error_name(errno),
- X error_description(errno));
- X (void)unlink(lock_name);
- X leave();
- X }
- X }
- X dprint(2, (debugfile,
- X "Mailbox '%s' already locked! Waiting...(lock)\n", cur_folder));
- X error1(
- X "Waiting to read mailbox while mail is being received: attempt #%d",
- X flock_iteration);
- X sleep(5);
- X } while (flock_iteration++ < MAX_ATTEMPTS);
- X clear_error();
- X
- X if(errno != 0) {
- X
- X /* We couldn't lock the file. We die and leave not updating
- X * the mailfile mbox or any of those! */
- X
- X if (direction == INCOMING) {
- X PutLine1(LINES, 0, "\n\r\n\rGiving up after %d iterations.\n\r",
- X flock_iteration);
- X PutLine0(LINES, 0,
- X "\n\rPlease try to read your mail again in a few minutes.\n\r\n\r");
- X dprint(1, (debugfile,
- X "Warning: bailing out after %d iterations...(lock)\n",
- X flock_iteration));
- X } else {
- X dprint(1, (debugfile,
- X "Warning: after %d iterations, timed out! (lock)\n",
- X flock_iteration));
- X }
- X#ifndef LOCK_FLOCK_ONLY
- X (void)unlink(lock_name);
- X#endif
- X leave(error("Timed out on locking mailbox. Leaving program."));
- X }
- X
- X /* We locked the file */
- X dprint(5,
- X (debugfile, "Lock %s on file %s on.\n",
- X (direction == INCOMING ? "incoming" : "outgoing"), cur_folder));
- X#endif
- X
- X dprint(5,
- X (debugfile, "Lock %s for file %s on successfully.\n",
- X (direction == INCOMING ? "incoming" : "outgoing"), cur_folder));
- X lock_state = ON;
- X return(0);
- X}
- X
- Xint
- Xunlock()
- X{
- X /** Remove the lock file! This must be part of the interrupt
- X processing routine to ensure that the lock file is NEVER
- X left sitting in the mailhome directory!
- X
- X If also using flock(), remove the file lock as well.
- X **/
- X
- X int retcode = 0;
- X
- X dprint(5,
- X (debugfile, "Lock %s for file %s %s off.\n",
- X (*lock_name ? lock_name : "none"), cur_folder,
- X (lock_state == ON ? "going" : "already")));
- X
- X if(lock_state == ON) {
- X
- X#ifdef LOCK_BY_FLOCK
- X if((retcode = flock(flock_fd, LOCK_UN)) == -1) {
- X dprint(1, (debugfile,
- X "Error %s (%s)\n\ttrying to unlock file %s (%s)\n",
- X error_name(errno), error_description(errno), cur_folder, "unlock"));
- X
- X /* try to force unlock by closing file */
- X if(close(flock_fd) == -1) {
- X dprint(1, (debugfile,
- X "Error %s (%s)\n\ttrying to force unlock file %s via close() (%s)\n",
- X error_name(errno), error_description(errno), cur_folder, "unlock"));
- X error1("Couldn't unlock my own mailbox %s!", cur_folder);
- X return(retcode);
- X }
- X }
- X (void)close(flock_fd);
- X#endif
- X#ifdef LOCK_FLOCK_ONLY /* { LOCK_FLOCK_ONLY */
- X *lock_name = '\0'; /* null lock file name */
- X lock_state = OFF; /* indicate we don't have a lock on */
- X#else
- X if((retcode = unlink(lock_name)) == 0) { /* remove lock file */
- X *lock_name = '\0'; /* null lock file name */
- X lock_state = OFF; /* indicate we don't have a lock on */
- X } else {
- X dprint(1, (debugfile,
- X "Error %s (%s)\n\ttrying to unlink file %s (%s)\n",
- X error_name(errno), error_description(errno), lock_name,"unlock"));
- X error1("Couldn't remove my own lock file %s!", lock_name);
- X }
- X#endif /* } LOCK_FLOCK_ONLY */
- X }
- X return(retcode);
- X}
- SHAR_EOF
- echo "File src/leavembox.c is complete"
- chmod 0444 src/leavembox.c || echo "restore of src/leavembox.c fails"
- echo "x - extracting src/limit.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/limit.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: limit.c,v 4.1 90/04/28 22:43:21 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@DSI.COM dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: limit.c,v $
- X * Revision 4.1 90/04/28 22:43:21 syd
- X * checkin of Elm 2.3 as of Release PL0
- X *
- X *
- X ******************************************************************************/
- X
- X/** This stuff is inspired by MH and dmail and is used to 'select'
- X a subset of the existing mail in the folder based on one of a
- X number of criteria. The basic tricks are pretty easy - we have
- X as status of VISIBLE associated with each header stored in the
- X (er) mind of the computer (!) and simply modify the commands to
- X check that flag...the global variable `selected' is set to the
- X number of messages currently selected, or ZERO if no select.
- X**/
- X
- X#include "headers.h"
- X
- X#define TO 1
- X#define FROM 2
- X
- Xchar *shift_lower();
- X
- Xint
- Xlimit()
- X{
- X /** returns non-zero if we changed selection criteria = need redraw **/
- X
- X char criteria[STRING], first[STRING], rest[STRING], msg[STRING];
- X static char prompt[] = "Enter criteria or '?' for help: ";
- X int last_selected, all;
- X
- X last_selected = selected;
- X all = 0;
- X
- X if (selected) {
- X PutLine1(LINES-2, 0,
- X "Already have selection criteria - add more? (y/n) n%c",
- X BACKSPACE);
- X criteria[0] = ReadCh();
- X if (tolower(criteria[0]) == 'y') {
- X Write_to_screen("Yes.", 0);
- X PutLine0(LINES-3, COLUMNS-30, "Adding criteria...");
- X } else {
- X Write_to_screen("No.", 0);
- X selected = 0;
- X PutLine0(LINES-3, COLUMNS-30, "Change criteria...");
- X }
- X }
- X
- X while(1) {
- X PutLine1(LINES-2, 0, prompt);
- X CleartoEOLN();
- X
- X criteria[0] = '\0';
- X optionally_enter(criteria, LINES-2, strlen(prompt), FALSE, FALSE);
- X error("");
- X
- X if (strlen(criteria) == 0) {
- X /* no change */
- X selected = last_selected;
- X return(FALSE);
- X }
- X
- X split_word(criteria, first, rest);
- X
- X if (equal(first, "?")) {
- X if(last_selected)
- X error(
- X "Enter: {\"subject\",\"to\",\"from\"} [pattern] OR \"all\"");
- X else
- X error("Enter: {\"subject\",\"to\",\"from\"} [pattern]");
- X continue;
- X } else if (equal(first, "all")) {
- X all++;
- X selected = 0;
- X }
- X else if (equal(first, "subj") || equal(first, "subject"))
- X selected = limit_selection(SUBJECT, rest, selected);
- X else if (equal(first, "to"))
- X selected = limit_selection(TO, rest, selected);
- X else if (equal(first, "from"))
- X selected = limit_selection(FROM, rest, selected);
- X else {
- X error1("\"%s\" not a valid criterion.", first);
- X continue;
- X }
- X break;
- X }
- X
- X if(all && last_selected)
- X strcpy(msg, "Returned to unlimited display.");
- X else if(selected)
- X sprintf(msg, "%d message%s selected.", selected, plural(selected));
- X else
- X strcpy(msg, "No messages selected.");
- X set_error(msg);
- X
- X /* we need a redraw if there had been a selection or there is now. */
- X if(last_selected || selected) {
- X /* if current message won't be on new display, go to first message */
- X if(selected && !(headers[current-1]->status & VISIBLE))
- X current = visible_to_index(1)+1;
- X return(TRUE);
- X } else {
- X return(FALSE);
- X }
- X}
- X
- Xint
- Xlimit_selection(based_on, pattern, additional_criteria)
- Xint based_on, additional_criteria;
- Xchar *pattern;
- X{
- X /** Given the type of criteria, and the pattern, mark all
- X non-matching headers as ! VISIBLE. If additional_criteria,
- X don't mark as visible something that isn't currently!
- X **/
- X
- X register int iindex, count = 0;
- X
- X dprint(2, (debugfile, "\n\n\n**limit on %d - '%s' - (%s) **\n\n",
- X based_on, pattern, additional_criteria?"add'tl":"base"));
- X
- X if (based_on == SUBJECT) {
- X for (iindex = 0; iindex < message_count; iindex++)
- X if (! in_string(shift_lower(headers[iindex]->subject), pattern))
- X headers[iindex]->status &= ~VISIBLE;
- X else if (additional_criteria &&
- X !(headers[iindex]->status & VISIBLE))
- X headers[iindex]->status &= ~VISIBLE; /* shut down! */
- X else { /* mark it as readable */
- X headers[iindex]->status |= VISIBLE;
- X count++;
- X dprint(5, (debugfile,
- X " Message %d (%s from %s) marked as visible\n",
- X iindex, headers[iindex]->subject,
- X headers[iindex]->from));
- X }
- X }
- X else if (based_on == FROM) {
- X for (iindex = 0; iindex < message_count; iindex++)
- X if (! in_string(shift_lower(headers[iindex]->from), pattern))
- X headers[iindex]->status &= ~VISIBLE;
- X else if (additional_criteria &&
- X !(headers[iindex]->status & VISIBLE))
- X headers[iindex]->status &= ~VISIBLE; /* shut down! */
- X else { /* mark it as readable */
- X headers[iindex]->status |= VISIBLE;
- X count++;
- X dprint(5, (debugfile,
- X " Message %d (%s from %s) marked as visible\n",
- X iindex, headers[iindex]->subject,
- X headers[iindex]->from));
- X }
- X }
- X else if (based_on == TO) {
- X for (iindex = 0; iindex < message_count; iindex++)
- X if (! in_string(shift_lower(headers[iindex]->to), pattern))
- X headers[iindex]->status &= ~VISIBLE;
- X else if (additional_criteria &&
- X !(headers[iindex]->status & VISIBLE))
- X headers[iindex]->status &= ~VISIBLE; /* shut down! */
- X else { /* mark it as readable */
- X headers[iindex]->status |= VISIBLE;
- X count++;
- X dprint(5, (debugfile,
- X " Message %d (%s from %s) marked as visible\n",
- X iindex, headers[iindex]->subject,
- X headers[iindex]->from));
- X }
- X }
- X
- X dprint(4, (debugfile, "\n** returning %d selected **\n\n\n", count));
- X
- X return(count);
- X}
- X
- Xint
- Xnext_message(iindex, skipdel)
- Xregister int iindex, skipdel;
- X{
- X /** Given 'iindex', this routine will return the actual iindex into the
- X array of the NEXT message, or '-1' iindex is the last.
- X If skipdel, return the iindex for the NEXT undeleted message.
- X If selected, return the iindex for the NEXT message marked VISIBLE.
- X **/
- X
- X register int remember_for_debug;
- X
- X if(iindex < 0) return(-1); /* invalid argument value! */
- X
- X remember_for_debug = iindex;
- X
- X for(iindex++;iindex < message_count; iindex++)
- X if (((headers[iindex]->status & VISIBLE) || (!selected))
- X && (!(headers[iindex]->status & DELETED) || (!skipdel))) {
- X dprint(9, (debugfile, "[Next%s%s: given %d returning %d]\n",
- X (skipdel ? " undeleted" : ""),
- X (selected ? " visible" : ""),
- X remember_for_debug+1, iindex+1));
- X return(iindex);
- X }
- X return(-1);
- X}
- X
- Xint
- Xprev_message(iindex, skipdel)
- Xregister int iindex, skipdel;
- X{
- X /** Like next_message, but the PREVIOUS message. **/
- X
- X register int remember_for_debug;
- X
- X if(iindex >= message_count) return(-1); /* invalid argument value! */
- X
- X remember_for_debug = iindex;
- X for(iindex--; iindex >= 0; iindex--)
- X if (((headers[iindex]->status & VISIBLE) || (!selected))
- X && (!(headers[iindex]->status & DELETED) || (!skipdel))) {
- X dprint(9, (debugfile, "[Previous%s%s: given %d returning %d]\n",
- X (skipdel ? " undeleted" : ""),
- X (selected ? " visible" : ""),
- X remember_for_debug+1, iindex+1));
- X return(iindex);
- X }
- X return(-1);
- X}
- X
- X
- Xint
- Xcompute_visible(message)
- Xint message;
- X{
- X /** return the 'virtual' iindex of the specified message in the
- X set of messages - that is, if we have the 25th message as
- X the current one, but it's #2 based on our limit criteria,
- X this routine, given 25, will return 2.
- X **/
- X
- X register int iindex, count = 0;
- X
- X if (! selected) return(message);
- X
- X if (message < 1) message = 1; /* normalize */
- X
- X for (iindex = 0; iindex < message; iindex++)
- X if (headers[iindex]->status & VISIBLE)
- X count++;
- X
- X dprint(4, (debugfile,
- X "[compute-visible: displayed message %d is actually %d]\n",
- X count, message));
- X
- X return(count);
- X}
- X
- Xint
- Xvisible_to_index(message)
- Xint message;
- X{
- X /** Given a 'virtual' iindex, return a real one. This is the
- X flip-side of the routine above, and returns (message_count+1)
- X if it cannot map the virtual iindex requested (too big)
- X **/
- X
- X register int iindex = 0, count = 0;
- X
- X for (iindex = 0; iindex < message_count; iindex++) {
- X if (headers[iindex]->status & VISIBLE)
- X count++;
- X if (count == message) {
- X dprint(4, (debugfile,
- X "visible-to-index: (up) index %d is displayed as %d\n",
- X message, iindex));
- X return(iindex);
- X }
- X }
- X
- X dprint(4, (debugfile, "index %d is NOT displayed!\n", message));
- X
- X return(message_count+1);
- X}
- SHAR_EOF
- chmod 0444 src/limit.c || echo "restore of src/limit.c fails"
- echo "x - extracting src/mailmsg1.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/mailmsg1.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: mailmsg1.c,v 4.1 90/04/28 22:43:26 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@DSI.COM dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: mailmsg1.c,v $
- X * Revision 4.1 90/04/28 22:43:26 syd
- X * checkin of Elm 2.3 as of Release PL0
- X *
- X *
- X ******************************************************************************/
- X
- X/** Interface to allow mail to be sent to users. Part of ELM **/
- X
- X
- X#include "headers.h"
- X
- X/** strings defined for the hdrconfg routines **/
- X
- Xchar subject[SLEN], in_reply_to[SLEN], expires[SLEN],
- X action[SLEN], priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING],
- X cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING],
- X expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN],
- X bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
- X
- Xchar *format_long(), *strip_commas(), *tail_of_string(), *strcpy();
- Xunsigned long sleep();
- X
- Xint
- Xsendmsg(given_to, given_cc, given_subject, edit_message, form_letter, replying)
- Xchar *given_to, *given_cc, *given_subject;
- Xint edit_message, form_letter, replying;
- X{
- X /** Prompt for fields and then call mail() to send the specified
- X message. If 'edit_message' is true then don't allow the
- X message to be edited. 'form_letter' can be "YES" "NO" or "MAYBE".
- X if YES, then add the header. If MAYBE, then add the M)ake form
- X option to the last question (see mailsg2.c) etc. etc.
- X if (replying) then add an In-Reply-To: header...
- X Return TRUE if the main part of the screen has been changed
- X (useful for knowing whether a redraw is needed.
- X **/
- X
- X int copy_msg = FALSE, is_a_response = FALSE;
- X
- X /* First: zero all current global message strings */
- X
- X cc[0] = bcc[0] = reply_to[0] = expires[0] = '\0';
- X action[0] = priority[0] = user_defined_header[0] = in_reply_to[0] ='\0';
- X expanded_to[0] = expanded_cc[0] = expanded_bcc[0] = '\0';
- X
- X strcpy(subject, given_subject); /* copy given subject */
- X strcpy(to, given_to); /* copy given to: */
- X strcpy(cc, given_cc); /* and so on.. */
- X
- X /******* And now the real stuff! *******/
- X
- X copy_msg=copy_the_msg(&is_a_response); /* copy msg into edit buffer? */
- X
- X if (get_to(to, expanded_to) == 0) /* get the To: address and expand */
- X return(0);
- X
- X /** if we're batchmailing, let's send it and GET OUTTA HERE! **/
- X
- X if (batch_only) {
- X return(mail(FALSE, FALSE, form_letter));
- X }
- X
- X display_to(expanded_to); /* display the To: field on screen... */
- X
- X dprint(3, (debugfile, "\nMailing to \"%s\"\n", expanded_to));
- X
- X if (get_subject(subject) == 0) /* get the Subject: field */
- X return(0);
- X
- X dprint(4, (debugfile, "Subject is %s\n", subject));
- X
- X if (prompt_for_cc) {
- X if (get_copies(cc, expanded_to, expanded_cc, copy_msg) == 0)
- X return(0);
- X
- X if (strlen(cc) > 0)
- X dprint(4, (debugfile, "Copies to %s\n", expanded_cc));
- X }
- X
- X MoveCursor(LINES,0); /* so you know you've hit <return> ! */
- X
- X /** generate the In-Reply-To: header... **/
- X
- X if (is_a_response && replying)
- X generate_reply_to(current-1);
- X
- X /* and mail that puppy outta here! */
- X
- X return(mail(copy_msg, edit_message, form_letter));
- X}
- X
- Xget_to(to_field, address)
- Xchar *to_field, *address;
- X{
- X /** prompt for the "To:" field, expanding into address if possible.
- X This routine returns ZERO if errored, or non-zero if okay **/
- X
- X if (strlen(to_field) == 0) {
- X if (user_level < 2) {
- X PutLine0(LINES-2, 0, "Send the message to: ");
- X (void) optionally_enter(to_field, LINES-2, 21, FALSE, FALSE);
- X }
- X else {
- X PutLine0(LINES-2, 0, "To: ");
- X (void) optionally_enter(to_field, LINES-2, 4, FALSE, FALSE);
- X }
- X if (strlen(to_field) == 0) {
- X ClearLine(LINES-2);
- X return(0);
- X }
- X (void) build_address(strip_commas(to_field), address);
- X }
- X else if (mail_only)
- X (void) build_address(strip_commas(to_field), address);
- X else
- X strcpy(address, to_field);
- X
- X if (strlen(address) == 0) { /* bad address! Removed!! */
- X ClearLine(LINES-2);
- X return(0);
- X }
- X
- X return(1); /* everything is okay... */
- X}
- X
- Xget_subject(subject_field)
- Xchar *subject_field;
- X{
- X char ch;
- X
- X /** get the subject and return non-zero if all okay... **/
- X int len = 9, prompt_line;
- X
- X prompt_line = mail_only ? 4 : LINES-2;
- X
- X if (user_level == 0) {
- X PutLine0(prompt_line,0,"Subject of message: ");
- X len = 20;
- X }
- X else
- X PutLine0(prompt_line,0,"Subject: ");
- X
- X CleartoEOLN();
- X
- X if(optionally_enter(subject_field, prompt_line, len, TRUE, FALSE)==-1){
- X /** User hit the BREAK key! **/
- X MoveCursor(prompt_line,0);
- X CleartoEOLN();
- X error("Mail not sent.");
- X return(0);
- X }
- X
- X if (strlen(subject_field) == 0) { /* zero length subject?? */
- X PutLine1(prompt_line,0,
- X "No subject - Continue with message? (y/n) n%c", BACKSPACE);
- X
- X ch = ReadCh();
- X if (tolower(ch) != 'y') { /* user says no! */
- X Write_to_screen("No.", 0);
- X ClearLine(prompt_line);
- X error("Mail not sent.");
- X return(0);
- X }
- X else {
- X Write_to_screen("Yes.", 0);
- X PutLine0(prompt_line,0,"Subject: <none>");
- X CleartoEOLN();
- X }
- X }
- X
- X return(1); /** everything is cruising along okay **/
- X}
- X
- Xget_copies(cc_field, address, addressII, copy_message)
- Xchar *cc_field, *address, *addressII;
- Xint copy_message;
- X{
- X /** Get the list of people that should be cc'd, returning ZERO if
- X any problems arise. Address and AddressII are for expanding
- X the aliases out after entry!
- X If 'bounceback' is nonzero, add a cc to ourselves via the remote
- X site, but only if hops to machine are > bounceback threshold.
- X If copy-message, that means that we're going to have to invoke
- X a screen editor, so we'll need to delay after displaying the
- X possibly rewritten Cc: line...
- X **/
- X int prompt_line;
- X
- X prompt_line = mail_only ? 5 : LINES - 1;
- X PutLine0(prompt_line,0,"Copies to: ");
- X
- X fflush(stdout);
- X
- X if (optionally_enter(cc_field, prompt_line, 11, FALSE, FALSE) == -1) {
- X ClearLine(prompt_line-1);
- X ClearLine(prompt_line);
- X
- X error("Mail not sent.");
- X return(0);
- X }
- X
- X /** The following test is that if the build_address routine had
- X reason to rewrite the entry given, then, if we're mailing only
- X print the new Cc line below the old one. If we're not, then
- X assume we're in screen mode and replace the incorrect entry on
- X the line above where we are (e.g. where we originally prompted
- X for the Cc: field).
- X **/
- X
- X if (build_address(strip_commas(cc_field), addressII)) {
- X PutLine1(prompt_line, 11, "%s", addressII);
- X if ((strcmp(editor, "builtin") != 0 && strcmp(editor, "none") != 0)
- X || copy_message)
- X sleep(2);
- X }
- X
- X if (strlen(address) + strlen(addressII) > VERY_LONG_STRING) {
- X dprint(2, (debugfile,
- X "String length of \"To:\" + \"Cc\" too long! (get_copies)\n"));
- X error("Too many people. Copies ignored.");
- X sleep(2);
- X cc_field[0] = '\0';
- X }
- X
- X return(1); /* everything looks okay! */
- X}
- X
- Xint
- Xcopy_the_msg(is_a_response)
- Xint *is_a_response;
- X{
- X /** Returns True iff the user wants to copy the message being
- X replied to into the edit buffer before invoking the editor!
- X Sets "is_a_response" to true if message is a response...
- X **/
- X
- X int answer = FALSE;
- X
- X if (forwarding)
- X answer = TRUE;
- X else if (strlen(to) > 0 && !mail_only) { /* predefined 'to' line! */
- X if (auto_copy)
- X answer = TRUE;
- X else
- X answer = (want_to("Copy message? (y/n) ", 'n') == 'y');
- X *is_a_response = TRUE;
- X }
- X
- X return(answer);
- X}
- X
- Xstatic int to_line, to_col;
- X
- Xdisplay_to(address)
- Xchar *address;
- X{
- X /** Simple routine to display the "To:" line according to the
- X current configuration (etc)
- X **/
- X register int open_paren;
- X
- X to_line = mail_only ? 3 : LINES - 3;
- X to_col = mail_only ? 0 : COLUMNS - 50;
- X if (names_only)
- X if ((open_paren = chloc(address, '(')) > 0) {
- X if (open_paren < chloc(address, ')')) {
- X output_abbreviated_to(address);
- X return;
- X }
- X }
- X if(mail_only)
- X if(strlen(address) > 80)
- X PutLine1(to_line, to_col, "To: (%s)",
- X tail_of_string(address, 75));
- X else
- X PutLine1(to_line, to_col, "To: %s", address);
- X else if (strlen(address) > 45)
- X PutLine1(to_line, to_col, "To: (%s)",
- X tail_of_string(address, 40));
- X else {
- X if (strlen(address) > 30)
- X PutLine1(to_line, to_col, "To: %s", address);
- X else
- X PutLine1(to_line, to_col, " To: %s", address);
- X CleartoEOLN();
- X }
- X}
- X
- Xoutput_abbreviated_to(address)
- Xchar *address;
- X{
- X /** Output just the fields in parens, separated by commas if need
- X be, and up to COLUMNS-50 characters...This is only used if the
- X user is at level BEGINNER.
- X **/
- X
- X char newaddress[LONG_STRING];
- X register int iindex, newindex = 0, in_paren = 0, add_len;
- X
- X iindex = 0;
- X
- X add_len = strlen(address);
- X while (newindex < 55 && iindex < add_len) {
- X if (address[iindex] == '(') in_paren++;
- X else if (address[iindex] == ')') {
- X in_paren--;
- X if (iindex < add_len-4) {
- X newaddress[newindex++] = ',';
- X newaddress[newindex++] = ' ';
- X }
- X }
- X
- X /* copy if in_paren but not at the opening outer parens */
- X if (in_paren && !(address[iindex] == '(' && in_paren == 1))
- X newaddress[newindex++] = address[iindex];
- X
- X iindex++;
- X }
- X
- X newaddress[newindex] = '\0';
- X
- X if (mail_only)
- X if (strlen(newaddress) > 80)
- X PutLine1(to_line, to_col, "To: (%s)",
- X tail_of_string(newaddress, 60));
- X else
- X PutLine1(to_line, to_col, "To: %s", newaddress);
- X else if (strlen(newaddress) > 50)
- X PutLine1(to_line, to_col, "To: (%s)",
- X tail_of_string(newaddress, 40));
- X else {
- X if (strlen(newaddress) > 30)
- X PutLine1(to_line, to_col, "To: %s", newaddress);
- X else
- X PutLine1(to_line, to_col, " To: %s", newaddress);
- X CleartoEOLN();
- X }
- X
- X return;
- X}
- SHAR_EOF
- chmod 0444 src/mailmsg1.c || echo "restore of src/mailmsg1.c fails"
- echo "x - extracting src/mailmsg2.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/mailmsg2.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: mailmsg2.c,v 4.1 90/04/28 22:43:28 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@DSI.COM dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: mailmsg2.c,v $
- X * Revision 4.1 90/04/28 22:43:28 syd
- X * checkin of Elm 2.3 as of Release PL0
- X *
- X *
- X ******************************************************************************/
- X
- X/** Interface to allow mail to be sent to users. Part of ELM **/
- X
- X#include "headers.h"
- X#include <errno.h>
- X#include <ctype.h>
- X
- X#ifdef BSD
- X#undef tolower
- X#undef toupper
- X#endif
- X
- Xextern int errno;
- Xextern char version_buff[];
- X
- Xchar *error_name(), *error_description(), *strip_parens();
- Xchar *strcat(), *strcpy(), *index();
- Xchar *format_long(), *strip_commas(), *tail_of_string();
- X
- Xunsigned long sleep();
- X
- X#ifdef SITE_HIDING
- X char *get_ctime_date();
- X#endif
- XFILE *write_header_info();
- X
- X/* these are all defined in the mailmsg1.c file! */
- X
- Xextern char subject[SLEN], in_reply_to[SLEN], expires[SLEN],
- X action[SLEN], priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING],
- X cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING],
- X expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN],
- X bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
- X
- X
- Xint gotten_key;
- Xchar *bounce_off_remote();
- X
- Xmail(copy_msg, edit_message, form)
- Xint copy_msg, edit_message, form;
- X{
- X /** Given the addresses and various other miscellany (specifically,
- X 'copy-msg' indicates whether a copy of the current message should
- X be included, 'edit_message' indicates whether the message should
- X be edited) this routine will invoke an editor for the user and
- X then actually mail off the message. 'form' can be YES, NO, or
- X MAYBE. YES=add "Content-Type: mailform" header, MAYBE=add the
- X M)ake form option to last question, and NO=don't worry about it!
- X Also, if 'copy_msg' = FORM, then grab the form temp file and use
- X that...
- X Return TRUE if the main part of the screen has been changed
- X (useful for knowing whether a redraw is needed.
- X **/
- X
- X FILE *reply, *real_reply; /* second is post-input buffer */
- X char *whole_msg_file, *tempnam();
- X char filename[SLEN], fname[SLEN], copy_file[SLEN],
- X very_long_buffer[VERY_LONG_STRING], mailerflags[NLEN];
- X int ch, sys_status;
- X register int retransmit = FALSE;
- X int already_has_text = FALSE; /* we need an ADDRESS */
- X int signature_done = FALSE;
- X int need_redraw = 0;
- X
- X static int cancelled_msg = 0;
- X
- X dprint(4, (debugfile, "\nMailing to \"%s\" (with%s editing)\n",
- X expanded_to, edit_message? "" : "out"));
- X
- X gotten_key = 0; /* ignore previously gotten encryption key */
- X
- X /** first generate the temporary filename **/
- X
- X sprintf(filename,"%s%s%d", temp_dir, temp_file, getpid());
- X
- X /** if possible, let's try to recall the last message? **/
- X
- X if (! batch_only && copy_msg != FORM && user_level != 0)
- X retransmit = recall_last_msg(filename, copy_msg, &cancelled_msg,
- X &already_has_text);
- X
- X /** if we're not retransmitting, create the file.. **/
- X
- X if (! retransmit)
- X if ((reply = fopen(filename,"w")) == NULL) {
- X dprint(1, (debugfile,
- X "Attempt to write to temp file %s failed with error %s (mail)\n",
- X filename, error_name(errno)));
- X if(batch_only)
- X printf("Could not create file %s (%s).\n",filename,
- X error_name(errno));
- X else
- X error2("Could not create file %s (%s).",filename,
- X error_name(errno));
- X return(need_redraw);
- X }
- X
- X chown (filename, userid, groupid);
- X
- X /* copy the message from standard input */
- X if (batch_only) {
- X while (fgets(very_long_buffer, VERY_LONG_STRING, stdin) != NULL)
- X fprintf(reply, "%s", very_long_buffer);
- X }
- X
- X if (copy_msg == FORM) {
- X sprintf(fname, "%s%s%d", temp_dir, temp_form_file, getpid());
- X fclose(reply); /* we can't retransmit a form! */
- X if (access(fname,ACCESS_EXISTS) != 0) {
- X if(batch_only)
- X printf("Couldn't find forms file!\n");
- X else
- X error("Couldn't find forms file!");
- X return(need_redraw);
- X }
- X dprint(4, (debugfile, "-- renaming existing file %s to file %s --\n",
- X fname, filename));
- X rename(fname, filename);
- X }
- X else if (copy_msg && ! retransmit) { /* if retransmit we have it! */
- X if (attribution[0]) {
- X fprintf(reply, attribution, headers[current-1]->from);
- X fputc('\n', reply);
- X }
- X else if (forwarding) {
- X fputs("Forwarded message:\n", reply);
- X }
- X if (edit_message) {
- X copy_message(prefixchars, reply, noheader, FALSE, FALSE, TRUE);
- X already_has_text = TRUE; /* we just added it, right? */
- X }
- X else
- X copy_message("", reply, noheader, FALSE, FALSE, TRUE);
- X }
- X
- X /* append signature now if we are going to use an external editor */
- X /* Don't worry about the remote/local determination too much */
- X
- X if (already_has_text ||
- X (strcmp(editor,"builtin") != 0 && strcmp(editor,"none") != 0)) {
- X signature_done = TRUE;
- X if (!retransmit && copy_msg != FORM)
- X already_has_text |= append_sig(reply);
- X }
- X
- X if (! retransmit && copy_msg != FORM)
- X if (reply != NULL)
- X (void) fclose(reply); /* on replies, it won't be open! */
- X
- X /** Edit the message **/
- X
- X if (edit_message)
- X create_readmsg_file(); /* for "readmsg" routine */
- X
- X ch = edit_message? 'e' : ' '; /* drop through if needed... */
- X
- X /* calculate default save_file name */
- X if(auto_cc) {
- X if(save_by_name) {
- X if(force_name) {
- X strcpy(copy_file, "="); /* signals save by 'to' logname */
- X } else {
- X strcpy(copy_file, "=?"); /* conditional save by 'to' logname */
- X }
- X } else {
- X strcpy(copy_file, "<"); /* signals save to sentmail */
- X }
- X } else *copy_file = '\0'; /* signals to not save a copy */
- X
- X
- X if (! batch_only) {
- X do {
- X switch (ch) {
- X case 'e': need_redraw = 1;
- X if (edit_the_message(filename, already_has_text)) {
- X cancelled_msg = TRUE;
- X return(need_redraw);
- X }
- X break;
- X
- X case 'c': if (name_copy_file(copy_file))
- X need_redraw = 1;
- X break;
- X
- X case 'h': edit_headers();
- X need_redraw = 1;
- X break;
- X
- X#ifdef ALLOW_SUBSHELL
- X case '!': if (subshell()) {
- X ClearScreen();
- X need_redraw = 1;
- X }
- X break;
- X#endif
- X
- X default : /* do nothing */ ;
- X }
- X
- X /** ask that silly question again... **/
- X
- X if ((ch = verify_transmission(filename, &form)) == 'f') {
- X cancelled_msg = TRUE;
- X return(need_redraw);
- X }
- X
- X } while (ch != 's');
- X
- X if (form == YES)
- X if (format_form(filename) < 1) {
- X cancelled_msg = TRUE;
- X return(need_redraw);
- X }
- X
- X if ((reply = fopen(filename,"r")) == NULL) {
- X dprint(1, (debugfile,
- X "Attempt to open file %s for reading failed with error %s (mail)\n",
- X filename, error_name(errno)));
- X error1("Could not open reply file (%s).", error_name(errno));
- X return(need_redraw);
- X }
- X }
- X else if ((reply = fopen(filename,"r")) == NULL) {
- X dprint(1, (debugfile,
- X "Attempt to open file %s for reading failed with error %s (mail)\n",
- X filename, error_name(errno)));
- X printf("Could not open reply file (%s).\n", error_name(errno));
- X return(need_redraw);
- X }
- X
- X cancelled_msg = FALSE; /* it ain't cancelled, is it? */
- X
- X /** ask about bounceback if the user wants us to.... **/
- X
- X if (uucp_hops(to) > bounceback && bounceback > 0 && copy_msg != FORM)
- SHAR_EOF
- echo "End of part 17"
- echo "File src/mailmsg2.c is continued in part 18"
- echo "18" > s2_seq_.tmp
- exit 0
-