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