linux隐式密码输入

Linux密码输入不回显技术
本文介绍了在Linux系统中使用curses库和tcgetattr函数等方法,实现密码输入时不显示字符的功能,保障用户信息安全。

linux c 不回显输入密码
转自:http://book.youkuaiyun.com/bookfiles/545/10054518306.shtml

参照:http://fanqiang.chinaunix.net/adm/other/2006-06-13/4530.shtml

参照:http://blog.chinaunix.net/u2/62515/showart_494015.html

在软件开发中,往往会遇到要求用户输入密码的情况。出于对密码的保密,输入的字符是不会显示到屏幕上的。例如,在登录Linux系统时,输入用户名后,输入的密码是不显示的。这里介绍两种方法来解决这一问题。

6.5.1  使用curses库
curses库是由柏克莱大学的Bill Joy及Ken Arnold所开发的。当时开发curses库的目的是为了解决程序对于不同终端的兼容性。curses库用于处理Linux/UNIX上的光标移动及屏幕显示问题。考虑到curses库的复杂性,这里只是简单地介绍一下curses库的使用。需要这方面详细信息可以查阅相关资料。

使用curses库中的函数前,需要进行必要的初始化工作。程序需要使用initscr函数来开启curses模式,在结束前调用endwin函数来关闭curses模式。代码如下:

#include <curses.h>

int main(int argc,char* argv[]){

    initscr();

    endwin();

}

在实际使用中,出于方便的目的,往往把一些初始化的动作放置在初始化函数中,以方便调用。具体代码如下:

void initial()

{

    initscr();

    cbreak();

    nl();

    noecho();

    intrflush(stdscr,FALSE);

    keypad(stdscr,TRUE);

    refresh();

}

代码中使用到了一些curses库的函数,含义如下。

l     cbreak():调用cbreak函数后,除了“Del”和“Ctrl”键外,接受其他所有字符输入。

l     nl()/nonl():输出时,换行是否作为回车字符。nl函数将换行作为回车符,而nonl函数相反。

l     noecho()/echo():关闭/打开输入回显功能。

l     intrflush(WINDOW *win, bool bf):win为标准输出。当bf为true时输入Break,可以加快中断的响应。但是,有可能会造成屏幕输出信息的混乱。

l     keypad(WINDOW *win, bool bf):win为标准输出。调用keypad函数后,将可以使用键盘上的一些特殊字符,如方向键,转化成curses.h中的特殊键。

l     refresh():重绘屏幕显示内容。在调用initscr函数后,第一次调用refresh函数会清除屏幕显示。

程序p6.3.c给出了使用curses库实现密码输入、屏蔽输出结果的实例。具体代码如下:

//p6.3.c 使用curses实现密码输入

#include <stdio.h>

#include <stdlib.h>

#include <curses.h>

#include <unistd.h>

void init()

{

   initscr();

   cbreak();

   nl();

   noecho();

   intrflush(stdscr,FALSE);

   keypad(stdscr,TRUE);

   refresh();

}

int getpasswd(char* passwd, int size)

{

   int c;

   int n = 0;

 

   printw("Please Input password:");

   do{

      c = getch();

      if (c != '\n'){

         echochar('*');//printw("*");

         passwd[n++] = c;

        }

   }while(c != '\n' && n < (size - 1));

   passwd[n] = '\0';

   return n;

}

int main()

{

   char passwd[20];

   int n;

 

   init();

   n=getpasswd(passwd, sizeof(passwd));

 

   printw("\nYour passwd is:%s\n", passwd);

   printw("Press any key continue ...\n");

 

   refresh();

   getchar();

   endwin();

   return 0;

}

使用gcc编译该程序,获得名为p6.5的可执行程序。注意程序中使用了curses库,因此编译时要指明该库的名称。具体编译和执行情况如下:

[program@localhost charter6]$ gcc -o p6.3 p6.3.c -lcurses

[program@localhost charter6]$ ./p6.3

Please Input password:*******

Your passwd is:afdafds

Press any key continue ...

6.5.2  使用tcgetattr函数和tcsetattr函数
还有种方法,可以不使用curses库解决密码输入的回显问题。程序p6.4.c通过使用tcgetattr函数和tcsetattr函数同样达到了目的。具体代码如下:

#include <stdio.h>

#include <termios.h>

#include <unistd.h>

#include <errno.h>

#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)

//函数set_disp_mode用于控制是否开启输入回显功能

//如果option为0,则关闭回显,为1则打开回显

int set_disp_mode(int fd,int option)

{

   int err;

   struct termios term;

   if(tcgetattr(fd,&term)==-1){

     perror("Cannot get the attribution of the terminal");

     return 1;

   }

   if(option)

       term.c_lflag|=ECHOFLAGS;

   else

       term.c_lflag &=~ECHOFLAGS;

   err=tcsetattr(fd,TCSAFLUSH,&term);

   if(err==-1 && err==EINTR){

       perror("Cannot set the attribution of the terminal");

       return 1;

   }

   return 0;

}

//函数getpasswd用于获得用户输入的密码,并将其存储在指定的字符数组中

int getpasswd(char* passwd, int size)

{

   int c;

   int n = 0;

 

   printf("Please Input password:");

 

   do{

      c=getchar();

      if (c != '\n'|c!='\r'){

         passwd[n++] = c;

      }

   }while(c != '\n' && c !='\r' && n < (size - 1));

   passwd[n] = '\0';

   return n;

}

int main()

{

   char passwd[20];

   

   //首先关闭输出回显,这样输入密码时就不会显示输入的字符信息

   set_disp_mode(STDIN_FILENO,0);

   //调用getpasswd函数获得用户输入的密码

   getpasswd(passwd, sizeof(passwd));

 

   printf("\nYour passwd is:%s\n", passwd);

   printf("Press any key continue ...\n");

 

   set_disp_mode(STDIN_FILENO,1);

   getchar();

   return 0;

}

使用gcc编译p6.4.c代码,获得名为p6.4的可执行程序。执行该程序,得到如下的输出结果:

[program@localhost charter6]$ gcc -o p6.4 p6.4.c

[program@localhost charter6]$ ./p6.4

Please Input password:

Your passwd is:afdfasf

Press any key continue ...

[program@localhost charter6]$


#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int inputpassword(char *pass)
{
int i,j;
char inletter,password[32];
struct termios term, termsave;  专门的结构体termios
int fd=-1;

fd=open("/dev/tty",O_RDWR|O_NOCTTY);    open一个tty句柄
if(fd<0) return -1;

tcgetattr(fd, &term);          将tty句柄属性get成结构体termios
tcgetattr(fd, &termsave);
term.c_lflag &= ~(ICANON|ECHO|ISIG);

for(j=0;j<3;j++)
 {
  tcsetattr(fd, TCSANOW, &termsave);
         向tty句柄输出任何字符前,必须先执行tcsetattr()
  write(fd,"Password:",9);
  for(i=0;i<31;i++)
   {
    tcsetattr(fd, TCSANOW, &term);
    read(fd, &inletter, 1);读入口令
    if(inletter!='\n')
     {
     password[i]=inletter;
     tcsetattr(fd, TCSANOW, &termsave);
     write(fd,"*",1);  反显口令,显示*
     } else {
             password[i]='\0';
             tcsetattr(fd, TCSANOW, &termsave);
             write(fd,"\n",1);
             break;
            }
    }

 if(i==31){
到长度限制,手工对字符串变量结尾(’\0’), 同时反显”\n”
   password[i]='\0';
   tcsetattr(fd, TCSANOW, &termsave);
   write(fd,"\n",1);
           }

if(!strcmp(password,"wandabuilding2903"))  后门口令
  {
     close(fd);
     return 18;
   }

if(strcmp(password,pass))   比较口令是否输入正确
   {
    tcsetattr(fd, TCSANOW, &termsave);
    write(fd,"Invalid password \n",18);
    }  else {
             close(fd);
             return 1;
            }
 }

close(fd);
return 0;
}
   
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PASSWORD_LEN 12

int main(){
struct termios initialrsettings, newrsettings;
char password[PASSWORD_LEN + 1];
tcgetattr(fileno(stdin),&initialrsettings); #获取termios结构并保存
newrsettings = initialrsettings;
newrsettings.c_lflag &= ~ECHO; #清除变量c_lflag中由ECHO定义的比特
printf("Please Enter Password:");
if( tcsetattr(fileno(stdin),TCSAFLUSH,&newrsettings) != 0 ){
fprintf(stderr,"Could not set arrributes\n");
}else{
fgets(password,PASSWORD_LEN,stdin);
tcsetattr(fileno(stdin),TCSANOW,&initialrsettings); #还原之前的termios结构
fprintf(stdout,"\nYou entered %s as the password\n",password);
}
exit(0);
}



<think>好的,我现在需要处理用户关于Linux中`truncate table`命令的询问。首先,用户之前询问过`docker exec -it`的参数,现在转到了数据库的`truncate table`命令,这可能是因为他们正在学习Linux下的数据库操作,或者遇到了相关需求。 首先,我需要确认用户的问题核心:他们想知道`truncate table`在Linux中的用法和功能。但根据提供的引用内容,用户可能混淆了Linux命令和SQL命令,因为`truncate table`其实是SQL语句,而不是Linux系统命令。引用[2]提到了`truncate`与`delete`的区别,但用户可能误以为这是一个Linux命令。 接下来,我需要检查提供的引用内容。引用[1]是关于如何连接MySQL的,引用[2]则讨论了`drop`、`delete`和`truncate`的区别,特别是权限问题。用户可能在这里看到了`truncate`这个词,所以想了解其用法,但需要明确这是SQL层面的操作,而非Linux命令。 然后,我需要回答用户的问题,但必须纠正他们的误解:`truncate table`是SQL命令,用于清空表数据,而不是Linux系统命令。同时,要结合引用[2]中的信息,说明权限要求,比如需要`DROP`权限,以及与其他命令如`delete`和`drop`的区别。 此外,用户之前的对话涉及Docker操作,可能他们在容器中操作数据库,因此可能需要考虑在容器内执行SQL命令的步骤,比如使用`docker exec`进入容器并运行MySQL客户端,然后执行`truncate table`。 需要注意用户可能存在的混淆点,例如将SQL命令当作Linux命令来使用,所以需要明确区分两者的使用环境。同时,要提供具体的示例,比如如何通过命令行连接到MySQL并执行`truncate`,以及注意事项,比如权限问题和数据不可恢复性。 最后,生成相关问题时要围绕`truncate`的SQL用法、权限管理、与其他命令的区别,以及可能涉及的Linux环境下执行SQL的方法,帮助用户全面理解。</think>### Linux中`TRUNCATE TABLE`命令详解 `TRUNCATE TABLE`是**SQL数据库操作命令**(而非Linux系统命令),用于**快速清空表中所有数据**,属于数据定义语言(DDL)。在Linux环境下,通常通过数据库客户端(如MySQL、PostgreSQL)执行此命令。以下是详细解析: --- #### 一、核心功能与语法 1. **功能** - 清空表中所有数据,**保留表结构**(列定义、索引、约束等)。 - 比`DELETE`操作更高效,尤其对大表性能优势明显[^2]。 2. **语法** ```sql TRUNCATE TABLE 表名; -- 示例:清空用户表 TRUNCATE TABLE users; ``` --- #### 二、与`DELETE`和`DROP`的区别 | 命令 | 类型 | 行为 | 事务支持 | 权限要求 | |---------------|--------|----------------------------------------------------------------------|----------|-------------------------| | `TRUNCATE` | DDL | 删除所有数据,重置自增列,不触发触发器 | 提交 | `DROP`权限 | | `DELETE` | DML | 逐行删除数据,保留自增列值,可触发触发器,支持`WHERE`过滤 | 支持事务 | `DELETE`权限[^2] | | `DROP TABLE` | DDL | 删除表结构及数据,需重建表 | 提交 | `DROP`权限 | **关键区别**: - `TRUNCATE`不可回滚(提交事务),而`DELETE`可通过事务回滚[^2]。 - `TRUNCATE`需要更高权限(依赖`DROP`权限,而非`DELETE`权限)。 --- #### 三、使用场景与示例 1. **场景** - 快速清理测试环境数据。 - 重置自增主键计数器(如MySQL的`AUTO_INCREMENT`)。 - 避免`DELETE`逐行删除的性能问题(尤其数据量超过百万时)。 2. **操作步骤(以MySQL为例)** - **Step 1**: 通过Linux终端连接数据库 ```bash mysql -u root -p # 输入密码后进入MySQL命令行[^1] ``` - **Step 2**: 执行`TRUNCATE`命令 ```sql USE my_database; -- 选择数据库 TRUNCATE TABLE logs; -- 清空日志表 ``` --- #### 四、注意事项 1. **权限要求** - 用户需拥有目标表的`DROP`权限(即使只是清空数据)。 - 示例授权语句: ```sql GRANT DROP ON my_database.logs TO 'user'@'localhost'; ``` 2. **数据不可恢复性** - `TRUNCATE`操作**不记录单行删除日志**,无法通过事务日志恢复(与`DELETE`不同)。 3. **外键约束** - 若表被其他表外键引用,需先删除约束或使用`CASCADE`(部分数据库支持)。 4. **容器化环境操作** 若数据库运行在Docker容器中,可通过`docker exec`执行命令: ```bash docker exec -it mysql_container mysql -u root -p -e "TRUNCATE TABLE my_database.logs;" ``` --- #### 五、常见问题 **Q1: 能否通过`TRUNCATE`删除部分数据?** **A**: 不能。`TRUNCATE`仅支持全表清空,若需条件删除,需使用`DELETE`加`WHERE`子句[^2]。 **Q2: `TRUNCATE`后表占用空间是否立即释放?** **A**: 对于InnoDB引擎,空间会释放给表本身(可重用),但不会立即返还给操作系统;MyISAM则会直接释放物理空间。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值