]> andersk Git - moira.git/blob - clients/passwd/chfn.c
second code style cleanup: void/void * usage, proper #includes. try to
[moira.git] / clients / passwd / chfn.c
1 /* $Id $
2  *
3  * Talk to the Moira database to change a person's GECOS information.
4  *
5  * chfn with no modifiers changes the information of the user who is
6  * running the program.
7  *
8  * If a commandline argument is given, it is taken to be the username
9  * of the user whose information is to be changed.
10  *
11  * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology
12  * For copying and distribution information, please see the file
13  * <mit-copyright.h>.
14  */
15
16 #include <mit-copyright.h>
17 #include <moira.h>
18 #include <moira_site.h>
19
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 #include <krb.h>
25
26 RCSID("$Header$");
27
28 #define FALSE 0
29 #define TRUE 1
30
31 char *whoami;
32
33 struct finger_info {
34   char *fullname;
35   char *nickname;
36   char *home_address;
37   char *home_phone;
38   char *office_address;
39   char *office_phone;
40   char *mit_department;
41   char *mit_year;
42 };
43
44 int usage(void);
45 int leave(int status);
46 int chfn(char *uname);
47 int get_user_info(int argc, char *argv[], void *message);
48 char *ask(char *question, char *def_val, int phone_num);
49 void get_new_info(struct finger_info *old_info, struct finger_info *new_info);
50
51 int main(int argc, char *argv[])
52 {
53   char pname[ANAME_SZ];
54   char *uname = pname;
55   int k_errno;
56
57   initialize_krb_error_table();
58
59   if ((whoami = strrchr(argv[0], '/')) == NULL)
60     whoami = argv[0];
61   else
62     whoami++;
63
64   if (argc > 2)
65     usage();
66
67   if (argc == 2)
68     uname = argv[1];
69   else
70     {
71       /* Do it right; get name from kerberos ticket file rather than
72          from passord file. */
73
74       if ((k_errno = tf_init(TKT_FILE, R_TKT_FIL)))
75         {
76           com_err(whoami, k_errno, "reading ticket file");
77           exit(1);
78         }
79
80       if ((k_errno = tf_get_pname(pname)))
81         {
82           com_err(whoami, k_errno, "getting kerberos principal name");
83           exit(1);
84         }
85
86       tf_close();
87     }
88
89   exit(chfn(uname));
90 }
91
92 /* This should be called rather than exit once connection to moira server
93    has been established. */
94 int leave(int status)
95 {
96   mr_disconnect();
97   exit(status);
98 }
99
100 int chfn(char *uname)
101 {
102   int status;                   /* general purpose exit status */
103   int q_argc;                   /* argc for mr_query */
104   char *q_argv[F_END];          /* argv for mr_query */
105   char *motd;                   /* for Moira server status */
106   int i;
107
108   struct finger_info old_info;
109   struct finger_info new_info;
110
111   /* Try each query.  If we ever fail, print error message and exit. */
112
113   status = mr_connect(NULL);
114   if (status)
115     {
116       com_err(whoami, status, "while connecting to Moira");
117       exit(1);
118     }
119
120   status = mr_motd(&motd);
121   if (status)
122     {
123       com_err(whoami, status, "unable to check server status");
124       leave(1);
125     }
126   if (motd)
127     {
128       fprintf(stderr, "The Moira server is currently unavailable:\n%s\n",
129               motd);
130       leave(1);
131     }
132
133   status = mr_auth("chfn");     /* Don't use argv[0] - too easy to fake */
134   if (status)
135     {
136       com_err(whoami, status,
137               "while authenticating -- run \"kinit\" and try again.");
138       leave(1);
139     }
140
141   /* First, do an access check. */
142
143   q_argv[F_NAME] = uname;
144   for (i = F_NAME + 1; i < F_MODTIME; i++)
145     q_argv[i] = "junk";
146   q_argc = F_MODTIME;           /* one more than the last updatable field */
147
148   if ((status = mr_access("update_finger_by_login", q_argc, q_argv)))
149     {
150       com_err(whoami, status, "; finger\ninformation not changed.");
151       leave(2);
152     }
153
154   printf("Changing finger information for %s.\n", uname);
155
156   /* Get information */
157
158   q_argv[NAME] = uname;
159   q_argc = NAME + 1;
160   if ((status = mr_query("get_finger_by_login", q_argc, q_argv,
161                          get_user_info, &old_info)))
162     {
163       com_err(whoami, status, "while getting user information.");
164       leave(2);
165     }
166
167   /* Get the new information from the user */
168
169   get_new_info(&old_info, &new_info);
170
171   /* Do the update */
172
173   printf("Changing finger information...\n");
174
175   q_argv[F_NAME] = uname;
176   q_argv[F_FULLNAME] = new_info.fullname;
177   q_argv[F_NICKNAME] = new_info.nickname;
178   q_argv[F_HOME_ADDR] = new_info.home_address;
179   q_argv[F_HOME_PHONE] = new_info.home_phone;
180   q_argv[F_OFFICE_ADDR] = new_info.office_address;
181   q_argv[F_OFFICE_PHONE] = new_info.office_phone;
182   q_argv[F_MIT_DEPT] = new_info.mit_department;
183   q_argv[F_MIT_AFFIL] = new_info.mit_year;
184   q_argc = F_MODTIME;           /* First non-update query argument */
185
186   if ((status = mr_query("update_finger_by_login", q_argc, q_argv,
187                          NULL, NULL)))
188     {
189       com_err(whoami, status, "while updating finger information.");
190       leave(1);
191     }
192
193   printf("Finger information updated succesfully.\n");
194
195   return 0;
196 }
197
198 int get_user_info(int argc, char *argv[], void *message)
199 {
200   struct finger_info *old_info = message;
201
202   if (argc != F_END)
203     {
204       fprintf(stderr, "Some internal error occurred; try again.\n");
205       leave(3);
206     }
207
208   printf("Info last changed on %s by user %s with %s.\n",
209          argv[F_MODTIME], argv[F_MODBY], argv[F_MODWITH]);
210
211   old_info->fullname = strdup(argv[F_FULLNAME]);
212   old_info->nickname = strdup(argv[F_NICKNAME]);
213   old_info->home_address = strdup(argv[F_HOME_ADDR]);
214   old_info->home_phone = strdup(argv[F_HOME_PHONE]);
215   old_info->office_address = strdup(argv[F_OFFICE_ADDR]);
216   old_info->office_phone = strdup(argv[F_OFFICE_PHONE]);
217   old_info->mit_department = strdup(argv[F_MIT_DEPT]);
218   old_info->mit_year = strdup(argv[F_MIT_AFFIL]);
219
220   /* Only pay attention to the first match since login names are
221      unique in the database. */
222   return MR_ABORT;
223 }
224
225 char *ask(char *question, char *def_val, int phone_num)
226 {
227   static char buf[BUFSIZ];
228   int ok = FALSE;
229   char *result;
230   int i;
231   int dashes = FALSE;
232
233 #define BLANK "none"
234
235   while (!ok)
236     {
237       ok = TRUE;
238       printf("%s [%s]: ", question, def_val);
239       if (!fgets(buf, sizeof(buf), stdin))
240         leave(0);
241       buf[strlen(buf) - 1] = '\0';
242       if (strlen(buf) == 0)
243         result = def_val;
244       else if (!strcasecmp(buf, BLANK))
245         result = "";
246       else
247         result = buf;
248
249       for (i = 0; i < strlen(buf); i++)
250         {
251           switch (buf[i])
252             {
253             case '"':
254               printf("'\"' is not allowed.\n");
255               ok = FALSE;
256               break;
257             case ',':
258               printf("',' is not allowed.\n");
259               ok = FALSE;
260               break;
261             case ':':
262               printf("':' is not allowed.\n");
263               ok = FALSE;
264               break;
265             default:
266               if (iscntrl(buf[i]))
267                 {
268                   printf("Control characters are not allowed.\n");
269                   ok = FALSE;
270                   break;
271                 }
272             }
273           if (!ok)
274             break;
275         }
276
277       if (phone_num && ok)
278         {
279           for (i = 0; i < strlen(result); i++)
280             {
281               if (!isdigit(result[i]) && (result[i] != '-'))
282                 {
283                   printf("Phone numbers can contain only digits.\n");
284                   ok = FALSE;
285                   break;
286                 }
287               if (result[i] == '-')
288                 dashes = TRUE;
289             }
290         }
291     }
292
293   /* Remove dashes if necessary */
294   if (dashes && result == buf)
295     {
296       char *tmp1, *tmp2;
297       tmp1 = tmp2 = (char *)buf;
298       do
299         {
300           if (*tmp1 != '-')
301             *tmp2++ = *tmp1;
302         }
303       while (*tmp1++);
304     }
305
306     return result;
307 }
308
309 void get_new_info(struct finger_info *old_info, struct finger_info *new_info)
310 {
311   printf("Default values are printed inside of '[]'.\n");
312   printf("To accept the default, type <return>.\n");
313   printf("To have a blank entry, type the word '%s'.\n\n", BLANK);
314
315 #define GETINFO(m, v, n) new_info->v = strdup(ask(m, old_info->v, n))
316
317   GETINFO("Full name", fullname, FALSE);
318   GETINFO("Nickname", nickname, FALSE);
319   GETINFO("Home address (Ex: EC Bemis 514)", home_address, FALSE);
320   GETINFO("Home phone number (Ex: 3141592)", home_phone, TRUE);
321   GETINFO("Office address (Exs: E40-342 or 2-108)",
322           office_address, FALSE);
323   GETINFO("Office phone (Ex: 3-7619)", office_phone, TRUE);
324   GETINFO("MIT department (Exs: 9, Biology, Information Services)",
325           mit_department, FALSE);
326   GETINFO("MIT year (Exs: 1989, '91, Faculty, Grad)", mit_year, FALSE);
327 }
328
329 int usage(void)
330 {
331   fprintf(stderr, "Usage: %s [user]\n", whoami);
332   exit(1);
333 }
This page took 0.152645 seconds and 5 git commands to generate.