]> andersk Git - moira.git/blob - gen/letter.dc
update lastrun calc
[moira.git] / gen / letter.dc
1 /* $Header$
2  *
3  * This generates confirmation letters to people who recently set
4  * their secure instance passwords.
5  *
6  *  (c) Copyright 1992 by the Massachusetts Institute of Technology.
7  *  For copying and distribution information, please see the file
8  *  <mit-copyright.h>.
9  */
10
11 #include <mit-copyright.h>
12 #include <stdio.h>
13 #include <moira.h>
14 #include <moira_site.h>
15 #include <ctype.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/time.h>
19 #include <sys/file.h>
20 EXEC SQL INCLUDE sqlca;
21
22 #define LETTER "letter.template"
23
24 extern int errno;
25 char *whoami = "letter.gen";
26
27
28 main(argc, argv)
29 int argc;
30 char **argv;
31 {
32     FILE *out = stdout;
33     char *outf = NULL, outft[64];
34     struct stat sb;
35     int flag;
36     struct timeval tv;
37     EXEC SQL BEGIN DECLARE SECTION;
38     char login[10], fullname[34], addr[84];
39     int lastrun, when;
40     EXEC SQL END DECLARE SECTION;
41
42 #ifsql INGRES
43     EXEC SQL CONNECT sms;
44 #endsql
45 #ifsql INFORMIX
46     EXEC SQL DATABASE sms;
47 #endsql
48
49     if (argc == 2) {
50         if (stat(argv[1], &sb) == 0) {
51             if (ModDiff (&flag, "users", sb.st_mtime))
52               exit(MR_DATE);
53             if (flag < 0) {
54                 fprintf(stderr, "File %s does not need to be rebuilt.\n",
55                         argv[1]);
56                 exit(MR_NO_CHANGE);
57             }
58         }
59         outf = argv[1];
60         sprintf(outft, "%s~", outf);
61         if ((out = fopen(outft, "w")) == NULL) {
62             fprintf(stderr, "unable to open %s for output\n", outf);
63             exit(MR_OCONFIG);
64         }
65     } else if (argc != 1) {
66         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
67         exit(MR_ARGS);
68     } else {
69         outf = NULL;
70     }
71
72     init_letter();
73
74     EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
75
76     EXEC SQL SELECT secure INTO :lastrun FROM users WHERE users_id = 0;
77
78     gettimeofday(&tv, NULL);
79
80     EXEC SQL DECLARE x CURSOR FOR SELECT 
81       login, fullname, xaddress, secure
82         FROM users WHERE secure > :lastrun;
83     EXEC SQL OPEN x;
84     while (1) {
85         EXEC SQL FETCH x INTO :login, :fullname, :addr, :when;
86         if (sqlca.sqlcode != 0) break;
87         strtrim(login);
88         strtrim(fullname);
89         print_letter(out, login, fullname, strtrim(addr), when);
90     }
91
92     EXEC SQL CLOSE x;
93
94     lastrun = tv.tv_sec;
95     EXEC SQL UPDATE users SET secure = :lastrun WHERE users_id = 0;
96
97 #ifsql INGRES
98     EXEC SQL DISCONNECT;
99 #endsql
100 #ifsql INFORMIX
101     EXEC SQL CLOSE DATABASE;
102 #endsql
103
104     if (fclose(out)) {
105         perror("close failed");
106         exit(MR_CCONFIG);
107     }
108     if (outf)
109       fix_file(outf);
110     exit(MR_SUCCESS);
111
112  sqlerr:
113     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
114     critical_alert("DCM", "Letter build encountered INGRES ERROR %d",
115                    sqlca.sqlcode);
116     exit(MR_INGRES_ERR);
117 }
118
119
120 char *letter_text;
121
122
123 /* Read the template into a buffer */
124
125 init_letter()
126 {
127     int fd;
128     char filename[256];
129     struct stat stbuf;
130
131     sprintf(filename, "%s/%s", DCM_DIR, LETTER);
132     if ((fd = open(filename, O_RDONLY, 0)) < 0) {
133         com_err(whoami, MR_OCONFIG, " opening letter template %s", filename);
134         exit(MR_OCONFIG);
135     }
136     if (fstat(fd, &stbuf)) {
137         com_err(whoami, MR_OCONFIG, " stating letter template %s", filename);
138         exit(MR_OCONFIG);
139     }
140     if ((letter_text = (char *)malloc(stbuf.st_size + 1)) == NULL) {
141         com_err(whoami, MR_NO_MEM, " reading letter template");
142         exit(MR_NO_MEM);
143     }
144     if (read(fd, letter_text, stbuf.st_size) < stbuf.st_size) {
145         com_err(whoami, MR_OCONFIG, " unable to read all of letter");
146         exit(MR_OCONFIG);
147     }
148     letter_text[stbuf.st_size] = 0;
149     close(fd);
150 }
151
152
153 /* Print out a copy of the letter */
154
155 print_letter(out, login, fullname, addr, when)
156 FILE *out;
157 char *login, *fullname, *addr;
158 int when;
159 {
160     register char *p;
161     char buf[256], *a1, *a2;
162     char *rindex();
163
164     /* split address into two lines.
165      * First determine if postal or interdepartmental address.
166      * Postal addreses end in state & zip code, as in "MA02139"
167      * Anything else, assume interdepartmental.
168      */
169     strcpy(buf, addr);
170     a1 = buf;
171     a2 = rindex(buf, ' ');      /* before state & zip */
172     if (a2 && isupper(a2[1]) && isupper(a2[2]) &&
173         isdigit(a2[3]) && isdigit(a2[4]) && isdigit(a2[5]) &&
174         isdigit(a2[6]) && isdigit(a2[7])) {
175         /* Must be postal address. */
176         /* missing space between state & zip, fix */
177         for (p = a2; *p; p++);          /* find end of string */
178         for (p--; isdigit(*p); p--)
179           p[2] = p[1];
180         p[1] = ' ';
181         /* Backup to previous space, start of state */
182         for (; *a2 != ' '; a2--);
183         /* Backup to previous space, start of city */
184         for (a2--; *a2 != ' '; a2--);
185         /* terminate first line, leave a2 pointing at second */
186         *a2++ = 0;
187     } else {
188         /* Must be interdepartmental */
189         a2 = "MIT INTERDEPARTMENTAL MAIL";
190     }
191
192     for (p = letter_text; *p; p++) {
193         if (*p == '%') {
194             p++;
195             switch (*p) {
196             case 'l':
197                 fputs(login, out);
198                 break;
199             case 'n':
200                 fputs(fullname, out);
201                 break;
202             case 'A':
203                 fputs(addr, out);
204                 break;
205             case 'a':
206                 p++;
207                 switch (*p) {
208                 case '1':
209                     fputs(a1, out);
210                     break;
211                 case '2':
212                     fputs(a2, out);
213                     break;
214                 default:
215                     fputs(addr, out);
216                 }
217                 break;
218             case 'd':
219                 fputs(ctime(&when), out);
220                 break;
221             case '%':
222                 putc('%', out);
223                 break;
224             default:
225                 putc('%', out);
226                 putc(*p, out);
227             }
228         } else
229           putc(*p, out);
230     }
231     fflush(out);
232 }
This page took 0.053085 seconds and 5 git commands to generate.