This article is part <1> of the "write-A-shell" series, in which we first complete a shell-based implementation of the most basic functionality in the shells. In this article, I will describe the implementation of the idea, as well as the introduction of the following system API and some C language library functions.
Shell prompt
People who have used Linux know that when we open the terminal, there will be a line of words in the command line, there will be a cursor after the deletion, the line is the Shell prompt.
Prompt format
The format of the Shell prompt that we typically see is as follows:
[email protected]:~/path$
The first step of the Shell we're going to write is to implement this thing.
Implementation ideas
From the prompt format we know we need to get the first:
- User name
- Host Name
- Current path
We do this primarily by invoking the Linux system API.
Required function 0x00 get current user name passwd struct
A struct is defined in Linux that passwd
defines information about the user, /usr/include/pwd.h
The structure is defined as follows:
/* The passwd structure. */struct passwd{ char *pw_name; /* Username. */ char *pw_passwd; /* Password. */ __uid_t pw_uid; /* User ID. */ __gid_t pw_gid; /* Group ID. */ char *pw_gecos; /* Real name. */ char *pw_dir; /* Home directory. */ char *pw_shell; /* Shell program. */};
Getpwuid () and Getuid () functions
- getuid (): used to get the ID of the current user
- Getpwuid (uid_t uid): get struct based on user ID
passwd
Usage:
#include <pwd.h>#include <sys/types.h>#include <stdio.h>intMain () {uid_t my_uid; STRUCTPASSWD *my_info; My_info =getpwuid (Getuid ());printf("My name = [%s]\n", my_info->pw_name);printf("My passwd = [%s]\n", MY_INFO->PW_PASSWD);printf("My uid = [%d]\n", My_info->pw_uid);printf("My gid = [%d]\n", My_info->pw_gid);printf("My gecos = [%s]\n", My_info->pw_gecos);printf("My dir = [%s]\n", My_info->pw_dir);printf("My shell = [%s]\n], My_info->pw_shell); Return0;}
0X02 get the current host name
Through the gethostname()
function we can get the current hostname
int256;char hostname[max_name_len];gethostname(hostname, max_path_len);
0x03 getting the current path
getced()
we can get the current path through the function
int1024;char pathname[max_path_len];getcwd(pathname, max_path_len);
Other issues that the 0x04 needs to handle display in the current user directory
For the prompt in the current directory we use the home directory ~
to replace, for the prompt is not in the current directory we use the full directory to display, which is currently the default terminal in Ubuntu to take the prompt display format.
Implementation strategy:
- Displays the full directory if the previous part of the current directory does not match the user's home directory path
- Displays the full directory if the current directory length is less than the user home directory path
- In other cases, replace the current directory with the same part of the user's home directory
~
Implementation method:
- Get the user home directory:
We passwd
get the user home directory path by accessing the struct:
char home_dir[1024];pwd = getpwuid(getuid());home_dir = pwd->pw_dir;
Whether it is the root user
For the prompt that is the root user we will use #
to represent, for other users $
to use to represent.
Implementation method:
We use the getuid()
function to determine whether the current user is the root user, and if the return value is 0, it is the root user.
C library function sprintf () function
Its function is to write formatted data to a string buffer.
Header file
stdio.h
Prototype
int sprintf( char *buffer, const char *format, [ argument] … );
Parameter list
- Buffer : A char pointer that points to the buffer of the string that will be written.
- Format : formatted string.
- [Argument] ... : optional parameter, which can be any type of data.
STRNCMP () function
This function is used to compare the first num characters of a S1 and S2 string. If two strings are equal, STRNCMP will return 0.
Header file
string.h
Prototype
int strncmp ( const char * str1, const char * str2, size_t num );
Parameter list
- str1: string 1 to compare
- str2: string 2 to compare
- Num: The number of digits to compare
Reference Code
The following code is affixed to implement the Shell prompt:
See:https://github.com/luoyhang003/linux_kernel_expriment/tree/master/exp2
/ * * prompt.c----Description *------------------------------------------------------------* date:april 8th, 2 016 * Copyright:written by Jason Luo-[email protected] * Function:promption of the Shell *---------------------------- -------------------------------- */#include "lshell.h"Const intMax_name_len = the;Const intMax_path_len =1024x768;voidGet_prompt (Char*prompt) {extern structpasswd *pwd;CharHostname[max_name_len];CharPathname[max_path_len];intPrompt_length; PWD = Getpwuid (Getuid ()); GETCWD (pathname, Max_path_len);if(GetHostName (hostname, max_path_len) = =0) {sprintf(Prompt,"Lshell>%[email protected]%s:", Pwd->pw_name, hostname); }Else{sprintf(Prompt,"Lshell>%[email protected]:", pwd->pw_name); } prompt_length =strlen(prompt);if(strlen(pathname) <strlen(Pwd->pw_dir) | | (strncmp(Pathname, Pwd->pw_dir,strlen(Pwd->pw_dir))) !=0) {sprintf(Prompt + Prompt_length,'%s ', pathname); }Else{sprintf(Prompt + Prompt_length,"~%s", pathname +strlen(Pwd->pw_dir)); } prompt_length =strlen(prompt);if(Geteuid ()! =0) {sprintf(Prompt + Prompt_length,"$"); }Else{sprintf(Prompt + Prompt_length,"#"); }return;}
This article's copyright belongs to the author Luo voyage All, uses Attribution-noncommercial 3.0 License. Any person may reproduce, share, but not be used without permission for commercial purposes; reprint please specify the source. Thanks for cooperating!
Implementation of the part 1:shell prompt