Sabtu, 28 November 2015

File System : FUSE, Implementasi file system 'copy just once'

FUSE : File System in Userspace

sesuai dengan namanya dengan FUSE kita bisa mengimplementasikan file system dengan userspace program. Jadi implementasi dari FUSE bisa diprogram oleh penggunanya sendiri.

Apa itu file system :
File System adalah struktur logika yang digunakan untuk mengendalikan akses terhadap data yang ada pada harddisk. Terdapat berbagai jenis-jenisnya dan penggunaan algoritma yang berbeda.

FUSE

Filesystem in Userspace (FUSE) merupakan mekanisme sistem operasi untuk sistem operasi Unix-like yang memungkinkan pengguna tidak ber-hak istimewa menciptakan file system mereka sendiri tanpa mengubah kode kernel. Hal ini dicapai dengan menjalankan kode file system di userspace, sedangkan modul FUSE hanya menyediakan "jembatan" untuk antarmuka kernel yang sebenarnya.

Module kernel FUSE dan FUSE library berhubungan melalui sebuah special file descriptoryang didapatkan dengan membuka /dev/fuse. FUSE kernal module meneruskan request ke aplikasi fuse anda. aplikasi anda memerintahkan fuse cara menjawab request. FUSE kernal module dan FUSE library berkomunikasi lewat file deskriptor spesial yang diperoleh dengan membuka /dev/fuse. file ini dapat terbuka berkali-kali dan file deskriptor yang diperoleh diteruskan ke mount syscall, untuk menyesuaikan deskriptor dengan filesystem mount.

Contoh Penerapan :
Jihad dan Sekar adalah teman baik dan sangat dekat. Karena kedekatan itulah, timbul rasa yang berbeda di hati Jihad untuk Sekar. Suatu hari, Jihad mengutarakan isi hatinya kepada Sekar. Namun, Sekar ingin melihat dulu kesungguhan Jihad, Ia memberikan syarat bagi Jihad untuk mendapatkan hatinya. Syarat tersebut adalah Sekar ingin Jihad membuatkannya sebuah implementasi dari fuse yang baru saja didapatkannya dari asistensi praktikum sistem operasi. Sebelumnya, ketika asistensi hanya diajarkan implementasi dasar yaitu mengaitkan direktori lain (mount) dengan fuse. Padahal ketika dikaitkan dengan direktori (mount) Sekar ingin agar implementasi fuse tersebut memiliki kriteria sebagai berikut:
File dalam direktori tersebut hanya bisa di­copy atau dipindahkan sebanyak satu kali,sehingga file yang telah di­copy atau dipindahkan tersebut tidak dapat di­copy atau dipindahkan lagi (file terkunci). Contoh: terdapat file A. jika file A dicopy atau dipindahkan maka akan terbentuk file salinan atau hasil pindahan file A, sedangkan file A sendiri tidak bisa diapa­apakan lagi (terkunci). Namun file salinan A tetap bisa dicopy atau dipindahkan, begitu seterusnya.

Dari permasalah di atas fungsi yang kita implementasikan pada fuse yaitu.
getattr : Untuk memperoleh atribut/properties dari file yagn akan dicopy
getdir : Mendapatkan alamat file yang akan dicopy
mknod : membuat file baru yang kan dijadikan file hasil copy
chmod : digunakan untuk merubah permission agar file yang lama tidak bisa dicopy lagi.
open : membuka file yang akan dicopy untuk kemudian dibaca
read : membaca data dari file yang akan dicopy
write : menuliskan data ke file hasil mknod dan data hasil dari read

Penerapan :
Hanya dengan merubah pada fungsi write, yaitu merubah permission yang akan dicopy.
untuk mendapatkan alamat file yang akan dicopy, kita buat variabel baru, untuk mendapat alamat kita ambil pada variabel fpath di funsgi read.

Coding lengkap :

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <sys/statfs.h>

static const char *dirpath ="/home/mifta28/SISOP4";

char readPath[1000];

static int xmp_getattr(const char *path, struct stat *stbuf)
{
    int res;
    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    res = lstat(fpath, stbuf);  
    if (res == -1)
        return -errno;

    return 0;
}

static int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
{
    DIR *dp;
    struct dirent *de;
    int res = 0;
    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    dp = opendir(fpath);
    if(dp == NULL)
        return -errno;

    while((de = readdir(dp)) != NULL)
    {
        res = filler(h, de->d_name, de->d_type);
        if(res != 0)
            break;
    }

    closedir(dp);
    return res;
}

static int xmp_mknod(const char *path, mode_t mode, dev_t rdev)
{
    int res;
    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    res = mknod(fpath, mode, rdev);
    if(res == -1)
        return -errno;

    return 0;
}

static int xmp_chmod(const char *path, mode_t mode)
{
    int res;

    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    res = chmod(fpath, mode);
    if(res == -1)
        return -errno;

    return 0;
}

static int xmp_open(const char *path, int flags)
{
    int res;
    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    res = open(fpath, flags);
    if(res == -1)
        return -errno;

    close(res);
    return 0;
}

static int xmp_read(const char *path, char *buf, size_t size, off_t offset)
{
    int fd;
    int res;
    char fpath[1000];
    sprintf(fpath, "%s%s", dirpath, path);
    strcpy(readPath,path);
    fd = open(fpath, O_RDONLY);
    if(fd == -1)
        return -errno;
  
    res = pread(fd, buf, size, offset);
    if(res == -1)
        res = -errno;

    close(fd);
    return res;
}

static int xmp_write(const char *path, const char *buf, size_t size, off_t offset)
{
    int fd;
    int res;
    int res1;
    char fpath[1000],temp1[1000];

    sprintf(fpath, "%s%s", dirpath, path);
    fd = open(fpath, O_WRONLY);
    if(fd == -1)
        return -errno;

    res = pwrite(fd, buf, size, offset);
    if(res == -1)
        res = -errno;

    sprintf(temp1, "%s%s", dirpath, readPath);
    res1 = chmod(temp1, 0000);
    if(res1 == -1)
        res1 = -errno;

    close(fd);
    return res;
}

static struct fuse_operations xmp_oper = {
.getattr = xmp_getattr,
//.readlink = xmp_readlink,
.getdir = xmp_getdir,
.mknod = xmp_mknod,
//.mkdir = xmp_mkdir,
//.symlink = xmp_symlink,
//.unlink = xmp_unlink,
//.rmdir = xmp_rmdir,
//.rename = xmp_rename,
//.link = xmp_link,
.chmod = xmp_chmod,
//.chown = xmp_chown,
//.truncate = xmp_truncate,
//.utime = xmp_utime,
.open = xmp_open,
.read = xmp_read,
.write = xmp_write,
//.release = xmp_release,
//.fsync = xmp_fsync

};

int main(int argc, char *argv[])
{
    fuse_main(argc, argv, &xmp_oper);
    return 0;
}



Cara mengcompile program

Cara emnjalankan program , dimana tmp/fuse merupakan direktori tempat kita akan meng mount file

Proses copy pada file pertama sukses

Proses copy yang kedua untuk file yang sama maka akan terjadi error.

Sekian terimakasih :) semoga bermanfaat.


Jumat, 06 November 2015

IPC Aplikasi Penjualan dan Thread Music Player : Implementasi Thread dan IPC

THREAD & IPC 
Dalam suatu sistem operasi, thread adalah hal yang sangat penting, karena dengan adanya thread Program dapat menjalankan lebih dari satu tugas secara bersamaan. Misalnya saat kalian membaca tulisan ini dari web browser, sebenarnya terdapat thread untuk menerima data dari internet/server dan juga terdapat thread untuk menampilkan data seperti teks, gambar dll yang berjalan secara bersamaan. Bayangkan jika tidak ada thread, untuk menampilkan blog ini maka akan memakan waktu yang lebih lama. karena program harus melakukan proses secara bergantian.

Sedangkan IPC (Interprocess Communication) adalah suatu metode dimana suatu process bisa berkomunikasi dengan process lainnya. jadi hal ini juga sangat penting karena suatu proses bisa jadi membutuhkan data dari proses yang lain untuk menjalankan tugasnya. Contoh penerapan yang biasanya sering kita lakukan yaitu copy-paste dimana terjadi process sharing data/IPC anatara clipboard dengan process-process yang lainnya.

Secara singkat definisi Thread dan IPC menurut beberapa referensi di internet yaitu:

Thread : Merupakan unit dasar dari penggunaan CPU, thread saling berbagi bagian program, bagian data dan sumber daya sistem operasi dengan thread lain yang mengacu pada proses yang sama. Thread terdiri atas ID thread, program counter, himpunan register, dan stack. Dengan banyak kontrol thread proses dapat melakukan lebih dari satu pekerjaan pada waktu yang sama.

IPC : Mekanisme pertukaran data baik antara proses satu dengan proses lain dalam satu komputer maupun proses-proses dalam komputer yang berbeda.
Linux menyediakan beberapa metode IPC, yaitu: Shared Memory, Pipes, Message Queue, Semaphore, TCP/UDP socket.

implementasi thread : Music Player

Dalam implementasi kali ini akan membuat sebuah music player yang bisa memutar music namun tetap bisa menampilkan menu. detail deskripsi :

Fatih adalah seorang network administrator, dia bekerja menggunakan linux server. Suatu ketika fatih merasa jenuh dengan pekerjaannya dia ingin mendengarkan lagu, tetapi linux server tidak memiliki GUI sehingga fatih harus memutar musik menggunakan konsol/terminal. Bantulah fatih membuat pemutar musik berbasis konsol.

Pemutar musik memiliki spesifikasi sebagai berikut :
1. Perintah help untuk menampilkan daftar perintah yang dapat digunakan.
2. Memiliki fitur list untuk menampilkan semua lagu pada folder playlist
3. Memiliki fitur play untuk menjalankan lagu 
4. Memiliki fitur pause setelah t detik
5. Memiliki fitur continue setelah t detik
6. Memiliki fitur stop setelah t detik


Dari deskripsi permasalahan diatas kita akan membutuhkan 6 thread dimana masing-masing thread berfungsi untuk menampilkan menu, menampilkan playlist, menjalankan music, melakuan pause, melakukan resume dan men-stop lagu yang sedang diputar. untuk memutar suatu music disini kita menggunakan program mpg123.

untuk membuat suatu thread kita memerlukan pthread_t yang digunakan sibagad thread id.
kemudian kita buat suatu thread dengan pthread_create();
dimana fungsi tersebut akan memanggil program yang dijalankan dimana pada program dibawah berarti fungsi playandcount();
tiap-tiap thread akan menjalankan bagian fungsi sesuai dengan tid-nya masing-masing.

cara kerjanya apabila user memanggil thread ke 1 maka program akan menjalankan bagian menampilkan menu. lalu apabila user memanggil thread ke 3 maka program akan memutar music sesuai inputan user. apabila user kembali ke menu maka music amasih akan tetap diputar.


 #include <stdio.h>  
 #include <string.h>  
 #include <pthread.h>  
 #include <stdlib.h>  
 #include <unistd.h>  
 #include <string.h>  
 #define PATH "SISOP/LIST"  
 pthread_t tid[7];  
 int n;  
 char lagu[50];  
 char buf[100];  
 void* playandcount(void *arg)  
 {  
   pthread_t id=pthread_self();  
   int iter;  
   if(pthread_equal(id,tid[1]))  
   {  
     system("clear");  
      printf("-------------------------\n");  
      printf("ABAL-ABAL PLAYER\n");  
      printf("-------------------------\n");  
     printf("1. Help\n");  
     printf("2. Playlist\n");  
     printf("3. Play\n");  
     printf("4. Pause\n");  
     printf("5. Continue\n");  
     printf("6. Stop\n");  
   }  
   else if(pthread_equal(id,tid[2]))  
   {  
      system("clear");  
      printf("-------------------------\n");  
      printf("PLAYLIST\n");  
      printf("-------------------------\n");       
      snprintf(buf, sizeof(buf), "cd\ncd %s\nls | grep -v grep | grep .mp3", PATH);  
      system(buf);  
   }  
   else if(pthread_equal(id,tid[3]))  
   {  
     system("pkill mpg123");  
     system("clear");  
     snprintf(buf, sizeof(buf), "mpg123 %s",lagu);  
     system(buf);  
   }  
   else if(pthread_equal(id, tid[4]))  
   {  
     system("clear");  
     sleep(n);  
     system("pkill -STOP mpg123");  
   }  
   else if(pthread_equal(id, tid[5]))  
   {  
     system("clear");  
     sleep(n);  
     system("pkill -CONT mpg123");  
   }  
   else if(pthread_equal(id,tid[6]))  
   {  
     system("clear");  
     sleep(n);  
     system("pkill mpg123");  
   }  
   return NULL;  
 }  
 int main(void)  
 {  
 pthread_create(&(tid[1]), NULL, &playandcount, NULL);  
   system("clear");  
   while(1)  
   {  
      int input;  
     int err=0;  
     scanf("%d",&input);  
     if (err!=0) printf("\ncan't create thread : [%s]", strerror(err));  
     else if (input==1) err=pthread_create(&(tid[1]), NULL, &playandcount, NULL);  
     else if (input==2) err=pthread_create(&(tid[2]), NULL, &playandcount, NULL);  
     else if (input==3)  
     {  
       scanf("%s",lagu);  
       err=pthread_create(&(tid[3]), NULL, &playandcount, NULL);  
     }  
     else if (input==4)  
     {  
       scanf("%d",&n);  
       err=pthread_create(&(tid[4]), NULL, &playandcount, NULL);  
     }  
     else if (input==5)  
     {  
       scanf("%d",&n);  
       err=pthread_create(&(tid[5]), NULL, &playandcount, NULL);  
     }  
     else if (input==6)  
     {  
       scanf("%d",&n);  
       err=pthread_create(&(tid[6]), NULL, &playandcount, NULL);  
     }  
     else printf("Wrong Input\n");  
   }  
   return 0;  
 }  


Screenshot Menampilkan menu, music tetap play di background


implementasi : Aplikasi Penjual dan Pembeli

pada implementasi kali ini kita harus bisa mengkomunikasikan atara aplikasi penjual dan pembeli dengan IPC, dimana kedua aplikasi tersebut berbagi data stock barang. detail deskripsi :

Oink adalah seorang distributor komponen komputer untuk area Surabaya. Komponen yang tersedia di Oink Komputer yaitu RAM, harddisk, motherboard, PSU, VGA, dan processor. Setiap harinya dia melakukan banyak transaksi dengan beberapa pelanggannya. Setiap saat oink dapat menambahkan stok barangnya dan setiap pelanggan dapat membeli barang di oink comp. Oink merasa kesulitan dalam mencatat semua transaksinya dalam buku, jadi bantulah oink membuat sebuah aplikasi yang dapat memudahkan pekerjaannya. Terdapat 2 aplikasi, untuk penjual dan pembeli.
Berikut adalah kebutuhan dari aplikasi untuk penjual:
1. Terdapat fitur menu untuk menampilkan daftar menu: lihat stok, tambah stok
2. Fitur tambah stok memiliki format inputan: nama_barang jumlah_barang. Jika barang yang sudah ada di stok diinputkan kembali, maka stoknya bertambah.
3. FItur lihat stok menampilkan stok semua barang yang tersisa dengan format output: nama_barang jumlah_barang

Berikut adalah kebutuhan dari aplikasi untuk pembeli:
1. Terdapat fitur menu untuk menampilkan daftar menu: lihat stok, beli barang
2. Fitur beli barang memiliki format inputan: nama_barang jumlah_barang. Jika fitur ini dijalankan maka stok barang akan berkurang sesuai jumlah yang dibeli. Jika jumlah pembelian lebih dari stok yang tersedia, maka program menampilkan pesan kesalahan. 

3. FItur lihat stok menampilkan stok semua barang yang tersisa dengan format output: nama_barang jumlah_barang

Dari deskripsi diatas kita memerlukan metode IPC untuk bisa mengkomunikasikan data stock barang diantara dua proses. pada program kali ini kita akan menggunakan shared memory.


   key_t KEY;  --> Deklarasi key yang akan kita gunakan untuk mendapatkan ID share memory
   int ID;     --> Deklarasi variabel ID yang digunakan sebagai ID share memory
   Stock *data;  --> Tipe data dari share memory yang kita buat
   KEY = 6969;   --> Inisialisasi KEY, harus kita buat sama antar dua proses yang akan dihubungkan
   ID = shmget(KEY, sizeof(Stock), IPC_CREAT | 0666);  --> Mendapatakn ID dan mencreate share memory dari key yg sudah kita inisialisasi
   data = (Stock *) shmat(ID, NULL, 0);  --> meng assignmenkan share memory yg kita buat tadi ke variabel data

jadi pada program kali ini akan terdapat variabel data dimana variabel tersebut dimiliki dan diakses oleh kedua program. Ketika program pembeli mengubah data yang ada pada variabel data maka perubahan juga akan terjadi di palikasi penjual, dan begitupun sebaliknya.

Aplikasi Penjual
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <sys/types.h>  
 #include <sys/ipc.h>  
 #include <sys/shm.h>  
 #include <sys/stat.h>  
 #include <unistd.h>  
 #include <string.h>  
 typedef struct STOK  
 {  
   int RAM;  
   int harddisk;  
   int motherboard;  
   int PSU;  
   int VGA;  
   int processor;  
 } Stock;  
 void lihatBarang(Stock *data)  
 {  
   system("clear");  
   printf("DAFTAR STOCK BARANG\n")     ;  
   printf("-------------------------\n");  
   printf("RAM\t\t : %d \n",data->RAM);  
   printf("HARDDISK\t : %d \n",data->harddisk);  
   printf("MOTHERBOARD\t : %d \n",data->motherboard);  
   printf("PSU\t\t : %d \n",data->PSU);  
   printf("VGA\t\t : %d \n",data->VGA);  
   printf("PROCESSOR\t : %d \n",data->processor);  
   printf("-------------------------\n");  
 }  
 void tambahBarang(Stock *data)  
 {  
   int pilihan, tambah;  
   system("clear");  
   printf("LIST BARANG\n");  
   printf("-------------------------\n");  
   printf("1.RAM\n2.harddisk\n3.motherboard\n4.PSU\n5.VGA\n6.processor\n");  
   printf("\n\nPilih barang : ");  
   scanf("%d", &pilihan);  
   printf("Jumlah barang : ");  
   scanf("%d",&tambah);  
   switch(pilihan)  
   {  
   case 1:  
     data->RAM += tambah;  
     printf("STOK RAM : %d \n", data->RAM);  
     break;  
   case 2:  
     data->harddisk += tambah;  
     printf("STOK harddisk : %d \n", data->harddisk);  
     break;  
   case 3:  
     data->motherboard += tambah;  
     printf("STOK motherboard : %d \n", data->motherboard);  
     break;  
   case 4:  
     data->PSU += tambah;  
     printf("STOK PSU : %d \n", data->PSU);  
     break;  
   case 5:  
     data->VGA += tambah;  
     printf("STOK VGA : %d \n", data->VGA);  
     break;  
   case 6:  
     data->processor += tambah;  
     printf("STOK processor : %d \n", data->processor);  
     break;  
   default:  
     printf("PILIHAN SALAH : Barang Tidak Ada\n");  
   }  
 }  
 int main()  
 {  
   key_t KEY;  
   int ID;  
   Stock *data;  
   int pilihan;  
   KEY = 6969;  
   ID = shmget(KEY, sizeof(Stock), IPC_CREAT | 0666);  
   data = (Stock *) shmat(ID, NULL, 0);  
   data->RAM = 0;  
   data->harddisk = 0;  
   data->motherboard = 0;  
   data->PSU = 0;  
   data->VGA = 0;  
   data->processor = 0;  
   while(1)  
   {  
     printf("-------------------------\n");  
      printf("PENJUAL APP");  
     printf("\n-------------------------\n");  
     printf("1. Lihat Stok Barang\n");  
     printf("2. Tambah Barang\n");  
      printf("3. Exit\n");  
     printf("-------------------------\n");  
     printf("Pilih menu : ");  
     scanf("%d",&pilihan);  
     if (pilihan == 1)  
     {  
       lihatBarang(data);  
     }  
     else if(pilihan == 2)  
     {  
       tambahBarang(data);  
     }  
      else if(pilihan == 3)  
      {  
        system("clear");  
        return 0;  
      }  
     else getchar();  
   }  
 }  


Aplikasi Pembeli
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <sys/types.h>  
 #include <sys/ipc.h>  
 #include <sys/shm.h>  
 #include <sys/stat.h>  
 #include <unistd.h>  
 #include <string.h>  
 typedef struct STOK  
 {  
   int RAM;  
   int harddisk;  
   int motherboard;  
   int PSU;  
   int VGA;  
   int processor;  
 } Stock;  
 void lihatBarang(Stock *data)  
 {  
   system("clear");  
   printf("DAFTAR STOCK BARANG\n")     ;  
   printf("-------------------------\n");  
   printf("RAM\t\t : %d \n",data->RAM);  
   printf("HARDDISK\t : %d \n",data->harddisk);  
   printf("MOTHERBOARD\t : %d \n",data->motherboard);  
   printf("PSU\t\t : %d \n",data->PSU);  
   printf("VGA\t\t : %d \n",data->VGA);  
   printf("PROCESSOR\t : %d \n",data->processor);  
   printf("-------------------------\n");  
 }  
 void beliBarang(Stock *data)  
 {  
   int pilihan, jumlah;  
   system("clear");  
   printf("LIST BARANG\n");  
   printf("-------------------------\n");  
   printf("1.RAM\n2.harddisk\n3.motherboard\n4.PSU\n5.VGA\n6.processor\n");  
   printf("\n\nPilih barang : ");  
   scanf("%d", &pilihan);  
   printf("Jumlah pembelian : ");  
   scanf("%d",&jumlah);  
   switch(pilihan)  
   {  
   case 1:  
     if (jumlah > data->RAM)  
     {  
       printf("OUT OF STOCK\n");  
     }  
     else  
     {  
       printf("Anda membeli %d RAM\n", jumlah);  
       data->RAM -= jumlah;  
     }  
     break;  
   case 2:  
     if (jumlah > data->harddisk)  
     {  
       printf("OUT OF STOCK\n");  
     }  
     else  
     {  
       printf("Anda membeli %d harddisk\n",jumlah);  
       data->harddisk -= jumlah;  
     }  
     break;  
   case 3:  
     if (jumlah > data->motherboard)  
     {  
       printf("OUT OF STOCK\n");  
     }  
     else  
     {  
       printf("Anda membeli %d motherboard\n",jumlah);  
       data->motherboard -= jumlah;  
     }  
     break;  
   case 4:  
     if (jumlah > data->PSU)  
     {  
       printf("OUT OF STOCK\n");  
     }  
     else  
     {  
       printf("Anda membeli %d PSU\n",jumlah);  
       data->PSU -= jumlah;  
     }  
     break;  
   case 5:  
     if (jumlah > data->VGA)  
     {  
       printf("OUT OF STOCK\n");  
     }  
     else  
     {  
       printf("Anda membeli %d VGA\n",jumlah);  
       data->VGA -= jumlah;  
     }  
     break;  
   case 6:  
     if (jumlah > data->processor)  
     {  
       printf("OUT OF STOCK\n");  
     }  
     else  
     {  
       printf("Anda membeli %d processor\n",jumlah);  
       data->processor -= jumlah;  
     }  
     break;  
   default:  
     printf("PILIHAN SALAH : Barang Tidak Ada\n");  
   }  
 }  
 int main(void)  
 {  
   key_t KEY;  
   int ID;  
   Stock *data;  
   int pilih;  
   KEY = 6969;  
   ID = shmget(KEY, sizeof(Stock), 0666);  
   data = (Stock *) shmat(ID, NULL, 0);  
   while(1)  
   {  
     printf("-------------------------\n");  
      printf("PEMBELI APP");  
     printf("\n-------------------------\n");  
     printf("1. Lihat Stok Barang\n");  
     printf("2. Beli Barang\n");  
      printf("3. Exit\n");  
     printf("-------------------------\n");  
     printf("Pilih menu : ");  
     scanf("%d",&pilih);  
     if(pilih == 1)  
     {  
       lihatBarang(data);  
     }  
     else if(pilih == 2)  
     {  
       beliBarang(data);  
     }  
      else if(pilih == 3)  
      {  
        system("clear");  
        return 0;  
      }  
     else getchar();  
   }  
 }  


Aplikasi penjual menampilkan menu

Aplikasi penjual fitur Lihat Stock Barang

Aplikasi penjual Fitur Tambah Barang

Aplikasi Pembeli ftur Lihat stock Barang

Aplikasi pembeli fitur Beli Barang


Semoga bermanfaat :)

Sabtu, 17 Oktober 2015

Convert Gambar ke Grayscale Otomatis Menggunakan Program Daemon

Sebelum melangkah ke programnya alangkah baiknya kita berkenalan dulu dengan daemon, apa itu daemon?

Daemon adalah sebuah proses yang bekerja pada background. Daemon adalah sebuah proses yang didesain supaya proses tersebut tidak mendapatkan intervensi dari user biasanya bekerja dalam jangka waktu yang sangat lama dan bertugas menerima request dan menjalankan responsnya.

Proses pembuatan daemonnya sendiri yaitu dengan
1. melakukan forking, kemudian membunuh proses induk. Setelah proses induk mati maka process child tadi akan bekerja dibackground.
2. memanggil fungsi umask() Untuk memproteksi setiap file yg dibuta oleh daemon dan mencegah file-file previleges yang tidak aman dalam setiap pembuatan file.
3. melakukan setsid() agar proses mendapat session id baru untuk membuat proses daemon bekerja secara independen daripada proses-proses lain, termasuk juga proses yang induknya.
4. Merubah direktori kerja, program daemon haruslah berjalan didirektori yang selalu bisa diakses. agar ketika reboot daemon bisa dijalankan.
5. Untuk mencegah terjadinya intervensi dari user maka standar I/O descriptor dan descriptor yang diwarisi dari proses induk harus ditutup yaitu STDIN (standar input), STDOUT (standar output), STDERR (standar error).
6. Membuat loop untuk proses utama.
 
Untuk mencoba aplikasi dari daemon ini, Kali ini kita akan membuat suatu program yang bisa merubah suatu gambar menjadi gambar dengan mode grayscale.

Dalam melakukan proses merubah gambar menjadi grayscale kita memerlukan software, dan yang kita gunakan untuk program kali ini yaitu dengan software imagemagick.
Jadi yang pertama kita lakukan yaitu menginstall software imagemagick dulu, berikut langkah-langkah yg bisa kita gunakan :

 sudo -i  
 cd  
 apt-get install build-essential checkinstall && apt-get build-dep imagemagick -y  
 wget http://www.imagemagick.org/download/ImageMagick-6.8.7-7.tar.gz  
 tar xzvf ImageMagick-6.8.9-1.tar.gz  
 cd ImageMagick-6.8.9-1/  
 ./configure --prefix=/opt/imagemagick-6.8 && make  
 checkinstall  

Nah untuk memastikan software benar-benar terinstall kita cek dengan convert -version
akan terlihat versi dari imagemagick yang terinstall pada OS kita.


Nah, dalam program yang akan kita buat nanti, program akan terus berjalan dibackground (daemon) ketika ada suatu gambar dengan format jpg yang dibuka, maka program akan membuat salinan dari gambar tersebut dengan format grayscale dan nama filename_copy.jpg.

Jadi langkah pertama yang kita lakukan yaitu membuat dulu program untuk daemonnya.

 #include <sys/types.h>  
 #include <sys/stat.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <fcntl.h>  
 #include <errno.h>  
 #include <unistd.h>  
 #include <syslog.h>  
 #include <string.h>  
 int main(void)  
 {  
   pid_t pid, sid;  
   pid = fork();  
   if (pid < 0)  
   {  
     exit(EXIT_FAILURE);  
   }  
   if (pid > 0)  
   {  
     exit(EXIT_SUCCESS);  
   }  
   umask(0);  
   sid = setsid();  
   if (sid < 0)  
   {  
     exit(EXIT_FAILURE);  
   }  
   if((chdir("/")) < 0)  
   {  
     exit(EXIT_FAILURE);  
   }  
   close(STDIN_FILENO);  
   close(STDOUT_FILENO);  
   close(STDERR_FILENO);  
   while(1)  
   {  
 //Main Program  
   }  
   exit(EXIT_SUCCESS);  
 }  

Setelah selesai dengan program daemonnya. kita buat program intinya.
untuk bisa mengetahui file jpg sedang dibuka kita perlu melihat dari process table.
kemudian kita grep process yang mengandung filename jpg dan nama program dari imageviewer.


Dari proses tersebut kita akan mendapatkan user, pid, time, dan file location dll, padahal yang kita butuhkan hanyalah file locationnya saja.
jadi selain kita grep kita gunakan perintah awk.
Kita hanya perlu mengambil nama file dari proses dan kolom terakhir dari ps aux jadi kita gunakan 'END{print $NF}' dimana END berarti baris terkahir dan $NF berarti kolom terakhir.


Dari proses diatas kita akan mendapatkan file location dari gambar yang sedang dibuka. hasil outputan tersebut kita simpan kedalam file dengan menggunakan funsgi popen.
Dari file tersebut kita baca dan kita masukkan nilainya kedalam string dengan fungsi fgets.
apabila tidak ada file yang dibuka maka nilai dari string akan kosong atau hanya mengandung enter saja.
apabila ada gambar yg sedang dibuka maka string akan bernilai lokasi dari gambar beserta ekstensinya.

kita perlu menghilangkan ekstensi dari file location tersebut supaya bisa di append dengan kata _copy.jpg
jadi kita ganti '.' pada nama file dengan penutup string '\0'
kemudian kita tambahkan kata _copy.jpg untuk disimpan divariabel string yang baru.

kita sudah mendapatkan nama file asli beserta lokasinya. dan nama file baru yg akan dibuat.
selanjutnya kita cek dulu apakah file yg akan kita grayscale kan sudah ada gambar grayscalenya (sudah dilakukan proses yg sama), dengan memanggil funsgi acces dimana parameter pertama yaitu nama file yg kita cek, kemudian parameter kedua yaitu F_OK yg artinya file exist.
bila file not exist fungsi acces akan mereturn -1, baru kita lakukan proses convert dengan imagemagick.

berikut program lengkapnya :

 #include <sys/types.h>  
 #include <sys/stat.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <fcntl.h>  
 #include <errno.h>  
 #include <unistd.h>  
 #include <syslog.h>  
 #include <string.h>  
 int main(void)  
 {  
   pid_t pid, sid;  
   pid = fork();  
   if (pid < 0)  
   {  
     exit(EXIT_FAILURE);  
   }  
   if (pid > 0)  
   {  
     exit(EXIT_SUCCESS);  
   }  
   umask(0);  
   sid = setsid();  
   if (sid < 0)  
   {  
     exit(EXIT_FAILURE);  
   }  
   if((chdir("/")) < 0)  
   {  
     exit(EXIT_FAILURE);  
   }  
   close(STDIN_FILENO);  
   close(STDOUT_FILENO);  
   close(STDERR_FILENO);  
   while(1)  
   {  
       FILE *fp;  
     char file_type[400];  
     fp = popen("ps aux | grep Sl | grep .jpg | awk 'END{print $NF}'", "r");  
     if(fgets(file_type, sizeof(file_type), fp) != NULL)  
     {  
       if(file_type[0] == '\n')  
       {  
             sleep(2);  
         system("echo No JPG Open >> log.txt");  
       }  
       else  
       {  
         file_type[strlen(file_type)-5]='\0';  
         char file_name[400];  
         strcpy(file_name, file_type);  
         strcat(file_name, "_copy.jpg");  
         if(access(file_name, F_OK) == -1)  
         {  
           char buf[500];  
           snprintf(buf, sizeof(buf), "convert %s.jpg -colorspace Gray -gamma 2.2 %s", file_type, file_name);  
           system(buf);  
         }  
       }  
     }  
   }  
   fclose(fp);  
   exit(EXIT_SUCCESS);  
 }  

Dan ini hasilnya :


Sepertinya ribet ya, kalo masih ada yang bingung, bisa tanya di komentar ya guys :) happy coding...

Jumat, 25 September 2015

Belajar Bash Shell

Sekilah Tentang Bash Shell


Bash adalah singkatan dari Bourne Again SHell. Shell adalah program yang menghubungkan antara inputan user dengan sistem operasi. Bash ini adalah shell yang paling umum digunakan pengguna Linux.  Sekarang ini, program seperti shell ini sudah tergantikan oleh user interface yang lebih mudah digunakan. Pemrograman bash shell itu sendiri adalah pemrograman kumpulan perintah menggunakan script yang ditulis ke dalam bash shell, sehingga nantinya dapat dieksekusi oleh sistem operasi. Pemrograman menggunakan shell terutama bash shell berkembang terus sampai sekarang karena penggunaannya di kalangan system administrator sangat dibutuhkan.

Perintah-Perintah Dasar Di Bash Shell


cd : digunakan untuk berpindah ke direktori lain.
chmod : digunakan untuk mengatur hak akses suatu file atau direktori
clear : digunakan untuk membersihkan seluruh layar terminal
cp : digunakan untuk menyalin sebuah file
date : digunakan untuk menampilkan tanggal dan waktu
halt : digunakan untuk mematikan sistem
ls : digunakan untuk melihat isi dari suatu direktori
mkdir : digunakan untuk membuat direktori baru.
mv : untuk memindahkan file, bisa juga untuk merubah nama sebuah file.
nano : digunakan untuk text editor
passwd : digunakan untuk menggunakan password
pwd : digunakan untuk menampilkan nama direktori dimana Anda sedang berada
reboot : digunakan untuk menghidupkan ulang sistem/komputerrestart : menjalankan ulang service yang sedang berjalan.
rm : digunakan untuk menghapus file.
rmdir : digunakan untuk menghapus direktori
halt: digunakan untuk mematikan sistem
sudo : menjalankan perintah sebagai root
tar : digunakan untuk mengekstrak file dengan format *tar.gz *.tgz
touch : digunakan untuk membuat file baru dalam keadaan kosong.
who : digunakan untuk melihat siapa saja yang sedang login

Selain perintah-perintah diatas masih ada lagi perintah-perintah lainnyayang disediakan oleh bash shell.

Bash Script Bilangan Prima

Sudah pada tau kan apa itu bilangan prima? Bilangan prima yaitu suatu bilangan yang hanya mempunyai faktor 1 dan bilangan itu sendiri. Seperti misalnya 2 yang hanya punya faktor 1 dan 2. Kemudian 5 yg hanya punya faktor 1 dan 5, begitu juga dengan bilangan 3, 7 , 13 dan lainnya.

Salah satu logika yang bisa kita gunakan untuk menentukan suatu bilangan merupakan bilangan prima atau bukan yaitu dengan cara : Memastikan bilangan tersebut tidak habis dibagi 2 sampai n-1. dengan syarat bilangan tersebut harus lebih besar dari 2.

Contoh misalnya 7, untuk menentukan 7 adalah bilangan prima atau bukan. Kita harus membagi bilangan 7 dengan 2,3,4,5 dan 6. Dan dari kelima bilangan tersebut tidak ada yg habis membagi 7 dengan demikian 7 adalah bilangan prima.

Contoh lain misalnya 8, kita bagi 8 dengan 2, 3, 4, 5, 6 dan 7. Dari keenam bilangan tersebut 2 dan 4 habis membagi 8 dengan demikian 8 bukanlah bilangan prima.

Dibawah ini adalah contoh penerapan logika untuk mencari bilangan prima sampai batas a dengan menggunakan bash script.



 #!/bin/bash  
 read a  
 for((i=2; i<=$a; i++));do  
   cek=0  
   for((j=2; j<i; j++));  
      do  
      if [ $((i%j)) -eq 0 ];  
      then  
       cek=1  
       break  
      fi  
   done  
   if [ $cek -eq 0 ]; then  
      printf "%d " $i  
   fi  
 done  
 printf "\n"  

Contoh program saat dijalankan



Bash Scritp Untuk Mendownload, Merename dan memindahkan suatu berkas/direktori.


Contoh permasalahan:
Selain kuliah, Cayza juga merupakan seorang dokter praktik, dia memiliki 5 pasien yang harus rutin meminum obat. Sebagai dokter yg baik, Cayza ingin terus memantau sudah berapa jumlah obat yang sudah diminum oleh setiap pasien. Cayza harus mengunduh berkas "laporan minum obat pasien" yang berada di kantornya melalui alamat http://10.151.36.201/sisop/jadwal.txt. Setiap berkas yang diunduh otomatis diletakkan pada sebuah direktori yang namanya sesuai dengan tanggal bulan dan tahun saat ini dengan format dd_mm_yyyy (contoh: 11_12_2013). Berkasnya juga otomatis di-rename sesuai dengan jam, menit, dan detik ketika berkas tersebut diunduh dengan format HH_MM_SS (contoh: 17_18_19). Buatlah script untuk membantu Cayza dalam melakukan hal ini agar pekerjaannya berjalan lebih mudah hanya dalam sekali proses.

Dari deskripsi diatas langkah-langkah yg haru dilakukan yaitu
1. Mendapatkan waktu (kalender) saat program dijalankan yang direpresentasikan dalam jam_menit_detik dan juga tanggal_bulan_tahun
2. Membuat direktori sesuai tanggal download
3. Mendownload file dari alamat yg ditentukan
4. Mensave file hasil download dengan jam download
5. Memindahkan hasil download ke direktori yg sudah dibuat sebelumnya tadi.


Bash script
 t=$(date +"%H_%M_%S")  
 d=$(date +"%m_%d_%Y")  
 mkdir -p "$d"  
 wget -O "$t" http://10.151.36.201/sisop/jadwal.txt  
 mv -i "$t" "$d"  


Contoh program saat dijalankan
File hasil download dipindah ke folder




Bash Script untuk membaca file dan Menulis file


Contoh permasalahan:
Dalam file tersebut terdapat lima waktu pasien mendatangi Cayza untuk check up. Setiap harinya, semua pasien diperbolehkan minum obat mulai jam 6 pagi hingga jam 12 malam dengan selang waktu 3 jam sekali. Cayza harus mengetahui jumlah obat yang telah diminum oleh setiap pasien hingga waktu pasien check up pada hari itu. Oleh karena itu dia harus menambahkan keterangan jumlah obat yang sudah diminum setiap pasien hingga  waktu check up pada berkas yang sudah diunduh sebelumnya. Buatlah script untuk membantu cayza dalam melakukan hal ini.
File sebelum script dijalankan:
08:00:01
10:30:34
11:32:46
15:30:10
17:22:30

Contoh file setelah script dijalankan:
08:00:01 - Pasien A Sudah Minum 1 obat
10:30:34 - Pasien B Sudah Minum 2 obat
11:32:46 - Pasien C Sudah Minum 2 obat
15:30:10 - Pasien D Sudah Minum 4 obat
17:22:30 - Pasien E Sudah Minum 4 obat

Dari deskripsi diatas logika yang dapat kita gunakan untuk menyelesaikannya yaitu
1. Membaca jam, menit dan detik yang terdapat di file secara baris perbaris
2. Menghitung jumlah obat yang diminum oleh pasien dengan cara mengurangi jam dengan 6 (jam pasien mulai minum obat) kemudian membagi dengan 3 (selang waktu pasien minum obat) kemudian ditambah dengan 1.
3. Menampilkan/menulis hasil perhitungan dan jam kedalam file.

Bash script
 cd "$d"  
 t=$(date +"%H_%M_%S")  
 huruf=(A B C D E)  
 i=0  
 x="$t"  
 while IFS=":" read hour minute second; do  
     let "m=${hour#0}-6"  
     let "n=${m}/3+1"  
     if [ $m -lt 0 ]; then  
         let "n=0"      
     fi  
     echo "$hour:$minute:$second - Pasien ${huruf[$i]} Sudah Minum $n Obat" >> newfile  
     let "i++"  
 done < $x  
 mv newfile "$t"  

File hasil keluaran



Mengarsipkan Berkas dan Membuat Log


Contoh permasalahan:
Cayza harus mengarsipkan folder berisi berkas yang sudah disunting dalam bentuk kompresi tar.gz. dengan format XZZ (X = kelas, ZZ = Nomor Kelompok), contoh: A01.tar.gz. Setiap kali terjadi pengarsipan, akan otomatis dicatat ke dalam log file dengan format nama file log_XZZ.txt (X = kelas, ZZ = Nomor Kelompok), contoh: log_A01.txt.

Langkah-langkah yang bisa kita gunakan untuk menyelesaikan permasalahan diatas yaitu:
1. Mendapatkan jam dan tanggal ketika program dijalankan untuk kperluan log
2. Menentukan file/berkas yang akan diarsiapkan
3. Melakukan proses penarsipan berkas
4. Mencetak jam, tanggal dan berkas yang diarsipkan kedalam log file

Bash Script
 tn=$(date +"%H_%M_%S")  
 dn=$(date +"%m_%d_%Y")  
 in="$d"  
 cd -  
 class="B02"  
 file="log_$class.txt"  
 printf "File Archieved : " >> "$file"  
 tar -zcvf "$class".tar.gz $in >> "$file"  
 printf "Date : $dn ---- Time : $tn\n" >> "$file"  
 echo "ARCHIEVED SUCCES"  

File hasil keluaran
isi berkas
isi log file




Bash Script Lengkap Untuk Permasalahan di atas
 #!/bin/bash  

 t=$(date +"%H_%M_%S")  
 d=$(date +"%m_%d_%Y")  
 mkdir -p "$d"  
 wget -O "$t" http://10.151.36.201/sisop/jadwal.txt  
 mv -i "$t" "$d"  
 
 cd "$d"  
 huruf=(A B C D E)  
 i=0  
 x="$t"  
 while IFS=":" read hour minute second; do  
     let "m=${hour#0}-6"  
     let "n=${m}/3+1"  
     if [ $m -lt 0 ]; then  
         let "n=0"      
     fi  
     echo "$hour:$minute:$second - Pasien ${huruf[$i]} Sudah Minum $n Obat" >> newfile  
     let "i++"  
 done < $x  
 mv newfile "$t"  

 tn=$(date +"%H_%M_%S")  
 dn=$(date +"%m_%d_%Y")  
 in="$d"  
 cd -  
 class="B02"  
 file="log_$class.txt"  
 printf "File Archieved : " >> "$file"  
 tar -zcvf "$class".tar.gz $in >> "$file"  
 printf "Date : $dn ---- Time : $tn\n" >> "$file"  
 echo "ARCHIEVED SUCCES"  

Semoga Bermanfaat :)