Subversion Repositories Kolibri OS

Rev

Rev 3981 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;                                                                 ;;
  7. ;;         GNU GENERAL PUBLIC LICENSE                              ;;
  8. ;;          Version 2, June 1991                                   ;;
  9. ;;                                                                 ;;
  10. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  11.  
  12.  
  13. server_parser:
  14.  
  15.         mov     esi, servercommand
  16.  
  17.         cmp     byte [esi], ':'
  18.         jne     .parse
  19.  
  20.   .spaceloop:
  21.         lodsb
  22.         test    al, al
  23.         jz      .fail
  24.         cmp     al, ' '
  25.         jne     .spaceloop
  26.  
  27.   .parse:
  28.         mov     eax, [esi]
  29.         or      eax, 0x20202020
  30.         mov     edi, server_commands
  31.         mov     ecx, server_commands.number
  32.  
  33.   .loop:
  34.         scasd
  35.         je      .got_cmd
  36.         add     edi, 4
  37.         dec     ecx
  38.         jnz     .loop
  39.  
  40.   .fail:
  41.         ret
  42.  
  43.   .got_cmd:
  44.         jmp     dword[edi]
  45.  
  46.  
  47. server_commands:
  48.  
  49.         dd      '322 ', cmd_322         ; RPL_LIST
  50.         dd      '323 ', cmd_323         ; RPL_LISTEND
  51.         dd      '328 ', cmd_328
  52.         dd      '332 ', cmd_topic
  53.         dd      '333 ', cmd_333         ; nickname and time of topic
  54.         dd      '353 ', cmd_353         ; name reply
  55.         dd      '366 ', cmd_366         ; end of names list
  56.         dd      '372 ', cmd_372         ; motd
  57.         dd      '375 ', cmd_375         ; start of motd
  58.         dd      '376 ', cmd_376         ; end of motd
  59.         dd      '421 ', cmd_421         ; unknown command
  60.         dd      'join', cmd_join
  61.         dd      'kick', cmd_kick
  62.         dd      'mode', cmd_mode
  63.         dd      'nick', cmd_nick
  64.         dd      'part', cmd_part
  65.         dd      'ping', cmd_ping
  66.         dd      'priv', cmd_privmsg
  67.         dd      'quit', cmd_quit
  68.         dd      'noti', cmd_notice
  69.  
  70.         .number = ($ - server_commands) / 8
  71.  
  72.  
  73. align 4
  74. compare_to_nick:
  75.  
  76.         push    esi
  77.         mov     ecx, MAX_NICK_LEN
  78.         mov     esi, user_nick
  79.   .loop:
  80.         lodsb
  81.         cmp     al, ' '
  82.         jbe     .done
  83.         cmp     al, 'a'
  84.         jb      .ok
  85.         cmp     al, 'z'
  86.         ja      .ok
  87.         sub     al, 0x20
  88.   .ok:
  89.  
  90.         mov     bl, byte[edi]
  91.         cmp     bl, 'a'
  92.         jb      .ok2
  93.         cmp     bl, 'z'
  94.         ja      .ok2
  95.         sub     bl, 0x20
  96.   .ok2:
  97.         cmp     bl, al
  98.         jne     .not_equal
  99.         inc     edi
  100.         dec     ecx
  101.         jnz     .loop
  102.  
  103.   .done:
  104.         xor     eax, eax
  105.         pop     esi
  106.         ret
  107.  
  108.   .not_equal:
  109.         or      eax, -1
  110.         pop     esi
  111.         ret
  112.  
  113. align 4
  114. skip_nick:
  115.  
  116. ; First: skip the NICK (maybe we should verify it?)
  117.   .nick:
  118.         lodsb
  119.         cmp     al, ' '
  120.         je      .skip
  121.         cmp     al, ':'
  122.         je      .skip
  123.         jmp     .nick
  124.  
  125. ; skip all leading spaces and semicolons
  126.   .skip:
  127.         lodsb
  128.         cmp     al, ' '
  129.         je      .skip
  130.         cmp     al, ':'
  131.         je      .skip
  132.         dec     esi
  133.  
  134.         ret
  135.  
  136.  
  137. align 4
  138. find_window:                            ; esi is ptr to windowname
  139.  
  140.         push    esi
  141.  
  142.         mov     edi, esi
  143.         call    compare_to_nick
  144.         jne     .nochat
  145.  
  146.         mov     esi, servercommand+1
  147.   .nochat:
  148.  
  149. ; now search for window in list
  150.         mov     ebx, windows
  151.         mov     [window_print], ebx     ; set first window (server window) as default output window
  152.   .scanloop:
  153.         cmp     [ebx + window.data_ptr], 0
  154.         je      .create_it
  155.         push    esi
  156.         lea     edi, [ebx + window.name]
  157.         mov     ecx, MAX_WINDOWNAME_LEN
  158.         repe    cmpsb
  159.         pop     esi
  160.         cmp     byte[edi-1], 0
  161.         je      .got_it
  162.         add     ebx, sizeof.window
  163.         ; TODO: check buffer limits ?
  164.         jmp     .scanloop
  165.  
  166. ; create channel window - search for empty slot
  167.   .create_it:
  168.         mov     ebx, windows
  169.         mov     ecx, MAX_WINDOWS
  170.   .scanloop2:
  171.         cmp     [ebx + window.data_ptr], 0
  172.         je      .free_found
  173.         add     ebx, sizeof.window
  174.         dec     ecx
  175.         jnz     .scanloop2
  176. ; Error: no more available windows!
  177.         jmp     .just_skip
  178.  
  179.   .free_found:
  180.         push    ebx
  181.         call    window_create
  182.         pop     ebx
  183.         test    eax, eax
  184.         jz      .just_skip
  185.         mov     [ebx + window.data_ptr], eax
  186.         mov     [ebx + window.type], WINDOWTYPE_CHAT
  187.         mov     [ebx + window.flags], 0
  188.  
  189.         call    window_set_name
  190.  
  191.         mov     [window_open], ebx
  192.         mov     [window_print], ebx
  193.         call    window_refresh
  194.  
  195.         call    draw_windownames
  196.         jmp     .just_skip
  197.  
  198. ; found it!
  199.   .got_it:
  200.         mov     [window_print], ebx
  201.         call    window_refresh
  202.  
  203.   .just_skip:
  204.         pop     esi
  205.   .skip1:
  206. ; skip text
  207.         lodsb
  208.         test    al, al
  209.         jz      .quit
  210.         cmp     al, ' '
  211.         jne     .skip1
  212.         dec     esi
  213. ; now skip trailing spaces and semicolons
  214.   .skip2:
  215.         lodsb
  216.         test    al, al
  217.         jz      .quit
  218.         cmp     al, ' '
  219.         je      .skip2
  220.         cmp     al, ':'
  221.         je      .skip2
  222.         dec     esi
  223.  
  224.   .quit:
  225.         ret
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232. cmd_328:
  233. cmd_421:
  234. cmd_372:
  235. cmd_375:
  236. cmd_376:
  237.         add     esi, 4
  238.         jmp     cmd_notice.loop
  239.  
  240. cmd_notice:
  241.  
  242.         cmp     byte[servercommand], ':'
  243.         jne     .gogogo
  244.  
  245.         mov     byte [esi-1], 0
  246.         push    esi
  247.         mov     esi, str_1
  248.         call    print_text2
  249.         mov     esi, servercommand+1
  250.         call    print_text2
  251.         mov     esi, str_2
  252.         call    print_text2
  253.         pop     esi
  254.  
  255.   .gogogo:
  256.         add     esi, 6
  257.  
  258.   .loop:
  259.         inc     esi
  260.         cmp     byte [esi], 0
  261.         je      .fail
  262.         cmp     byte [esi], ' '
  263.         jne     .loop
  264.  
  265.   .loop2:
  266.         inc     esi
  267.         cmp     byte [esi], 0
  268.         je      .fail
  269.         cmp     byte [esi], ' '
  270.         je      .loop2
  271.         cmp     byte [esi], ':'
  272.         je      .loop2
  273.  
  274.         call    print_text2
  275.         mov     esi, str_newline
  276.         call    print_text2
  277.  
  278.   .fail:
  279.  
  280.         ret
  281.  
  282.  
  283.  
  284. cmd_ping:
  285.  
  286. ; Just change PING to PONG
  287.         mov     dword[esi], 'PONG'
  288.  
  289. ; Find the end of the command
  290.         lea     edi, [esi + 5]
  291.         xor     al, al
  292.         repne   scasb
  293.  
  294. ; Now send it back
  295.         mov     edx, esi
  296.         mov     esi, edi
  297.         mov     word [esi], 0x0d0a
  298.         inc     esi
  299.         inc     esi
  300.         sub     esi, edx
  301.         mcall   send, [socketnum], , , 0
  302.  
  303.         ret
  304.  
  305.  
  306.  
  307. cmd_privmsg:
  308.  
  309.         add     esi, 8          ; skip 'PRIVMSG '
  310.         call    find_window     ; esi now points to end of destination name
  311.  
  312.         cmp     byte[esi], 1
  313.         je      cmd_ctcp
  314.  
  315.         cmp     dword[esi], 'ACTI'      ; Action?
  316.         je      .action
  317.  
  318. ; nope, just plain old privmsg
  319. if TIMESTAMP
  320.         call    print_timestamp
  321. end if
  322.  
  323.         push    esi
  324.         mov     bl, '<'
  325.         call    print_character
  326.  
  327.         mov     eax, servercommand+1
  328.         mov     dl, '!'
  329.         call    print_text
  330.  
  331.         mov     bl, '>'
  332.         call    print_character
  333.  
  334.         mov     bl, ' '
  335.         call    print_character
  336.  
  337.         pop     esi
  338.         call    print_text2
  339.  
  340.         mov     bl, 10
  341.         call    print_character
  342.  
  343.   .fail:
  344.         ret
  345.  
  346.   .action:
  347.         add     esi, 8
  348.         push    esi
  349.         if TIMESTAMP
  350.         call    print_timestamp
  351.         end if
  352.  
  353.         mov     esi, action_header_short
  354.         call    print_text2
  355.  
  356.         mov     eax, servercommand+1
  357.         mov     dl, ' '
  358.         call    print_text
  359.  
  360.         mov     bl, ' '
  361.         call    print_character
  362.  
  363.         pop     esi
  364.         call    print_text2
  365.  
  366.         mov     bl, 10
  367.         call    print_character
  368.  
  369.         ret
  370.  
  371. cmd_ctcp:
  372.         inc     esi
  373.  
  374.         cmp     dword[esi], 'VERS'
  375.         je      .version
  376.  
  377.         cmp     dword[esi], 'TIME'
  378.         je      .time
  379.  
  380.         cmp     dword[esi], 'PING'
  381.         je      .ping
  382.  
  383.         ret
  384.  
  385.   .time:
  386.         mov     byte [esi+4], ' '
  387.         lea     edi, [esi+5]
  388.  
  389.         ; TODO: add system date (fn 29) in human readable format
  390.  
  391.         mcall   3                       ; get system time
  392.  
  393.         mov     ecx, 3
  394.   .timeloop:
  395.         mov     bl, al
  396.         shr     al, 4
  397.         add     al, '0'
  398.         stosb
  399.  
  400.         mov     al, bl
  401.         and     al, 0x0f
  402.         add     al, '0'
  403.         stosb
  404.  
  405.         dec     ecx
  406.         jz      .timedone
  407.  
  408.         mov     al, ':'
  409.         stosb
  410.         shr     eax, 8
  411.         jmp     .timeloop
  412.  
  413.   .timedone:
  414.         xor     al, al
  415.         stosb
  416.         call    ctcp_reply
  417.  
  418.         if TIMESTAMP
  419.         call    print_timestamp
  420.         end if
  421.  
  422.         mov     esi, ctcp_header
  423.         call    print_text2
  424.  
  425.         mov     esi, servercommand+1
  426.         call    print_text2
  427.  
  428.         mov     esi, ctcp_time
  429.         call    print_text2
  430.  
  431.         ret
  432.  
  433.   .version:
  434.         mov     esi, str_version
  435.         call    ctcp_reply
  436.  
  437.         if TIMESTAMP
  438.         call    print_timestamp
  439.         end if
  440.  
  441.         mov     esi, ctcp_header
  442.         call    print_text2
  443.  
  444.         mov     esi, servercommand+1
  445.         call    print_text2
  446.  
  447.         mov     esi, ctcp_version
  448.         call    print_text2
  449.  
  450.         ret
  451.  
  452.   .ping:
  453.         call    ctcp_reply
  454.  
  455.         if TIMESTAMP
  456.         call    print_timestamp
  457.         end if
  458.  
  459.         mov     esi, ctcp_header
  460.         call    print_text2
  461.  
  462.         mov     esi, servercommand+1
  463.         call    print_text2
  464.  
  465.         mov     esi, ctcp_ping
  466.         call    print_text2
  467.  
  468.         ret
  469.  
  470.  
  471.  
  472. ctcp_reply:
  473.  
  474.         push    esi
  475.  
  476.         mov     dword [usercommand], 'NOTI'
  477.         mov     dword [usercommand+4], 'CE  '
  478.  
  479.         mov     esi, servercommand+1
  480.         mov     edi, usercommand+7
  481.   .nickloop:
  482.         lodsb
  483.         cmp     al, '!'
  484.         je      .done
  485.         cmp     al, ' '
  486.         je      .done
  487.         test    al, al
  488.         je      .fail
  489.         stosb
  490.         jmp     .nickloop
  491.   .done:
  492.         mov     byte [esi-1], 0
  493.         mov     ax, ' :'
  494.         stosw
  495.         mov     al, 1
  496.         stosb
  497.  
  498.         pop     esi
  499.   .replyloop:
  500.         lodsb
  501.         cmp     al, 1
  502.         jbe     .done2
  503.         stosb
  504.         jmp     .replyloop
  505.   .done2:
  506.  
  507.         mov     al, 1
  508.         stosb
  509.         mov     ax, 0x0a0d
  510.         stosw
  511.  
  512.         lea     esi, [edi - usercommand]
  513.         mcall   send, [socketnum], usercommand, , 0
  514.   .fail:
  515.         ret
  516.  
  517.  
  518.  
  519. cmd_part:
  520.         add     esi, 5  ; skip 'PART '
  521.         push    esi
  522.         call    skip_nick
  523.         call    find_window
  524.         pop     esi
  525.  
  526. ; Is it me who parted?
  527.         mov     edi, servercommand+1
  528.         call    compare_to_nick
  529.         jne     .dont_close
  530.  
  531. ; yes, close the window
  532.         mov     edi, [window_print]
  533.         mov     [edi + window.flags], FLAG_UPDATED + FLAG_CLOSE
  534.  
  535.         ret
  536.  
  537. ; somebody else parted, just print message
  538.   .dont_close:
  539.         push    esi
  540.         mov     esi, action_header
  541.         call    print_text2
  542.  
  543.         mov     eax, servercommand+1
  544.         mov     dl, '!'
  545.         mov     cl, ' '
  546.         call    print_text
  547.  
  548.         mov     esi, has_left_channel
  549.         call    print_text2
  550.  
  551.         pop     esi
  552.         call    print_text2
  553.  
  554.         mov     esi, str_newline
  555.         call    print_text2
  556.  
  557.         mov     ebx, [window_print]
  558.         mov     esi, servercommand+1
  559.         call    user_remove
  560.  
  561.         ret
  562.  
  563.  
  564.  
  565. cmd_join:
  566.         add     esi, 5  ; skip 'JOIN '
  567.  
  568. ; compare nick: did we join a channel?
  569.         mov     edi, servercommand+1
  570.         call    compare_to_nick
  571.         jne     .no_new_window
  572.  
  573. ; create channel window - search for empty slot
  574.         mov     ebx, windows
  575.         mov     ecx, MAX_WINDOWS
  576.   .loop:
  577.         cmp     [ebx + window.data_ptr], 0
  578.         je      .free_found
  579.         add     ebx, sizeof.window
  580.         dec     ecx
  581.         jnz     .loop
  582. ; Error: no more available windows!! ;;;;; TODO
  583.   .fail:
  584.         ret
  585.  
  586.   .free_found:
  587.         push    ebx
  588.         call    window_create
  589.         pop     ebx
  590.         test    eax, eax
  591.         jz      .fail
  592.         mov     [ebx + window.data_ptr], eax
  593.         mov     [ebx + window.type], WINDOWTYPE_CHANNEL
  594.         mov     [ebx + window.flags], 0
  595.  
  596.         call    window_set_name
  597.  
  598.         mov     [window_open], ebx
  599.         mov     [window_print], ebx
  600.         call    window_refresh
  601.  
  602.         push    esi
  603.         mov     esi, action_header
  604.         call    print_text2
  605.  
  606.         mov     esi, str_talking
  607.         call    print_text2
  608.  
  609.         pop     eax
  610.         mov     dl, ' '
  611.         call    print_text
  612.  
  613.         mov     esi, str_dotnewline
  614.         call    print_text2
  615.  
  616.         call    draw_window
  617.  
  618.         ret
  619.  
  620.   .no_new_window:
  621.         push    esi
  622.         call    find_window
  623.  
  624.         mov     esi, action_header
  625.         call    print_text2
  626.  
  627.         mov     eax, servercommand+1
  628.         mov     dl, '!'
  629.         call    print_text
  630.  
  631.         mov     esi, joins_channel
  632.         call    print_text2
  633.  
  634.         pop     esi
  635.         call    print_text2
  636.  
  637.         mov     esi, str_newline
  638.         call    print_text2
  639.  
  640.         mov     ebx, [window_print]
  641.         mov     esi, servercommand+1
  642.         call    user_add
  643.  
  644.         ret
  645.  
  646.  
  647.  
  648.  
  649. cmd_nick:
  650. ; NOTE: This command applies to a user, and thus has no specific channel
  651.         add     esi, 5  ; skip 'NICK '
  652.  
  653.         cmp     byte[esi], ':'          ; TODO: skip all spaces and semicolons?
  654.         jne     @f
  655.         inc     esi
  656.        @@:
  657.  
  658. ; Change the nick in the current userlist. TODO: check other channels too!
  659.         push    esi
  660.         mov     ebx, [window_print]
  661.  
  662.         mov     esi, servercommand+1
  663.         call    user_remove
  664.  
  665.         mov     esi, [esp]
  666.         call    user_add
  667.  
  668.         call    redraw_channel_list
  669.  
  670. ; Is it me who changed nick?
  671.         mov     edi, servercommand+1
  672.         call    compare_to_nick
  673.         pop     esi
  674.         jne     .not_me
  675.  
  676.         mov     ecx, MAX_NICK_LEN-1
  677.         push    esi
  678.   .copyloop:
  679.         lodsb
  680.         test    al, al
  681.         jz      .copydone
  682.         cmp     al, ' '
  683.         je      .copydone
  684.         stosb
  685.         dec     ecx
  686.         jnz     .copyloop
  687.   .copydone:
  688.         xor     al, al
  689.         stosb
  690.         pop     esi
  691.   .not_me:
  692.  
  693. ; Now print a message on the current channel
  694.         push    esi
  695.         mov     esi, action_header_short
  696.         call    print_text2
  697.  
  698.         mov     eax, servercommand+1
  699.         mov     dl, '!'
  700.         call    print_text
  701.  
  702.         mov     esi, is_now_known_as
  703.         call    print_text2
  704.  
  705.         pop     esi
  706.         call    print_text2
  707.  
  708.         mov     esi, str_newline
  709.         call    print_text2
  710.  
  711.         ret
  712.  
  713.  
  714.  
  715.  
  716. cmd_kick:
  717.         add     esi, 5  ; skip 'KICK '
  718. ; Is it me who got kicked?
  719.         mov     edi, servercommand+1
  720.         call    compare_to_nick
  721.         jne     .not_me
  722.  
  723. ; TODO: mark channel as disconnected
  724.  
  725.   .not_me:
  726. ; find the channel user has been kicked from
  727.         push    esi
  728.         call    skip_nick
  729.         call    find_window
  730.  
  731.         mov     esi, action_header_short
  732.         call    print_text2
  733.  
  734.         mov     eax, servercommand+1
  735.         mov     dl, '!'
  736.         call    print_text
  737.  
  738.         mov     esi, kicked
  739.         call    print_text2
  740.  
  741.         pop     esi
  742.         call    print_text2
  743.  
  744.         mov     esi, str_newline
  745.         call    print_text2
  746.  
  747.         mov     ebx, [window_print]
  748.         mov     esi, servercommand+1
  749.         call    user_remove
  750.  
  751.         ret
  752.  
  753.  
  754.  
  755. cmd_quit:
  756. ; NOTE: This command applies to a user, and thus has no specific channel
  757.  
  758.         mov     esi, action_header
  759.         call    print_text2
  760.  
  761.         mov     eax, servercommand+1
  762.         mov     dl, '!'
  763.         call    print_text
  764.  
  765.         mov     esi, has_quit_irc
  766.         call    print_text2
  767.  
  768. ; TODO: check other channels on same server too!
  769.         mov     ebx, [window_print]
  770.         mov     esi, servercommand+1
  771.         call    user_remove
  772.  
  773.         ret
  774.  
  775.  
  776.  
  777. cmd_mode:
  778.  
  779.         add     esi, 5  ; skip 'MODE '
  780.  
  781.         push    esi
  782.         mov     esi, action_header_short
  783.         call    print_text2
  784.  
  785.         mov     eax, servercommand+1
  786.         mov     dl, ' '
  787.         call    print_text
  788.  
  789.         mov     esi, sets_mode
  790.         call    print_text2
  791.  
  792.         pop     esi
  793.         call    print_text2
  794.  
  795.         mov     esi, str_newline
  796.         call    print_text2
  797.  
  798. ;;; TODO: change username if needed
  799.  
  800.         ret
  801.  
  802.  
  803. cmd_353:                ; channel usernames reply
  804.  
  805.         add     esi, 4  ; skip '353 '
  806.         call    skip_nick
  807.         inc     esi     ; channel type '*', '=' or '@'
  808.         inc     esi     ; ' '
  809.         call    find_window
  810.  
  811. ; now find window ptr and check if this is the first 353 message
  812.         mov     ebx, [window_print]
  813.         test    [ebx + window.flags], FLAG_RECEIVING_NAMES
  814.         jnz     .add
  815.  
  816.         or      [ebx + window.flags], FLAG_RECEIVING_NAMES
  817. ;        mov     [ebx + window.users], 0
  818.         ; TODO: remove all users?
  819.  
  820.   .add:
  821.         push    esi
  822.         call    user_add
  823.         pop     esi
  824.  
  825.   .namesloop:
  826.         lodsb
  827.         test    al, al
  828.         jz      .done
  829.         cmp     al, ' '                 ; names list is separated with spaces
  830.         jne     .namesloop
  831.         jmp     .add
  832.  
  833.   .done:
  834.         call    redraw_channel_list
  835.  
  836.         ret
  837.  
  838.  
  839.  
  840.  
  841.  
  842. cmd_366:        ; channel usernames end
  843.  
  844.         add     esi, 4          ; skip '366 '
  845.         call    skip_nick
  846.         call    find_window
  847.  
  848.         mov     ebx, [window_print]
  849.         and     [ebx + window.flags], not FLAG_RECEIVING_NAMES
  850.  
  851.         ret
  852.  
  853.  
  854.  
  855.  
  856. cmd_topic:
  857.  
  858.         add     esi, 4          ; skip '332 '
  859.         call    skip_nick
  860.         call    find_window
  861.  
  862.         push    esi
  863.         mov     esi, action_header
  864.         call    print_text2
  865.  
  866.         mov     esi, str_topic
  867.         call    print_text2
  868.  
  869.         pop     esi
  870.         call    print_text2
  871.  
  872.         mov     esi, str_newline
  873.         call    print_text2
  874.  
  875.         ret
  876.  
  877.  
  878. cmd_333:
  879.  
  880.         add     esi, 4          ; skip '333 '
  881.         call    skip_nick               ;;;;
  882.         call    find_window
  883.  
  884. ;        mov     ecx, 2  ; number of spaces to find    ;;; CHECKME
  885. ;  .loop:
  886. ;        lodsb
  887. ;        test    al, al
  888. ;        je      .fail
  889. ;        cmp     al, ' '
  890. ;        jne     .loop
  891. ;        dec     ecx
  892. ;        jnz     .loop   ; find some more spaces
  893.  
  894.         push    esi
  895.         mov     esi, action_header
  896.         call    print_text2
  897.  
  898.         mov     esi, str_setby
  899.         call    print_text2
  900.  
  901. ;        pop     esi
  902. ;        call    print_text2
  903.  
  904.         pop     eax
  905.         mov     dl, '!'
  906.         call    print_text
  907.  
  908.         mov     esi, str_newline
  909.         call    print_text2
  910.  
  911.   .fail:
  912.         ret
  913.  
  914. cmd_322:
  915.         add     esi, 4
  916.  
  917.         call    skip_nick
  918.  
  919.         call    print_text2
  920.  
  921.         mov     esi, str_newline
  922.         call    print_text2
  923.  
  924.         ret
  925.  
  926. cmd_323:
  927.  
  928.         ret