BAB III. ANALISA DAN DESAIN
3.2. Perancangan Data
Untuk melakukan initialisasi terhadap socket, perlu dibuat sebuah input data sebagai masukan dari user.
Data keterangan
Config_dir Untuk meletakkan configurasi directory
Perldef Memberikan keterangan tentang letak directory perl
Real_os_type Nama sistem operasi
Real_os_version Versi sistem operasi
Port Nomer port yang digunakan
Login Input data login
Passw Input data password
Host Nama host
Tabel 3.1. Tabel data Initialisasi
Untuk melakukan penyuntingan terhadap user administrator maka dibutuhkan data-data yang berisi user administrator, password dan hak akses. Data tersebut merupakan konfigurasi dari pengguna program admin yang pertama kali.
Perlu untuk dimasukkan pada saat initialisasi karena untuk menggunakan program ini paling sedikit harus ada satu user.
Data Keterangan
Mods Daftar modul/Task
Ulist Daftar user dari pwfile
PWFILE File berisi user password
Tabel 3.2. Tabel data user administrator
Pada module Schedule Cron Job dibutuhkan data-data yang akan digunakan
untuk menampilkan seluruh cronjob yang terdapat dalam sistem.
Data Keterangan
TAB Daftar seluruh cron job yang dimiliki oleh user
Jlist Daftar seluruh cron job beserta user name dan perintahnya
cron_allow_file Daftar user diterima (allowed)
cron_deny_file Daftar user ditolak (denied)
Tabel 3.3. data Cron job
Modul export membutuhkan data yang berisi seluruh export file atau directory yang ada di dalam sistem untuk digunakan sebagai input untuk proses
editing export.
Data Keterangan
Exp Berisi daftar export
Tabel 3.4. data export
Pada tabel 3.5 merupakan data-data yang akan berfungsi untuk menyimpan informasi tentang protocol dan service yang terdapat di dalam sistem.
Data Keterangan
Config{service_file} Konfigurasi services dari service file
Config{Inetd_conf_file} Berisi configurasi internet service
Config{protocol_file} Berisi daftar protocols dalam sistem
SERVICES Daftar service
Tabel 3.5. Data service & protocol
Pada modul printer administration diperlukan tempat untuk menyimpan data-data yang akan digunakan untuk proses edit, delete, maupun create.
Data Keterangan
Prn Menampung nama printer
Jobs Daftar printer Jobs
CAP File princap
Plist Daftar semua printer
Tabel 3.6. Data printer
Untuk menunjukkan status file-file maupun direktori tertentu dapat menggunakan data-data seperti di bawah ini untuk menyimpan informasi dari sistem tentang status file maupun direktori yang ada dalam sistem.
Data Keterangan
MTAB Daftar mount (/etc/mtab)
FSTAB Daftar filesystem saat booting (/etc/fstab)
Tabel 3.7. Data Mount
Berikut adalah data-data yang diambil dari sistem yang akan digunakan untuk administrasi dan konfigurasi network .
Data Keterangan
HOTS Daftar hosts dan alamat
IFC Daftar Interface
RESOLV Konfigurasi dns
STATIC Konfigurasi rute statis
Tabel 3.8. Data Network
Untuk melakukan proses administrasi terhadap unix/linux user dibutuhkan informasi tentang user, group dan password. Untuk menyimpan informasi tersebut dibutuhkan data seperti daftar linux user maupun daftar group user.
Data Keterangan
Passwd Daftar linux user
Group Daftar linux group
Pam Daftar Password acak
Base uid UID untuk user
Base gid GID untuk group
Tabel 3.9. Data Linux user
3.3. Perancangan Proses.
Sebelum melakukan proses pengiriman dan penerimaan data (HTTP
Interactions), terlebih dahulu dilakukan proses membuka socket. Socket dapat
diibaratkan sebagai chanel pada sebuah radio yang mempunyai
gelombang-gelombang tertentu dalam proses pengiriman dan penerimaan data. Apabila sebuah socket dibuka dengan “gelombang” tertentu, maka hanya komputer dengan “gelombang” yang sama yang dapat menerima data yang dikirim. Setelah socket dibuka, maka dialokasikan alamat protokol lokal ke dalamnya. Alamat protokol terdiri dari kombinasi 32-bit sampai dengan 128-bit alamat internet (IP Address) ditambah dengan 16-bit nomor port pada protokol TCP dan UDP. Proses
pengalokasian alamat protokol disebut proses BIND. Socket yang telah diaktifkan
dan dialokasikan kemudian bersiap untuk merima data yang dikirim oleh komputer lain (listen). Pada server, proses ini digunakan untuk menunggu koneksi dari client. Setiap koneksi ditampung dalam satu antrian dan secara otomatis server akan mengatur koneksi-koneksi tersebut serta memilih koneksi mana yang benar-benar komplit dan siap untuk ditanggani (accept). Client yang sudah terkoneksi dapat melakukan proses pengiriman dan penerimaan data antar client-client yang lain.
Server akan menunggu koneksi terhadap network pada port, ketika client terhubung dengan port, server akan menerima koneksi tersebut dan kemudian akan berhubungan dengan client dengan menggunakan protocol yang mereka sepakati (tcp, http, nntp, smtp, dll).
Server akan menggunakan socket() system call untuk menciptakan socket,
dan bind() call akan menugaskan socket pada port tertentu pada host. Server
kemudian akan menggunakan rutin listen() dan accept() untuk menciptakan
komunikasi pada port. Pada sisi yang lain client juga menggunakan socket() system
call to create socket dan kemudian akan menggunakan connect() call untuk
inisialisasi koneksi yang berasosiasi dengan socket pada remote host tertentu dan
port. Server menggunakan accept() call untuk menerima koneksi yang datang dan inisialisasi komunikasi dengan client. Client dan server akan menggunakan
sysread() dan syswrite() untuk berkomunikasi pada HTTP sampai transaksi selesai. Apabila transaksi telah selesai maka baik client maupun server akan menggunakan
close() atau shutdown() untuk mengakhiri koneksi. Proses-proses yang terjadi diatas akan dijelaskan dalam sebagai berikut:
3.3.1. Proses transaksi http.
Sebelum memasuki proses penerimaan dan pengiriman data yang merupakan inti dari sistem aplikasi ini, diperlukan beberapa deklarasi awal yang berlaku secara global atau menyeluruh disemua proses-proses yang ada didalam sistem. Setelah itu dilakukan inisialisasi terhadap proses dan prosedur yang telah dibuat tersebut sebagai tanda dimulainya proses pengiriman dan penerimaan data.
Salah satu deklarasi yang perlu didefinisikan adalah terlebih dahulu adalah
socket. Function dari pendeklarasian tersebut adalah sebagai berikut :
$perl -e 'use Socket; socket(FOO, PF_INET, SOCK_STREAM,
getprotobyname("tcp")); setsockopt(FOO, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)); bind(FOO, sockaddr_in($ARGV[0], INADDR_ANY)) || exit(1); exit(0);' $port
if [ $? != "0" ]; then
echo "ERROR: TCP port $port is already in use by another program" echo ""
exit 13
Baik client dan server keduanya sama-sama menggunakan fungsi socket()
untuk menciptakan I/O buffer dalam sistem operasi. Socket() memerlukan
beberapa argumen yang berupa file handle yang berasosiasi dengan socket,
network protocol, dan bagaimana tipe socket, stream-oriented atau
record-oriented. Untuk transaksi HTTP, tipe socket yang digunakan adalah tipe stream-oriented. Dalam contoh berikut di bawah ini, file handle SH berasosiasi dengan
socket yang baru diciptakan. PF_INET adalah indikasi dari internet protocol,
sedangkan getprotobyname('tcp') merupakan indikasi dari Transmission Control
Protocol (TCP), sedangkan SOCK_STREAM adalah indikasi dari tipe socket stream-oriented. Bila socket calls gagal maka program akan die() menggunakan
pesan kesalahan (error message) yang terdapat dalam $!. Di bawah adalah
berbagai macam variasi yang biasa digunakan untuk melalukan insialisasi socket: socket(SH, PF_INET, SOCK_STREAM, getprotobyname("tcp")) || $!;
$proto = getprotobyname('tcp');
socket(MAIN, PF_INET, SOCK_STREAM, $proto) || die "Failed to open main socket : $!";
socket($h, PF_INET, SOCK_STREAM, getprotobyname("tcp")) || &error("Failed to create socket : $!");
Kemudian socket diinisialisasi (dibuka) sesuai dengan jenis protocol yang digunakan. Berikut ini adalah inisialisasi socket dengan menggunakan protocol TCP secara lengkap.
# Open main socket {miniserv.pl}
$proto = getprotobyname('tcp');
socket(MAIN, PF_INET, SOCK_STREAM, $proto) || die "Failed to open main socket : $!";
setsockopt(MAIN, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)); $baddr = $config{"bind"} ? inet_aton($config{"bind"}) : INADDR_ANY; bind(MAIN, sockaddr_in($config{port}, $baddr)) ||
die "Failed to bind port $config{port} : $!"; listen(MAIN, SOMAXCONN);
# Read the HTTP request and headers ($reqline = &read_line()) =~ s/\r|\n//g;
if (!($reqline =~ /^(GET|POST)\s+(.*)\s+HTTP\/1\..$/)) { &http_error(400, "Bad Request");
}
$method = $1; $request_uri = $page = $2; %header = ();
while(1) {
($headline = &read_line()) =~ s/\r|\n//g; if ($headline eq "") { last; }
($headline =~ /^(\S+):\s+(.*)$/) || &http_error(400, "Bad Header"); $header{lc($1)} = $2;
}
if (defined($header{'host'})) {
if ($header{'host'} =~ /^([^:]+):([0-9]+)$/) { $host = $1; } else { $host = $header{'host'}; }
}
if ($page =~ /^([^\?]+)\?(.*)$/) {
# There is some query string information $page = $1; $querystring = $2; if ($querystring !~ /=/) { $queryargs = $querystring; $queryargs =~ s/\+/ /g; $queryargs =~ s/%(..)/pack("c",hex($1))/ge;
$querystring = ""; }
}
b. Membuat koneksi network
Dengan mengunakan fungsi connect() dapat dibuat sebuah hubungan dengan
server dalam sebuah network (network connections) berikut host dan port yang
dikehendaki, dan menyelaraskan (associate) dengan I/O buffer yang telah
diciptakan oleh socket().
$sin = sockaddr_in (80, inet_aton, (‘localhost.localdomain.com’)); connect(SH,$sin) || die $!;
Rutin sockaddr_in() menerima sebuah port number sebagai parameter
pertama dan IP address sebaggai parameter kedua. Inet_aton() menerjemahkan
(translates) sebuah hostname string atau sebuah dotted decimal string menjadi
sebuah IP address 32-bit. sockaddr_in mengembalikan struktur data yang datang
melalui fungsi connect(), dari sanalah connect() mampu melakukan proses
koneksi pada sebuah jaringan komputer pada server dan port secara spesifik.
Berikut adalah penerapan fungsi connect() pada aplikasi:
($addr = inet_aton($_[0])) ||
&error("Failed to lookup IP address for $_[0]"); connect($h, sockaddr_in($_[1], $addr)) ||
&error("Failed to connect to $_[0]:$_[1] : $!");
Apabila koneksi terhadap network tersebut sukses, maka nilai yang kembali
adalah true, namun apabila gagal maka nilai false akan diberikan, untuk
setelah connect() untuk menghentikan program dan melaporkan kesalahan.
Fungsi connect() ini hanya dapat digunakan oleh client saja.
# open_socket(host, port, handle) <weblib.pl> sub open_socket
{
local($addr, $h); $h = $_[2];
socket($h, PF_INET, SOCK_STREAM, getprotobyname("tcp")) || &error("Failed to create socket : $!");
($addr = inet_aton($_[0])) ||
&error("Failed to lookup IP address for $_[0]"); connect($h, sockaddr_in($_[1], $addr)) ||
&error("Failed to connect to $_[0]:$_[1] : $!"); select($h); $| =1; select(STDOUT);
}
c. Menulis data pada koneksi network
Untuk menulis file handle (data) yang berasosiasi dengan socket (network
connection), dapat digunakan rutin syswrite(). Parameter pertama merupakan file
handle untuk menulis data, sedang data yang akan ditulis dijadikan parameter kedua. Sedangkan parameter ketiga adalah panjang data yang akan ditulis.
Syswrite() digunakan oleh client dan server. $buffer = ”Linux Web Administration”;
syswrite (FH, $buffer, length($buffer)); # sysprint(handle, [string]+) sub sysprint { local($str, $fh); $str = join('', @_[1..$#_]); $fh = $_[0]; syswrite $fh, $str, length($str); }
Untuk membaca data dari sebuah koneksi network dapat digunakan rutin
sysread() fungsi tersebut dapat berjalan baik pada server maupun client sysread()
membaca data dari file handle yang berasosiasi dengan socket tersebut, pada
parameter pertama file handle diberikan untuk menerangkan koneksi yang akan dibaca. Sedangkan parameter kedua menunjukkan sebuah variabel scalar untuk menyimpan data yang telah dibaca. Parameter ketiga menunjukkan bytes maksimum yang akan dibaca dari sebuah koneksi.
Sysread(FH, $buffer, 200); # read at most 200 bytes from FH $buffer = <FH>;
e. Mengakhiri Koneksi
Setelah transaksi selesai (complete), rutin close() akan mengakhiri koneksi
jaringan (closing network connections). Fungsi ini dapat digunakan baik oleh
client maupun server. close(FH);
f. Mendengarkan port
Fungsi bind() digunakan hanya oleh server. Rutin bind() menyelaraskan
(associate) antara socket buffer dengan port pada perangkat keras (computer).
Apabila port yang dimaksud telah digunakan oleh program lain maka bind() akan
memberikan nilai false (zero). Sockaddr_in() dapat digunakan untuk identifikasi
atau mengenali port untuk bind(). Definisi port dapat berupa variabel dapat juga
ditulis secara langsung. Proses ini dikenal dengan Binding the Port.
bind(MAIN, sockaddr_in($config{port}, $baddr)) || die "Failed to bind port $config{port} : $!";
Socket yang telah diinisialisasi atau diaktifkan, menandai dibukanya jalur akses ke alamat lokal protokol. Oleh karena itu diperlukan proses untuk memasuki jalur yang telah disediakan oleh socket tersebut.
Fungsi bind akan sukses atau berhasil dijalankan jika nilai yang dihasilkan berupa 0 (null) dan bernilai –1 (socket_error) jika tidak berjalan semestinya. Proses bind akan menspesifikasikan alamat lokal dan port yangg sudah didefinisikan sebelumnya. Alamat lokal yang tidak didefinisikan secara jelas (inaddr_any), akan menonaktifkan sistem untuk memilih alamat lokal sampai adanya koneksi dari socket yang lain. Dengan demikian default alamat lokal dengan INADDR_ANY sangat effisien dipakai diawal pertama kali socket diaktifkan.
g. Menunggu koneksi
Fungsi listen() hanya digunakan oleh server untuk menunggu datangnya
koneksi dari client. Fungsi listen() memberitahukan pada sistem operasi bahwa
server siap untuk menerima koneksi jaringan yang akan masuk pada port yang telah ditentukan. Parameter pertama merupakan file handle pada socket untuk melakukan proses listen.
listen(MAIN, SOMAXCONN);
h. Menerima Koneksi
menerima datangnya koneksi dari client. Dengan kata lain Accept() berfungsi
untuk menunggu datangnya permintaan (request) pada server. Untuk parameter
accept() menggunakan dua file handle, satu berassosiasi dengan socket sedang
yang lain berassosiasi dengan koneksi network tertentu (specifik network
connections).
# got new connection
$acptaddr = accept(SOCK, MAIN); if (!$acptaddr) { next; }
Proses yang terjadi pada program aplikasi ini akan dikelompokkan berdasar fungsi-fungsi yang ada dalam program aplikasi.
i. Proses penerimaan data
Pada saat data yang diminta dikirim segera dijalankan proses penerimaan data. Proses ini merupakan tahap dari sistem untuk menerima koneksi dari socket lain. Setelah alamat dan port sudah teralokasikan melalui proses bind, dapat diartikan bahwa socket telah diaktifkan untuk menerima koneksi dari socket lain serta membuka jalur bagi data-data yang akan memasuki sistem (receive).
# read_line()
# Reads one line from SOCK sub read_line
{
local($idx, $more, $rv); if ($use_ssl) {
while(($idx = index($read_buffer, "\n")) < 0) { # need to read more..
if (!($more = Net::SSLeay::read($ssl_con))) { # end of the data
$rv = $read_buffer; undef($read_buffer); return $rv;
}
$read_buffer .= $more; }
$rv = substr($read_buffer, 0, $idx+1);
$read_buffer = substr($read_buffer, $idx+1); return $rv;
}
else { return <SOCK>; } }
Fungsi receive form berfungsi sebagai jalur pembuka yang selalu siap menangani setiap socket yang berinteraksi.
j. Proses pengiriman data
Proses listen atau proses penerimaan data diulang secara terus menerus agar sistem selalu siap menerima semua paket data yang yang ditujukan ke alamat sistem. Proses penerimaan data sistem bersifat pasif yaitu menunggu datangnya
data sehingga sistem harus selalu stand by.
# write_data(data)
# Writes a string to SOCK sub write_data { if ($use_ssl) { Net::SSLeay::write($ssl_con, $_[0]); } else { print SOCK $_[0]; } $write_data_count += length($_[0]); }
3.3.2. Proses dalam Modul
Proses modul adalah proses pasif, artinya proses tersebut tidak akan dijalankan apabila tidak ada perintah dari user, meskipun user telah terlebih dahulu
mengaktifkan proses transaksi http.
a. Admin Users
Admin user adalah sebuah tools untuk membuat, edit, menghapus, user administrator, atau orang-orang yang memiliki hak untuk melakukan proses administrasi dengan menggunakan program aplikasi ini. Dalam tools ini seorang administrator dapat mengatur fasilitas-fasilitas mana saja yang diperkenankan untuk dipakai oleh setiap user administrator.
Untuk menampilkan data-data user yang berhak untuk menggunakan program admin dibuat subrutin yang berfungsi untuk mengambil data user yang berada dalam /etc/admin. Data tersebut kemudian ditempatkan dalam sebuah file handle bernama PWFILE. PWFILE akan disimpan dalam array untuk ditampilkan pada form yang disediakan.
sub list_users {
local(@mods, %miniserv, $_, @rv, %acl); &read_acl(undef, \%acl); @mods = &list_modules(); &get_miniserv_config(\%miniserv); open(PWFILE, $miniserv{'userfile'}); while(<PWFILE>) { if (/^([^:\s]+):([^:\s]+)(:(\d+))?/) { local(%user); $user{'name'} = $1; $user{'pass'} = $2; $user{'sync'} = $4 if ($3); $user{'modules'} = $acl{$1}; push(@rv, \%user); } } close(PWFILE);
Untuk menciptakan user baru bagi administrator maka perlu membuka file handle PWFILE. Program admin akan menerima input dari user, kemudian akan menjalan subrutin create_user yang akan menambahkan input dari user untuk disimpan dalam /etc/admin.
# create_user(&details) sub create_user
{
local(%user, %miniserv, @mods); %user = %{$_[0]};
&get_miniserv_config(\%miniserv);
open(PWFILE, ">> $miniserv{'userfile'}");
print PWFILE "$user{'name'}:$user{'pass'}:$user{'sync'}\n"; close(PWFILE);
Sama dengan ketika membuat user baru, untuk merubah user data-data tentang user perlu ditampilkan terlebih dahulu, user akan menekan tombol save apabila telah selesai melakukan perubahan. Ketika tombol save ditekan maka subrutin modify user akan dijalankan. File handle PWFILE yang menyimpan data user akan ditulis kembali menggantikan data yang lama.
# modify_user(name, &details) sub modify_user
{
local(%user, %miniserv, @pwfile, @acl, @mods, $_, $m); %user = %{$_[1]}; &get_miniserv_config(\%miniserv); open(PWFILE, $miniserv{'userfile'}); @pwfile = <PWFILE>; close(PWFILE); open(PWFILE, "> $miniserv{'userfile'}"); foreach (@pwfile) { if (/^([^:\s]+):([^:\s]+)/ && $1 eq $_[0]) {
print PWFILE "$user{'name'}:$user{'pass'}:$user{'sync'}\n"; }
}
close(PWFILE);
Data user masih harus ditampilkan apabila hendak menghapus user yang telah ada. Input dari user yang berupa penekanan tombol delete akan menjalankan subrutin delete_user. Data yang tersimpan dalam PWFILE akan disimpan kembali menggantikan data sebelumnya.
# delete_user(name){func del_usr-/acl/acl-lib.pl} sub delete_user
{
local($_, @pwfile, @acl, %miniserv); &get_miniserv_config(\%miniserv); open(PWFILE, $miniserv{'userfile'}); @pwfile = <PWFILE>; close(PWFILE); open(PWFILE, "> $miniserv{'userfile'}"); foreach (@pwfile) { if (!/^([^:\s]+):([^:\s]+)/ || $1 ne $_[0]) { print PWFILE $_; } } close(PWFILE);
Apabila ada kegagalan dalam proses penghapusan user maka error message dapat ditampilkan dalam $whatfailed.
# modify_user(name, &details){func edt_usr-/acl-lib.pl} sub modify_user
{
local(%user, %miniserv, @pwfile, @acl, @mods, $_, $m); %user = %{$_[1]}; &get_miniserv_config(\%miniserv); open(PWFILE, $miniserv{'userfile'}); @pwfile = <PWFILE>; close(PWFILE); open(PWFILE, "> $miniserv{'userfile'}"); foreach (@pwfile) {
if (/^([^:\s]+):([^:\s]+)/ && $1 eq $_[0]) {
print PWFILE "$user{'name'}:$user{'pass'}:$user{'sync'}\n"; }
else { print PWFILE $_; } }
close(PWFILE);
b. Linux Users
Linux user adalah modul yang mengatur administrasi terhadap user-user linux. Dalam modul ini seorang administrator mampu untuk membuat user baru,
menghapus user, atau melakukan proses editing terhadap account seorang user.
Untuk keperluan tersebut diperlukan sebuah fungsi yang dapat mencari acount dari linux user. Berikut adalah fungsi untuk mengetahui user-user yang memiliki hak untuk menggunakan linux.
# password_file(file){user-lib.pl} sub password_file { if (!$_[0]) { return 0; } elsif (open(SHTEST, $_[0])) { local($line); $line = <SHTEST>; close(SHTEST); return $line =~ /^\S+:\S*:/; } else { return 0; } } # list_users() sub list_users {
# read the password file . . .
# start by reading /etc/passwd $lnum = 0;
open(PASSWD, $config{'passwd_file'}); while(<PASSWD>) {
s/\r|\n//g;
if (/\S/ && !/^[#\+\-]/) {
@pw = split(/:/, $_, -1);
push(@rv, { 'user' => $pw[0], 'pass' => $pw[1],
'uid' => $pw[2], 'gid' => $pw[3],
'real' => $pw[4], 'home' => $pw[5],
'shell' => $pw[6], 'line' => $lnum, 'num' => scalar(@rv) }); $idx{$pw[0]} = $rv[$#rv]; } $lnum++; } close(PASSWD);
Fungsi ini mencari file yang berada pada lokasi /etc/passwd, yaitu lokasi untuk menyimpan data-data password dari linux user. Data-data ini kemudian
dibaca dan disimpan dalam hashtable array bernama PASSWD, dari data ini
akan diperoleh informasi tentang user, pass, uid, gid, real, home, shell karena setiap file yang diambil mengandung informasi tersebut untuk masing-masing user.
Pada prinsipnya untuk membuat user baru, dapat ditambahkan pada daftar user yang disimpan dalam passwd, untuk selanjutnya disimpan kembali dalam direktory /etc/passwd.
sub crete_user < Creates a new user with the given details >
{
local(%u) = %{$_[0]}; if (&passfiles_type() == 1) {
# just need to add to master.passwd
open(PASSWD, ">> $config{'master_file'}"); print PASSWD "$u{'user'}:$u{'pass'}:$u{'uid'}:$u{'gid'}:$u{'class'}:$u{'change'}:$u{'expire'}:$ u{'real'}:$u{'home'}:$u{'shell'}\n"; close(PASSWD); }
else {
# add to /etc/passwd
open(PASSWD, ">> $config{'passwd_file'}");
print PASSWD "$u{'user'}:",&passfiles_type() == 2 ? "x" : $u{'pass'}, ":$u{'uid'}:$u{'gid'}:$u{'real'}:$u{'home'}:$u{'shell'}\n"; close(PASSWD);
if (&passfiles_type() == 2) { # add to shadow as well..
open(SHADOW, ">> $config{'shadow_file'}"); print SHADOW "$u{'user'}:$u{'pass'}:$u{'change'}:$u{'min'}:$u{'max'}:$u{'warn'}:$u{'inactive' }:$u{'expire'}:\n"; close(SHADOW); } } }
Hal yang sama terjadi juga terhadap fungsi modify user. Data-data dapat diambil dari passwd, kemudian merubah data tersebut dan menyimpannya kembali dalam lokasi yang sama.
# modify_user(&old, &details) sub modify_user { local(%u) = %{$_[1]}; local(@passwd, @shadow); if (&passfiles_type() == 1) {
# just need to update master.passwd
&replace_file_line($config{'master_file'}, $_[0]->{'line'}, "$u{'user'}:$u{'pass'}:$u{'uid'}:$u{'gid'}:$u{'class'}:". "$u{'change'}:$u{'expire'}:$u{'real'}:$u{'home'}:$u{'shell'}\n"); } else { # update /etc/passwd &replace_file_line($config{'passwd_file'}, $_[0]->{'line'}, "$u{'user'}:".(&passfiles_type() == 2 ? "x" : $u{'pass'}). ":$u{'uid'}:$u{'gid'}:$u{'real'}:$u{'home'}:$u{'shell'}\n"); if (&passfiles_type() == 2) {
&replace_file_line($config{'shadow_file'}, $_[0]->{'sline'}, "$u{'user'}:$u{'pass'}:$u{'change'}:$u{'min'}:". "$u{'max'}:$u{'warn'}:$u{'inactive'}:$u{'expire'}:\n"); } } }
Berikut adalah fungsi yang bertugas untuk menghapus user. Masih memanfaatkan daftar user passwd.
# delete_user(&details) sub delete_user { if (&passfiles_type() == 1) { &replace_file_line($config{'master_file'}, $_[0]->{'line'}); } else { &replace_file_line($config{'passwd_file'}, $_[0]->{'line'}); if (&passfiles_type() == 2) { &replace_file_line($config{'shadow_file'}, $_[0]->{'sline'}); } } }
Untuk melakukan administrasi pada group masih sama seperti diatas, informasi tentang group, pass, gid, members disimpan dalam array hashtable
bernama GROUP.
# list_groups() sub list_groups {
local(@rv, $lnum, $_, %idx, $g, $i, $j); $lnum = 0; open(GROUP, $config{'group_file'}); while(<GROUP>) { s/\r|\n//g; if (/\S/ && !/^[#\+\-]/) { @gr = split(/:/, $_, -1);
'gid' => $gr[2],'members' => $gr[3], 'line' => $lnum,'num' => scalar(@rv) }); $idx{$gr[0]} = $rv[$#rv];
} $lnum++; }
close(GROUP);
Untuk fungsi-fungsi yang lain seperti, menambah group baru, edit group, atau menghapus group pada prinsipnya sama seperti yang terjadi pada user. Perbedaannya hanya terdapat pada ulist dan glist nya saja.
c. Administrasi Printer
Dengan memanfaatkan PRINCAP (Printer Capability Database) dapat
dibuat fungsi-fungsi yang berguna untuk menambah, menghapus maupun edit printer. Princap berfungsi untuk menerjemahkan line printer. Berikut adalah program untuk mendapatkan printer sekaligus untuk mengetahui status printer tersebut.
#Sub_get_printer
# found the printer.. get info from printcap $prn{'name'} = $n[0]; if (@n > 2) { $prn{'alias'} = [ @n[1..$#n-1] ]; } if (@n > 1) { $prn{'desc'} = $n[$#n]; } $prn{'iface'} = $l->{'if'}; $prn{'banner'} = !defined($l->{'sh'}); $prn{'dev'} = $l->{'lp'}; $prn{'rhost'} = $l->{'rm'}; $prn{'rqueue'} = $l->{'rp'}; $prn{'msize'} = $l->{'mx#'}; # call lpc to get status
$out = `lpc status $prn{'name'} 2>&1`;
$prn{'accepting'} = ($out =~ /queuing is enabled/); $prn{'enabled'} = ($out =~ /printing is enabled/); # call lpq to get print jobs
while(<LPQ>) { chop;
if (/^Rank\s+Owner\s+/) { $doneheader++; }
elsif ($doneheader && /^(\S+)\s+(\S+)\s+(\d+)\s+(.*\S)\s+(\d+)\s+(\S+)$/) { local(%job); $job{'id'} = $3; $job{'user'} = $2; $job{'size'} = $5; $job{'file'} = $4; $job{'printing'} = ($1 eq "active"); push(@jobs, \%job);
Untuk menambah account printer baru dalam direktori /etc/printcap, panggil file handle CAP simpan dalam config{‘printcap_file’} cetak CAP dan jalankan subrutin make_printcap, maka data baru yang diinputkan oleh user akan disimpan dalam printcap_file. # create_printer(&details) sub create_printer { local(%cap); $cap{'sd'} = "$config{'spool_dir'}/$_[0]->{'name'}"; mkdir($cap{'sd'}, 0755); open(CAP, ">> $config{'printcap_file'}"); print CAP &make_printcap($_[0], \%cap),"\n"; close(CAP);
&apply_status($_[0]); }
Untuk merubah account yang sudah ada dapat mengambil daftar printer dalam list_printcab yang kemudian disimpan dalam sebuah array. Nama printer yang akan dihapus merupakan input dari user. Bila nama yang diinginkan tidak terdapat dalam daftar printer akan ditampilkan pesan kesalahan. Namun bila printer ditemukan akan ditampilkan.
# modify_printer(&details) sub modify_printer
{
local(@old, $o, $old, @cap); @old = &list_printcap(); foreach $o (@old) {
$o->{'name'} =~ /^([^\|]+)/; if ($1 eq $_[0]->{'name'}) {
# found current details $old = $o;
last; } }
if (!$old) { &error("Printer '$_[0]->{'name'}' no longer exists"); } open(CAP, $config{'printcap_file'});
@cap = <CAP>; close(CAP);
splice(@cap, $old->{'line'},
$old->{'eline'} - $old->{'line'} + 1, &make_printcap($_[0], $old)."\n");