Initial revision
[mmh] / uip / annosbr.c
1
2 /*
3  * annosbr.c -- prepend annotation to messages
4  *
5  * $Id$
6  */
7
8 #include <h/mh.h>
9 #include <zotnet/tws/tws.h>
10 #include <fcntl.h>
11 #include <errno.h>
12
13 extern int  errno;
14
15 /*
16  * static prototypes
17  */
18 static int annosbr (int, char *, char *, char *, int, int);
19
20
21 int
22 annotate (char *file, char *comp, char *text, int inplace, int datesw)
23 {
24     int i, fd;
25
26     /* open and lock the file to be annotated */
27     if ((fd = lkopen (file, O_RDWR, 0)) == NOTOK) {
28         switch (errno) {
29             case ENOENT: 
30                 break;
31
32             default: 
33                 admonish (file, "unable to lock and open");
34                 break;
35         }
36         return 1;
37     }
38
39     i = annosbr (fd, file, comp, text, inplace, datesw);
40     lkclose (fd, file);
41     return i;
42 }
43
44
45 static int
46 annosbr (int fd, char *file, char *comp, char *text, int inplace, int datesw)
47 {
48     int mode, tmpfd;
49     char *cp, *sp;
50     char buffer[BUFSIZ], tmpfil[BUFSIZ];
51     struct stat st;
52     FILE *tmp;
53
54     mode = fstat (fd, &st) != NOTOK ? (st.st_mode & 0777) : m_gmprot ();
55
56     strncpy (tmpfil, m_scratch (file, "annotate"), sizeof(tmpfil));
57
58     if ((tmp = fopen (tmpfil, "w")) == NULL) {
59         admonish (tmpfil, "unable to create");
60         return 1;
61     }
62     chmod (tmpfil, mode);
63
64     if (datesw)
65         fprintf (tmp, "%s: %s\n", comp, dtimenow (0));
66     if ((cp = text)) {
67         do {
68             while (*cp == ' ' || *cp == '\t')
69                 cp++;
70             sp = cp;
71             while (*cp && *cp++ != '\n')
72                 continue;
73             if (cp - sp)
74                 fprintf (tmp, "%s: %*.*s", comp, cp - sp, cp - sp, sp);
75         } while (*cp);
76         if (cp[-1] != '\n' && cp != text)
77             putc ('\n', tmp);
78     }
79     fflush (tmp);
80     cpydata (fd, fileno (tmp), file, tmpfil);
81     fclose (tmp);
82
83     if (inplace) {
84         if ((tmpfd = open (tmpfil, O_RDONLY)) == NOTOK)
85             adios (tmpfil, "unable to open for re-reading");
86         lseek (fd, (off_t) 0, SEEK_SET);
87         cpydata (tmpfd, fd, tmpfil, file);
88         close (tmpfd);
89         unlink (tmpfil);
90     } else {
91         strncpy (buffer, m_backup (file), sizeof(buffer));
92         if (rename (file, buffer) == NOTOK) {
93             switch (errno) {
94                 case ENOENT:    /* unlinked early - no annotations */
95                     unlink (tmpfil);
96                     break;
97
98                 default:
99                     admonish (buffer, "unable to rename %s to", file);
100                     break;
101             }
102             return 1;
103         }
104         if (rename (tmpfil, file) == NOTOK) {
105             admonish (file, "unable to rename %s to", tmpfil);
106             return 1;
107         }
108     }
109
110     return 0;
111 }