static char
*sccsid
= "@(#)chfn.sh 4.8 (Berkeley) %G%";
* changefinger
- change
finger entries
#include <sys/resource.h>
char temp
[] = "/etc/ptmp";
char passwd
[] = "/etc/passwd";
char replacement
[4*BUFSIZ
];
printf("Usage: changefinger [user]\n");
* Error check to
make sure the user
(foolishly
) typed their own name.
if ((argc
== 2) && (user_uid
!= 0)) {
printf("%s%s%s%s%s%s%s%s",
"There is no account for ", argv
[1],
"You probably mispelled your login name;\n",
"only root is allowed to change another",
" person's finger entry.\n",
"Note: you do not need to type your login",
" name as an argument.\n");
if (pwd-
>pw_uid
!= user_uid
) {
"You are not allowed to change another",
" person's finger entry.\n");
* If root is changing a
finger entry
, then find the uid that
* corresponds to the user
's login name.
if ((argc == 2) && (user_uid == 0)) {
printf("There is no account for %s on this machine\n",
pwd = getpwuid(user_uid);
fprintf(stderr, "No passwd file entry!?\n");
* Collect name, room number, school phone, and home phone.
get_info(pwd->pw_gecos, replacement);
(void) signal(SIGHUP, SIG_IGN);
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGTSTP, SIG_IGN);
if ((fd = open(temp, O_CREAT|O_EXCL|O_RDWR, 0644)) < 0) {
printf("Temporary file busy -- try again\n");
if ((tf = fdopen(fd, "w")) == NULL) {
printf("Absurd fdopen failure - seek help\n");
if ((dp = ndbmopen(passwd, O_RDWR, 0644)) == NULL) {
fprintf(stderr, "Warning: dbminit failed: ");
} else if (flock(dp->db_dirf, LOCK_EX) < 0) {
perror("Warning: lock failed");
* Copy passwd to temp, replacing matching lines
while ((pwd = getpwent()) != NULL) {
if (pwd->pw_uid == user_uid) {
pwd->pw_gecos = replacement;
fprintf(tf,"%s:%s:%d:%d:%s:%s:%s\n",
if (rename(temp, passwd) < 0) {
fprintf(stderr, "chfn: "), perror("rename");
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
(void) setrlimit(lim, &rlim);
* Replace the password entry in the dbm data base with pwd.
#define COMPACT(e) tp = pwd->pw_/**/e; while (*cp++ = *tp++);
*(int *)cp = pwd->pw_uid; cp += sizeof (int);
*(int *)cp = pwd->pw_gid; cp += sizeof (int);
*(int *)cp = pwd->pw_quota; cp += sizeof (int);
content.dsize = cp - buf;
key.dsize = strlen(pwd->pw_name);
dbmstore(dp, key, content, DB_REPLACE);
key.dptr = (char *)&pwd->pw_uid;
key.dsize = sizeof (int);
dbmstore(dp, key, content, DB_REPLACE);
* Get name, room number, school phone, and home phone.
get_info(gecos_field, answer)
char *strcpy(), *strcat();
struct default_values *defaults, *get_defaults();
defaults = get_defaults(gecos_field);
printf("Default values are printed inside of of '[]'.\n");
printf("To accept the default, type <return>.\n");
printf("To have a blank entry, type the word 'none
'.\n");
printf("\nName [%s]: ", defaults->name);
(void) fgets(in_str, BUFSIZ, stdin);
if (special_case(in_str, defaults->name))
} while (illegal_input(in_str));
(void) strcpy(answer, in_str);
printf("Room number (Exs: 597E or 197C) [%s]: ",
(void) fgets(in_str, BUFSIZ, stdin);
if (special_case(in_str, defaults->office_num))
} while (illegal_input(in_str) || illegal_building(in_str));
(void) strcat(strcat(answer, ","), in_str);
* Get office phone number.
* Remove hyphens and 642, x2, or 2 prefixes if present.
printf("Office Phone (Ex: 1632) [%s]: ",
(void) fgets(in_str, BUFSIZ, stdin);
if (special_case(in_str, defaults->office_phone))
if ((strlen(in_str) == 8) && (strcmpn(in_str, "642", 3) == 0))
(void) strcpy(in_str, in_str+3);
if ((strlen(in_str) == 7) && (strcmpn(in_str, "x2", 2) == 0))
(void) strcpy(in_str, in_str+2);
if ((strlen(in_str) == 6) && (in_str[0] == '2'))
(void) strcpy(in_str, in_str+1);
} while (illegal_input(in_str) || not_all_digits(in_str)
|| wrong_length(in_str, 4));
(void) strcat(strcat(answer, ","), in_str);
* Remove hyphens if present.
printf("Home Phone (Ex: 9875432) [%s]: ", defaults->home_phone);
(void) fgets(in_str, BUFSIZ, stdin);
if (special_case(in_str, defaults->home_phone))
} while (illegal_input(in_str) || not_all_digits(in_str));
(void) strcat(strcat(answer, ","), in_str);
* Prints an error message if a ':' or a newline is found in the string.
* A message is also printed if the input string is too long.
* The password file uses :'s as seperators
, and are not allowed
in the
"gcos"
* field. Newlines serve as delimiters between users
in the password
file,
* and so
, those too
, are checked
for.
(I don
't think that it is possible to
* type them in, but better safe than sorry)
* Returns '1' if a colon or newline is found or the input line is too long.
int length = strlen(input_str);
if (index(input_str, ':')) {
printf("':' is not allowed.\n");
if (input_str[length-1] != '\n') {
/* the newline and the '\
0' eat up two characters */
printf("Maximum number of characters allowed is %d\n",
/* flush the rest of the input line */
while (getchar() != '\n')
* Delete newline by shortening string by 1.
input_str[length-1] = '\
0';
* Don't allow control characters
, etc
in input string.
for (ptr
=input_str
; *ptr
!= '\0'; ptr
++) {
printf("Control characters are not allowed.\n");
* Removes
'-'s from the input string.
char
*hyphen
, *index
(), *strcpy
();
while ((hyphen
=index
(str
, '-')) != NULL
) {
(void
) strcpy
(hyphen
, hyphen
+1);
* Checks to see
if 'str' contains only digits
(0-9). If not
, then
* an error message is printed and
'1' is returned.
for (ptr
=str
; *ptr
!= '\0'; ++ptr
) {
printf("Phone numbers can only contain digits.\n");
* Returns
1 when the length of the input string is not zero or equal to n.
* Prints an error message
in this
case.
if ((strlen
(str
) != 0) && (strlen
(str
) != n
)) {
printf("The phone number should be %d digits long.\n", n
);
* Make sure that building is
'E' or
'C'.
* Error correction is
done if building is
'e', 'c', "evans", or
"cory".
* Correction changes
"str".
* The
finger program determines the building by looking
at the last
* character. Currently
, finger only allows that character to be
'E' or
'C'.
* Returns
1 if incorrect room format.
* Note
: this
function assumes that the newline has been removed from str.
int length
= strlen
(str
);
* Zero length
strings are acceptable input.
* Delete
"vans" and
"ory".
if (strcmpn
(str
+length-4
, "vans", 4) == 0) {
if (strcmpn
(str
+length-3
, "ory", 3) == 0) {
* Now change e to E or c to C.
* Delete any spaces before the E or C.
for (ptr
=last_ch-1
; ptr
>str
; ptr--
) {
(void
) strcpy
(ptr
+1, last_ch
);
* Make sure building is evans or cory.
if ((*last_ch
!= 'E') && (*last_ch
!= 'C')) {
"The finger program requires that your",
" office be in Cory or Evans.\n",
"Enter this as (for example) 597E or 197C.\n");
/* get_defaults picks apart
"str" and returns a structure points.
* "str" contains up to
4 fields separated by commas.
* Any field that is missing is
set to blank.
struct default_values
*answer
;
char
*malloc
(), *index
();
answer
= (struct default_values
*)
malloc
((unsigned
)sizeof
(struct default_values
));
if (answer
== (struct default_values
*) NULL
) {
"\nUnable to allocate storage in get_defaults!\n");
* Values
if no corresponding string
in "str".
answer-
>office_phone
= "";
str
= index
(answer-
>name
, ',');
answer-
>office_num
= str
+ 1;
str
= index
(answer-
>office_num
, ',');
answer-
>office_phone
= str
+ 1;
str
= index
(answer-
>office_phone
, ',');
answer-
>home_phone
= str
+ 1;
* special_case returns true when either the default is accepted
* (str
= '\n'), or when
'none' is typed.
'none' is accepted
in
* either upper or lower
case (or any combination
).
'str' is modified
int special_case
(str
,default_str
)
static char word
[] = "none\n";
* If the default is accepted
, then change the old string
do the
(void
) strcpy
(str
, default_str
);
* Check to see
if str is
'none'.
(It is questionable
if case
* insensitivity is worth the hair
).
for (ptr
=str
; *ptr
!= '\0'; ++ptr
) {
if (*wordptr
== '\0') /* then words are different sizes
*/
if (isupper
(*ptr
) && (tolower
(*ptr
) == *wordptr
))
* At this point we have a mismatch
, so we
return
* Make sure that words are the same length.
if (*(wordptr
+1) != '\0')
* Change
'str' to be the null string