Arsip mwmag[Files]  [Up]© 2002 PT Masterweb Media

Bagian Tiga: Perl di Windows Tutorial Perl

Perl yang mana? Windows yang mana?

Memakai Perl di Windows

Ilmu Unix di Windows

Subrutin di Perl

Mengenal Modul Perl

Hanya di Windows

System Service di Windows

Satu Program, Lebih dari Satu Sistem Operasi

Ada apa dengan OLE?

Bagian Tiga: Perl di Windows

Tutorial Perl

Yohanes Nugroho

Larry Wall pernah menulis dalam bukunya: “And to program Visual Basic portably, you just need a more flexible definition of the word ‘portable’.” Kita tidak perlu melakukan hal sesulit itu untuk memrogram secara portabel di Perl.

Dalam 2 edisi pertama fokus pembahasan tutorial Perl ada pada dunia Unix, padahal Perl tidak hanya untuk Unix. Perl adalah salah satu lingkungan pemrograman yang paling portabel saat ini. Program-program sederhana—yaitu program yang tidak memanfaatkan fitur spesifik OS tertentu—akan langsung bisa berjalan di OS lain tanpa (atau dengan sedikit) perubahan.

Namun itu bukan berarti Perl tidak bisa memanfaatkan fitur spesifik suatu sistem operasi. Sudah ada interface Perl yang dibuat untuk memanfaatkan fitur spesifik dari semua OS yang ada saat ini. Di Windows misalnya, sudah ada modul untuk memanfaatkan clipboard Windows, Registry, ODBC, bahkan sampai OLE.

Di tutorial ketiga ini, Anda akan belajar mengenai penggunaan Perl di Windows. Apa saja yang berbeda dari Perl versi Unix, dan bagaimana menggunakan fitur Windows yang spesifik. Anda juga akan diperkenalkan bagaimana caranya memakai modul Perl. Dan tentunya pelajaran ini diberikan dengan contoh di dunia nyata untuk membuat program pembuat user di Windows dan program untuk mengecek status System Service di Windows (semacam daemon di Unix).

Perl yang mana? Windows yang mana?

Dalam menulis artikel ini, versi Perl yang saya pakai adalah ActivePerl binary build 631. Installernya bisa di-download dari www.activestate.com atau dari CD majalah. Sebaiknya Anda tidak bersusah-payah mencoba mengkompile sendiri source Perl, karena selain sulit, hal tersebut tidak perlu. Tidak ada petunjuk khusus untuk menginstall ActivePerl di Windows, Anda akan dipandu oleh wizard seperti ketika Anda menginstall program Windows yang lain.

Artikel ini ditulis di Windows XP dan dites Windows XP, namun seharusnya semua yang tertulis berlaku juga untuk semua versi Windows keluarga NT (NT/2K/XP). Bagian yang tidak berlaku di Windows yang bukan keluarga NT (95/98/ME) adalah bagian yang berhubungan dengan administrasi user (karena OS memang tersebut tidak multiuser), dan security (karena OS tersebut memang tidak secure).

Windows tidak memiliki tool command line (aplikasi console) sebanyak yang ada di Unix. Hal ini sangat benar, terutama untuk Windows selain Windows 2K dan XP (di Windows 2K dan XP, tools standar yang disertakan secara default sudah cukup banyak), karena itu sebaiknya Anda menginstall tool-tool Unix yang di port ke Windows dari cygwin (sources.redhat.com/cygwin/download.html). Cygwin bisa juga Anda jumpai di CD majalah. Anda yang sudah terbiasa dengan Unix akan menemukan bahwa banyak program di Unix yang lebih enak dipakai dibanding program serupa di Windows (coba saja bandingkan grep dengan FINDSTR.EXE).

 

Memakai Perl di Windows

Sebelum pemakai Windows merasa syok, karena tidak melihat ada menu Perl di Start Menu mereka, saya akan menjelaskan bagaimana memakai interpreter Perl di Windows. Di Start Menu, di menu ActiveState ActivePerl 5.6 Anda hanya akan melihat tiga ikon Documentation, OLE Browser, dan, Perl Package Manager. Ketiga-tiganya bukan yang harus Anda jalankan. Pergilah ke command prompt (cari di Start Menu, atau ketikkan CMD dan enter di menu Run, atau tekan tombol Windows-R lalu ketik CMD dan Enter).

Setelah sampai di command prompt, coba ketikkan perl -v. Seharusnya akan keluar pesan mengenai versi Perl. Jika ada pesan “Bad Command or Filename”, atau “’perl’ is not recognized as an internal or external command, operable program or batch file.”, ada 2 kemungkinan: instalasi Anda gagal, atau path ke perl.exe belum diset. Cobalah reboot komputer setelah instalasi, mungkin setting autoexec.bat belum tereksekusi setelah instalasi.

Untuk menjalankan program Perl, lakukan:

prompt> perl namafile.pl

atau dobel klik pada ikon file itu di Windows Explorer (atau klik saja, bergantung setting Explorer Anda).

Di Windows 2K/XP, asosiasi program di command line sudah bisa dilakukan (dan otomatis dilakukan oleh instaler Perl), sehingga Anda bisa langsung melakukan ini di command prompt:

prompt> namafile.pl

Sebenarnya ada cara lain untuk menjalankan Perl di Windows, yaitu dengan WSH, tapi tidak akan dibahas di sini karena tidak terlalu berguna.

Ilmu Unix di Windows

Sebagian ilmu Unix yang Anda miliki dapat dipakai di Windows. Windows mendukung pipa dan redireksi sehingga Anda masih dapat mengendalikan program eksternal dengan Perl seperti yang telah dijelaskan pada edisi lalu. Sekali lagi harus di ingat, bahwa program eksternal yang ada di Windows berbeda dengan yang ada di Unix.

Misalnya, untuk mengganti password user di Windows 2K/XP, Anda bisa melakukannya seperti ini (dari DOS prompt, atau dari menu Start > Run):

NET USER carol Caroline

Perintah tersebut mengganti password user carol menjadi Caroline. Yang berbeda dengan di Linux:

echo "Caroline" | passwd --stdin carol

Di Windows 2000 dan XP ada beberapa tool command line yang cukup membantu, yang sangat spesifik untuk Windows. Berikut ini saya berikan deskripsi mengenai dua tools command line yang sangat berguna yaitu net.exe dan cacls.exe, dua tool ini sangat berguna untuk administrasi jaringan (yang menjadi topik tutorial ini).

NET.EXE

Tools ini seperti Swiss army knife, tool serba bisa yang dapat dipakai untuk banyak hal. Mulai dari menciptakan user, mengganti password, mengkonfigurasi server, mengatur share, mengatur system service, sampai mereboot sistem. Untuk melihat help program ini ketikkan:

prompt> NET HELP

untuk melihat help terhadap command tertentu

prompt> NET HELP command

Anda juga bisa melihat dokumentasi tools tersebut di menu help Windows (lakukan search terhadap net.exe).

CACLS.EXE

Tidak seperti (kebanyakan) Unix yang hanya mengenal permission file dengan atribut r (read), w (write) dan x (executable), di Windows NT/2K/XP permission yang ada sangat kompleks. Hak akses terhadap suatu file atau direktori dapat dibatasi sampai level per user dengan menggunakan ACL (Access Control List). Program CACLS.EXE dapat dipakai untuk melihat dan mengubah ACL dari command line (dan dari Perl juga tentunya). Dalam administrasi sistem, Anda akan sering berurusan dengan hal semacam ini.

Mungkin sekarang Anda baru sadar, bahwa ini adalah tutorial Perl (bukan tutorial administrasi Windows), tapi sampai baris ini, belum ada satu baris pun kode program Perl yang Anda lihat. Di bawah ini, saya berikan program yang serupa dengan tutorial edisi lalu (menambah user secara massal), namun program ini dapat dipakai di Windows.

open(F, "user.txt");
open(L, ">laporan.txt");
while (<F>) {
chomp; # hilangkan 'enter' di akhir baris
($login, $nama) = split(/,/);
print L "Nim : $login ";
$login =~ s/^(.)35.(.)(...)$/if$1$2$3/;
print L "Login: $login Nama: $nama ";

#ciptakan usernya
system("NET USER $login /ADD /FULLNAME:\"$nama\"");

#buat password barunya
$password = gen_password(8);

print L "Password: $password\n";

#set password baru
system("NET USER $login $password");
}
close(F);
close(L);

sub gen_password() {
my ($length) = @_;
my @allowedchar = split(//,"abcdefghijklmnopqrstuvwxyz");

my $pass = "";
for (1..$length) {
$pass .= $allowedchar[rand @allowedchar];
}
return $pass;
}

Jika Anda perhatikan, ada bagian yang berubah dari program yang ada di tutorial edisi lalu. perintah ini:

dd if=/dev/urandom bs=1 count=6 2>/dev/null | mimencode

Tidak bisa dilakukan di Windows, karena beberapa hal. Pertama, perintah dd dan mimencode tidak ada. Jika Anda mau, Anda bisa menginstal dd dan mimencode yang versi Windows. Masalah kedua lebih sulit, /dev/urandom tidak ada di Windows. Di beberapa OS /dev/random merupakan device yang mengumpulkan entropi dari sekitar komputer, dan menjadikannya sumber bilangan acak, sedangkan /dev/urandom melakukan hal yang sama, namun jika entropi tidak cukup maka device tersebut akan membuat hash kriptografi dari entropi yang sudah terkumpul. Meskipun Windows Anda bisa hang secara random, Windows tidak memiliki device penghasil bilangan random untuk melakukan hal itu. Masalah ketiga, hanya akan ditemui di Windows 95/ME, shell standar (COMMAND.COM) di Windows 95/98/ME, tidak mendukung redireksi STDERR dengan notasi 2 > namafile.

Karena kita tidak bisa dengan mudah membuat password random dengan perintah sederhana, maka kita harus membuat sendiri fungsi/subrutin untuk menghasilkan password random ini. Sebelum saya menjelaskan bagian program penghasil password random itu, saya jelaskan dulu mengenai subrutin di Perl.

Subrutin di Perl

Seperti hampir semua bahasa, Perl juga menyediakan fasilitas untuk menciptakan subrutin yang didefinisikan sendiri. Subrutin kadang disebut juga fungsi, dan nanti kalau Anda belajar pemrograman berorientasi objek di Perl, subrutin ini disebut juga metode.

Subrutin yang paling sederhana tentunya adalah subrutin yang tidak menerima parameter apa-apa, dan tidak mengembalikan apa-apa. Misalnya kita selalu ingin mencetak header di setiap halaman

sub header{
print "Yayasan Anti Banjir\n";
print "Laporan Bulanan\n";
}

Untuk memanggil subrutin tersebut, kita dapat melakukannya dengan:

header();

atau boleh juga dengan (ini sama dengan di atas):

&header();

Sekarang kita melangkah ke subrutin yang menerima parameter, tapi tidak mengembalikan apa-apa:

sub header_bulan {
print "Laporan bulan ".$_[0];
}

subrutin itu dipanggil seperti ini:

header_bulan("Mei");

Di Perl, semua parameter dilewatkan sebagai array yang bernama @_. Jadi parameter pertama adalah $_[0], parameter kedua $_[1] dan seterusnya. Biasanya, agar mudah mengakses parameternya, programer Perl melakukannya seperti ini:

my ($param1, $param2) = @_;

Sekarang parameter ($_[0]) pertama bisa diakses sebagai $param1, dan parameter ke dua ($_[1]) sebagai $param2. Keyword my dipakai untuk mendeklarasikan variabel yang lingkupnya lokal, sedangkan assignment @_ ke $param1 dan $param2 adalah assignment list.

Setelah tahu bagaimana memberikan parameter ke subrutin, sekarang kita melangkah ke subrutin yang mengembalikan nilai (umumnya ini disebut fungsi). Apapun nilai ekspresi terakhir dalam suatu subrutin, itu adalah nilai kembalian subrutin tersebut. Misalnya:

sub PI {22/7}

maka jika kita melakukan ini:

print PI();

hasilnya akan tercetak angka 3.14285714285714.

Atau jika Anda ingin mengembalikan nilai secara eksplisit, Anda bisa melakukannya dengan pernyataan return.

sub PI { return 355/113 }

Masih ada banyak hal dalam subrutin Perl yang tidak saya jelaskan di sini, saya akan menjelaskan hal-hal yang lebih rumit ketika hal tersebut sudah dibutuhkan dalam program. Sekarang kita tengok kembali fungsi untuk menghasilkan password:

sub gen_password() {
my ($length) = @_;
my @allowedchar = split(//,"abcdefghijklmnoqrstuvwxyz");

my $pass = "";
for (1..$length) {
$pass .= $allowedchar[rand @allowedchar];
}
return $pass;
}

Subrutin ini mengambil satu parameter, yaitu panjang password yang ingin dihasilkan. Dalam subrutin ini, ada proses untuk memecah string karakter yang diijinkan dalam password ke dalam suatu array. Sebenarnya ini tidak optimal (@allowedchar bisa dibuat sebagai variabel global), tapi hal ini dimaksudkan supaya subrutin ini bisa di-copy paste dan langsung jalan.

Subrutin ini kemudian melakukan loop dari 1 sampai $length, mengambil karakter secara acak dari array karakter yang dibolehkan. Array ini tentunya bisa Anda modifikasi sesuai keinginan Anda. Misalnya Anda ingin menambahkan bahwa angka boleh dipakai sebagai password kecuali mungkin angka 0 yang sering tertukar dengan huruf o dan O (O kecil dan O besar), serta angka 1 yang sering tertukar dengan huruf l atau I (huruf el kecil dan huruf i besar). Maka arraynya bisa diubah menjadi "abcdefghijklmnopqrstuvwxyz23456789". Hasil rangkaian karakter random itu kemudian dimasukkan ke dalam variabel $pass dan nilai kembalian subrutin ini adalah nilai variabel $pass.

Mengenal Modul Perl

Selain menggunakan program eksternal untuk membantu melakukan pekerjaan kita, cara lain untuk memudahkan pekerjaan kita adalah dengan menggunakan modul yang ditulis oleh orang lain. Umumnya untuk setiap hal yang terpikirkan oleh Anda, sudah ada orang yang membuatkan modulnya. Dalam instalasi Perl sudah banyak modul standar yang disertakan, namun jika kurang, Anda bisa mendownload dari mirror CPAN terdekat (atau cukup mencari CD edisi 1 majalah ini). Untuk saat ini, kita akan bermain dulu dengan modul standar, dan pada edisi ini, hanya modul standar Windows.

Pertama perlu dijelaskan dulu bahwa secara sederhana sebuah modul adalah kumpulan subrutin berikut variabel (atau konstanta) Perl yang diletakkan dalam sebuah file (dengan ekstensi .pm), yang dapat digunakan oleh suatu program. Ada dua jenis modul, yang tradisional dan yang object oriented. Modul tradisional dapat digunakan seperti kita memakai subrutin biasa, sedangkan untuk menggunakan yang modul yang berorientasi objek, perlu sedikit pemahaman terhadap konsep OO di Perl.

Perl dibuat dengan harapan dapat berjalan cross platform namun dengan semangat Unix, sehingga dukungan terhadap sistem operasi lain tidak tercakup dalam bahasa itu sendiri, dan ada pada modul yang spesifik terhadap suatu OS tertentu. Untuk dunia Windows, sudah disediakan modul-modul yang namanya dimulai dengan Win32::.

Untuk memakai sebuah modul caranya:

use NamaModul;

Jika modul tersebut mengekspor subrutin secara otomatis dengan menyertakan daftarnya pada @EXPORT maka kita bisa langsung memakai subrutin yang diekspor. Ada modul yang tidak melakukan hal itu, sehingga kita harus secara eksplisit menyatakan mana subrutin yang akan kita impor. Seperti ini:

use Matematika ("kali", "bagi", "tambah", "kurang");

atau:

use Kalender qw(hari hari_pasaran hari_libur);

Operator qw() merupakan salah satu operator pengutip yang gunanya untuk memudahkan kita membentuk list. Ada beberapa operator pengutip yang lain di Perl, tapi saat ini qw() saja yang akan kita pakai.

Hanya di Windows

Untuk menunjukkan bagaimana memakai modul, kita akan bermain-main sedikit dengan modul standar Windows. Modul standar yang cukup menarik adalah Win32::Sound. Modul ini tidak mengekspor fungsi apa-apa; jika kita ingin memakai fungsinya kita langsung melakukannya dengan menyebut lengkap nama modulnya, seperti ini:

use Win32::Sound;
Win32::Sound::Volume('100%');
Win32::Sound::Play("c:\\out.wav");
Win32::Sound::Stop();

Jika Anda tidak punya file .wav untuk contoh, Anda bisa menggunakan plugin DiskWriter yang ada di WinAmp untuk mengubah file mp3 menjadi file wav.

Sebenarnya modul Win32::Sound bukanlah modul tradisional (modul OO), namun karena semua metodenya statik, maka kita dapat memperlakukannya seolah-olah itu adalah modul tradisional. Bedanya adalah kita tidak perlu (dan tidak bisa) mengimpor fungsi-fungsinya, dan harus menyebut nama metodenya lengkap dengan nama modulnya (nama kelasnya).

Sayangnya sebagian besar modul untuk Windows dibuat berorientasi objek, dan karena penjelasan mengenai OO belum diberikan, saya akan menunda penjelasan pemakaian modul-modul Windows yang memakai konsep OO ini.

System Service di Windows

Kalau di Unix kita mengenal daemon, di Windows NT/2K/XP, ada yang namanya System Service. Service yang ada dapat dikendalikan melalui MMC (Microsoft Management Console), konsep service di Windows ini sudah sangat baik, Anda bisa mengeset apakah service dijalankan ketika startup atau harus dijalankan manual, jika service ini mati, apa yang harus dilakukan (misalnya merestart servicenya) ,jika sudah mati n kali, apa yang harus dilakukan (misalnya kirim email ke administrator). Semuanya sempurna, eh tidak, hampir sempurna. Tool GUI yang diberikan tidak menyediakan kemampuan untuk menyimpan daftar service yang ada, berikut statusnya, sehingga Anda akan kesulitan membandingkan service apa saja yang telah berubah konfigurasinya sejak ditinggalkan oleh Anda terakhir kali (mungkin ada admin lain yang mengubah, atau ada penyusup).

Para guru Windows tentunya akan langsung berkata, “kan ada SC.EXE!!!” Memang benar, sudah ada tool command line yang namanya SC.EXE, yang bisa melakukan apa saja, termasuk men-dump status semua service saat ini. Namun tool ini terlalu bagus (baca: rumit), sampai-sampai sulit dipakai.

Dengan menggunakan modul Win32::Service kita akan membuat sebuah program, yang akan mencatat apa saja service yang ada saat ini, berikut dengan statusnya (apakah berjalan/running atau tidak), lalu membandingkannya dengan catatan sebelumnya, dan memberitahukan jika ada service yang statusnya berubah sejak terakhir kali catatan itu dibuat. Source code program bisa Anda dapatkan di CD, berikut ini saya jelaskan bagaimana program ini bekerja.

use Win32::Service qw(GetServices GetStatus);

Kita memakai modul service, dan mengimpor fungsi GetServices dan GetStatus

$domain = "";
$filename = "status.txt";

Konstanta untuk nama domain dan nama file. Nama domain kosong, artinya menggunakan domain saat ini (domain di mana user login).

@status_names = qw (undef stopped start_pending stop_pending
running continue_pending pause_pending paused);

Ini adalah nama-nama status, nama-nama ini diambil dari file winsvc.h.

if ($#ARGV != 0 ) {
usage();
exit;
}

Parameter program diberikan ke Perl melalui array @ARGV, $ARGV[0] adalah parameter pertama. Jika jumlah parameter tidak sama dengan 1 (@#ARGV berisi jumlah elemen array-1) maka tampilkan pesan.

if ($ARGV[0] eq "check") {
compare_services($filename);
} elsif ($ARGV[0] eq "check") {
save_services($filename);
} else {
usage();
exit;
}

Parameter program harus "check" untuk memeriksa apakah service berubah, atau "save" untuk menyimpan status saat ini. Jika bukan keduanya, tampilkan layar bantuan. Jika parameter benar, panggil subrutin yang bersesuaian (save_services, atau compare_services).

sub compare_services {
my ($filename) = @_;
my (%services,$name, %status, @prev, $berubah);
my (@svclist);

Subrutin untuk membandingkan service dengan yang ada di file.

    open(F, "$filename");
@prev=<F>;
close(F);

Baca filenya. Masukkan isi file ke array @prev.

    foreach (@prev) {
($name, $oldstat) = split(/,/);
push @svclist, $name;

Untuk setiap service, nama dan statusnya di simpan di file dengan format CSV. Sekarang service dan nama tersebut kita pisahkan kembali, lalu daftar nama service yang ada di file kita letakkan di array @svclist.

        if (!GetStatus($domain, $name, \%status)) {
print "tidak bisa mendapatkan status untuk $name, ".
"mungkin service telah dihapus\n";
next;
};

Jika kita tidak bisa mendapatkan status service, kemungkinan service tersebut telah dihapus.

        if ($oldstat != $status{"CurrentState"}) {
print "Status service ".$name. " berubah ".
"dari ".$status_names[$oldstat]. " menjadi ".
$status_names[$status{"CurrentState"}]."\n";
}

Lalu periksa apakah status saat ini, sama dengan status lama. Jika tidak, cetak pesan:

    #cari apakah ada service baru
GetServices($domain, \%services);

Ambil nama semua service yang ada.

    foreach (sort keys %services){
$name = $services{$_};
if (!grep(/$name/, @svclist)) {
print "Service baru : $name\n";
}
}
}

Kalau kita tidak bisa menemukan nama service di dalam @svclist, maka service tersebut pasti service baru. Kita mencari dengan menggunakan fungsi grep.

sub save_services {
my ($filename) = @_;
my (%services,$name, %status);
GetServices($domain, \%services);
open(F, ">$filename");
foreach (sort keys %services){
$name = $services{$_};
GetStatus($domain, $name, \%status);
print F "$name,".$status{"CurrentState"}."\n";
}
close(F);
}

Subrutin ini mengambil daftar semua service yang ada dengan:

    GetServices($domain, \%services);

Parameter pertama adalah nama domain. Parameter kedua adalah referencsi (ada karakter backslash "\" di depan nama variabelnya) ke suatu hash. Saya tidak akan membahas referensi kali ini. Namun referensi ini diperlukan agar subrutin GetServices dapat mengubah isi hash %services.

Sebagai tambahan, sebenarnya status yang kita dapatkan ada banyak, meliputi: CurrentState, ServiceType, CheckPoint, ServiceSpecificExitCode, WaitHint, Win32ExitCode, dan ControlsAccepted, namun saat ini kita hanya peduli dengan status run servicenya saja, sehingga hanya itu yang dicatat.

sub usage {
print "service.pl [check|save]\n";
}

Dan subrutin di atas ini menampilkan layar bantuan.

Satu Program, Lebih dari Satu Sistem Operasi

Sekarang Anda sudah memahami bagaimana cara memrogram di Windows dan juga di Unix. Sekarang Anda sudah dapat membuat dua program yang mengerjakan hal yang sama di Unix dan di Windows. Tapi apakah itu yang Anda inginkan? Mengelola dua buah program tidaklah mudah, Anda harus mengubah dua program meskipun yang diubah adalah bagian yang tidak spesifik terhadap OS tertentu.

Ada beberapa cara untuk membuat program Anda portabel. Prinsip pertama adalah dengan mengurangi ketergantungan terhadap feature spesifik OS tertentu. Lalu yang kedua adalah menyatukan program dari kedua OS dengan menggunakan pernyataan kondisional if. Variabel $^O (huruf O besar, bukan angka nol) menyatakan OS saat ini. Anda bisa berlatih menggabungkan program edisi lalu dengan edisi ini untuk mendapatkan skrip yang berjalan di dua OS.

Ada apa dengan OLE?

Jika Anda pencinta Windows, mungkin Anda bertanya-tanya, kenapa OLE tidak dibahas? Padahal OLE sangat berguna, mulai dari mengendalikan Word untuk mencetak dokumen, sampai mengadministrasi jaringan dengan menggunakan ADSI (Active Directory Service Interface). Seperti yang sudah disinggung di awal artikel ini, Perl mendukung OLE. Namun OLE sendiri merupakan hal yang sangat rumit, butuh satu artikel sendiri untuk menjelaskan mengenai apa itu OLE dan bagaimana menggunakannya di Perl.

Artikel ini hanya berusaha memperkenalkan penggunaan Perl di Windows, supaya Anda yang ada di dunia Windows juga tertarik menggunakan Perl. Pembahasan tingkat lanjut tentu akan ada di edisi-edisi mendatang. Bagi Anda yang memakai beberapa OS (seperti saya), semoga sekarang bisa melihat, bahwa belajar Perl tidak sia-sia, karena ilmunya dapat dipakai di berbagai OS. Sampai jumpa di edisi depan.

Yohanes Nugroho mahasiswa tingkat akhir Teknik Informatika ITB, administrator jaringan jurusan dan saat ini menjadi programer satgas pengolah data di ITB.

mw

Arsip mwmag[Files]  [Up]www.master.web.id/mwmag