.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 "" .ascii "
" .ascii "Description: " .ascii "URL: " .ascii "" .ascii "
" .ascii "" ok_end: submit_str: .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 "\n" .ascii "" .ascii "" submit_str_end: saved_qs: .long 0 link_start_str: .ascii "