]> andersk Git - moira.git/blob - gen/letter.dc
Added warning comment before WHENEVER.
[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 #endsql
45 #ifsql INFORMIX
46     EXEC SQL DATABASE moira;
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     /* The following is declarative, not executed,
75      * and so is dependent on where it is in the file,
76      * not in the order of execution of statements.
77      */
78     EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
79
80     EXEC SQL SELECT secure INTO :lastrun FROM users WHERE users_id = 0;
81
82     gettimeofday(&tv, NULL);
83
84     EXEC SQL DECLARE x CURSOR FOR SELECT 
85       login, first, last, xaddress, secure
86         FROM users WHERE secure > :lastrun;
87     EXEC SQL OPEN x;
88     while (1) {
89         EXEC SQL FETCH x INTO :login, :first, :last, :addr, :when;
90         if (sqlca.sqlcode != 0) break;
91         strtrim(login);
92         strtrim(first);
93         strtrim(last);
94         sprintf(fullname, "%s %s", first, last);
95         print_letter(out, login, fullname, strtrim(addr), when);
96     }
97
98     EXEC SQL CLOSE x;
99
100     lastrun = tv.tv_sec;
101     EXEC SQL UPDATE users SET secure = :lastrun WHERE users_id = 0;
102
103 #ifsql INGRES
104     EXEC SQL DISCONNECT;
105 #endsql
106 #ifsql INFORMIX
107     EXEC SQL CLOSE DATABASE;
108 #endsql
109
110     if (fclose(out)) {
111         perror("close failed");
112         exit(MR_CCONFIG);
113     }
114     if (outf)
115       fix_file(outf);
116     exit(MR_SUCCESS);
117
118  sqlerr:
119     com_err(whoami, MR_INGRES_ERR, " code %d\n", sqlca.sqlcode);
120     critical_alert("DCM", "Letter build encountered INGRES ERROR %d",
121                    sqlca.sqlcode);
122     exit(MR_INGRES_ERR);
123 }
124
125
126 char *letter_text;
127
128
129 /* Read the template into a buffer */
130
131 init_letter()
132 {
133     int fd;
134     char filename[256];
135     struct stat stbuf;
136
137     sprintf(filename, "%s/%s", DCM_DIR, LETTER);
138     if ((fd = open(filename, O_RDONLY, 0)) < 0) {
139         com_err(whoami, MR_OCONFIG, " opening letter template %s", filename);
140         exit(MR_OCONFIG);
141     }
142     if (fstat(fd, &stbuf)) {
143         com_err(whoami, MR_OCONFIG, " stating letter template %s", filename);
144         exit(MR_OCONFIG);
145     }
146     if ((letter_text = (char *)malloc(stbuf.st_size + 1)) == NULL) {
147         com_err(whoami, MR_NO_MEM, " reading letter template");
148         exit(MR_NO_MEM);
149     }
150     if (read(fd, letter_text, stbuf.st_size) < stbuf.st_size) {
151         com_err(whoami, MR_OCONFIG, " unable to read all of letter");
152         exit(MR_OCONFIG);
153     }
154     letter_text[stbuf.st_size] = 0;
155     close(fd);
156 }
157
158
159 /* Print out a copy of the letter */
160
161 print_letter(out, login, fullname, addr, when)
162 FILE *out;
163 char *login, *fullname, *addr;
164 int when;
165 {
166     register char *p;
167     char buf[256], *a1, *a2, *d;
168     char *rindex();
169
170     /* split address into two lines.
171      * First determine if postal or interdepartmental address.
172      * Postal addreses end in state & zip code, as in "MA02139"
173      * Anything else, assume interdepartmental.
174      */
175     strcpy(buf, addr);
176     a1 = buf;
177     a2 = rindex(buf, ' ');      /* before state & zip */
178     if (a2 && isupper(a2[1]) && isupper(a2[2]) &&
179         isdigit(a2[3]) && isdigit(a2[4]) && isdigit(a2[5]) &&
180         isdigit(a2[6]) && isdigit(a2[7])) {
181         /* Must be postal address. */
182         /* missing space between state & zip, fix */
183         for (p = a2; *p; p++);          /* find end of string */
184         for (p--; isdigit(*p); p--)
185           p[2] = p[1];
186         p[2] = p[1];
187         p[1] = ' ';
188         /* Backup to previous space, start of state */
189         for (; *a2 != ' '; a2--);
190         /* Backup to previous space, start of city */
191         for (a2--; *a2 != ' '; a2--);
192         /* terminate first line, leave a2 pointing at second */
193         *a2++ = 0;
194     } else {
195         /* Must be interdepartmental */
196         a2 = "MIT INTERDEPARTMENTAL MAIL";
197     }
198     d = ctime(&when);
199     d[strlen(d)-1] = 0;
200
201     for (p = letter_text; *p; p++) {
202         if (*p == '%') {
203             p++;
204             switch (*p) {
205             case 'l':
206                 fputs(login, out);
207                 break;
208             case 'n':
209                 fputs(fullname, out);
210                 break;
211             case 'A':
212                 fputs(addr, out);
213                 break;
214             case 'a':
215                 p++;
216                 switch (*p) {
217                 case '1':
218                     fputs(a1, out);
219                     break;
220                 case '2':
221                     fputs(a2, out);
222                     break;
223                 default:
224                     fputs(addr, out);
225                 }
226                 break;
227             case 'd':
228                 fputs(d, out);
229                 break;
230             default:
231                 putc('%', out);
232                 putc(*p, out);
233             }
234         } else
235           putc(*p, out);
236     }
237     fflush(out);
238 }
This page took 0.054763 seconds and 5 git commands to generate.