xref: /titanic_41/usr/src/cmd/scadm/sparc/mpxu/common/user.c (revision 40db2e2b777b79f3dd0d6d9629593a07f86b9c0a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * user.c: support for the scadm useradd, userdel, usershow, userpassword,
31  * userperm options (administration of service processor users)
32  */
33 
34 #include <libintl.h>
35 #include <signal.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <termios.h>
39 #include <time.h>  /* required by librsc.h */
40 
41 #include "librsc.h"
42 #include "adm.h"
43 
44 
45 static void ADM_Get_Password(char  *password);
46 static void ADM_Destroy_Password(char  *password);
47 static void max_username();
48 static void malformed_username();
49 static void wrong_response();
50 static void no_user();
51 static void no_info();
52 static void userperm_usage();
53 static void show_header();
54 static void cleanup();
55 
56 
57 /* Globals so that exit routine can clean up echo */
58 static int		echoOff = 0;
59 static struct termios	oldOpts;
60 
61 typedef union {
62 	char	DataBuffer[DP_MAX_MSGLEN];
63 	void	*DataBuffer_p;
64 } data_buffer_t;
65 
66 
67 void
68 ADM_Process_useradd(int argc, char *argv[])
69 {
70 	static data_buffer_t	dataBuffer;
71 	rscp_msg_t		Message;
72 	struct timespec		Timeout;
73 	dp_user_adm_t		*admMessage;
74 	dp_user_adm_r_t		*admResponse;
75 	char			*userName;
76 
77 
78 	if (argc != 3) {
79 		(void) fprintf(stderr, "\n%s\n\n",
80 		    gettext("USAGE: scadm useradd <username>"));
81 		exit(-1);
82 	}
83 
84 	ADM_Start();
85 
86 	if (strlen(argv[2]) > DP_USER_NAME_SIZE) {
87 		max_username();
88 		exit(-1);
89 	}
90 
91 	admMessage = (dp_user_adm_t *)&dataBuffer;
92 	userName   = (char *)(&((char *)admMessage)[sizeof (dp_user_adm_t)]);
93 	admMessage->command = DP_USER_CMD_ADD;
94 	(void) strcpy(userName, argv[2]);
95 
96 	Message.type = DP_USER_ADM;
97 	Message.len  = sizeof (dp_user_adm_t) + strlen(userName) + 1;
98 	Message.data = admMessage;
99 	ADM_Send(&Message);
100 
101 	Timeout.tv_nsec = 0;
102 	Timeout.tv_sec  = ADM_SEPROM_TIMEOUT;
103 	ADM_Recv(&Message, &Timeout, DP_USER_ADM_R, sizeof (dp_user_adm_r_t));
104 
105 	admResponse = (dp_user_adm_r_t *)Message.data;
106 	if (admResponse->command != DP_USER_CMD_ADD) {
107 		wrong_response();
108 		exit(-1);
109 	}
110 
111 	if (admResponse->status == DP_ERR_USER_FULL) {
112 		(void) fprintf(stderr, "\n%s\n\n",
113 		    gettext("scadm: all user slots are full"));
114 		exit(-1);
115 	} else if (admResponse->status == DP_ERR_USER_THERE) {
116 		(void) fprintf(stderr, "\n%s\n\n",
117 		    gettext("scadm: user already exists"));
118 		exit(-1);
119 	} else if (admResponse->status == DP_ERR_USER_WARNING) {
120 		(void) fprintf(stderr, "\n%s\n\n",
121 		    gettext("scadm: username did not start with letter\n"
122 		    "        or did not contain lower case letter\n"));
123 		exit(-1);
124 	} else if (admResponse->status == DP_ERR_USER_BAD) {
125 		malformed_username();
126 		exit(-1);
127 	} else if (admResponse->status != 0) {
128 		(void) fprintf(stderr, "\n%s\n\n",
129 		    gettext("scadm: couldn't add user"));
130 		exit(-1);
131 	}
132 
133 	ADM_Free(&Message);
134 }
135 
136 
137 void
138 ADM_Process_userdel(int argc, char *argv[])
139 {
140 	static data_buffer_t	dataBuffer;
141 	rscp_msg_t		Message;
142 	struct timespec		Timeout;
143 	dp_user_adm_t		*admMessage;
144 	dp_user_adm_r_t		*admResponse;
145 	char			*userName;
146 
147 
148 	if (argc != 3) {
149 		(void) fprintf(stderr, "\n%s\n\n",
150 		    gettext("USAGE: scadm userdel <username>"));
151 		exit(-1);
152 	}
153 
154 	ADM_Start();
155 
156 	if (strlen(argv[2]) > DP_USER_NAME_SIZE) {
157 		max_username();
158 		exit(-1);
159 	}
160 
161 	admMessage = (dp_user_adm_t *)&dataBuffer;
162 	userName   = (char *)(&((char *)admMessage)[sizeof (dp_user_adm_t)]);
163 	admMessage->command = DP_USER_CMD_DEL;
164 	(void) strcpy(userName, argv[2]);
165 
166 	Message.type = DP_USER_ADM;
167 	Message.len  = sizeof (dp_user_adm_t) + strlen(userName) + 1;
168 	Message.data = admMessage;
169 	ADM_Send(&Message);
170 
171 	Timeout.tv_nsec = 0;
172 	Timeout.tv_sec  = ADM_SEPROM_TIMEOUT;
173 	ADM_Recv(&Message, &Timeout, DP_USER_ADM_R, sizeof (dp_user_adm_r_t));
174 
175 	admResponse = (dp_user_adm_r_t *)Message.data;
176 	if (admResponse->command != DP_USER_CMD_DEL) {
177 		wrong_response();
178 		exit(-1);
179 	}
180 
181 	if (admResponse->status == DP_ERR_USER_NONE) {
182 		no_user();
183 		exit(-1);
184 	} else if (admResponse->status == DP_ERR_USER_BAD) {
185 		malformed_username();
186 		exit(-1);
187 	} else if (admResponse->status != 0) {
188 		(void) fprintf(stderr, "\n%s\n\n",
189 		    gettext("scadm: couldn't delete user"));
190 		exit(-1);
191 	}
192 
193 	ADM_Free(&Message);
194 }
195 
196 
197 void
198 ADM_Process_usershow(int argc, char *argv[])
199 {
200 	static data_buffer_t	dataBuffer;
201 	rscp_msg_t		Message;
202 	struct timespec		Timeout;
203 	dp_user_adm_t		*admMessage;
204 	dp_user_adm_r_t		*admResponse;
205 	char			*userName;
206 	char			*permissions;
207 	char			*passwd;
208 	int			index;
209 
210 
211 
212 	if ((argc != 2) && (argc != 3)) {
213 		(void) fprintf(stderr, "\n%s\n\n",
214 		    gettext("USAGE: scadm usershow [username]"));
215 		exit(-1);
216 	}
217 
218 	ADM_Start();
219 
220 	if (argc == 3) {
221 		admMessage = (dp_user_adm_t *)&dataBuffer;
222 		admMessage->command = DP_USER_CMD_SHOW;
223 		Message.type = DP_USER_ADM;
224 		Message.data = admMessage;
225 
226 		if (strlen(argv[2]) > DP_USER_NAME_SIZE) {
227 			max_username();
228 			exit(-1);
229 		}
230 		userName = (char *)(&((char *)admMessage)[
231 		    sizeof (dp_user_adm_t)]);
232 		(void) strcpy(userName, argv[2]);
233 		admMessage->parm = DP_USER_SHOW_USERNAME;
234 		Message.len = sizeof (dp_user_adm_t) + strlen(userName) + 1;
235 		ADM_Send(&Message);
236 
237 		Timeout.tv_nsec = 0;
238 		Timeout.tv_sec  = ADM_SEPROM_TIMEOUT;
239 		ADM_Recv(&Message, &Timeout,
240 		    DP_USER_ADM_R, sizeof (dp_user_adm_r_t));
241 
242 		admResponse = (dp_user_adm_r_t *)Message.data;
243 		if (admResponse->command != DP_USER_CMD_SHOW) {
244 			wrong_response();
245 			exit(-1);
246 		}
247 
248 		if (admResponse->status == DP_ERR_USER_NONE) {
249 			no_user();
250 			exit(-1);
251 		} else if (admResponse->status == DP_ERR_USER_BAD) {
252 			malformed_username();
253 			exit(-1);
254 		} else if (admResponse->status != 0) {
255 			no_info();
256 			exit(-1);
257 		}
258 
259 		userName = &(((char *)admResponse)[
260 		    sizeof (dp_user_adm_r_t)]);
261 		permissions = &userName[strlen(userName)+1];
262 		passwd = &permissions[strlen(permissions)+1];
263 		show_header();
264 		(void) printf(" %-16s    %-15s    ", userName, permissions);
265 		if (strncmp(passwd, "Assigned", 12) == 0) {
266 			(void) printf("%s\n\n", gettext("Assigned"));
267 		} else if (strncmp(passwd, "None", 12) == 0) {
268 			(void) printf("%s\n\n", gettext("None"));
269 		} else {
270 			(void) printf("%-12s\n\n", passwd);
271 		}
272 		ADM_Free(&Message);
273 	} else {
274 		show_header();
275 		for (index = 1; index <= DP_USER_MAX; index++) {
276 			admMessage = (dp_user_adm_t *)&dataBuffer;
277 			admMessage->command = DP_USER_CMD_SHOW;
278 			admMessage->parm    = index;
279 
280 			Message.type = DP_USER_ADM;
281 			Message.data = admMessage;
282 			Message.len  = sizeof (dp_user_adm_t);
283 			ADM_Send(&Message);
284 
285 			Timeout.tv_nsec = 0;
286 			Timeout.tv_sec  = ADM_SEPROM_TIMEOUT;
287 			ADM_Recv(&Message, &Timeout,
288 			    DP_USER_ADM_R, sizeof (dp_user_adm_r_t));
289 
290 			admResponse = (dp_user_adm_r_t *)Message.data;
291 			if (admResponse->command != DP_USER_CMD_SHOW) {
292 				wrong_response();
293 				exit(-1);
294 			}
295 
296 			if (admResponse->status == DP_ERR_USER_NONE) {
297 				ADM_Free(&Message);
298 				continue;
299 			} else if (admResponse->status == DP_ERR_USER_BAD) {
300 				malformed_username();
301 				exit(-1);
302 			} else if (admResponse->status != 0) {
303 				no_info();
304 				exit(-1);
305 			}
306 
307 			userName = &(((char *)admResponse)[
308 			    sizeof (dp_user_adm_r_t)]);
309 			permissions = &userName[strlen(userName)+1];
310 			passwd = &permissions[strlen(permissions)+1];
311 			(void) printf(" %-16s    %-15s    ",
312 			    userName, permissions);
313 			if (strncmp(passwd, "Assigned", 12) == 0) {
314 				(void) printf("%s\n", gettext("Assigned"));
315 			} else if (strncmp(passwd, "None", 12) == 0) {
316 				(void) printf("%s\n", gettext("None"));
317 			} else {
318 				(void) printf("%-12s\n", passwd);
319 			}
320 
321 			ADM_Free(&Message);
322 		}
323 		(void) printf("\n");
324 	}
325 }
326 
327 
328 void
329 ADM_Process_userpassword(int argc, char *argv[])
330 {
331 	static data_buffer_t	dataBuffer;
332 	rscp_msg_t		Message;
333 	struct timespec		Timeout;
334 	dp_user_adm_t		*admMessage;
335 	dp_user_adm_r_t		*admResponse;
336 	char			*userName;
337 	char			*password;
338 	int			passTry;
339 
340 
341 	/* Try to set password up to 3 times on Malformed password */
342 	passTry = 3;
343 
344 	if (argc != 3) {
345 		(void) fprintf(stderr, "\n%s\n\n",
346 		    gettext("USAGE: scadm userpassword <username>"));
347 		exit(-1);
348 	}
349 
350 	ADM_Start();
351 
352 	if (strlen(argv[2]) > DP_USER_NAME_SIZE) {
353 		max_username();
354 		exit(-1);
355 	}
356 
357 	admMessage = (dp_user_adm_t *)&dataBuffer;
358 	admMessage->command = DP_USER_CMD_PASSWORD;
359 	userName = (&((char *)admMessage)[sizeof (dp_user_adm_t)]);
360 	(void) strcpy(userName, argv[2]);
361 	password = (&((char *)admMessage)[sizeof (dp_user_adm_t) +
362 	    strlen(userName) + 1]);
363 
364 	for (;;) {
365 		ADM_Get_Password(password);
366 
367 		Message.type = DP_USER_ADM;
368 		Message.len  = sizeof (dp_user_adm_t) + strlen(userName) +
369 		    strlen(password) + 2;
370 		Message.data = admMessage;
371 		ADM_Send(&Message);
372 
373 		ADM_Destroy_Password(password);
374 		Timeout.tv_nsec = 0;
375 		Timeout.tv_sec  = ADM_SEPROM_TIMEOUT;
376 		ADM_Recv(&Message, &Timeout,
377 		    DP_USER_ADM_R, sizeof (dp_user_adm_r_t));
378 
379 		admResponse = (dp_user_adm_r_t *)Message.data;
380 		if (admResponse->command != DP_USER_CMD_PASSWORD) {
381 			wrong_response();
382 			exit(-1);
383 		}
384 
385 		if (admResponse->status == DP_ERR_USER_NONE) {
386 			no_user();
387 			exit(-1);
388 		} else if (admResponse->status == DP_ERR_USER_BAD) {
389 			malformed_username();
390 			exit(-1);
391 		} else if (admResponse->status == DP_ERR_USER_PASSWD) {
392 			(void) fprintf(stderr, "\n%s\n\n",
393 			    gettext("scadm: malformed password\n"
394 			    "        A valid password is between 6 and 8 "
395 			    "characters,\n"
396 			    "        has at least two alphabetic characters, "
397 			    "and at\n"
398 			    "        least one numeric or special character. "
399 			    "The\n"
400 			    "        password must differ from the user's "
401 			    "login name\n"
402 			    "        and any reverse or circular shift of that "
403 			    "login\n"
404 			    "        name.\n"));
405 			passTry--;
406 			if (passTry > 0) {
407 				ADM_Free(&Message);
408 				continue;
409 			} else
410 				exit(-1);
411 		} else if (admResponse->status != 0) {
412 			(void) fprintf(stderr, "\n%s\n\n",
413 			    gettext("scadm: couldn't change password"));
414 			exit(-1);
415 		}
416 
417 		/* password was changed successfully, get out of while */
418 		break;
419 	}
420 
421 	ADM_Free(&Message);
422 }
423 
424 
425 void
426 ADM_Process_userperm(int argc, char *argv[])
427 {
428 	static data_buffer_t	dataBuffer;
429 	rscp_msg_t		Message;
430 	struct timespec		Timeout;
431 	dp_user_adm_t		*admMessage;
432 	dp_user_adm_r_t		*admResponse;
433 	char			*userName;
434 	int			permissions;
435 	int			index;
436 
437 
438 	if ((argc != 3) && (argc != 4)) {
439 		userperm_usage();
440 		exit(-1);
441 	}
442 
443 	if (argc == 3) {
444 		permissions = 0;
445 	} else {
446 		if ((strlen(argv[3]) > 4) || (strlen(argv[3]) < 1)) {
447 			userperm_usage();
448 			exit(-1);
449 		}
450 
451 		permissions = 0;
452 		for (index = 0; index < strlen(argv[3]); index++) {
453 			if ((argv[3][index] != 'c') &&
454 			    (argv[3][index] != 'C') &&
455 			    (argv[3][index] != 'u') &&
456 			    (argv[3][index] != 'U') &&
457 			    (argv[3][index] != 'a') &&
458 			    (argv[3][index] != 'A') &&
459 			    (argv[3][index] != 'r') &&
460 			    (argv[3][index] != 'R')) {
461 				userperm_usage();
462 				exit(-1);
463 			}
464 
465 			if ((argv[3][index] == 'c') ||
466 			    (argv[3][index] == 'C')) {
467 				/* See if this field was entered twice */
468 				if ((permissions & DP_USER_PERM_C) != 0) {
469 					userperm_usage();
470 					exit(-1);
471 				}
472 				permissions = permissions | DP_USER_PERM_C;
473 			}
474 
475 			if ((argv[3][index] == 'u') ||
476 			    (argv[3][index] == 'U')) {
477 				/* See if this field was enetered twice */
478 				if ((permissions & DP_USER_PERM_U) != 0) {
479 					userperm_usage();
480 					exit(-1);
481 				}
482 				permissions = permissions | DP_USER_PERM_U;
483 			}
484 
485 			if ((argv[3][index] == 'a') ||
486 			    (argv[3][index] == 'A')) {
487 				/* See if this field was enetered twice */
488 				if ((permissions & DP_USER_PERM_A) != 0) {
489 					userperm_usage();
490 					exit(-1);
491 				}
492 				permissions = permissions | DP_USER_PERM_A;
493 			}
494 
495 			if ((argv[3][index] == 'r') ||
496 			    (argv[3][index] == 'R')) {
497 				/* See if this field was enetered twice */
498 				if ((permissions & DP_USER_PERM_R) != 0) {
499 					userperm_usage();
500 					exit(-1);
501 				}
502 				permissions = permissions | DP_USER_PERM_R;
503 			}
504 		}
505 	}
506 
507 	ADM_Start();
508 
509 	if (strlen(argv[2]) > DP_USER_NAME_SIZE) {
510 		max_username();
511 		exit(-1);
512 	}
513 
514 	admMessage = (dp_user_adm_t *)&dataBuffer;
515 	admMessage->command = DP_USER_CMD_PERM;
516 	admMessage->parm    = permissions;
517 	userName   = (char *)(&((char *)admMessage)[sizeof (dp_user_adm_t)]);
518 	(void) strcpy(userName, argv[2]);
519 
520 	Message.type = DP_USER_ADM;
521 	Message.len  = sizeof (dp_user_adm_t) + strlen(userName) + 1;
522 	Message.data = admMessage;
523 	ADM_Send(&Message);
524 
525 	Timeout.tv_nsec = 0;
526 	Timeout.tv_sec  = ADM_SEPROM_TIMEOUT;
527 	ADM_Recv(&Message, &Timeout, DP_USER_ADM_R, sizeof (dp_user_adm_r_t));
528 
529 	admResponse = (dp_user_adm_r_t *)Message.data;
530 	if (admResponse->command != DP_USER_CMD_PERM) {
531 		wrong_response();
532 		exit(-1);
533 	}
534 
535 	if (admResponse->status == DP_ERR_USER_NONE) {
536 		no_user();
537 		exit(-1);
538 	} else if (admResponse->status == DP_ERR_USER_BAD) {
539 		malformed_username();
540 		exit(-1);
541 	} else if (admResponse->status != 0) {
542 		(void) fprintf(stderr, "\n%s\n\n",
543 		    gettext("scadm: couldn't change permissions"));
544 		exit(-1);
545 	}
546 
547 	ADM_Free(&Message);
548 }
549 
550 
551 static void
552 ADM_Get_Password(char *password)
553 {
554 	static char		pass1[64];
555 	static char		pass2[64];
556 	static struct termios	newOpts;
557 	int			passTry;
558 	int			validPass;
559 
560 
561 	validPass = 0;
562 	passTry   = 3;
563 
564 	if (signal(SIGINT, cleanup) == SIG_ERR) {
565 		(void) fprintf(stderr, "\n%s\n\n",
566 		    gettext("scadm: cleanup() registration failed"));
567 		exit(-1);
568 	}
569 
570 	echoOff = 1;
571 	(void) tcgetattr(0, &oldOpts);
572 	newOpts = oldOpts;
573 	newOpts.c_lflag &= ~ECHO;
574 	(void) tcsetattr(0, TCSANOW, &newOpts);
575 
576 	while ((passTry > 0) && (validPass == 0)) {
577 		passTry = passTry - 1;
578 		(void) printf("%s", gettext("Password: "));
579 		(void) scanf("%s", pass1);
580 		(void) printf("\n");
581 		(void) fflush(stdin);
582 		(void) printf("%s", gettext("Re-enter Password: "));
583 		(void) scanf("%s", pass2);
584 		(void) printf("\n");
585 
586 		/* Truncate at 8 characters  */
587 		pass1[8] = pass2[8] = '\0';
588 
589 		if ((strcmp(pass1, pass2) != 0) && (passTry > 0)) {
590 			ADM_Destroy_Password(pass1);
591 			ADM_Destroy_Password(pass2);
592 			(void) fprintf(stderr, "%s\n\n",
593 			    gettext("Passwords didn't match, try again"));
594 		} else if ((strcmp(pass1, pass2) != 0) && (passTry <= 0)) {
595 			ADM_Destroy_Password(pass1);
596 			ADM_Destroy_Password(pass2);
597 			(void) fprintf(stderr, "\n%s\n\n",
598 			    gettext("scadm: ERROR, passwords didn't match"));
599 			(void) tcsetattr(0, TCSANOW, &oldOpts);
600 			exit(-1);
601 		} else {
602 			validPass = 1;
603 		}
604 	}
605 
606 	(void) tcsetattr(0, TCSANOW, &oldOpts);
607 	echoOff = 0;
608 	(void) strcpy(password, pass1);
609 	ADM_Destroy_Password(pass1);
610 	ADM_Destroy_Password(pass2);
611 }
612 
613 
614 static void
615 cleanup()
616 {
617 	if (echoOff)
618 		(void) tcsetattr(0, TCSANOW, &oldOpts);
619 
620 	exit(-1);
621 }
622 
623 
624 static void
625 ADM_Destroy_Password(char *password)
626 {
627 	int index;
628 
629 	for (index = 0; index < strlen(password); index++)
630 		password[index] = 0x1;
631 }
632 
633 
634 static void
635 max_username()
636 {
637 	(void) fprintf(stderr,
638 	    gettext("\nscadm: maximum username length is %d\n\n"),
639 	    DP_USER_NAME_SIZE);
640 }
641 
642 
643 static void
644 malformed_username()
645 {
646 	(void) fprintf(stderr,
647 	    "\n%s\n\n", gettext("scadm: malformed username"));
648 }
649 
650 
651 static void
652 wrong_response()
653 {
654 	(void) fprintf(stderr, "\n%s\n\n",
655 	    gettext("scadm: SC returned wrong response"));
656 }
657 
658 
659 static void
660 no_user()
661 {
662 	(void) fprintf(stderr,
663 	    "\n%s\n\n", gettext("scadm: username does not exist"));
664 }
665 
666 
667 static void
668 no_info()
669 {
670 	(void) fprintf(stderr, "\n%s\n\n",
671 	    gettext("scadm: couldn't get information on user"));
672 }
673 
674 
675 static void
676 userperm_usage()
677 {
678 	(void) fprintf(stderr, "\n%s\n\n",
679 	    gettext("USAGE: scadm userperm <username> [cuar]"));
680 }
681 
682 
683 static void
684 show_header()
685 {
686 	int i;
687 	int usernLen = strlen(gettext("username"));
688 	int permLen = strlen(gettext("permissions"));
689 	int pwdLen = strlen(gettext("password"));
690 
691 	(void) printf("\n");
692 	(void) putchar(' ');
693 	(void) printf("%s", gettext("username"));
694 	for (i = 0; i < (20 - usernLen); i++)
695 		(void) putchar(' ');
696 
697 	(void) printf("%s", gettext("permissions"));
698 	for (i = 0; i < (19 - permLen); i++)
699 		(void) putchar(' ');
700 
701 	(void) printf("%s\n", gettext("password"));
702 
703 	(void) putchar(' ');
704 	for (i = 0; i < usernLen; i++)
705 		(void) putchar('-');
706 	for (; i < 20; i++)
707 		(void) putchar(' ');
708 
709 	for (i = 0; i < permLen; i++)
710 		(void) putchar('-');
711 	for (; i < 19; i++)
712 		(void) putchar(' ');
713 
714 	for (i = 0; i < pwdLen; i++)
715 		(void) putchar('-');
716 	(void) printf("\n");
717 }
718