.globl main
main:
/* Change to the working directory */
xorl %eax,%eax
pushl $dir // path
movb $12,%al
pushl %eax // chdir
int $0x80
setc %bl
addl $8,%esp
testb %bl,%bl
jnz out
/* Allow up to 32 links */
pushl $(32*256)
calll alloc
addl $4,%esp
movl %eax,links
/*
* Read each link.
* They are stored in files whose name start at 'a' and is
* incremented at each new link.
* XXX Allow for more than 26
*/
xorl %eax,%eax
movb $'a',%al
pushl %eax
movl %esp,%ecx // ecx = path
read_link:
xorl %eax,%eax
pushl %eax // O_RDONLY
pushl %ecx // path
movb $5,%al
pushl %eax // open
int $0x80
setc %bl
addl $12,%esp
testb %bl,%bl
jnz out_link2
movl %eax,%edx // edx = fd
leal tmp_buf,%edi
pushl $256 // len
pushl %edi // buf
pushl %eax // fd
xorl %eax,%eax
movb $3,%al
pushl %eax // read
int $0x80
setc %bl
addl $16,%esp
testb %bl,%bl
jnz out_link
movb $0,0(%edi,%eax)
/*
* Store in the "links" array
*/
pushl %ecx
/* Copy url */
pushl $0xa // '\n'
pushl %edi // url
calll _strchr
addl $8,%esp
subl %edi,%eax
movl %eax,%ecx
movl %edi,%esi
movl nlinks,%ebx
movl links,%edi
shll $8,%ebx // ebx = nlinks * 256
leal 0(%edi,%ebx),%edi
cld
rep movsb
movb $0,(%edi)
/* Copy description */
incl %esi
pushl $0xa
pushl %esi
calll _strchr
addl $8,%esp
subl %esi,%eax
movl %eax,%ecx
movl links,%edi
leal 128(%edi,%ebx),%edi
cld
rep movsb
movb $0,(%edi)
/* Copy path */
movl 4(%esp),%ecx
movl links,%edi
movl %ecx,248(%edi,%ebx)
/* Copy score */
incl %esi
pushl %esi
calll _atoi
addl $4,%esp
movl links,%edi
leal 252(%edi,%ebx),%edi
movl %eax,(%edi)
popl %ecx
pushl %edx // fd
movl $6,%eax
pushl %eax // close
int $0x80
addl $8,%esp
incl (%esp) // Next file (increment the filename)
incl nlinks
jmp read_link
out_link:
pushl %edx // fd
movl $6,%eax
pushl %eax // close
int $0x80
addl $8,%esp
out_link2:
addl $4,%esp
/* XXX Implement my own qsort */
pushl $compar
pushl $256
pushl nlinks
pushl links
calll qsort
addl $16,%esp
/* get QUERY_STRING */
pushl $query_string
calll getenv
addl $4,%esp
testl %eax,%eax
jz 1f
movl (%eax),%ebx
testb %bl,%bl
jz 1f
movl %eax,saved_qs
jmp have_qs
1:
/* Output header */
xorl %eax,%eax
pushl $(ok_end-ok) // len
pushl $ok // buf
movb $1,%al
pushl %eax // stdout
movb $4,%al
pushl %eax // write
int $0x80
addl $16,%esp
/* Print the links */
movl nlinks,%ecx
movl links,%edx
1:
leal tmp_buf,%edi
/* Upvote */
xorl %ebx,%ebx
pushl %ebx
pushl $0x003d703f // ?p=
movl %esp,%eax
movl 248(%edx),%ebx
movb %bl,3(%eax)
pushl $uarr // desc
pushl %eax // url
pushl %edi // dst
calll make_a_href
addl $20,%esp
movl %eax,%edi
/*
*/
movl $0x2f72623c,%eax
stosl
movb $0x3e,%al
stosb
/* Score */
movl 252(%edx),%eax
/* XXX Use a proper itoa() */
addl $'0',%eax
stosb
movb $' ',%al
stosb
/* The actual link */
leal 128(%edx),%ebx
pushl %ebx // desc
pushl %edx // url
pushl %edi // dst
calll make_a_href
addl $12,%esp
movl %eax,%edi
/*
*/
movl $0x2f72623c,%eax
stosl
movb $0x3e,%al
stosb
/* Downvote */
xorl %ebx,%ebx
pushl %ebx
pushl $0x003d643f // ?d=
movl %esp,%eax
movl 248(%edx),%ebx
movb %bl,3(%eax)
pushl $darr // desc
pushl %eax // url
pushl %edi // dst
calll make_a_href
addl $20,%esp
movl %eax,%edi
/*
*/
movl $0x2f72623c,%eax
stosl
movb $0x3e,%al
stosb
leal tmp_buf,%eax
subl %eax,%edi
pushl %edi // len
pushl %eax // buf
xorl %eax,%eax
movb $1,%al
pushl %eax // stdout
movb $4,%al
pushl %eax // write
int $0x80
addl $16,%esp
addl $256,%edx
decl %ecx
jnz 1b
jmp out
have_qs:
/* Output header */
xorl %eax,%eax
pushl $(submit_str_end-submit_str) // len
pushl $submit_str // buf
movb $1,%al
pushl %eax // stdout
movb $4,%al
pushl %eax // write
int $0x80
addl $16,%esp
/* URL submit? */
movl saved_qs,%eax
cmpw $0x3d74,(%eax) // "t="
jnz 9f
/* Get Title */
incl %eax
incl %eax
movl %eax,%ebx
pushl $'&'
pushl %eax
calll _strchr
addl $8,%esp
movb $0,(%eax)
pushl %ebx
/* Get URL */
incl %eax
cmpw $0x3d75,(%eax) // "u="
jnz 2f
incl %eax
incl %eax
/* Build file */
/* strlen(URL) < 120 */
movl %eax,%esi
pushl %eax
calll _strlen
addl $4,%esp
cmpl $120,%eax
jge 2f
movl %eax,%ecx
leal tmp_buf,%edi
/* Decode URL */
0:
movb (%esi),%al // XXX use lodsb
cmpb $'%',%al
jne 1f
incl %esi
decl %ecx
movb (%esi),%al
cmpb $'9',%al
jg 3f
subb $'0',%al
jmp 4f
3:
subb $'A',%al // XXX lowercase too
addb $10,%al
4:
shlb $4,%al
movb 1(%esi),%bl
cmpb $'9',%bl
jg 3f
subb $'0',%bl
jmp 4f
3:
subb $'A',%bl // XXX lowercase too
addb $10,%bl
4:
orb %bl,%al
incl %esi
decl %ecx
1:
stosb
incl %esi
loop 0b
movb $'\n',(%edi)
incl %edi
/* strlen(title) < 128 */
movl (%esp),%esi
pushl %esi
calll _strlen
addl $4,%esp
cmpl $128,%eax
jge 2f
/* Replace '+' with ' ' in title */
/* XXX also do the same thing as URL decoding */
movl %eax,%ecx
0:
movb (%esi),%al
cmpb $'+',%al
jne 1f
movb $' ',%al
1:
stosb
incl %esi
loop 0b
movb $'\n',(%edi)
incl %edi
movw $0x0a30,%ax // "0\n"
stosw
leal tmp_buf,%esi
subl %esi,%edi // edi = len
movl nlinks,%eax
addl $'a',%eax // XXX more than 26?
pushl %eax
movl %esp,%ecx // ecx = path
pushl $0644 // mode
pushl $0x202 // O_RDWR | O_CREAT
pushl %ecx // path
movb $5,%al
pushl %eax // open
int $0x80
setc %bl
addl $20,%esp
testb %bl,%bl
jnz 2f
pushl %edi // len
pushl $tmp_buf // buf
pushl %eax // fd
movl $4,%eax
pushl %eax // write
int $0x80
addl $16,%esp
2:
addl $4,%esp
jmp out
9:
/* Upvote? */
cmpw $0x3d70,(%eax) // "p="
jnz 1f
movl $1,%ebx // ebx = up
jmp 2f
/* Downvote? */
1:
cmpw $0x3d64,(%eax) // "d="
jnz out
movl $~0,%ebx // ebx = down
2:
xorl %edx,%edx
movb 2(%eax),%dl
/* Look for the link we voted on */
movl nlinks,%ecx
movl links,%edi
1:
cmpb %dl,248(%edi)
je 2f
addl $256,%edi
loop 1b
2:
testl %ecx,%ecx
jz out
addl %ebx,252(%edi) // Update the score
movl 252(%edi),%ecx
cmpb $0,%cl
js out
cmpb $10,%cl
jge out
/* Get offset in the file to update */
pushl %edi
calll _strlen
addl $4,%esp
movl %eax,%ebx
leal 128(%edi),%edx
pushl %edx
calll _strlen
addl $4,%esp
addl %eax,%ebx
incl %ebx
incl %ebx // Account for the two '\n'
xorl %eax,%eax
movb $2,%al
pushl %eax // O_RDWR
leal 248(%edi),%esi
pushl %esi // path
movb $5,%al
pushl %eax // open
int $0x80
setc %cl
addl $12,%esp
testb %cl,%cl
jnz out
movl %eax,%ecx // ecx = fd
xorl %eax,%eax
pushl %eax // SEEK_SET
pushl %ebx // offset
pushl %ecx // fd
movb $19,%al
pushl %eax // lseek
int $0x80
setc %bl
addl $16,%esp
testb %bl,%bl
jnz out
/* Write the new score */
movl 252(%edi),%eax
addl $'0',%eax // XXX proper itoa()
orl $0x0a00,%eax // '\n'
movw %ax,tmp_buf
write:
pushl $2 // len
pushl $tmp_buf // buf
pushl %ecx // fd
movl $4,%eax
pushl %eax // write
int $0x80
addl $16,%esp
out:
xorl %eax,%eax
retl
/*
* char *make_a_href(char *dst, char *url, char *desc)
*/
make_a_href:
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
movl 20(%esp),%edi
/* */
movw $0x3e22,%ax
stosw
/* Description */
movl 28(%esp),%edx
pushl %edx
calll _strlen
addl $4,%esp
movl %eax,%ecx
movl %edx,%esi
rep movsb
/* */
movl $0x3e612f3c,%eax
stosl
movl %edi,%eax
popl %esi
popl %edi
popl %edx
popl %ecx
retl
/*
* char *strchr(char *s, int c)
*/
_strchr:
pushl %ecx
pushl %edi
xorl %ecx,%ecx
notl %ecx
movl 12(%esp),%edi
movl 16(%esp),%eax
cld
repnz scasb
leal -1(%edi),%eax
popl %edi
popl %ecx
retl
_strlen:
movl 4(%esp),%eax
pushl $0
pushl %eax
calll _strchr
addl $8,%esp
subl 4(%esp),%eax
retl
compar:
pushl %ebx
movl 8(%esp),%ebx
movl 252(%ebx),%ebx
movl 12(%esp),%eax
movl 252(%eax),%eax
subl %ebx,%eax
popl %ebx
retl
/*
* void *alloc(int size)
*/
alloc:
pushl %ecx
movl 8(%esp),%ecx
addl $(0x1000 - 1),%ecx
andl $~(0x1000 - 1),%ecx
xorl %eax,%eax
pushl %eax
pushl %eax // offset
pushl $~0 // fd
pushl $0x1000 // flags = MAP_ANON
pushl $3 // prot = PROT_READ | PROT_WRITE
pushl %ecx // len
pushl %eax // addr
movb $197,%al // mmap
pushl %eax
int $0x80
addl $32,%esp
popl %ecx
retl
/*
* int atoi(char *s)
*/
_atoi:
movl 4(%esp),%eax
pushl %ebx
pushl %ecx
pushl %edx
pushl %edi
movl %eax,%ecx // end
movl %eax,%edx // beginning
xorl %eax,%eax
xorl %ebx,%ebx
movl $1,%edi
/* Find the end */
1:
movb (%ecx),%bl
subb $'0',%bl
js 2f
cmp $10,%bl
jge 2f
incl %ecx
jmp 1b
2:
decl %ecx
cmp %edx,%ecx
jl 3f
movb (%ecx),%bl
subb $'0',%bl
/* XXX choose registers better to avoid this crap */
pushl %eax
pushl %edx
movl %edi,%eax
mull %ebx
movl %eax,%ebx
popl %edx
popl %eax
addl %ebx,%eax
leal 0(%edi,%edi,4),%edi
addl %edi,%edi
jmp 2b
3:
popl %edi
popl %edx
popl %ecx
popl %ebx
retl
.data
query_string:
.asciz "QUERY_STRING"
ok:
.ascii "HTTP/1.1 200 OK\r\n"
.ascii "Server: r.cgi\r\n"
.ascii "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
.ascii "