Friday, February 15, 2008

C Code To Add User Accounts And Introduce C/Shell/Perl Porting.

Ahoy (I've always wanted to use that greeting ;)

Today, we're putting out a little (?) c code we wrote to standardize user account creations across any sized environment on Unix or Linux (slight modifications may need to be made depending on your environment).

C code isn't generally what we concentrate on in this blog, but we thought it would be interesting to put this out today, and follow it up with the exact same script in ksh/bash and Perl on the next successive days. Kind of a slam-bang intro to porting (Which, you may recall, we began a long time - and many scripts - ago - in this post on the shebang line.

We will, eventually, come full circle with that. It's the blessing and the curse of a blog like this: There's so much to write about and share that maintaining a really specific thread (especially a long one) can sometimes take a while and be presented in a scatter shot manner. Thank goodness for HTML hyperlinks ;)

Note that, in the code below, everything is set up to be interactive and only a few assumptions are made (which you can, of course, change to your liking). We'll keep them consistent between ports of this code, so it's easier to follow, but none of this stuff is set in stone.

Things to look for in this c code that you might want to change and/or may be confusing:

1. The "userdir" variable is the main user directory (like "/users" or something), except we ask that no slashes be used in the input. We actually do ask that in the code itself. We tried to keep it polite ;)

2. The "username" variable is used to both name the user and his/her account. So the user "bobby" would have a home directory of "/users/bobby" in this case.

3. After the fopen of /etc/passwd, we've hard coded the group number to "1" and the shell to "/bin/ksh"

4. You can change anything about this c code that you want to. This code is actually utile, but is also being used as a massive example of porting that we'll explore in the following few posts.

5. You can compile this program easily with gcc, like so:

host # gcc -o whateverNameYouWantToCallTheBinary adduser.c

For now, whether it makes sense to you or not, enjoy!

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License


#include
#include
#include
#include
#include

/* adduser.c
Add Users, Set Up Profiles,
Set The Password And Email
An Admin
2008 - Mike Golvach - eggi@comcast.net
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
*/

main(int argc, char **argv)
{

struct passwd *userlist;
int count, usernumber;
FILE *tmp, *stmp, *mailer, *profile;
char *commentfield, *username, *userdir, *home;
char *mailcomment, *mailemail, reply;

commentfield = (char *)malloc(1024*sizeof(char));
username = (char *)malloc(8*sizeof(char));
userdir = (char *)malloc(256*sizeof(char));
home = (char *)malloc(256*sizeof(char));
mailcomment = (char *)malloc(1024*sizeof(char));
mailemail = (char *)malloc(512*sizeof(char));

if (argc != 4) {
printf("Usage: %s [dirname - no slashes ] [ logname ] [ comment - in quotes ]\n", argv[0]);
exit(1);
}

if (strlen(argv[2]) > 8 || strlen(argv[2]) < 5) {
printf("Please choose a logname between 5 and 8 characters!\n");
exit(1);
}

signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);

setpwent();

count = 0;

while ((userlist = getpwent()) != NULL) {
if (count < userlist->pw_uid) {
count = userlist->pw_uid;
usernumber = count+1;
}
}

endpwent();

sprintf(commentfield, "%s", argv[3]);
sprintf(userdir, "%s", argv[1]);
sprintf(username, "%s", argv[2]);
sprintf(home, "/%s/%s", argv[1], argv[2]);

printf("\n");
printf("Check this out before proceeding!!!\n");
printf("-----------------------------------\n");
printf("Logname:\t%s\n", username);
printf("Homedir:\t/%s/%s\n", userdir, username);
printf("Comment:\t%s\n", commentfield);
printf("-----------------------------------\n");
printf("\n");

printf("\n");
printf("All of this ok?\n");
printf("\n");
printf("y or n [n is the default]\n");
printf("\n");

scanf("%c", &reply);

if ( reply != 'y') {
printf("\n");
printf("All right, give it another shot if you want!\n");
exit(0);
}

tmp = fopen("/etc/passwd", "a");
fprintf(tmp, "%s:x:%d:1:%s:/%s/%s:/bin/ksh\n", username, usernumber, commentfield, userdir, username);
fclose(tmp);

stmp = fopen("/etc/shadow", "a");
fprintf(stmp, "%s:*LK*:::::::\n", username);
fclose(stmp);

mkdir(home, 0755);
chdir(home);

profile = fopen(".profile", "a");
fprintf(profile, "stty istrip\n");
fprintf(profile, "PATH=/bin:/usr/bin:/usr/local/bin:/usr/share/bin:.\n");
fprintf(profile, "export PATH\n");
fprintf(profile, "\n");
fprintf(profile, "\n");
fclose(profile);

chown(home, usernumber, 1);
chown(".profile", usernumber, 1);
chmod(".profile", 0644);

if ((mailer = popen("/usr/lib/sendmail -t", "w")) == NULL) {
perror("Mailer");
exit(1);
}

sprintf(mailcomment, "%s\n", commentfield);
sprintf(mailemail, "The email address is %s@host.com!\n", username);

fputs("To: bob@host.com\n", mailer);
fputs("Subject: New User Added!!!\n", mailer);
fputs("\n", mailer);
fputs(mailcomment, mailer);
fputs("has a new account set up!\n", mailer);
fputs(mailemail, mailer);
fputs("\n", mailer);
fputs("Thank you,\n", mailer);
fputs("\t Mike Golvach\n", mailer);

pclose(mailer);

printf("\n");
printf("All Done!!!\n");
printf("\n");
printf("Now set the Password!\n");
printf("\n");
execl("/usr/bin/passwd", "passwd", username, NULL);
printf("\n");
printf("Password set!!! Take a break...\n");

}


, Mike