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