Mercurial > hg > Members > kono > nitros9-code
view 3rdparty/packages/uucpbb/src/adduser.c @ 3295:6b7a7b233925 default tip
makefile: Allow PORTS with level1/2 mix
https://sourceforge.net/p/nitros9/feature-requests/10/
author | Tormod Volden <debian.tormod@gmail.com> |
---|---|
date | Tue, 19 Apr 2022 18:12:17 +0200 |
parents | c4c7facbd082 |
children |
line wrap: on
line source
/* adduser.c Program to allow new user accounts to be added to the system. Copyright (C) 1990, 1993 Mark Griffith and Bob Billson This file is part of the OS-9 UUCP package, UUCPbb. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The author of UUCPbb, Bob Billson, can be contacted at: bob@kc2wz.bubble.org or uunet!kc2wz!bob or by snail mail: 21 Bates Way, Westfield, NJ 07090 */ /* Adds a new user to the system by updating the password file and creating required user files. Requires my LOGIN and PASSWORD utilities to work correctly. * * * N O T I C E * * * This code assumes the use of Shell+ Requires the Kreider library to compile Mark Griffith DeLand, Fl. 91 Jun o Changes to Mark's code made by Bob Billson <uunet!kc2wz!bob> are indicated by 'REB' ?? ??? ?? o Further changes made by Charles Ownes <trystro!czos9!chuck> to make it work more happily with Rick Adams' UUCP are indicated by 'CNO'. HINT: If you edit /dd/sys/password by hand, be sure you don't add any extra carrige returns at the end of the file. Each line should end with one carrige return. There should be no blank lines between entries. If this format is not adhered to, ADDUSER will not work properly. -- CNO 92 Oct 20 o Minor additions to allow compiling with the makefile in Rick Adams' UUCP. o Improved the way chk_uid() picks its own user id. o get_entries() now detects and reports blank lines in the password file. o User's login file script can now be customized. -- REB 93 Feb 14 o User name can now be given on the command line -- REB 93 Sep 4 o Special processing for user named 'daemon' --REB 94 Mar 30 o Added -s option for super user, fixed for OSK -- BGP */ #define MAIN /* To compile for UUCPbb, make the next line '#undef MARK' To compile for Mark's original, make the next line '#define MARK' */ #undef MARK /* To send certain login messages to the Speech Sound Pak, make the next line '#define SSP'. ***NOTE*** do this only if you ALWAYS have the SSP in place. If you do NOT wish to send messages to the SSP, make the next line '#undef SSP' -- CNO */ #undef SSP #ifndef MARK #include "uucp.h" /* default to Rick's */ #else /* uucp -- REB */ #include <stdio.h> #include <string.h> #endif #include <modes.h> #include <ctype.h> /* Added -- REB */ #include <password.h> #include <sgstat.h> /* Defines for password file array */ #define NAME 0 /* User name */ #define PASS 1 /* User password */ #define ID 2 /* User ID */ #define PRI 3 /* User priority */ #define DIRX 4 /* Execution directory */ #define DIRW 5 /* Working directory */ #define CMD 6 /* first command to run */ #define PW_SIZE 7 /* Number of entries */ #define ON 1 #define OFF 0 /* made direct page -- REB */ QQ char *daemon = "daemon", *Sorry = "Sorry, only the Superuser can use this utility!", *NewID = "Enter new user ID number\n ('Q' to quit) or press <ENTER> and I'll pick: "; /* Change the filenames below as needed ONLY if compiling for Mark's version. For UUCPbb: userdir, maildir and logdir are defined in uucp.h PASSWORD and PWEMAX are defined in password.h -- REB */ #ifdef MARK QQ char *userdir = "/DD/USR", /* default user directory */ *logdir = "/DD/LOG", /* default user log file */ *maildir = "/DD/MAIL"; /* default mail directory */ #else QQ char *userdir = USERDIR; #endif /* these apply to both UUCPbb and Mark's version */ QQ char *passfile = PASSWORD, /* default password file */ *motd = "/DD/SYS/motd"; /* location of motd file */ char pw[PW_SIZE][30], tempstr[256], dirname[256], u_name[PWEMAX][20], mailname[256]; /* added -- REB */ flag isdaemon = FALSE; /* */ unsigned u_uid[PWEMAX]; #ifdef _OSK QQ int super = 256; #else QQ int super = 1; /* added -- BGP for super user creation */ #endif QQ int entries = 0; /* made direct page -- REB */ QQ FILE *fp; /* */ QQ PWENT *entry; /* */ int main (argc, argv) int argc; char *argv[]; { register int i; /* made register -- REB */ int path, uloginpath; flag ipickit; /* added --REB */ unsigned userid; char *p; /* Get the user's userid */ /* Must be the superuser to add a new user */ if ( getuid() ) exit (_errmsg (0, "%s\n", Sorry)); /* need help? */ if (argc > 3 || strcmp (argv[1], "-?") == 0) usage(); *tempstr = '\0'; #ifndef MARK if ((maildir = getenv ("MAIL")) != NULL) maildir = strdup (maildir); else fatal ("MAIL is undefined"); if ((logdir = getenv ("LOGDIR")) != NULL) logdir = strdup (logdir); else logdir = LOGDIR; #endif /* allow creation of super users? */ if (argc >= 2 && strcmp (argv[1], "-s") == 0) { if (argc == 3) strcpy (tempstr, argv[2]); argc = 1; /* so that we don't get caught later on -- BGP */ super = 0; } /* delete a local user? */ if (argc >= 2 && strcmp (argv[1], "-r") == 0) if (argc == 3) removeuser (argv[2]); else { fputs ("adduser: -r requires a username\n\n", stderr); usage(); } /* Set up some default password file entries -- edit as you require */ strcpy (pw[PRI], "128"); strcpy (pw[DIRX], "/dd/cmds"); strcat (strcpy (pw[DIRW], userdir), "/"); strcpy (pw[PASS], "000000"); get_entries(); /* read the password file */ /* user name given on command line? --REB */ if (argc >= 2) strcpy (tempstr, argv[1]); /* Get the new username. If they enter a 'Q', end the program. Otherwise, check to see if the username is already used. If it is, ask them for another one. */ do { while (*tempstr == '\0') { printf ("\nEnter username (Q to quit): "); fflush (stdout); if (mfgets (tempstr, sizeof (tempstr), stdin) == NULL) { errno = 0; fatal ("<ESC> hit...exiting"); } } if (*tempstr == 'Q' || *tempstr == 'q') exit (0); } while ( chk_name() ); /* name already in use? */ if (strucmp (tempstr, daemon) == 0) /* user 'daemon' is special */ isdaemon = TRUE; strcat (pw[DIRW], tempstr); strcpy (pw[NAME], tempstr); /* user ID given on command line? --REB */ if (argc == 3) strcpy (tempstr, argv[2]); else *tempstr = '\0'; /* Get the new user ID number -- make my own if user enters nothing changed -- REB */ putchar ('\n'); do { if (*tempstr == '\0') { fputs (NewID, stdout); fflush (stdout); if (mfgets (tempstr, sizeof (tempstr), stdin) == NULL) { errno = 0; fatal ("<ESC> hit...exiting"); } if (*tempstr == 'Q' || *tempstr == 'q') exit (0); else if (*tempstr == '\0') ipickit = TRUE; else ipickit = FALSE; } else ipickit = FALSE; #ifndef _OSK userid = (unsigned) atoi (tempstr); #else userid = (unsigned) uIDtoInt (tempstr); #endif } while (chk_uid (&userid, ipickit)); #ifdef _OSK p = InttouID (userid); strcpy (pw[ID], p); free (p); #else sprintf (pw[ID], "%u", userid); #endif printf ("\nAdding new user '%s' as UID %s\n", pw[NAME], pw[ID]); /* Create user login file */ sprintf (tempstr, "%s/%s.login", logdir, pw[NAME]); if ((path = create (tempstr, S_IREAD+S_IWRITE, S_IREAD+S_IWRITE)) == ERROR) { sprintf (tempstr, "%s.login already exists\n", pw[NAME]); fatal (tempstr); } close (path); /* Open and add user data to password file */ if ((fp = fopen (passfile, "a")) == NULL) fatal ("can't open password file"); for (i = 0; i < (PW_SIZE - 1); i++) fprintf (fp, "%s,", pw[i]); /* Create the commands the user will use after logging in. Changed --REB */ #ifndef _OSK # ifdef SHELLPLUS /* turn off Shell+ shell variable expansion so MAIL works properly make prompt user's name -- REB */ fprintf (fp, "ulogin; ex shell -v p=\"%s\"\n", pw[NAME]); # else fprintf (fp, "ulogin;ex shell\n"); # endif #else fprintf (fp, "ulogin;ex shell\n"); #endif fclose (fp); /* Create user directory with owner bits only set. */ strcpy (tempstr, pw[NAME]); sprintf (dirname, "%s/%s", userdir, strupr (tempstr)); setuid (atoi (pw[ID])); /* set uid to new user */ if ((mknod (dirname, S_IREAD+S_IWRITE+S_IEXEC)) == ERROR) { sprintf (tempstr, "can't create user's home directory...error %d\n", errno); fatal (tempstr); } #ifndef _OSK /* CoCo user needs a UUCP directory in their home directory for UUCPbb */ sprintf (tempstr, "%s/UUCP", dirname); if ((mknod (tempstr, S_IREAD+S_IWRITE+S_IEXEC)) == ERROR) { sprintf (tempstr, "can't create user's home UUCP directory...error %d\n", errno); fatal (tempstr); } #endif /* Create user mail directory with owner bits only set. Mail directory is compatible with UUCPbb --REB */ /* user 'daemon' does not need a mail directory */ if (!isdaemon) { strcpy (tempstr, pw[NAME]); sprintf (mailname, "%s/%s", maildir, strupr (tempstr)); if ((mknod (mailname, S_IREAD+S_IWRITE+S_IEXEC)) == ERROR) { sprintf (tempstr, "can't create user's mail directory '%s'...error %d\n", mailname, errno); fatal (tempstr); } } /* Setup users login file in their directory */ sprintf (tempstr, "%s/%s/ulogin", userdir, pw[NAME]); /* changed -- REB */ if ((uloginpath = create (tempstr, S_IWRITE, S_IREAD+S_IWRITE)) == ERROR) { sprintf (tempstr, "Can't create user's ulogin file '%s'...error %d\n", tempstr, errno); fatal (tempstr); } /* now turn the path number in a file descriptor for writing -- REB */ if ((fp = fdopen (uloginpath, "w")) == NULL) fatal ("can't create user's 'ulogin' file"); asetuid (0); /* set uid back to SuperUser */ /* create user's ulogin file...moved -- REB */ make_ulogin (fp); /* make sure all I/O is flushed and chop off any junk at the end before we close the file -- REB */ fflush (fp); _ss_size (uloginpath, ftell (fp)); fclose (fp); printf ("\n\nUser '%s' has been added to the system\n\n", pw[NAME]); printf ("**NOTE** the password for user '%s' is NOT set right now.\n", pw[NAME]); puts (" You must use the utility PASSWORD to set it.\n"); free (maildir); free (logdir); exit (0); } /* Read the password file getting all the usernames and UID there. */ int get_entries() { register char *p; char tmpstr[PWSIZ]; int line, badline; p = tmpstr; line = 0; badline = FALSE; if ((fp = fopen (passfile, "r")) == NULL) { sprintf (tempstr, "can't open password file...error %d\n", errno); fatal (tempstr); } while (fgets (p, sizeof (tmpstr), fp) != NULL) { ++line; if (*p == '\n') { fputs ("adduser: illegal password entry...line", stderr); fprintf (stderr, "%d starts with a CR.\n", line); badline = TRUE; } } fclose (fp); if (badline) { fputs ("There cannot be blank lines anywhere in the ", stderr); fputs ("password file. These lines must\nbe fixed ", stderr); fputs ("fixed before continuing.\n", stderr); exit (0); } while((entry = getpwent()) != NULL) { if (entry == (PWENT *)ERROR) fatal ("error in the password file!"); strcpy (u_name[entries], entry->unam); #ifndef OSK u_uid[entries++] = (unsigned) atoi (entry->uid); #else u_uid[entries++] = (unsigned) uIDtoInt (entry->uid); #endif } endpwent(); } /* Check password file entries. If 'ipickit' is FALSE, see if there is a UID of the same number already used. If 'ipickit' is TRUE, pick the next highest available UID. If all the UID (0-255) are picked, exit with an error. Global variable 'tempstr' has the user ID to be checked on entry. If the user ID is already used, we exit with 'tempstr' set to a NULL string. -- REB */ int chk_uid (uid, ipickit) int ipickit; unsigned *uid; { register int i; /* made register -- REB */ unsigned j; /* added -- REB */ /* UID was passed to us, is it taken? */ if (!ipickit) { for (i = 0; i < entries; i++) if (*uid == u_uid[i]) { fprintf (stderr, "\nUID '%d' is already used\n\n", *uid); *tempstr = '\0'; return (TRUE); } return (FALSE); } else { /* we have to pick the UID. find the lowest unused one */ for (j = super; j < 65536; ++j) { for (i = 0; i < entries; i++) if (j == u_uid[i]) break; /* didn't find a match, this is our UID */ if (i == entries) { *uid = j; return (FALSE); } } /* all 65535 user IDs are taken (wow!) */ fatal ("all user IDs are used"); } } /* Check the password file entries and see if the username entered is already in the file. global variable 'tempstr' has the username on entry. */ int chk_name() { register int i; /* made register -- REB */ for (i = 0; i < entries; i++) if ((strucmp (tempstr, u_name[i])) == 0) { fprintf (stderr, "\nUsername '%s' already exists\n", tempstr); if (strucmp (tempstr, daemon) == 0) exit (0); else *tempstr = '\0'; return (TRUE); } return (FALSE); } /* make the user's ulogin file...expanded -- REB */ int make_ulogin (fptr) FILE *fptr; { char script[256], answer, get_yn(); int done = FALSE; /* user 'daemon' has a really short login script */ if (isdaemon) { fputs ("echo daemon is logged in; echo", fptr); return (0); } while (!done) { /* start script */ fprintf (fptr, "* Login file for %s *\n", pw[NAME]); cls(); printf ("Do you wish to customize %s's login script?\n", pw[NAME]); fputs (" (NO means use default script) y/n --> ", stdout); fflush (stdout); answer = get_yn(); /* customize our own ulogin script */ if (answer == 'y') { cls(); printf (" "); ReVOn(); printf (" Customize ulogin script "); ReVOff(); puts ("\nEnter commands one line at time. Check for waiting mail has already been"); puts ("included at the beginning of the script.\n"); puts ("<ENTER> only for any line ends the customizing. If you make a mistake, end"); fputs ("customizing and answer 'N' (no) to 'Script okay?' prompt. You may then start\nover.\n", stdout); #ifdef SSP puts ("\nYou may send text to the Speech Sound Pak by redirecting it. For example:"); puts (" echo hi there >/ssp"); #endif fputs ("\nHit <ENTER> to begin --> ", stdout); fflush (stdout); answer = getchar(); cls(); ReVOn(); fputs (" ulogin script so far: ", stdout); ReVOff(); puts ("\n"); /* put in the standard stuff */ fputs ("-x\n", fptr); puts ("-x"); fprintf (fptr, "list %s\n", motd); printf ("list %s\n", motd); fputs ("echo\n", fptr); puts ("echo"); #ifndef SSP fprintf (fptr, "echo Hello %s\n", pw[NAME]); printf ("echo Hello %s\n", pw[NAME]); #else /* Send 'hello <name>' to speech pak if SSP is set -- CNO */ fprintf (fptr, "echo Hello %s >/ssp&\n", pw[NAME]); printf ("echo Hello %s >/ssp&\n", pw[NAME]); #endif /* This line is specific to the mail utility packaged with the OS9 uucp port. Added code for Rick Adams' UUCP enhancements -- REB */ #ifdef MARK fputs ("lmail -c\n", fptr); /* Mark's original UUCP */ puts ("lmail -c"); #else fputs ("mailx -c\n", fptr); /* Rick Adams' UUCP */ puts ("mailx -c"); #endif putchar ('\n'); ReVOn(); printf (" Continue script... "); ReVOff(); puts("\n"); for (;;) { fgets (script, sizeof (script), stdin); if (*script == '\n') break; else fputs (script, fptr); } fputs ("\nScript okay? (y/n) --> ", stdout); fflush (stdout); answer = get_yn(); if (answer == 'y') done = TRUE; else rewind (fptr); /* try again */ } else { /* make the default login script */ fputs ("-x\n", fptr); fprintf (fptr, "list %s\n", motd); fputs("x\n", fptr); fputs ("echo\n", fptr); #ifndef SSP fprintf (fptr, "echo Hello %s\n", pw[NAME]); #else /* Send 'hello <name>' to speech pak if SSP is set -- CNO */ fprintf (fptr, "echo Hello %s >/ssp&\n", pw[NAME]); #endif /* This line is specific to the mail utility packaged with the OS9 uucp port. Added code for Rick Adams' UUCP enhancement -- REB */ #ifdef MARK fputs ("lmail -c\n", fptr); /* Mark's original mailer */ #else fputs ("mailx -c\n", fptr); /* UUCPbb */ #endif fputs ("echo\n", fptr); fputs ("echo Please use the 'bye' command to log off\n\n", fptr); done = TRUE; } } fputs ("* End of Script *\n", fptr); return (0); } /* get a single character response from the user. Added --REB */ char get_yn() { char answer; echo (OFF); for (;;) { while (_gs_rdy (0) <= 0) tsleep (4); read (0, &answer, 1); answer &= 0xff; answer = tolower (answer); if (answer == 'y' || answer == 'n') { putchar (answer); break; } } echo (ON); return (answer); } /* Turn off or on echo on the standard input path --REB */ int echo (onoroff) int onoroff; { struct sgbuf stdinpath; _gs_opt (1, &stdinpath); stdinpath.sg_echo = onoroff; /* switch standard input echo */ _ss_opt (1, &stdinpath); /* update the path descriptor */ } /* Convert a string to upper case. Returns a pointer to the start of the string. --REB */ char *strupr (string) char *string; { register char *p; p = string; while (*p) { *p = toupper (*p); ++p; } return (string); } int usage() { char temp[80], *strdetab(); register char **use; static char *usetext[] = { "ADDUSER: add a user to or remove a user from the system", "Usage: adduser [opts] [<username> [<userid>] ]", " ", "opts: -r <username> - remove <username> from the system", " -s - allow the creation of super users", "\t-?\t\t - this message", " ", "\tacceptable command lines are:", "\t adduser", "\t adduser <username>", "\t adduser <username> <userid>", "\t adduser -r <username>", "\t adduser -s <username>", NULL }; for (use = usetext; *use != NULL; ++use) fprintf (stderr, " %s\n", strdetab (strcpy (temp, *use), 6)); fprintf (stderr, "\nv%s (%s) This is free software released under the GNU General Public\n", version, VERDATE); fputs ("License. Please send suggestions/bug reports to: bob@kc2wz.bubble.org\n", stderr); exit (0); } int fatal (msg) char *msg; { fprintf (stderr, "adduser: %s", msg); if (errno != 0) fprintf (stderr, "...error %d", errno); putc ('\n', stderr); exit (0); } int removeuser (username) char *username; { userbegone (username); fatal ("removing user is not implemented yet"); } int userbegone (name) { }