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