1. 程式人生 > >unix/linux程式設計實踐教程:who命令

unix/linux程式設計實踐教程:who命令

1. who命令的編寫

1) 通過man命令的幫助,找到who命令的儲存檔案

man who
2) 在man who的幫助下,找到utmp這個資訊
man -k utmp

3) 看man -k utmp的輸出,找到以下這條資訊:
utmp (5)             - login records

4) 然後通過指令:
man 5 utmp

    裡面就有我們需要的一切資訊了。

程式碼如下:

#include <stdio.h>
#include <utmp.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

void showtime( long );
void show_info( struct utmp * utbufp );
int main()
{
	struct utmp	current_record;
	int		utmpfd;
	int		reclen = sizeof( current_record );

	if ( ( utmpfd = open( UTMP_FILE, O_RDONLY ) ) == -1 ){
		perror( UTMP_FILE );
		exit( 1 );
	}

	while ( read( utmpfd, ¤t_record, reclen ) == reclen )
		show_info( ¤t_record );
	close( utmpfd );
	return 0;
}

void show_info( struct utmp *utbufp )
{
	if ( utbufp->ut_type != USER_PROCESS )
		return;
	printf("%-8.8s ", utbufp->ut_name );
	printf("%-8.8s ", utbufp->ut_line );
	showtime( utbufp->ut_time );
#ifdef SHOWHOST
	if ( utbufp->ut_host[ 0 ] != '\0' )
		printf("(%s)", utbufp->ut_host);
#endif
	printf("\n");
}

void showtime( long timeval )
{
	char	*cp;
	cp = ctime( &timeval );

	printf("%12.12s", cp + 4 );
}

    程式輸出:
[email protected]:~$ ./a.out
leichaoj :0       Aug 25 21:39
leichaoj pts/0    Aug 25 21:43

2. who原始碼的學習

    核心程式碼用到了快取的技術(即一次讀取多個使用者,然後輸出):

static void
who (const char *filename, int options)
{
  size_t n_users;
  STRUCT_UTMP *utmp_buf;

  if (read_utmp (filename, &n_users, &utmp_buf, options) != 0)
    error (EXIT_FAILURE, errno, "%s", filename);

  if (short_list)
    list_entries_who (n_users, utmp_buf);
  else
    scan_entries (n_users, utmp_buf);

  free (utmp_buf);
}

static void
list_entries_who (size_t n, const STRUCT_UTMP *utmp_buf)
{
  unsigned long int entries = 0;
  char const *separator = "";

  while (n--)
    {
      if (IS_USER_PROCESS (utmp_buf))
        {
          char *trimmed_name;

          trimmed_name = extract_trimmed_name (utmp_buf);

          printf ("%s%s", separator, trimmed_name);
          free (trimmed_name);
          separator = " ";
          entries++;
        }
      utmp_buf++;
    }
  printf (_("\n# users=%lu\n"), entries);
}

3. 編寫終端登出程式碼

    將登入記錄從UTMP檔案中刪除即可。

#include <stdio.h>
#include <utmp.h>
#include <unistd.h>
#include <fcntl.h>

int logout_tty( char *line );
int main( int argc, char **argv )
{
	if ( 2 != argc ){
		printf("please enter the logout name\n");
		return -1;
	}
	if ( logout_tty( argv[ 1 ] ) == 0 )
		printf("success\n");
	else{
		printf("fail\n");
	}
	
	return 0;
}

int logout_tty( char *line )
{
	int	fd;
	struct utmp rec;
	int	len = sizeof( struct utmp );
	int	retval = -1;
	if ( ( fd = open( UTMP_FILE, O_RDWR ) ) == -1 )
		return -1;
	while ( read( fd, &rec, len ) == len )
		if ( strncmp( rec.ut_line, line, sizeof( rec.ut_line ) ) == 0 ){
			rec.ut_type = DEAD_PROCESS;
			if ( time( &rec.ut_time ) != -1 )
				if ( lseek( fd, -len, SEEK_CUR ) != -1 )
					if ( write( fd, &rec, len ) == len )
						return 0;
		break;
		}
	if ( close( fd ) == -1 )
		retval = -1;
	return retval;
}

切換到管理員許可權進行執行:
[email protected]:/home/leichaojian# who
leichaojian :0           2014-08-25 21:39 (:0)
leichaojian pts/0        2014-08-25 21:43 (:0)
[email protected]:/home/leichaojian# ./a.out :0
success
[email protected]:/home/leichaojian# who
leichaojian pts/0        2014-08-25 21:43 (:0)

4. whoami的編寫

1)

#include<stdio.h>
#include<unistd.h>
int main()
{
        printf("%s\n", getlogin() );
        return 0;
}

2) 
#include<stdio.h>
#include<unistd.h>
#include <pwd.h>
#include <sys/types.h>
int main()
{
        struct passwd *p;
        p = getpwuid( geteuid() );
        printf("%s\n", p->pw_name );
        return 0;
}

5. cp命令的編寫

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#define MAXLINE 4096
int main( int argc, char **argv )
{
	int	n;
	int	fd1;
	int 	fd2;
	char	buf[ MAXLINE ];
	if ( argc != 3 ){
		printf("argument should be 3\n");
		return -1;
	}

	if ( strcmp( argv[ 1 ], argv[ 2 ] ) == 0 ){
		printf("same file\n");
		return -1;
	}

	if ( ( fd1 = open( argv[ 1 ], O_RDONLY ) ) == -1 ){
		printf("open file error\n");
		return -1;
	}
	if ( ( fd2 = open( argv[ 2 ], O_WRONLY | O_CREAT | O_TRUNC ) ) == -1 ){
		printf("create file error\n");
		return -1;
	}
	while ( ( n = read( fd1, buf, MAXLINE ) ) > 0 ){
		if ( write( fd2, buf, n ) != n ){
			printf("write error\n");
			return -1;
		}
	}
	if (n == -1 ){
		printf("read error\n");
		return -1;
	}

	if ( close( fd1 ) == -1 || close( fd2 ) == -1 ){
		printf("error close\n");
		return -1;
	}

	return 0;
}

    程式輸出:
[email protected]:~$ cc cp.c
[email protected]:~$ ./a.out cp.c cp.c
same file
[email protected]:~$ ./a.out cp.c foo
[email protected]:~$ chmod 777 foo

有三條命令不知道如何進行編寫:ac,last,od