]>
Commit | Line | Data |
---|---|---|
48fbc492 | 1 | /* |
2 | * Copyright 1987 by the Massachusetts Institute of Technology. For copying | |
3 | * and distribution information, see the file "mit-copyright.h". | |
4 | * | |
5 | * $Source$ | |
6 | * $Header$ | |
7 | * $Author$ | |
8 | * $Log$ | |
67655a21 | 9 | * Revision 1.2 1987-08-02 19:51:53 ambar |
10 | * changed from chhome to chpobox; added | |
11 | * #include "mit-copyright.h" | |
48fbc492 | 12 | * |
67655a21 | 13 | * Revision 1.1 87/08/02 19:47:52 ambar |
14 | * Initial revision | |
48fbc492 | 15 | * |
16 | */ | |
17 | ||
18 | #ifndef lint | |
67655a21 | 19 | static char *rcsid_chpobox_c = "$Header$"; |
48fbc492 | 20 | #endif not lint |
21 | ||
22 | /* | |
23 | * Talk to the SMS database to change a person's home mail machine. This may | |
24 | * be an Athena machine, or a completely arbitrary address. | |
25 | * | |
67655a21 | 26 | * chpobox with no modifiers reports all current mailboxes. |
48fbc492 | 27 | * |
67655a21 | 28 | * chpobox -a [address] means add (not replace) a mailbox to the ones |
48fbc492 | 29 | * the user already has. Complains if the user tries to give herself |
30 | * more than one mailbox of type pop. | |
31 | * | |
67655a21 | 32 | * chpobox -d [address] means delete the specified mailbox from the list. |
48fbc492 | 33 | * Complains if this would mean leaving the user with no mailbox at all. |
34 | * | |
67655a21 | 35 | * chpobox -u [user] is needed if you are logged in as one user, but |
48fbc492 | 36 | * are trying to change the email address of another. You must have |
37 | * Kerberos tickets as the person whose address you are trying to | |
38 | * change, or the attempt will fail. | |
39 | * | |
40 | * [address] must always have an @ sign in it. | |
41 | * | |
42 | */ | |
43 | ||
44 | #include <sys/types.h> | |
45 | #include <stdio.h> | |
46 | #include <pwd.h> | |
47 | #include <strings.h> | |
48 | #include <ctype.h> | |
49 | #include <netdb.h> | |
50 | #include <errno.h> | |
51 | ||
52 | /* SMS includes */ | |
53 | #include <sms.h> | |
54 | #include <sms_app.h> | |
67655a21 | 55 | #include "mit-copyright.h" |
48fbc492 | 56 | |
57 | char *getlogin(); | |
58 | char *malloc(); | |
59 | char *strcpy(); | |
60 | char *strcat(); | |
61 | char *whoami; | |
62 | ||
63 | int getopt(); | |
64 | int status; | |
65 | ||
66 | extern int h_errno; | |
67 | static int match; | |
68 | ||
69 | uid_t getuid(); | |
70 | ||
71 | #define DOMAIN ".MIT.EDU" | |
72 | #define NET_ADDRESS_SIZE 500 /* You would not believe the length of some | |
73 | * addresses.. */ | |
74 | main(argc, argv) | |
75 | char *argv[]; | |
76 | ||
77 | { | |
78 | struct passwd *pwd; | |
79 | struct pobox_values getnewmach(), pobox; | |
80 | char *smsarg[1], buf[BUFSIZ]; | |
81 | char *ds(), *trim(), *in(), *canon(); | |
82 | char *address, *uname, *machine; | |
83 | char **return_args, **crunch_pobox_args(); | |
84 | uid_t u; | |
85 | int get_machine(), scream(); | |
86 | int c, delflag, add, usageflag; | |
87 | ||
88 | extern int optind; | |
89 | extern char *optarg; | |
90 | ||
91 | init_sms_err_tbl(); | |
92 | init_krb_err_tbl(); | |
93 | c = delflag = add = usageflag = 0; | |
94 | address = uname = (char *) NULL; | |
95 | u = getuid(); | |
96 | ||
97 | if ((whoami = rindex(argv[0], '/')) == NULL) | |
98 | whoami = argv[0]; | |
99 | else | |
100 | whoami++; | |
101 | ||
102 | if (argc > 5) { | |
103 | usage(); | |
104 | } | |
105 | ||
106 | while ((c = getopt(argc, argv, "d:a:u:")) != EOF) | |
107 | switch (c) { | |
108 | ||
109 | case 'd': | |
110 | if (add) | |
111 | usageflag++; | |
112 | else { | |
113 | delflag++; | |
114 | address = ds(optarg); | |
115 | } | |
116 | break; | |
117 | case 'a': | |
118 | if (delflag) | |
119 | usageflag++; | |
120 | else { | |
121 | add++; | |
122 | address = ds(optarg); | |
123 | } | |
124 | break; | |
125 | case 'u': | |
126 | uname = ds(optarg); | |
127 | break; | |
128 | default: | |
129 | usageflag++; | |
130 | break; | |
131 | } | |
132 | if (argc == 2 && optind == 1 && !uname) { | |
133 | uname = argv[optind++]; | |
134 | } | |
135 | if (usageflag || optind != argc) { | |
136 | usage(); | |
137 | } | |
138 | if (!uname) { | |
139 | if ((uname = getlogin()) == NULL) { | |
140 | usage(); | |
141 | } | |
142 | if (uname[0] == '\0') { | |
143 | pwd = getpwuid((int) u); | |
144 | (void) strcpy(uname, pwd->pw_name); | |
145 | } | |
146 | } | |
147 | smsarg[0] = uname; | |
148 | ||
149 | status = sms_connect(); | |
150 | if (status) { | |
151 | (void) sprintf(buf, "\nConnection to SMS server failed."); | |
152 | goto punt; | |
153 | } | |
154 | ||
155 | status = sms_auth(); | |
156 | if (status) { | |
157 | (void) sprintf(buf, "\nAuthorization failed -- please \ | |
158 | run \"kinit\" and try again."); | |
159 | goto punt; | |
160 | } | |
161 | ||
162 | /* | |
163 | * set up some bogus arguments to feed to sms_access | |
164 | */ | |
165 | pobox.login = uname; | |
166 | pobox.type = "foreign"; | |
167 | pobox.box = "foo"; | |
168 | pobox.machine = "baz.bat.quux"; | |
169 | return_args = crunch_pobox_args(pobox); | |
170 | /* | |
171 | * do an access check. | |
172 | */ | |
173 | status = sms_access("add_pobox", 4, return_args); | |
174 | if (status) { | |
175 | (void) sprintf(buf, "\nUnauthorized attempt to modify %s's \ | |
176 | email address.", uname); | |
177 | goto punt; | |
178 | } | |
179 | /* | |
180 | * address, if it exists, is of form user@host. It needs to be split up. | |
181 | */ | |
182 | if (address) { | |
183 | machine = index(address, '@'); | |
184 | if (machine) { | |
185 | *machine++ = '\0'; /* get rid of the @ sign */ | |
186 | machine = trim(machine); /* get rid of whitespace */ | |
187 | } | |
188 | else { | |
189 | fprintf(stderr, "%s: no at sign (@) in address\n", | |
190 | whoami); | |
191 | sms_disconnect(); | |
192 | exit(1); | |
193 | } /* now machine points to the machine name, | |
194 | * and address points to the "box" name */ | |
195 | pobox.machine = canon(machine); /* canonicalize the machine name */ | |
196 | if (machine == (char *) NULL) { /* nameserver failed in canon */ | |
197 | (void) sprintf(buf, "\nNameserver transaction \ | |
198 | failed.\nI cannot change your mailbox at this time. Please try again \ | |
199 | later.\n"); | |
200 | goto punt; | |
201 | } | |
202 | pobox.type = in(pobox.machine); /* find out the type */ | |
203 | pobox.login = uname; /* whose is changing? */ | |
204 | pobox.box = address; /* to what mailbox? */ | |
205 | } | |
206 | ||
207 | if (add) { | |
208 | printf("\nAdding email address %s@%s for %s.", | |
209 | pobox.box, pobox.machine, uname); | |
210 | ||
211 | if (strcmp(pobox.type, "pop") == 0) { | |
212 | /* | |
213 | * check to be sure that they're not getting more than one. If | |
214 | * they are, punt. | |
215 | */ | |
216 | } | |
217 | return_args = crunch_pobox_args(pobox); | |
218 | status = sms_query("add_pobox", 4, return_args, scream, | |
219 | (char *) NULL); | |
220 | if (status) { | |
221 | (void) sprintf(buf, "\nWrite failed to SMS \ | |
222 | database."); | |
223 | goto punt; | |
224 | } | |
225 | printf("..done.\n"); | |
226 | sms_disconnect(); | |
227 | exit(0); | |
228 | } | |
229 | else if (delflag) { /* isn't yet checking to make sure that the | |
230 | * user isn't being left without a mailbox. */ | |
231 | printf("Deleting email address %s@%s for %s.", pobox.box, | |
232 | pobox.machine, uname); | |
233 | return_args = crunch_pobox_args(pobox); | |
234 | status = sms_query("delete_pobox", 4, return_args, scream, | |
235 | (char *) NULL); | |
236 | if (status) { | |
237 | (void) sprintf(buf, "\nWrite failed to SMS \ | |
238 | database."); | |
239 | goto punt; | |
240 | } | |
241 | printf("..done.\n"); | |
242 | sms_disconnect(); | |
243 | exit(0); | |
244 | } | |
245 | else { /* report all current poboxes */ | |
246 | printf("Current mail address(es) for %s is/are:", uname); | |
247 | status = sms_query("get_pobox", 1, smsarg, get_machine, | |
248 | (char *) &pobox); | |
249 | if (status) { | |
250 | if (status == SMS_NO_MATCH) | |
251 | printf(" None\n"); | |
252 | else { | |
253 | (void) sprintf(buf, "\nRetrieve from \ | |
254 | SMS database failed."); | |
255 | goto punt; | |
256 | } | |
257 | } | |
258 | } | |
259 | sms_disconnect(); | |
260 | exit(0); | |
261 | ||
262 | punt: | |
263 | com_err(whoami, status, buf); | |
264 | sms_disconnect(); | |
265 | exit(1); | |
266 | } | |
267 | ||
268 | scream() | |
269 | { | |
270 | com_err(whoami, status, "Unexpected return value from SMS -- \ | |
271 | programmer botch\n"); | |
272 | sms_disconnect(); | |
273 | exit(1); | |
274 | } | |
275 | ||
276 | /* | |
277 | * get_machine gets all your poboxes and displays them. | |
278 | */ | |
279 | ||
280 | /* ARGSUSED */ | |
281 | int | |
282 | get_machine(argc, argv, callarg) | |
283 | int argc; | |
284 | char **argv, *callarg; | |
285 | { | |
286 | struct pobox_values *pobox = (struct pobox_values *) callarg; | |
287 | ||
288 | pobox->type = ds(argv[1]); | |
289 | pobox->machine = ds(argv[2]); | |
290 | pobox->box = ds(argv[3]); | |
291 | ||
292 | printf("\ntype: %s\naddress: %s@%s\n", pobox->type, | |
293 | pobox->box, pobox->machine); | |
294 | return (0); | |
295 | } | |
296 | ||
297 | char * | |
298 | ds(str) | |
299 | char *str; | |
300 | { | |
301 | register char *newstr = malloc((unsigned) strlen(str) + 1); | |
302 | ||
303 | if (newstr == (char *) NULL) | |
304 | return ((char *) NULL); | |
305 | else | |
306 | return (strcpy(newstr, str)); | |
307 | } | |
308 | ||
309 | char ** | |
310 | crunch_pobox_args(in) | |
311 | struct pobox_values in; | |
312 | { | |
313 | char **out; | |
314 | ||
315 | out = (char **) malloc((unsigned) sizeof(char *) * 4); | |
316 | out[0] = in.login; | |
317 | out[1] = in.type; | |
318 | out[2] = in.machine; | |
319 | out[3] = in.box; | |
320 | return (out); | |
321 | } | |
322 | ||
323 | /* | |
324 | * Trim whitespace off of cp. Side-effects cp. | |
325 | */ | |
326 | char * | |
327 | trim(cp) | |
328 | register char *cp; | |
329 | { | |
330 | register char *ep; | |
331 | ||
332 | while (isspace(*cp)) | |
333 | cp++; | |
334 | ep = cp; | |
335 | while (*ep) | |
336 | ep++; | |
337 | if (ep > cp) { | |
338 | for (--ep; isspace(*ep); --ep) | |
339 | continue; | |
340 | ep++; | |
341 | *ep = '\0'; | |
342 | } | |
343 | return cp; | |
344 | } | |
345 | ||
346 | /* | |
347 | * given a canonicalized machine name, ask the SMS server if it is of type | |
348 | * pop, or of type local -- if neither, we assume that it's of type foreign. | |
349 | */ | |
350 | char * | |
351 | in(machine) | |
352 | char *machine; | |
353 | { | |
354 | char *service[1], buf[BUFSIZ]; | |
355 | int check_match(); | |
356 | ||
357 | match = 0; | |
358 | service[0] = ds("pop"); | |
359 | status = sms_query("get_server_locations", 1, service, | |
360 | check_match, machine); | |
361 | if (status && (status != SMS_NO_MATCH)) { | |
362 | (void) sprintf(buf, "\nRead failed from SMS \ | |
363 | database."); | |
364 | goto punt; | |
365 | } | |
366 | if (match) | |
367 | return ("pop"); | |
368 | ||
369 | service[0] = ds("local"); | |
370 | status = sms_query("get_server_locations", 1, service, | |
371 | check_match, machine); | |
372 | if (status && (status != SMS_NO_MATCH)) { | |
373 | (void) sprintf(buf, "\nRead failed from SMS \ | |
374 | database."); | |
375 | goto punt; | |
376 | } | |
377 | if (match) | |
378 | return ("local"); | |
379 | else | |
380 | return ("foreign"); | |
381 | punt: | |
382 | com_err(whoami, status, buf); | |
383 | sms_disconnect(); | |
384 | exit(1); | |
385 | } | |
386 | ||
387 | /* ARGSUSED */ | |
388 | int | |
389 | check_match(argc, argv, callback) | |
390 | int argc; | |
391 | char **argv, *callback; | |
392 | { | |
393 | if (match) | |
394 | return (0); | |
395 | ||
396 | if (strcmp(argv[1], callback) == 0) | |
397 | match = 1; | |
398 | ||
399 | return (0); | |
400 | } | |
401 | ||
402 | /* | |
403 | * given a machine name, canonicalize it and return it. Returns (char *) | |
404 | * NULL if the nameserver returns any error. | |
405 | */ | |
406 | char * | |
407 | canon(machine) | |
408 | char *machine; | |
409 | { | |
410 | struct hostent *hostinfo; | |
411 | ||
412 | hostinfo = gethostbyname(machine); | |
413 | if (hostinfo != (struct hostent *) NULL) | |
414 | machine = hostinfo->h_name; | |
415 | else /* gethostbyname failed; this should be very | |
416 | * rare, since we're dealing with local | |
67655a21 | 417 | * hosts, so no fancy error recovery. |
418 | */ | |
48fbc492 | 419 | machine = (char *) NULL; |
420 | return (machine); | |
421 | } | |
422 | ||
423 | usage() | |
424 | { | |
425 | fprintf(stderr, "Usage: %s [-d|a address] [-u user]\n", whoami); | |
426 | exit(1); | |
427 | } | |
428 | ||
429 | /* | |
430 | * Local Variables: | |
431 | * mode: c | |
432 | * c-indent-level: 4 | |
433 | * c-continued-statement-offset: 4 | |
434 | * c-brace-offset: -4 | |
435 | * c-argdecl-indent: 4 | |
436 | * c-label-offset: -4 | |
437 | * End: | |
438 | */ |