]> andersk Git - moira.git/blob - gen/letter.dc
1ab107fdec0b60357efbdf73c2d94d7bc51025b9
[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], first[17], last[17], fullname[34], addr[84];
39     int lastrun, when;
40     EXEC SQL END DECLARE SECTION;
41
42 #ifsql INGRES
43     EXEC SQL CONNECT moira;
44     EXEC SQL SET LOCKMODE SESSION WHERE LEVEL=TABLE, READLOCK=SHARED;
45 #endsql
46 #ifsql INFORMIX
47     EXEC SQL DATABASE moira;
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
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      */
79     EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
80
81     EXEC SQL SELECT secure INTO :lastrun FROM users WHERE users_id = 0;
82
83     gettimeofday(&tv, NULL);
84
85     EXEC SQL DECLARE x CURSOR FOR SELECT 
86       login, first, last, xaddress, secure
87         FROM users WHERE secure > :lastrun;
88     EXEC SQL OPEN x;
89     while (1) {
90         EXEC SQL FETCH x INTO :login, :first, :last, :addr, :when;
91         if (sqlca.sqlcode != 0) break;
92         strtrim(login);
93         strtrim(first);
94         strtrim(last);
95         sprintf(fullname, "%s %s", first, last);
96         print_letter(out, login, fullname, strtrim(addr), when);
97     }
98
99     EXEC SQL CLOSE x;
100
101     lastrun = tv.tv_sec;
102     EXEC SQL UPDATE users SET secure = :lastrun WHERE users_id = 0;
103
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);
117
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
128 char *letter_text;
129
130
131 /* Read the template into a buffer */
132
133 init_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
163 print_letter(out, login, fullname, addr, when)
164 FILE *out;
165 char *login, *fullname, *addr;
166 int when;
167 {
168     register char *p;
169     char buf[256], *a1, *a2, *d;
170     char *rindex(), *index();
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;
179     if (a2 = index(buf, '|')) {
180         *a2++ = 0;
181     } else {
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         }
203     }
204
205     d = ctime(&when);
206     d[strlen(d)-1] = 0;
207
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':
235                 fputs(d, out);
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.133838 seconds and 3 git commands to generate.