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