]> andersk Git - moira.git/blob - clients/passwd/chpobox.c
document changed registering behavior
[moira.git] / clients / passwd / chpobox.c
1 /* $Id$
2  *
3  * Talk to the Moira database to change a person's home mail machine. This may
4  * be an Athena machine, or a completely arbitrary address.
5  *
6  * chpobox with no modifiers reports the current mailbox.
7  *
8  * chpobox -s [address] means set the mailbox to this address.
9  *
10  * chpobox -p restores the pobox to a previous POP box, if there was one.
11  *
12  * chpobox -u [user] is needed if you are logged in as one user, but
13  * are trying to change the email address of another.  You must have
14  * Kerberos tickets as the person whose address you are trying to
15  * change, or the attempt will fail.
16  *
17  * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
18  * For copying and distribution information, please see the file
19  * <mit-copyright.h>.
20  */
21
22 #include <mit-copyright.h>
23 #include <moira.h>
24 #include <moira_site.h>
25
26 #include <pwd.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include <krb.h>
33
34 RCSID("$Header$");
35
36 int get_pobox(int argc, char **argv, void *callarg);
37 char *potype(char *machine);
38 int check_match(int argc, char **argv, void *callback);
39 int check_match3(int argc, char **argv, void *callback);
40 int usage(void);
41
42 char *whoami;
43
44 static int match;
45
46 int main(int argc, char *argv[])
47 {
48   struct passwd *pwd;
49   char *mrarg[3], buf[BUFSIZ], pname[ANAME_SZ];
50   char *address, *uname, *machine, *motd;
51   uid_t u;
52   int c, setflag, prevpop, usageflag, status;
53
54   extern int optind;
55   extern char *optarg;
56
57   c = setflag = prevpop = usageflag = 0;
58   address = uname = NULL;
59   u = getuid();
60
61   if ((whoami = strrchr(argv[0], '/')) == NULL)
62     whoami = argv[0];
63   else
64     whoami++;
65
66   if (argc > 5)
67     usage();
68
69   while ((c = getopt(argc, argv, "s:pu:")) != -1)
70     switch (c)
71       {
72       case 's':
73         if (prevpop)
74           usageflag++;
75         else
76           {
77             setflag++;
78             strcpy(buf, optarg);
79             address = buf;
80           }
81         break;
82       case 'p':
83         if (setflag)
84           usageflag++;
85         else
86           prevpop++;
87         break;
88       case 'u':
89         uname = strdup(optarg);
90         break;
91       default:
92         usageflag++;
93         break;
94       }
95   if (argc == 2 && optind == 1 && !uname)
96     uname = argv[optind++];
97
98   if (usageflag || optind != argc)
99     usage();
100
101   if (!uname)
102     {
103       if ((status = tf_init(TKT_FILE, R_TKT_FIL)) ||
104           (status = tf_get_pname(pname)))
105         {
106           com_err(whoami, status, "reading Kerberos ticket file");
107           exit(1);
108         }
109       tf_close();
110       uname = pname;
111     }
112   mrarg[0] = uname;
113
114   status = mr_connect(NULL);
115   if (status)
116     {
117       com_err(whoami, status, " while connecting to Moira");
118       exit(1);
119     }
120
121   status = mr_motd(&motd);
122   if (status)
123     {
124       mr_disconnect();
125       com_err(whoami, status, " unable to check server status");
126       exit(1);
127     }
128   if (motd)
129     {
130       fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
131               motd);
132       mr_disconnect();
133       exit(1);
134     }
135
136   status = mr_auth("chpobox");
137   if (status)
138     {
139       com_err(whoami, status, " while authenticating -- "
140               "run \"kinit\" and try again.");
141       mr_disconnect();
142       exit(1);
143     }
144
145   if (setflag)
146     {
147       /* Address is of form user@host.  Split it up. */
148       if (!address)
149         {
150           fprintf(stderr, "%s: no address was specified.\n", whoami);
151           goto show;
152         }
153       machine = strchr(address, '@');
154       if (machine)
155         {
156           *machine++ = '\0';            /* get rid of the @ sign */
157           machine = strtrim(machine);   /* get rid of whitespace */
158         }
159       else
160         {
161           fprintf(stderr, "%s: no at sign (@) in address \"%s\"\n",
162                   whoami, address);
163           goto show;
164         }
165       mrarg[2] = canonicalize_hostname(strdup(machine));
166       mrarg[1] = potype(mrarg[2]);
167       if (!strcmp(mrarg[1], "POP"))
168         {
169           if (strcmp(address, uname))
170             {
171               fprintf(stderr,
172                       "%s: the name on the POP box must match the username\n",
173                       whoami);
174               goto show;
175             }
176         }
177       else if (!strcmp(mrarg[1], "LOCAL"))
178         {
179           strcat(address, "@");
180           strcat(address, mrarg[2]);
181           mrarg[2] = address;
182           if ((address = strchr(address, '@')) &&
183               (address = strchr(address, '.')))
184             *address = 0;
185           strcat(mrarg[2], ".LOCAL");
186           mrarg[1] = "SMTP";
187         }
188       else if (!strcmp(mrarg[1], "MAILHUB"))
189         {
190           if (!strcmp(address, uname))
191             {
192               fprintf(stderr,
193                       "Error: this will set a mail forwarding loop.\n");
194               fprintf(stderr,
195                       "Use \"%s -p\" to set a local post office server.\n",
196                       whoami);
197               exit(1);
198             }
199           fprintf(stderr, "Error: \"%s@%s\" is a local mail address.\n",
200                   address, machine);
201           fprintf(stderr, "Your mail drop must be on a post office server "
202                   "or an external mail address.\n");
203           exit(1);
204         }
205       else if (mrarg[1])
206         {
207           if (*machine != '"' && strcasecmp(mrarg[2], machine))
208             {
209               fprintf(stderr, "Warning: hostname %s canonicalized to %s\n",
210                       machine, mrarg[2]);
211             }
212           strcat(address, "@");
213           strcat(address, mrarg[2]);
214           mrarg[2] = address;
215         } else
216           goto show;
217       status = mr_query("set_pobox", 3, mrarg, NULL, NULL);
218       if (status)
219         com_err(whoami, status,
220                 " while setting pobox for %s to type %s, box %s",
221                 mrarg[0], mrarg[1], mrarg[2]);
222     }
223   else if (prevpop)
224     {
225       status = mr_query("set_pobox_pop", 1, mrarg, NULL, NULL);
226       if (status == MR_MACHINE)
227         {
228           fprintf(stderr,
229                   "Moira has no record of a previous POP box for %s\n", uname);
230         }
231       else if (status != 0)
232         com_err(whoami, status, " while setting pobox");
233     }
234
235   /*
236    * get current box
237    */
238 show:
239   status = mr_query("get_pobox", 1, mrarg, get_pobox, NULL);
240   if (status == MR_NO_MATCH)
241     printf("User %s has no pobox.\n", uname);
242   else if (status != 0)
243     com_err(whoami, status, " while retrieving current mailbox");
244   mr_disconnect();
245   exit(0);
246 }
247
248
249 /*
250  * get_pobox gets all your poboxes and displays them.
251  */
252
253 int get_pobox(int argc, char **argv, void *callarg)
254 {
255   if (!strcmp(argv[1], "POP"))
256     printf("User %s, Type %s, Box: %s@%s\n",
257            argv[0], argv[1], argv[0], argv[2]);
258   else
259     printf("User %s, Type %s, Box: %s\n",
260            argv[0], argv[1], argv[2]);
261   printf("  Modified by %s on %s with %s\n", argv[4], argv[3], argv[5]);
262   return 0;
263 }
264
265 /*
266  * given a canonicalized machine name, ask the Moira server if it is of type
267  * pop, or of type local -- if neither, we assume that it's of type foreign.
268  */
269 char *potype(char *machine)
270 {
271   char *service[1], *argv[3];
272   int status;
273
274   match = 0;
275   service[0] = "POP";
276   status = mr_query("get_server_locations", 1, service, check_match, machine);
277   if (status && (status != MR_NO_MATCH))
278     {
279       com_err(whoami, status, " while reading list of POP servers");
280       return NULL;
281     }
282   if (match)
283     return "POP";
284
285   service[0] = "LOCAL";
286   status = mr_query("get_server_locations", 1, service, check_match, machine);
287   if (status && (status != MR_NO_MATCH))
288     {
289       com_err(whoami, status, " while reading list of LOCAL servers");
290       return NULL;
291     }
292   if (match)
293     return "LOCAL";
294
295   argv[0] = "mailhub";
296   argv[1] = "TYPE";
297   argv[2] = "*";
298   status = mr_query("get_alias", 3, argv, check_match3, machine);
299   if (status && (status != MR_NO_MATCH))
300     {
301       com_err(whoami, status, " while reading list of MAILHUB servers");
302       return NULL;
303     }
304   if (match)
305     return "MAILHUB";
306   else
307     return "SMTP";
308 }
309
310 int check_match(int argc, char **argv, void *callback)
311 {
312   if (match)
313     return 0;
314
315   if (!strcasecmp(argv[1], callback))
316     match = 1;
317
318   return 0;
319 }
320
321 int check_match3(int argc, char **argv, void *callback)
322 {
323   if (match)
324     return 0;
325
326   if (!strcasecmp(argv[2], callback))
327     match = 1;
328
329   return 0;
330 }
331
332 int usage(void)
333 {
334   fprintf(stderr, "Usage: %s [-s address] [-p] [-u user]\n", whoami);
335   exit(1);
336 }
This page took 0.067143 seconds and 5 git commands to generate.