Marsha Nabilah Wibowo (05111840000027) || Muhammmad Daffa' Aflah Syarif (05111840000030)
Source Code : soal1.c
Buatlah program C yang menyerupai crontab untuk menjalankan script bash dengan ketentuan sebagai berikut: a. Program menerima 4 argumen berupa: i. Detik: 0-59 atau * (any value) ii. Menit: 0-59 atau * (any value) iii. Jam: 0-23 atau * (any value) iv. Path file .sh b. Program akan mengeluarkan pesan error jika argumen yang diberikan tidak sesuai c. Program hanya menerima 1 config cron d. Program berjalan di background (daemon) e. Tidak boleh menggunakan fungsi system()
int cek_bintang(char array[]){
if(array[0] == '*'){
return 1;
}
return 0;
}
- Untuk mengecek apakah ada * di argumen yang dimasukkan. Apabila ada akan me-return 1 yang berarti benar.
int check_number(char array[]){
for(int i=0; i<strlen(array); i++){
if(array[0]<'0' || array[0]>'9'){
return 0;
}
return 1;
}
}
- Untuk mengecek apakah inputan yang dimasukkan benar merupakan integer. Apabila bukan integer akan me-return nilai 0.
if(argc==5)
- Digunakan untuk mengecek apakah argumen benar ada 5 (termasuk run program) apabila tidak akan langsung masuk ke else untuk error.
int waktu[4], i;
for(i=1; i<4; i++){
if(check_number(argv[i])){
sscanf(argv[i], "%d", &waktu[i]);
} else if(cek_bintang(argv[i])){
waktu[i] = -1;
} else {
printf("argument %d is not valid.\n", i);
exit(EXIT_FAILURE);
}
}
if(waktu[0] > 59 && waktu[1] > 59 && waktu[2] > 23){
printf("argument is not valid.\n");
}
- Digunakan untuk melihat apakah ada error apa tidak. Apabila berupa integer akan dipindah ke array waktu yang berisi integer, apabila berupa * akan ditandai di array waktu dengan -1, selain itu akan ditunjukkan kalau argument tidak valid dan exit.
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);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
- Digunakan untuk membentuk daemon.
while(1){
time_t now;
time(&now);
struct tm *local = localtime(&now);
int skrg1, skrg2, skrg3;
skrg1 = local->tm_hour;
skrg2 = local->tm_min;
skrg3 = local->tm_sec;
if((skrg1 == waktu[3] || waktu[3] == -1) && (skrg2 == waktu[2] || waktu[2] == -1) && (skrg3 == waktu[1] || waktu[1] == -1)){
char *arg[] = {"bash", argv[4], NULL};
execv("/bin/bash", arg);
}
sleep(1);
}
- Variable skrg1, skrg2, skrg3 digunakan untuk menyimpan waktu sekarang dan dicocokkan dengan yang sudah diinput agar berjalan sesuai jam yang diinput.
Source Code : soal2.c
a. Pertama-tama, Kiwa membuat sebuah folder khusus, di dalamnya dia membuat sebuah program C yang per 30 detik membuat sebuah folder dengan nama timestamp [YYYY-mm-dd_HH:ii:ss].
while (1)
{
now = time(NULL);
info = localtime(&now);
char dirname[100];
strftime(dirname, 100, "%Y-%m-%d_%H:%M:%S", info);
pid_t c;
c = fork();
int status;
if (c < 0)
exit(EXIT_FAILURE);
if (c == 0)
{
if (fork() == 0)
{
char *argv[] = {"mkdir", "-p", dirname, NULL};
execv("/bin/mkdir", argv);
}
- Di-fork terlebih dahulu untuk membuat child process yang di dalamnya ada eksekusi dari membuat folder yang dilakukan setiap 30 detik.
- strftime digunakan untuk memasukkan tahun-bulan-hari_jam-menit-detik ke string bernama dirname yang akan digunakan untuk membuat directory.
b. Tiap-tiap folder lalu diisi dengan 20 gambar yang di download dari https://picsum.photos/, dimana tiap gambar di download setiap 5 detik. Tiap gambar berbentuk persegi dengan ukuran (t%1000)+100 piksel dimana t adalah detik Epoch Unix. Gambar tersebut diberi nama dengan format timestamp [YYYY- mm-dd_HH:ii:ss].
else
{
while ((wait(&status)) > 0);
for (int i = 0; i < 20; i++)
{
if (fork() == 0)
{
chdir(dirname);
time_t now1;
struct tm* info1;
now1 = time(NULL);
info1 = localtime(&now1);
int t = (int)time(NULL);
t = (t % 1000) + 100;
char web[100];
sprintf(web, "https://picsum.photos/%d", t);
char name[100];
strftime(name, 100, "%Y-%m-%d_%H:%M:%S", info1);
char *argv[] = {"wget", web, "-qO", name, NULL};
execv("/usr/bin/wget", argv);
}
sleep(5);
}
- Melakukan download di setiap folder yang sudah dibuat. Oleh karena itu membutuhkan fork lagi untuk membuat child process.
- sprintf digunakan untuk menyimpan url pada string web dan menyimpan ukuran dari foto tersebut.
- Dilakukan chdir agar download-an yang akan dilakukan masuk ke directory yang diinginkan.
- Eksekusi dari wget menggunakan execv.
c. Agar rapi, setelah sebuah folder telah terisi oleh 20 gambar, folder akan di zip dan folder akan di delete(sehingga hanya menyisakan .zip).
char zipname[150];
sprintf(zipname, "%s.zip", dirname);
char *argv[] = {"zip", "-qrm", zipname, dirname, NULL};
execv("/usr/bin/zip", argv);
- Zip dinamai sesuai nama folder awal sehingga perlu disave di-array bernama zipname untuk menyimpan nama folder awal dan sekaligus diremove menggunakan -rm.
- Digunakan excv untuk mengeksekusi zip.
d. Karena takut program tersebut lepas kendali, Kiwa ingin program tersebut men-generate sebuah program "killer" yang siap di run(executable) untuk menterminasi semua operasi program tersebut. Setelah di run, program yang menterminasi ini lalu akan mendelete dirinya sendiri.
void killer(char array[])
{
FILE *target;
target = fopen("killer.sh", "w");
int status;
if (strcmp(array, "-a") == 0)
fprintf(target, "#!/bin/bash\nkill -9 -%d", getpid());
if (strcmp(array, "-b") == 0)
fprintf(target, "#!/bin/bash\nkill %d", getpid());
if(fork() == 0)
{
if (fork() == 0)
{
char *argv[] = {"chmod", "u+x", "killer.sh", NULL};
execv("/bin/chmod", argv);
}
else
{
while ((wait(&status)) > 0);
char *argv[] = {"mv", "killer.sh", "killer", NULL};
execv("/bin/mv", argv);
}
}
fclose(target);
}
- Killer dibuat menggunakan bash "chmod", "u+x", "killer.sh" dan kemudian direname menjadi killer.
e. Kiwa menambahkan bahwa program utama bisa dirun dalam dua mode, yaitu MODE_A dan MODE_B. untuk mengaktifkan MODE_A, program harus dijalankan dengan argumen -a. Untuk MODE_B, program harus dijalankan dengan argumen -b. Ketika dijalankan dalam MODE_A, program utama akan langsung menghentikan semua operasinya ketika program killer dijalankan. Untuk MODE_B, ketika program killer dijalankan, program utama akan berhenti tapi membiarkan proses di setiap folder yang masih berjalan sampai selesai (semua folder terisi gambar, terzip lalu di delete).
void killer(char array[])
{
FILE *target;
target = fopen("killer.sh", "w");
int status;
if (strcmp(array, "-a") == 0)
fprintf(target, "#!/bin/bash\nkill -9 -%d", getpid());
if (strcmp(array, "-b") == 0)
fprintf(target, "#!/bin/bash\nkill %d", getpid());
if(fork() == 0)
{
if (fork() == 0)
{
char *argv[] = {"chmod", "u+x", "killer.sh", NULL};
execv("/bin/chmod", argv);
}
else
{
while ((wait(&status)) > 0);
char *argv[] = {"mv", "killer.sh", "killer", NULL};
execv("/bin/mv", argv);
}
}
fclose(target);
}
- strcmp untuk melihat apakah inputan -a atau -b.
- Apabila menggunakan -a akan langsung dikill tanpa menunggu program selesai berjalan sedangkan untuk -b dikill tanpa menggunakan -9 sehingga proses kill berjalan pelan-pelan.
Source Code : soal3.c
Dalam persoalan ini ada 4 soal : a. Membuat program dimana membuat 2 direktori, direktori pertama diberi nama "indomie", direktori kedua "sedaap". Direktori kedua dibuat setelah 5 detik.
pid_t child = fork();
int status;
if (child < 0){
exit(EXIT_FAILURE);
}
if (child == 0){
pid_t child_mie = fork();
//soal 3a
if (child_mie < 0){
exit(EXIT_FAILURE);
}
if (child_mie == 0){
char *argv[] = {"mkdir", "-p", "/home/syarif/sisop20/modul2/shift_modul2/soal3/indomie", NULL};
execv("/bin/mkdir", argv);
}
else{
while ((wait(&status)) > 0);
sleep(5);
char *argv[] = {"mkdir", "-p", "/home/syarif/sisop20/modul2/shift_modul2/soal3/sedaap", NULL};
execv("/bin/mkdir", argv);
}
}
pid_t child_mie = fork();
bagian ini membuat fork agar bisa menjalankan banyak proses dalam sekali menjalankanif (child_mie < 0) exit(EXIT_FAILURE);
bagian ini menunjukkan jika gagal dalam membuat proses baru, kemudian program akan berhentichar *argv[] = {"mkdir", "-p", "/home/syarif/sisop20/modul2/shift_modul2/soal3/indomie", NULL};
bagian ini untuk membuat direktori,"-p"
maksudnya membuat parent direktori nyawhile ((wait(&status)) > 0);
bagian ini untuk delay suatu prosessleep(5);
bagian ini agar menjalankan proses selanjutnya setelah 5 detik
b. Meng-ekstrak file jpg.zip
pada direktori
while ((wait(&status)) > 0);
pid_t child_unzip = fork();
//soal 3b
if (child_unzip < 0){
exit(EXIT_FAILURE);
}
if (child_unzip == 0){
char* argv[] = {"unzip", "/home/syarif/sisop20/modul2/shift_modul2/soal3/jpg.zip", NULL};
execv("/usr/bin/unzip", argv);
}
pid_t child_unzip = fork();
bagian ini membuat fork agar bisa menjalankan banyak proses dalam sekali menjalankanif (child_unzip < 0) exit(EXIT_FAILURE);
bagian ini menunjukkan jika gagal dalam membuat proses baru, kemudian program akan berhentichar* argv[] = {"unzip", "/home/syarif/sisop20/modul2/shift_modul2/soal3/jpg.zip", NULL};
bagian ini untuk membuat direktori,"-p"
maksudnya membuat parent direktori nya
c. Setelah meng-ekstrak file tersebut, hasil ekstrakan dipindahkan berdasarkan pengelompokkan. Jika hasil ekstrak berupa folder maka dimasukkan ke dalam "/indomie/"
sedangkan hasil ekstrak selain folder maka dimasukkan ke dalam "/sedaap/"
//soal 3c
while ((wait(&status)) > 0);
chdir("/home/syarif/sisop20/modul2/shift_modul2/soal3/jpg/");
DIR *directory;
directory = opendir(".");
struct dirent *dir;
if(directory){
while((dir = readdir(directory)) != NULL){
pid_t child_team = fork();
struct stat st;
stat(dir->d_name, &st);
if(child_team < 0){
exit(EXIT_FAILURE);
}
if(child_team == 0){
char path_file[1000];
sprintf(path_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/jpg/%s", dir->d_name);
if(S_ISDIR(st.st_mode)){
if(strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0);
else{
pid_t child_txt = fork();
if(child_txt < 0){
exit(EXIT_FAILURE);
}
if(child_txt == 0){
char* argv[] = {"mv", path_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/indomie/", NULL};
execv("/bin/mv", argv);
}
}
}
else{
char* argv[] = {"mv", path_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/sedaap/", NULL};
execv("/bin/mv", argv);
}
}
}
closedir(directory);
}
while ((wait(&status)) > 0);
bagian ini untuk delay suatu proseschdir("/home/syarif/sisop20/modul2/shift_modul2/soal3/jpg/");
bagian ini untuk mengubah direktoriDIR *directory;
bagian ini pointer untuk menunjuk ke direktoridirectory = opendir(".");
bagian ini untuk membuka direktori handlestruct dirent *dir;
bagian ini pointer untuk menunjukkan dalam direktoriif(directory)
bagian ini untuk mengecek pointer yang ditunjuk benar sebuah direktoriwhile((dir = readdir(directory)) != NULL)
bagian ini loop ketika sebuah direktori masih ada file/folder didalamnyapid_t child_team = fork();
bagian ini membuat fork agar bisa menjalankan banyak proses dalam sekali menjalankanstruct stat st;
bagian ini pointer status dalam proses mengecek sebuah direktorichar path_file[1000];
bagian ini untuk menyimpan hasil pencarianS_ISDIR(st.st_mode)
bagian ini fungsi untuk mengecek sebuah direktorisprintf(path_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/jpg/%s", dir->d_name);
bagian ini mencari file/folder yang ada dalam direktoriif (child_unzip < 0) exit(EXIT_FAILURE);
bagian ini menunjukkan jika gagal dalam membuat proses baru, kemudian program akan berhentichar* argv[] = {"mv", path_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/indomie/", NULL};
bagian ini untuk memindahkan folder dalam direktori ke dalam direktoriindomie
. Selain itu akan dimasukkan ke dalam direktorisedaap
d. Untuk setiap direktori yang sudah dipindahkan ke dalam direktori "/indomie"
harus membuat 2 file kosong dengan penamaan "coba1.txt"
dan "coba2.txt"
. Untuk file "coba2.txt"
dibuat setelah 3 detik.
//soal 3d
while((dir = readdir(directory)) != NULL){
pid_t child_indomie = fork();
int kasus;
if(child_indomie == 0){
char target_file[1000];
FILE *target;
sprintf(target_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/indomie/%s/coba1.txt", dir->d_name);
target = fopen(target_file,"w");
fclose(target);
}
else{
while((wait(&kasus)) > 0);
sleep(3);
char target_file[1000];
FILE *target;
sprintf(target_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/indomie/%s/coba2.txt", dir->d_name);
target = fopen(target_file,"w");
fclose(target);
exit(0);
}
}
while((dir = readdir(directory)) != NULL)
bagian ini loop ketika sebuah direktori masih ada file/folder didalamnyapid_t child_indomie = fork();
bagian ini membuat fork agar bisa menjalankan banyak proses dalam sekali menjalankanchar target_file[1000];
bagian ini untuk menyimpan hasil pencarianFILE *target;
bagian ini pointer untuk menunjuk sebuah file/foldersprintf(target_file, "/home/syarif/sisop20/modul2/shift_modul2/soal3/indomie/%s/coba1.txt", dir->d_name);
bagian ini mencari file/folder yang ada dalam direktoritarget = fopen(target_file,"w");
bagian ini untuk membuka file/folder kemudian memberikan perintah untuk membuat file"coba1.txt"
atau"coba2.txt"
pada direktorifclose(target); exit(0);
bagian ini untuk mengakhiri proses dalam membuat file dalam direktori