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