--- /dev/null
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology. For copying
+ * and distribution information, see the file "mit-copyright.h".
+ *
+ * $Source$
+ * $Header$
+ * $Author$
+ *
+ */
+
+#ifndef lint
+static char *rcsid_chfn_c = "$Header$";
+#endif not lint
+
+/*
+ * Talk to the SMS database to change a person's GECOS information.
+ *
+ * chfn with no modifiers changes the information of the user who is
+ * running the program.
+ *
+ * If a commandline argument is given, it is taken to be the username
+ * of the user whose information is to be changed.
+ *
+ */
+
+#define FALSE 0
+#define TRUE 1
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <sys/file.h>
+#include <krb.h>
+#include <ctype.h>
+#include <errno.h>
+
+/* SMS includes */
+#include <sms.h>
+#include <sms_app.h>
+#include "mit-copyright.h"
+
+char *whoami;
+
+extern char *krb_err_txt[];
+
+struct finger_info {
+ char *fullname;
+ char *nickname;
+ char *home_address;
+ char *home_phone;
+ char *office_address;
+ char *office_phone;
+ char *mit_department;
+ char *mit_year;
+};
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char pname[ANAME_SZ];
+ char *uname = pname;
+ int k_errno;
+ char *whoami;
+
+ if ((whoami = rindex(argv[0], '/')) == NULL)
+ whoami = argv[0];
+ else
+ whoami++;
+
+ if (argc > 2) {
+ usage();
+ }
+
+ if (argc == 2)
+ uname = argv[1];
+ else
+ {
+ /* Do it right; get name from kerberos ticket file rather than
+ from passord file. */
+
+ if (k_errno = tf_init(TKT_FILE, R_TKT_FIL)) {
+ fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+
+ if (k_errno = tf_get_pname(pname)) {
+ fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+
+ tf_close();
+ }
+
+ exit(chfn(uname));
+}
+
+leave(status)
+ int status;
+ /* This should be called rather than exit once connection to sms server
+ has been established. */
+{
+ sms_disconnect();
+ exit(status);
+}
+
+scream()
+{
+ com_err(whoami, 0, "Unexpected return value from SMS -- programmer botch");
+ leave(1);
+}
+
+chfn(uname)
+ char *uname;
+{
+ int status; /* general purpose exit status */
+ int q_argc; /* argc for sms_query */
+ char *q_argv[F_END]; /* argv for sms_query */
+ int i;
+
+ int get_user_info();
+ void get_new_info();
+
+ struct finger_info old_info;
+ struct finger_info new_info;
+
+ /* Try each query. If we ever fail, print error message and exit. */
+
+ status = sms_connect(SMS_SERVER);
+ if (status) {
+ com_err(whoami, status, " while connecting to SMS");
+ exit(1);
+ }
+
+ status = sms_auth("chfn"); /* Don't use argv[0] - too easy to fake */
+ if (status) {
+ com_err(whoami, status,
+ " while authenticating -- run \"kinit\" and try again.");
+ leave(1);
+ }
+
+ /* First, do an access check. */
+
+ q_argv[F_NAME] = uname;
+ for (i = F_NAME + 1; i < F_MODTIME; i++)
+ q_argv[i] = "junk";
+ q_argc = F_MODTIME; /* one more than the last updatable field */
+
+ if (status = sms_access("update_finger_by_login", q_argc, q_argv)) {
+ com_err(whoami, status, "; finger\ninformation not changed.");
+ leave(2);
+ }
+
+ printf("Changing finger information for %s.\n", uname);
+
+ /* Get information */
+
+ q_argv[NAME] = uname;
+ q_argc = NAME + 1;
+ if (status = sms_query("get_finger_by_login", q_argc, q_argv,
+ get_user_info, (char *) &old_info))
+ {
+ com_err(whoami, status, " while getting user information.");
+ leave(2);
+ }
+
+ /* Get the new information from the user */
+
+ get_new_info(&old_info, &new_info);
+
+ /* Do the update */
+
+ printf("Changing finger information...\n");
+
+ q_argv[F_NAME] = uname;
+ q_argv[F_FULLNAME] = new_info.fullname;
+ q_argv[F_NICKNAME] = new_info.nickname;
+ q_argv[F_HOME_ADDR] = new_info.home_address;
+ q_argv[F_HOME_PHONE] = new_info.home_phone;
+ q_argv[F_OFFICE_ADDR] = new_info.office_address;
+ q_argv[F_OFFICE_PHONE] = new_info.office_phone;
+ q_argv[F_MIT_DEPT] = new_info.mit_department;
+ q_argv[F_MIT_AFFIL] = new_info.mit_year;
+ q_argc = F_MODTIME; /* First non-update query argument */
+
+ if (status = sms_query("update_finger_by_login", q_argc, q_argv,
+ scream, (char *)NULL))
+ {
+ com_err(whoami, status, " while updating finger information.");
+ leave(1);
+ }
+
+ printf("Finger information updated succesfully.\n");
+
+ return(0);
+}
+
+get_user_info(argc, argv, message)
+ int argc;
+ char *argv[];
+ char *message;
+{
+ struct finger_info *old_info = (struct finger_info *) message;
+
+ if (argc != F_END) {
+ fprintf(stderr, "Some internal error occurred; try again.\n");
+ leave(3);
+ }
+
+ printf("Info last changed on %s by user %s with %s.\n",
+ argv[F_MODTIME], argv[F_MODBY], argv[F_MODWITH]);
+
+ old_info->fullname = strsave(argv[F_FULLNAME]);
+ old_info->nickname = strsave(argv[F_NICKNAME]);
+ old_info->home_address = strsave(argv[F_HOME_ADDR]);
+ old_info->home_phone = strsave(argv[F_HOME_PHONE]);
+ old_info->office_address = strsave(argv[F_OFFICE_ADDR]);
+ old_info->office_phone = strsave(argv[F_OFFICE_PHONE]);
+ old_info->mit_department = strsave(argv[F_MIT_DEPT]);
+ old_info->mit_year = strsave(argv[F_MIT_AFFIL]);
+
+ /* Only pay attention to the first match since login names are
+ unique in the database. */
+ return(SMS_ABORT);
+}
+
+char *ask(question, def_val, phone_num)
+ char *question;
+ char *def_val;
+ int phone_num; /* True if this must contain only digits */
+{
+ char buf[BUFSIZ];
+ int ok = FALSE;
+ char *result;
+ int i;
+ int dashes = FALSE;
+
+#define BLANK "none"
+
+ while (!ok)
+ {
+ ok = TRUE;
+ printf("%s [%s]: ", question, def_val);
+ (void) fgets(buf, sizeof(buf), stdin);
+ buf[strlen(buf) - 1] = NULL;
+ if (strlen(buf) == 0)
+ result = def_val;
+ else if (strcasecmp(buf, BLANK) == NULL)
+ result = "";
+ else
+ result = buf;
+
+ for (i = 0; i < strlen(buf); i++)
+ {
+ switch (buf[i])
+ {
+ case '"':
+ printf("'\"' is not allowed.\n");
+ ok = FALSE;
+ break;
+ case ',':
+ printf("',' is not allowed.\n");
+ ok = FALSE;
+ break;
+ case ':':
+ printf("':' is not allowed.\n");
+ ok = FALSE;
+ break;
+ default:
+ if (iscntrl(buf[i])) {
+ printf("Control characters are not allowed.\n");
+ ok = FALSE;
+ break;
+ }
+ }
+ if (!ok)
+ break;
+ }
+
+ if (phone_num && ok) {
+ for (i = 0; i < strlen(buf); i++) {
+ if (!isdigit(buf[i]) && (buf[i] != '-')) {
+ printf("Phone numbers can contain only digits.\n");
+ ok = FALSE;
+ break;
+ }
+ if (buf[i] == '-')
+ dashes = TRUE;
+ }
+ }
+ }
+
+ /* Remove dashes if necessary */
+ if (dashes) {
+ char *tmp1, *tmp2;
+ result = strsave(buf);
+ tmp1 = (char *)buf;
+ tmp2 = result;
+ do {
+ if (*(tmp1) != '-')
+ *(tmp2++) = *(tmp1);
+ }
+ while (*(tmp1++));
+ }
+
+ return(result);
+}
+
+void get_new_info(old_info, new_info)
+ struct finger_info *old_info;
+ struct finger_info *new_info;
+{
+ printf("Default values are printed inside of '[]'.\n");
+ printf("To accept the default, type <return>.\n");
+ printf("To have a blank entry, type the word '%s'.\n\n", BLANK);
+
+#define GETINFO(m,v,n) \
+ new_info->v = strsave(ask(m, old_info->v, n))
+
+ GETINFO("Full name", fullname, FALSE);
+ GETINFO("Nickname", nickname, FALSE);
+ GETINFO("Home address (Ex: Atkinson 304)", home_address, FALSE);
+ GETINFO("Home phone number (Ex: 3141592)", home_phone, TRUE);
+ GETINFO("Office address (Exs: E40-342 or 2-108)",
+ office_address, FALSE);
+ GETINFO("Office phone (Ex: 3-1300)", office_phone, TRUE);
+ GETINFO("MIT department (Exs: 9, Biology, Information Services",
+ mit_department, FALSE);
+ GETINFO("MIT year (Exs: 1989, '91, Faculty, Grad)", mit_year, FALSE);
+}
+
+usage()
+{
+ fprintf(stderr, "Usage: %s [user]\n", whoami);
+ exit(1);
+}
--- /dev/null
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology. For copying
+ * and distribution information, see the file "mit-copyright.h".
+ *
+ * $Source$
+ * $Header$
+ * $Author$
+ *
+ */
+
+#ifndef lint
+static char *rcsid_chsh_c = "$Header$";
+#endif not lint
+
+/*
+ * Talk to the SMS database to change a person's login shell. The chosen
+ * shell must exist. A warning will be issued if the shell is not in
+ * /etc/shells.
+ *
+ * chsh with no modifiers changes the shell of the user who is running
+ * the program.
+ *
+ * If a commandline argument is given, it is taken to be the username
+ * of the user whose shell is to be changed.
+ *
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <strings.h>
+#include <sys/file.h>
+#include <krb.h>
+#include <ctype.h>
+#include <errno.h>
+
+/* SMS includes */
+#include <sms.h>
+#include <sms_app.h>
+#include "mit-copyright.h"
+
+char *whoami;
+char *getusershell();
+
+extern char *krb_err_txt[];
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char pname[ANAME_SZ];
+ char *uname = pname;
+ int k_errno;
+ char *whoami;
+
+ if ((whoami = rindex(argv[0], '/')) == NULL)
+ whoami = argv[0];
+ else
+ whoami++;
+
+ if (argc > 2) {
+ usage();
+ }
+
+ if (argc == 2)
+ uname = argv[1];
+ else
+ {
+ /* Do it right; get name from kerberos ticket file rather than
+ from passord file. */
+
+ if (k_errno = tf_init(TKT_FILE, R_TKT_FIL)) {
+ fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+
+ if (k_errno = tf_get_pname(pname)) {
+ fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+
+ tf_close();
+ }
+
+ exit(chsh(uname));
+}
+
+leave(status)
+ int status;
+ /* This should be called rather than exit once connection to sms server
+ has been established. */
+{
+ sms_disconnect();
+ exit(status);
+}
+
+scream()
+{
+ com_err(whoami, 0, "Unexpected return value from SMS -- programmer botch");
+ leave(1);
+}
+
+chsh(uname)
+ char *uname;
+{
+ int status; /* general purpose exit status */
+ int q_argc; /* argc for sms_query */
+ char *q_argv[U_END]; /* argv for sms_query */
+
+ int got_one = 0; /* have we got a new shell yet? */
+ char shell[BUFSIZ]; /* the new shell */
+ int get_shell();
+ void check_shell(); /* make sure new shell is valid */
+
+ /* Try each query. If we ever fail, print error message and exit. */
+
+ status = sms_connect(SMS_SERVER);
+ if (status) {
+ com_err(whoami, status, " while connecting to SMS");
+ exit(1);
+ }
+
+ status = sms_auth("chsh"); /* Don't use argv[0] - too easy to fake */
+ if (status) {
+ com_err(whoami, status,
+ " while authenticating -- run \"kinit\" and try again.");
+ leave(1);
+ }
+
+ /* First, do an access check */
+
+ q_argv[USH_NAME] = uname;
+ q_argv[USH_SHELL] = "junk";
+ q_argc = USH_END;
+
+ if (status = sms_access("update_user_shell", q_argc, q_argv))
+ {
+ com_err(whoami, status, "; shell not\nchanged.");
+ leave(2);
+ }
+
+ printf("Changing login shell for %s.\n", uname);
+
+ /* Display current information */
+
+ q_argv[NAME] = uname;
+ q_argc = NAME + 1;
+
+ if ((status = sms_query("get_user_by_login", q_argc, q_argv,
+ get_shell, (char *) uname)))
+ {
+ com_err(whoami, status, " while getting user information.");
+ leave(2);
+ }
+
+ /* Ask for new shell */
+ while (!got_one)
+ {
+ printf("New shell: ");
+ (void) fgets(shell, sizeof(shell), stdin);
+ got_one = (strlen(shell) > 1);
+ }
+
+ shell[strlen(shell) - 1] = 0; /* strip off newline */
+
+ /* Make sure we have a valid shell. This routine could exit */
+ check_shell(shell);
+
+ /* Change shell */
+
+ printf("Changing shell to %s...\n", shell);
+
+ q_argv[USH_NAME] = uname;
+ q_argv[USH_SHELL] = shell;
+ q_argc = USH_END;
+ if (status = sms_query("update_user_shell", q_argc, q_argv,
+ scream, (char *) NULL))
+ {
+ com_err(whoami, status, " while changing shell.");
+ leave(2);
+ }
+
+ printf("Shell successfully changed.\n");
+ sms_disconnect();
+
+ return(0);
+}
+
+get_shell(argc, argv, uname)
+ int argc;
+ char **argv;
+ char *uname; /* for sanity checking */
+{
+ /* We'll just take the first information we get since login names
+ cannot be duplicated in the database. */
+
+ if (strcmp(argv[U_NAME], uname))
+ {
+ fprintf(stderr, "Some internal error has occurred. Try again.\n");
+ leave(3);
+ }
+
+ printf("Account information last changed on %s\n", argv[U_MODTIME]);
+ printf("by user %s with %s.\n", argv[U_MODBY], argv[U_MODWITH]);
+ printf("Current shell for %s is %s.\n", uname, argv[U_SHELL]);
+
+ return(SMS_ABORT); /* Don't pay attention to other matches. */
+}
+
+void check_shell(shell)
+ char *shell;
+{
+ char *valid_shell;
+ int ok = 0;
+
+ while (valid_shell = getusershell()) {
+ if (strcmp(shell, valid_shell) == NULL) {
+ ok = 1;
+ break;
+ }
+ else if (strcmp(shell, 1+rindex(valid_shell, '/')) == NULL) {
+ ok = 1;
+ (void) strcpy(shell, valid_shell);
+ break;
+ }
+ }
+
+ if (!ok) {
+ if (shell[0] != '/') {
+ fprintf(stderr, "%s it not a standard shell. ", shell);
+ fprintf(stderr, "You may choose to use a nonstandard\n");
+ fprintf(stderr, "shell, but you must specify its complete ");
+ fprintf(stderr, "path name.\n");
+ leave(2);
+ }
+ else if (access(shell, X_OK)) {
+ fprintf(stderr, "%s is not available.\n", shell);
+ leave(2);
+ }
+ else {
+ printf("%s exists but is an unusual choice.\n", shell);
+ printf("Try again if it is not what you wanted.\n");
+ }
+ }
+}
+
+usage()
+{
+ fprintf(stderr, "Usage: %s [user]\n", whoami);
+ exit(1);
+}