1: /* movemail foo bar -- move file foo to file bar,
   2:    locking file foo the way /bin/mail respects.
   3:    Copyright (C) 1985 Richard M. Stallman.
   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: #include <sys/types.h>
  22: #include <sys/stat.h>
  23: #include <sys/file.h>
  24: #define NO_SHORTNAMES   /* Tell config not to load remap.h */
  25: #include "../src/config.h"
  26: 
  27: #ifdef USG
  28: #include <fcntl.h>
  29: #endif /* USG */
  30: 
  31: /* Cancel substitutions made by config.h for Emacs.  */
  32: #undef open
  33: #undef read
  34: #undef write
  35: 
  36: char *concat ();
  37: 
  38: main (argc, argv)
  39:      int argc;
  40:      char **argv;
  41: {
  42:   char *inname, *outname;
  43:   int indesc, outdesc;
  44:   char buf[1024];
  45:   int nread;
  46: 
  47: #ifndef MAIL_USE_FLOCK
  48:   struct stat st;
  49:   long now;
  50:   int tem;
  51:   char *lockname, *p;
  52:   char tempname[40];
  53:   int desc;
  54: #endif /* not MAIL_USE_FLOCK */
  55: 
  56:   if (argc < 3)
  57:     fatal ("two arguments required");
  58: 
  59:   inname = argv[1];
  60:   outname = argv[2];
  61: 
  62: #ifndef MAIL_USE_FLOCK
  63:   /* Use a lock file named /usr/spool/mail/$USER.lock:
  64:      If it exists, the mail file is locked.  */
  65:   lockname = concat (inname, ".lock", "");
  66:   strcpy (tempname, inname);
  67:   p = tempname + strlen (tempname);
  68:   while (p != tempname && p[-1] != '/')
  69:     p--;
  70:   *p = 0;
  71:   strcpy (p, "EXXXXXX");
  72:   mktemp (tempname);
  73:   unlink (tempname);
  74: 
  75:   while (1)
  76:     {
  77:       /* Create the lock file, but not under the lock file name.  */
  78:       /* Give up if cannot do that.  */
  79:       desc = open (tempname, O_WRONLY | O_CREAT, 0666);
  80:       if (desc < 0)
  81:     exit (1);
  82:       close (desc);
  83: 
  84:       tem = link (tempname, lockname);
  85:       unlink (tempname);
  86:       if (tem >= 0)
  87:     break;
  88:       sleep (1);
  89: 
  90:       /* If lock file is a minute old, unlock it.  */
  91:       if (stat (lockname, &st) >= 0)
  92:     {
  93:       now = time (0);
  94:       if (st.st_ctime < now - 60)
  95:         unlink (lockname);
  96:     }
  97:     }
  98: #endif /* not MAIL_USE_FLOCK */
  99: 
 100: #ifdef MAIL_USE_FLOCK
 101:   indesc = open (inname, O_RDWR);
 102: #else /* if not MAIL_USE_FLOCK */
 103:   indesc = open (inname, O_RDONLY);
 104: #endif /* not MAIL_USE_FLOCK */
 105:   if (indesc < 0)
 106:     pfatal_with_name (inname);
 107: #ifdef BSD
 108:   /* In case movemail is setuid to root, make sure the user can
 109:      read the output file.  */
 110:   /* This is desirable for all systems
 111:      but I don't want to assume all have the umask system call */
 112:   umask (umask (0) & 0333);
 113: #endif /* BSD */
 114:   outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
 115:   if (outdesc < 0)
 116:     pfatal_with_name (outname);
 117: #ifdef MAIL_USE_FLOCK
 118:   (void) flock (indesc, LOCK_EX);
 119: #endif /* MAIL_USE_FLOCK */
 120: 
 121:   while (1)
 122:     {
 123:       nread = read (indesc, buf, sizeof buf);
 124:       if (nread != write (outdesc, buf, nread))
 125:     fatal ("error writing to %s", outname);
 126:       if (nread < sizeof buf)
 127:     break;
 128:     }
 129: 
 130: #ifdef MAIL_USE_FLOCK
 131:   (void) ftruncate (indesc, 0L);
 132: #endif /* MAIL_USE_FLOCK */
 133:   close (indesc);
 134:   close (outdesc);
 135: #ifndef MAIL_USE_FLOCK
 136:   unlink (inname);
 137:   unlink (lockname);
 138: #endif /* not MAIL_USE_FLOCK */
 139:   exit (0);
 140: }
 141: 
 142: /* Print error message and exit.  */
 143: 
 144: fatal (s1, s2)
 145:      char *s1, *s2;
 146: {
 147:   error (s1, s2);
 148:   exit (1);
 149: }
 150: 
 151: /* Print error message.  `s1' is printf control string, `s2' is arg for it. */
 152: 
 153: error (s1, s2)
 154:      char *s1, *s2;
 155: {
 156:   printf ("movemail: ");
 157:   printf (s1, s2);
 158:   printf ("\n");
 159: }
 160: 
 161: pfatal_with_name (name)
 162:      char *name;
 163: {
 164:   extern int errno, sys_nerr;
 165:   extern char *sys_errlist[];
 166:   char *s;
 167: 
 168:   if (errno < sys_nerr)
 169:     s = concat ("", sys_errlist[errno], " for %s");
 170:   else
 171:     s = "cannot open %s";
 172:   fatal (s, name);
 173: }
 174: 
 175: /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
 176: 
 177: char *
 178: concat (s1, s2, s3)
 179:      char *s1, *s2, *s3;
 180: {
 181:   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
 182:   char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
 183: 
 184:   strcpy (result, s1);
 185:   strcpy (result + len1, s2);
 186:   strcpy (result + len1 + len2, s3);
 187:   *(result + len1 + len2 + len3) = 0;
 188: 
 189:   return result;
 190: }
 191: 
 192: /* Like malloc but get fatal error if memory is exhausted.  */
 193: 
 194: int
 195: xmalloc (size)
 196:      int size;
 197: {
 198:   int result = malloc (size);
 199:   if (!result)
 200:     fatal ("virtual memory exhausted", 0);
 201:   return result;
 202: }

Defined functions

concat defined in line 177; used 3 times
error defined in line 153; used 1 times
fatal defined in line 144; used 4 times
main defined in line 38; never used
pfatal_with_name defined in line 161; used 2 times
xmalloc defined in line 194; used 1 times

Defined macros

NO_SHORTNAMES defined in line 24; never used
Last modified: 1986-03-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1066
Valid CSS Valid XHTML 1.0 Strict