Exemplo n.º 1
0
static int ti_refresh( int must )
/*******************************/
{
    int         i;
    int         incr;               // chars per line
    LP_PIXEL    bufp, sbufp;        // buffer and shadow buffer
    LP_PIXEL    pos;                // the address of the current char
    LP_PIXEL    blankStart;         // start of spaces to eos and then complete
                                    // draw
    int         lastattr = -1;
    int         bufSize;
    LP_PIXEL    bufEnd;
    bool        cls = dirty_area.row1;   // line on which we should clr_eos
                                    // and then continue to draw
    bool        done = false;

    // Need these for startup and the refresh key
    if( UserForcedTermRefresh ) {
        // in the case where a user has forced a refresh we must assume
        // the screen is trashed, and so our cursor position is unknown
        OldCol = -1;
        OldRow = -1;
    }
    must |= UserForcedTermRefresh;
    UserForcedTermRefresh = false;

    // Move the cursor & return if dirty box contains no chars
    if( dirty_area.row0 == dirty_area.row1 && dirty_area.col0 == dirty_area.col1 ) {
        ti_hwcursor();
        __flush();
        return( 0 );
    }

    QNXDebugPrintf4( "ti_refresh( %d, %d )->( %d, %d )", dirty_area.row0,
                                    dirty_area.col0, dirty_area.row1, dirty_area.col1 );

    // Disable cursor during draw if we can
    if( UIData->cursor_type != C_OFF ) {
        TI_CURSOR_OFF();
    }

    // Get our new and old buffers
    bufp = UIData->screen.origin;
    sbufp = shadow;

    // Get some screen statistics
    bufSize = UIData->height * UIData->width;
    bufEnd = &UIData->screen.origin[bufSize - 1];
    incr = UIData->screen.increment;

    // Find a place where we could use clear to end of screen
    if( OptimizeTerminfo ) {
        blankStart = NonBlankEnd( bufEnd, bufSize, *bufEnd ) + 1;
    } else {
        blankStart = bufEnd;
    }

    if( blankStart <= UIData->screen.origin && TCAP_CLS ) {
        // if we could do it at the top then we might as well
        // not bother doing anything else
        lastattr = new_attr( UIData->screen.origin->attr, -1 );
        done = true;
    } else {
        lastattr = -1;

        if( !must ) {
            int         r,c;
            int         pos;
            bool        diff = false;

            while( dirty_area.col0 < dirty_area.col1 ) {
                for( r = dirty_area.row0; r < dirty_area.row1; r++ ) {
                    pos = r * incr + dirty_area.col0;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.col0++;
            }

            diff = false;
            while( dirty_area.col0 < dirty_area.col1 ) {
                for( r = dirty_area.row0; r < dirty_area.row1; r++ ) {
                    pos = r * incr + dirty_area.col1 - 1;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.col1--;
            }

            diff = false;
            while( dirty_area.row0 < dirty_area.row1 ) {
                for( c = dirty_area.col0; c < dirty_area.col1; c++ ) {
                    pos = dirty_area.row0 * incr + c;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.row0++;
            }

            diff = false;
            while( dirty_area.row0 < dirty_area.row1 ) {
                for( c = dirty_area.col0; c < dirty_area.col1; c++ ) {
                    pos = ( dirty_area.row1 - 1 ) * incr + c;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] ) ) {
                        diff = true;
                        break;
                    }
                }
                if( diff )
                    break;
                dirty_area.row1--; 
            }
        }

        if( OptimizeTerminfo ) {
            // Set cls if drawing box is bottom part (or whole) of screen
            if( dirty_area.col0 == 0 &&
                dirty_area.row1 == UIData->height &&
                dirty_area.col1 == UIData->width &&
                TCAP_CLS ) {

                if( clr_eos[0] != '\0' ) {
                    cls = dirty_area.row0;
                } else if( dirty_area.row0 == 0 ) {
                    cls = 0;
                }
            }

            if( !must ) {
                // Adjust cls so refresh looks pretty
                for( ; cls < dirty_area.row1; cls++ ) {
                    int         pos;
                    int         pos2;

                    pos = cls * incr;
                    pos2 = pos + UIData->width - 1;
                    if( !PIXELEQUAL( bufp[pos], sbufp[pos] )
                      && ( bufp[pos].ch != sbufp[pos2].ch
                      || bufp[pos].attr == sbufp[pos2].attr) ) {
                        break;
                    }
                }
            }

            /*
            if( cls < dirty_area.row1 ) {
                // If cls is set to by this point we've decided to clear the area
                blankStart = bufEnd;
            }
            */
        }
    }

    if( cls == 0 || ( TI_FillColourSet && blankStart < bufp && TCAP_CLS ) ) {
        // Clear the screen if cls is set to 0 or if the screen
        // is supposed to be blank
        if( cls == 0 ) {
            TI_RESTORE_COLOUR();
        }
        TI_CLS();
    } else {
        // we still have work to do if it turned out we couldn't use the
        // blank start after all
        done = false;
    }

    if( !done ) {
        // If the screen isn't completely blank we have to do some work
        int             j;
        bool            ca_valid;       // is cursor address valid?

        int             rcount;         // repeat count
        char            rchar;          // repeated character
        bool            ralt;           // if repeated character is in acs
        int             rcol;           // starting column of repeated chars

        bufp += dirty_area.row0 * incr;
        sbufp += dirty_area.row0 * incr;

        for( i = dirty_area.row0; i < dirty_area.row1; i++ ) {
            ca_valid = false;
            rcount = 0;

            if( i == cls ) {
                TI_RESTORE_COLOUR();
                TI_CURSOR_MOVE( 0, i );
                putp( clr_eos );
                ca_valid = true;
                //assert( dirty_area.col0==0 && dirty_area.col1==UIData->width );
            }

            for( j = dirty_area.col0; j < dirty_area.col1; j++ ) {
                pos = &bufp[j];
                if( !must && (
                    ( cls <= i )
                    ? ( bufp[j].ch == ' ' && ( (bufp[j].attr & 0x70) == 0 ) )
                    : ( PIXELEQUAL( bufp[j], sbufp[j] ) && pos <= blankStart ) ) ) {
                    ca_valid = false;
                    continue;
                }

                if( !ca_valid ) {
                    QNXDebugPrintf2( "cursor address %d, %d\n", j, i );

                    // gotta dump chars before we move
                    TI_DUMPCHARS();
                    TI_CURSOR_MOVE( j, i );
                    ca_valid = true;
                }

                if( bufp[j].attr != lastattr ) {
                    // dump before changing attrs too...
                    TI_DUMPCHARS();
                    lastattr = new_attr( bufp[j].attr, lastattr );
                }

                // Clear to end of screen if we can
                if( pos > blankStart ) {
                    if( TI_FillColourSet ) {
                        // Dump before blank to end of screen...
                        TI_DUMPCHARS();
                        putp( clr_eos );
                        update_shadow();
                        return( 0 );
                    } else {
                        pos = bufEnd;
                    }
                }

                if( !TI_ignore_bottom_right || (j != UIData->width - 1) || (i != UIData->height - 1) ) {
                    // slurp up the char
                    TI_SLURPCHAR( bufp[j].ch );
                    OldCol++;

                    // if we walk off the edge our position is undefined
                    if( OldCol >= UIData->width ) {
                        OldCol = -1;
                        OldRow = -1;
                    }
                }
            }
            // Make sure we dump any stragglers
            TI_DUMPCHARS();

            bufp += incr;
            sbufp += incr;
        }
    }

    update_shadow();
    return( 0 );
}
Exemplo n.º 2
0
/*
 * passwd - change a user's password file information
 *
 *	This command controls the password file and commands which are used
 * 	to modify it.
 *
 *	The valid options are
 *
 *	-d	delete the password for the named account (*)
 *	-e	expire the password for the named account (*)
 *	-f	execute chfn command to interpret flags
 *	-g	execute gpasswd command to interpret flags
 *	-i #	set sp_inact to # days (*)
 *	-k	change password only if expired
 *	-l	lock the password of the named account (*)
 *	-n #	set sp_min to # days (*)
 *	-r #	change password in # repository
 *	-s	execute chsh command to interpret flags
 *	-S	show password status of named account
 *	-u	unlock the password of the named account (*)
 *	-w #	set sp_warn to # days (*)
 *	-x #	set sp_max to # days (*)
 *
 *	(*) requires root permission to execute.
 *
 *	All of the time fields are entered in days and converted to the
 * 	appropriate internal format. For finer resolute the chage
 *	command must be used.
 */
int main (int argc, char **argv)
{
	const struct passwd *pw;	/* Password file entry for user      */

#ifndef USE_PAM
	char *cp;		/* Miscellaneous character pointing  */

	const struct spwd *sp;	/* Shadow file entry for user   */
#endif				/* !USE_PAM */

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	/*
	 * The program behaves differently when executed by root than when
	 * executed by a normal user.
	 */
	amroot = (getuid () == 0);

	/*
	 * Get the program name. The program name is used as a prefix to
	 * most error messages.
	 */
	Prog = Basename (argv[0]);

	sanitize_env ();

	OPENLOG ("passwd");

	{
		/*
		 * Parse the command line options.
		 */
		int option_index = 0;
		int c;
		static struct option long_options[] = {
			{"all", no_argument, NULL, 'a'},
			{"delete", no_argument, NULL, 'd'},
			{"expire", no_argument, NULL, 'e'},
			{"help", no_argument, NULL, 'h'},
			{"inactive", required_argument, NULL, 'i'},
			{"keep-tokens", no_argument, NULL, 'k'},
			{"lock", no_argument, NULL, 'l'},
			{"mindays", required_argument, NULL, 'n'},
			{"quiet", no_argument, NULL, 'q'},
			{"root", required_argument, NULL, 'R'},
			{"repository", required_argument, NULL, 'r'},
			{"status", no_argument, NULL, 'S'},
			{"unlock", no_argument, NULL, 'u'},
			{"warndays", required_argument, NULL, 'w'},
			{"maxdays", required_argument, NULL, 'x'},
			{NULL, 0, NULL, '\0'}
		};

		while ((c = getopt_long (argc, argv, "adei:kln:qR:r:Suw:x:",
		                         long_options, &option_index)) != -1) {
			switch (c) {
			case 'a':
				aflg = true;
				break;
			case 'd':
				dflg = true;
				anyflag = true;
				break;
			case 'e':
				eflg = true;
				anyflag = true;
				break;
			case 'i':
				if (   (getlong (optarg, &inact) == 0)
				    || (inact < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				iflg = true;
				anyflag = true;
				break;
			case 'k':
				/* change only if expired, like Linux-PAM passwd -k. */
				kflg = true;	/* ok for users */
				break;
			case 'l':
				lflg = true;
				anyflag = true;
				break;
			case 'n':
				if (   (getlong (optarg, &age_min) == 0)
				    || (age_min < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				nflg = true;
				anyflag = true;
				break;
			case 'q':
				qflg = true;	/* ok for users */
				break;
			case 'R':
				if ('/' != optarg[0]) {
					fprintf (stderr,
					         _("%s: invalid chroot path '%s'\n"),
					         Prog, optarg);
					exit (E_BAD_ARG);
				}
				newroot = optarg;

				if (access (newroot, F_OK) != 0) {
					fprintf(stderr,
					        _("%s: chroot directory %s does not exist\n"),
					        Prog, newroot);
					exit (E_BAD_ARG);
				}
				if ( chroot(newroot) != 0 ) {
					fprintf(stderr,
				            _("%s: unable to chroot to directory %s\n"),
					        Prog, newroot);
					exit (E_BAD_ARG);
				}
				break;
			case 'r':
				/* -r repository (files|nis|nisplus) */
				/* only "files" supported for now */
				if (strcmp (optarg, "files") != 0) {
					fprintf (stderr,
					         _("%s: repository %s not supported\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
				break;
			case 'S':
				Sflg = true;	/* ok for users */
				break;
			case 'u':
				uflg = true;
				anyflag = true;
				break;
			case 'w':
				if (   (getlong (optarg, &warn) == 0)
				    || (warn < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				wflg = true;
				anyflag = true;
				break;
			case 'x':
				if (   (getlong (optarg, &age_max) == 0)
				    || (age_max < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				xflg = true;
				anyflag = true;
				break;
			default:
				usage (E_BAD_ARG);
			}
		}
	}

	/*
	 * Now I have to get the user name. The name will be gotten from the
	 * command line if possible. Otherwise it is figured out from the
	 * environment.
	 */
	pw = get_my_pwent ();
	if (NULL == pw) {
		fprintf (stderr,
		         _("%s: Cannot determine your user name.\n"), Prog);
		SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
		         (unsigned long) getuid ()));
		exit (E_NOPERM);
	}
	myname = xstrdup (pw->pw_name);
	if (optind < argc) {
		name = argv[optind];
	} else {
		name = myname;
	}

	/*
	 * Make sure that at most one username was specified.
	 */
	if (argc > (optind+1)) {
		usage (E_USAGE);
	}

	/*
	 * The -a flag requires -S, no other flags, no username, and
	 * you must be root.  --marekm
	 */
	if (aflg) {
		if (anyflag || !Sflg || (optind < argc)) {
			usage (E_USAGE);
		}
		if (!amroot) {
			fprintf (stderr, _("%s: Permission denied.\n"), Prog);
			exit (E_NOPERM);
		}
		setpwent ();
		while ( (pw = getpwent ()) != NULL ) {
			print_status (pw);
		}
		endpwent ();
		exit (E_SUCCESS);
	}
#if 0
	/*
	 * Allow certain users (administrators) to change passwords of
	 * certain users. Not implemented yet. --marekm
	 */
	if (may_change_passwd (myname, name))
		amroot = 1;
#endif

	/*
	 * If any of the flags were given, a user name must be supplied on
	 * the command line. Only an unadorned command line doesn't require
	 * the user's name be given. Also, -x, -n, -w, -i, -e, -d,
	 * -l, -u may appear with each other. -S, -k must appear alone.
	 */

	/*
	 * -S now ok for normal users (check status of my own account), and
	 * doesn't require username.  --marekm
	 */
	if (anyflag && optind >= argc) {
		usage (E_USAGE);
	}

	if (   (Sflg && kflg)
	    || (anyflag && (Sflg || kflg))) {
		usage (E_USAGE);
	}

	if (anyflag && !amroot) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		exit (E_NOPERM);
	}

	pw = xgetpwnam (name);
	if (NULL == pw) {
		fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog, name);
		exit (E_NOPERM);
	}
#ifdef WITH_SELINUX
	/* only do this check when getuid()==0 because it's a pre-condition for
	   changing a password without entering the old one */
	if ((is_selinux_enabled() > 0) && (getuid() == 0) &&
	    (check_selinux_access (name, pw->pw_uid, PASSWD__PASSWD) != 0)) {
		security_context_t user_context = NULL;
		const char *user = "******";
		if (getprevcon (&user_context) == 0) {
			user = user_context;
		}
		SYSLOG ((LOG_ALERT,
		         "%s is not authorized to change the password of %s",
		         user, name));
		fprintf(stderr,
		        _("%s: %s is not authorized to change the password of %s\n"),
		        Prog, user, name);
		if (NULL != user_context) {
			freecon (user_context);
		}
		exit (E_NOPERM);
	}
#endif				/* WITH_SELINUX */

	/*
	 * If the UID of the user does not match the current real UID,
	 * check if I'm root.
	 */
	if (!amroot && (pw->pw_uid != getuid ())) {
		fprintf (stderr,
		         _("%s: You may not view or modify password information for %s.\n"),
		         Prog, name);
		SYSLOG ((LOG_WARN,
			 "%s: can't view or modify password information for %s",
			 Prog, name));
		closelog ();
		exit (E_NOPERM);
	}

	if (Sflg) {
		print_status (pw);
		exit (E_SUCCESS);
	}
#ifndef USE_PAM
	/*
	 * The user name is valid, so let's get the shadow file entry.
	 */
	sp = getspnam (name); /* !USE_PAM, no need for xgetspnam */
	if (NULL == sp) {
		sp = pwd_to_spwd (pw);
	}

	cp = sp->sp_pwdp;

	/*
	 * If there are no other flags, just change the password.
	 */
	if (!anyflag) {
		STRFCPY (crypt_passwd, cp);

		/*
		 * See if the user is permitted to change the password. 
		 * Otherwise, go ahead and set a new password.
		 */
		check_password (pw, sp);

		/*
		 * Let the user know whose password is being changed.
		 */
		if (!qflg) {
			printf (_("Changing password for %s\n"), name);
		}

		if (new_password (pw)) {
			fprintf (stderr,
				 _("The password for %s is unchanged.\n"),
				 name);
			closelog ();
			exit (E_NOPERM);
		}
		do_update_pwd = true;
		do_update_age = true;
	}
#endif				/* !USE_PAM */
	/*
	 * Before going any further, raise the ulimit to prevent colliding
	 * into a lowered ulimit, and set the real UID to root to protect
	 * against unexpected signals. Any keyboard signals are set to be
	 * ignored.
	 */
	pwd_init ();

#ifdef USE_PAM
	/*
	 * Don't set the real UID for PAM...
	 */
	if (!anyflag) {
		do_pam_passwd (name, qflg, kflg);
		exit (E_SUCCESS);
	}
#endif				/* USE_PAM */
	if (setuid (0) != 0) {
		fputs (_("Cannot change ID to root.\n"), stderr);
		SYSLOG ((LOG_ERR, "can't setuid(0)"));
		closelog ();
		exit (E_NOPERM);
	}
	if (spw_file_present ()) {
		update_shadow ();
	} else {
		update_noshadow ();
	}

	nscd_flush_cache ("passwd");
	nscd_flush_cache ("group");

	SYSLOG ((LOG_INFO, "password for '%s' changed by '%s'", name, myname));
	closelog ();
	if (!qflg) {
		if (!anyflag) {
#ifndef USE_PAM
			printf (_("%s: password changed.\n"), Prog);
#endif				/* USE_PAM */
		} else {
			printf (_("%s: password expiry information changed.\n"), Prog);
		}
	}

	return E_SUCCESS;
}