From WikiChip
Difference between revisions of "mirc/commands/sockread"
< mirc‎ | commands

(Switches)
 
(25 intermediate revisions by 8 users not shown)
Line 1: Line 1:
{{mIRC menu}}
+
{{mirc title|/sockread Command}}
 
The '''/sockread''' command reads bytes from the receive buffer of a socket connection into a specified variable. This command must be and is to be used inside socket events.
 
The '''/sockread''' command reads bytes from the receive buffer of a socket connection into a specified variable. This command must be and is to be used inside socket events.
  
 
mIRC in general only understand {{mIRC|$crlf}} terminated line. With socket, mIRC only understands {{mIRC|$lf}} terminated line (any {{mirc|$cr}} before a {{mirc|$lf}} is removed).
 
mIRC in general only understand {{mIRC|$crlf}} terminated line. With socket, mIRC only understands {{mIRC|$lf}} terminated line (any {{mirc|$cr}} before a {{mirc|$lf}} is removed).
  
The number of bytes waiting to be read can be retrieved using {{mIRC|$sock|$sock(name).rq)
+
The number of bytes waiting to be read can be retrieved using {{mIRC|$sock|$sock(name).rq}}
  
 
By default:
 
By default:
Line 14: Line 14:
  
 
== Synopsis ==
 
== Synopsis ==
<source lang="mIRC">/sockread [-fn] [numbytes] <%var|&binvar></source>
+
<source lang="mIRC">
 +
/sockread [-fn] <%var|&binvar>
 +
/sockread [numbytes] <%var|&binvar>
 +
</source>
  
 
== Switches ==
 
== Switches ==
{| class="wikitable" style="line-height: 25px; margin-left: 75px;"
+
* '''f''' - When reading a terminated line (/sockread %var or /sockread -n &var), forces mIRC to fill the variable with whatever text is in the receive buffer, even if it does not end in a terminated line.
|-
+
* '''n''' - Reads a terminated line into a {{mIRC|binary variables|&binvars}}. If the incoming line does not contain a terminated line, no byte will be read into the {{mIRC|binary variables|&binvars}}, unless you specify the '''-f''' switch.
! Switch !! Description
 
|-
 
| '''f''' || When reading a terminated line (/sockread %var or /sockread -n &var), forces mIRC to fill the variable with whatever text is in the receive buffer, even if it does not end in a terminated line.
 
|-
 
| '''n''' || Reads a terminated line into a {{mIRC|binary variables|&binvars}}. If the incoming line does not contain a terminated line, no byte will be read into the {{mIRC|binary variables|&binvars}}, unless you specify the '''-f''' switch.
 
|}
 
  
 
== Parameters ==
 
== Parameters ==
{| class="wikitable" style="line-height: 25px; margin-left: 75px;"
+
* '''[numbytes]''' - The number of bytes to read from the receive buffer.
|-
+
* '''[%var/&binvar]''' - The name of the variable to read the socket buffer into.
! Parameter !! Description
 
|-
 
| '''[numbytes]''' || The number of bytes to read from the receive buffer.
 
|-
 
| '''[%var/&binvar]''' || The name of the variable to read the socket buffer into.
 
|}
 
  
 
== Reading ==
 
== Reading ==
Line 43: Line 34:
 
     b) you were reading into a %var and there is still a terminated line in the buffer waiting to be read.  
 
     b) you were reading into a %var and there is still a terminated line in the buffer waiting to be read.  
  
This means you will miss the last line if it does not end with a terminated line and you are reading line by line only.
+
This means you will miss the last line if it is not a terminated line and you are reading line by line only (and not in a binvar, although it's also easier to use on sockclose with binvar if you are reading line by line and facing this). You can read that line in the on sockclose event, {{mIRC|/sockread#Last line not showing up|see below}}.
  
'''Note''': It is possible to read such a last line inside the on sockclose event.
+
'''Note''' (fixed since mIRC 7.36): Using SSL, on sockread might not be retriggered as it should, {{mIRC|on events/on sockclose|on sockclose}} will be triggered too early with $sockerr sets to 3, you must read the receive buffer from that event
  
'''Note2''': Using SSL, on sockread might not be retriggered as it should, {{mIRC|on sockclose}} will be triggered too early with $sockerr sets to 3, you must read the receive buffer from that event
 
  
It is important to note that the data received will vary. Practically speaking, we receive several kilobytes per second, it is easy to assume that the data you want is going to be sent and received the same way and above all, the way you want, but that's incorrect, you might receive very small packet at a very small speed.
+
It is important to note that the data received will vary in size. Practically speaking, we receive several kilobytes per second, it is easy to assume that the data you want is going to be sent and received the same way and above all, the way you want, but that's incorrect, you might receive very small packet at a very small speed.
  
 
A common situation when dealing with HTML is to check the source of the page you are working with, to identify something that is unlikley to change, and to use that as a reference. Doing this is not bad, but the way it is usually implemented by mIRC user is incorrect.
 
A common situation when dealing with HTML is to check the source of the page you are working with, to identify something that is unlikley to change, and to use that as a reference. Doing this is not bad, but the way it is usually implemented by mIRC user is incorrect.
Line 70: Line 60:
 
  }
 
  }
 
}</source>
 
}</source>
If you do that, you cannot guarantee it will work 100% of the time, you cannot read the content of the received buffer, if the received buffer is filled with a few bytes and ends up being "this is my ref" when on sockread triggers, the if statement won't be true, for example here, the next time the event triggers, you might have a received buffer containing "erence:", but it might be "erence:\r\nI want that line" as well.
+
If you do that, you cannot guarantee it will work 100% of the time.
  
This scenario is very unlikely to happen, because you are reading line by line, which is much much slower than reading the whole content of the received buffer and as such, the received buffer is filled by mIRC faster than your socket code reads it. But it is still possible.
+
If the received buffer is filled with a few bytes and ends up being "this is my ref" when on sockread triggers, the -f switch will force mirc to read that, and you won't be able to match your full line, for example here, the next time the event triggers, you might have a received buffer containing "erence:", but it might be "erence:\r\nI want that line" as well, screwing you anyway.
You can fix this by changing the logic of your event to use /sockread %a instead of /sockread -f %a. Indeed, not using the -f switch, mIRC will only read data if you have a terminated line in the received buffer, so if you check $sockbr, (the number of bytes read), you can /return in the event if it's 0 and wait for it to retrigger, hopfully this time a terminated line will be in the received buffer. If you do this change and still need to get the last non terminated line, you will need do so inside the on sockclose event, no problem otherwise:
 
  
'''Note''': In this case we could ditch the "if ($sockbr == 0) return" because %a wouldn't be equal to "this is my reference:" anyway, but you could be checking that %a is $null there, so generally speaking you should use it in this situation
+
So you might think here "let's not use -f then":
  
 
<source lang="mIRC">
 
<source lang="mIRC">
Line 81: Line 70:
 
  var %a
 
  var %a
 
  sockread %a
 
  sockread %a
if ($sockbr == 0) return
 
;guaranteed to get %a with a full line.
 
 
  if (%a == this is my reference:) {
 
  if (%a == this is my reference:) {
 
     ...
 
     ...
Line 88: Line 75:
 
}</source>
 
}</source>
  
Another solution consists in making a buffer by yourself and adding what you are reading to it, until you get the correct portion you want (a terminated line in this example).
+
And that, assuming what you are looking for is not on the last non terminated line (which would be missed because -f is not there, although note that you can read that last non terminated line inside the {{mIRC|on sockclose}} event), should be fine. In fact, in this specific example and in general, it will work, because you are making sure %a is a full line or nothing. Well that's why it works in most situation, you are checking that %a is a specific text, which would fail if no byte were read into %a because a terminated line couldn't be found. However, if you are in a situation where you must check that %a is $null (usually because it read an empty $crlf line), you must check {{mIRC|$sockbr}} to know if you read bytes at all, a good example of this usage is shown below, which discard the headers of HTTP (check for an empty value after /Sockread %a reads an empty $crlf line):
 +
 
 +
<source lang="mIRC">
 +
alias testHTTP {
 +
sockclose testHTTP
 +
sockopen testHTTP mirc.com 80
 +
}
 +
 
 +
on *:sockopen:testHTTP:{
 +
if (!$sockerr) {
 +
  sockwrite -n $sockname GET / HTTP/1.1
 +
  sockwrite -n $sockname Host: mirc.com
 +
  sockwrite -n $sockname
 +
}
 +
}
 +
on *:sockread:testHTTP:{
 +
if (!$sockerr) {
 +
  if ($sock($sockname).mark) {
 +
  ; here you can start reading the real source the way you want
 +
  }
 +
  else {
 +
    var %a
 +
    sockread %a
 +
    if ($sockbr) {
 +
    if (%a == $null) sockmark $sockname 1
 +
    }
 +
  }
 +
}
 +
}</source>
 +
 
 +
Getting problem because you are not checking properly for $sockbr is very unlikely to happen if you are reading line by line, because it is much much slower than reading the whole content of the received buffer and as such, the received buffer is filled by mIRC faster than your socket code reads it. But it is still possible.
 +
 
 +
Another solution consists in making a buffer by yourself and adding what you are reading to it, until you get the correct portion you want (a terminated line in these examples).
  
 
If you are reading the whole content of the received buffer with one /sockread using binary variable or just large portion of the received buffer in a binary variable, you are more likely to see the  
 
If you are reading the whole content of the received buffer with one /sockread using binary variable or just large portion of the received buffer in a binary variable, you are more likely to see the  
issue because you are basically reading the buffer as fast as mIRC fills it (or faster than line by line for large portion). The same solutions exists for binary variables, use /sockread -n to read a terminated line into the binvar, check $sockbr to make sure you read something (cause if so, a whole line has been read).
+
issue because you are basically reading the buffer as fast as mIRC fills it (or faster than line by line for large portion). The same solutions exists for binary variables, use /sockread -n to read a terminated line into the binvar, check $sockbr to make sure you read something etc. Using $bfind is the correct way to parse, unless you have very good evidence about the length of the lines you are going to receive and you want to go the easy way: if (text operator $bvar(&a,1,4096)) or similar.
  
 
* Reading from the receive buffer
 
* Reading from the receive buffer
Line 126: Line 145:
 
</source>
 
</source>
  
'''General Note''': if you want to avoid any issue, you should write the whole source to a file and then parse that file, this might be easier.
+
'''General Note''': it can be a good idea and might be simpler for you to read everything to a file and then parse that file.
 +
 
 +
== Last line not showing up ==
 +
 
 +
Another common problem is reading the last line sent by an HTTP server, which isn't a terminated line (no $crlf or $lf).
 +
 
 +
Indeed, if you are using /sockread %var, you're will read properly line by line but that last line won't be read by this sockread command.
 +
 
 +
We also saw how this non terminated line in the received buffer wouldn't make mIRC retrigger the on sockread event.
 +
 
 +
One solution which doesn't involve more than that, is to read that line from the on sockclose event, indeed you are sure on sockread read the previous line, so inside on sockclose, you should get only that last non terminated line, this time we use the -f switch to force the read:
 +
 
 +
<source lang="mIRC">
 +
on *:sockclose:name:{
 +
  if (!$sockerr) {
 +
  var %a
 +
  sockread -f %a
 +
  if ($sockbr == 0) return
 +
  echo -a > %a
 +
}
 +
}
 +
</source>
 +
 
 +
If you are using HTTP 1.1 and you actually want the socket to remain open, you would need to grab the value of the content-length header, store that in a variable and increase another variable with the length of what you are reading, if the length of the received buffer + the value of that variable equal the value of the content length, you should first try to see if you have a line by reading with /sockread %a, and if no byte is read, then use /sockread -f %a.
  
 
== Example ==
 
== Example ==
Line 136: Line 178:
 
'''Note2''': too long line will produce an error.
 
'''Note2''': too long line will produce an error.
  
'''Note3''': Using SSL, the sockread might not be triggered though there are still datas to be read, you must read the rest in the on sockclose event.
+
'''Note3''': Using SSL, the on sockread event might not be triggered though it should, you must read the rest in the on sockclose event (has been fixed since mIRC 7.36).
  
 
<source lang="mIRC">ON *:SOCKREAD:mySocket:{
 
<source lang="mIRC">ON *:SOCKREAD:mySocket:{
Line 150: Line 192:
 
</source>
 
</source>
  
'''Note''': if the last line in the source does not end with a terminated line, it won't be read by that event, you might want to read that last line inside the on sockclose event. We can't use -f on sockread because it would allow the code to display whatever is in the buffer even if no terminated line is present.
+
'''Note''': as we just saw, if the last line in the source does not end with a terminated line, it won't be read by that event.
  
 
If you ever worked with HTTP 1.1, you know that it can send data in chunk, here is a way to write the real content to a file:
 
If you ever worked with HTTP 1.1, you know that it can send data in chunk, here is a way to write the real content to a file:
Line 176: Line 218:
 
       else {
 
       else {
 
         var %a
 
         var %a
     
+
         sockread %a
         ;when we start, the next line is the chunk size, but after reading a chunk, we must parse the $crlf ending that chunk
+
         ;skip empty line
         ;so if we read and %a is $null, it means we are after the start, we try to read the next line, if we can't find the next chunk in the current receive buffer, we return and allow the event to retrigger with more data.
+
         while ($sockbr) && (%a == $null) { sockread %a }
        sockread -f %a
 
         while ($sockbr) && (%a == $null) { sockread -f %a }
 
 
         if (!$sockbr) || (%a == $null) return
 
         if (!$sockbr) || (%a == $null) return
 
         ;last chunk
 
         ;last chunk

Latest revision as of 18:04, 2 May 2023

The /sockread command reads bytes from the receive buffer of a socket connection into a specified variable. This command must be and is to be used inside socket events.

mIRC in general only understand $crlf terminated line. With socket, mIRC only understands $lf terminated line (any $cr before a $lf is removed).

The number of bytes waiting to be read can be retrieved using $sock(name).rq

By default:

  • /sockread %var reads a terminated line into the variable, if the received buffer does not contain a terminated line, no byte are read into the variable.
  • /sockread &var try to read 4096 bytes into the variable.

The real number of bytes read by /sockread can be retrieved using $sockbr.

Synopsis[edit]

/sockread [-fn] <%var|&binvar>
/sockread [numbytes] <%var|&binvar>

Switches[edit]

  • f - When reading a terminated line (/sockread %var or /sockread -n &var), forces mIRC to fill the variable with whatever text is in the receive buffer, even if it does not end in a terminated line.
  • n - Reads a terminated line into a &binvars. If the incoming line does not contain a terminated line, no byte will be read into the &binvars, unless you specify the -f switch.

Parameters[edit]

  • [numbytes] - The number of bytes to read from the receive buffer.
  • [%var/&binvar] - The name of the variable to read the socket buffer into.

Reading[edit]

A single /sockread may not be enough to read the entire buffer (if you are reading line by line for example). You might want to keep reading until $sockbr (the number of bytes read) is set to zero. This is far faster than letting mIRC re-trigger the event. If your script does not read the whole buffer, the on sockread event is re-triggered if:

   a) you were reading into a &binvar.
   b) you were reading into a %var and there is still a terminated line in the buffer waiting to be read. 

This means you will miss the last line if it is not a terminated line and you are reading line by line only (and not in a binvar, although it's also easier to use on sockclose with binvar if you are reading line by line and facing this). You can read that line in the on sockclose event, see below.

Note (fixed since mIRC 7.36): Using SSL, on sockread might not be retriggered as it should, on sockclose will be triggered too early with $sockerr sets to 3, you must read the receive buffer from that event


It is important to note that the data received will vary in size. Practically speaking, we receive several kilobytes per second, it is easy to assume that the data you want is going to be sent and received the same way and above all, the way you want, but that's incorrect, you might receive very small packet at a very small speed.

A common situation when dealing with HTML is to check the source of the page you are working with, to identify something that is unlikley to change, and to use that as a reference. Doing this is not bad, but the way it is usually implemented by mIRC user is incorrect.

The common errors are to blindly try to match what you saw in the source as you read it with your socket but also to try to read from the received buffer assuming it will always have the data already, let's consider the following source of a page:

"this is my reference:

I want that line"

There are two mistakes:

  • Trying to match the reference as you are reading. Consider the following code
on *:sockread:name:{
 var %a
 sockread -f %a
 if (%a == this is my reference:) {
    ...
 }
}

If you do that, you cannot guarantee it will work 100% of the time.

If the received buffer is filled with a few bytes and ends up being "this is my ref" when on sockread triggers, the -f switch will force mirc to read that, and you won't be able to match your full line, for example here, the next time the event triggers, you might have a received buffer containing "erence:", but it might be "erence:\r\nI want that line" as well, screwing you anyway.

So you might think here "let's not use -f then":

on *:sockread:name:{
 var %a
 sockread %a
 if (%a == this is my reference:) {
    ...
 }
}

And that, assuming what you are looking for is not on the last non terminated line (which would be missed because -f is not there, although note that you can read that last non terminated line inside the on sockclose event), should be fine. In fact, in this specific example and in general, it will work, because you are making sure %a is a full line or nothing. Well that's why it works in most situation, you are checking that %a is a specific text, which would fail if no byte were read into %a because a terminated line couldn't be found. However, if you are in a situation where you must check that %a is $null (usually because it read an empty $crlf line), you must check $sockbr to know if you read bytes at all, a good example of this usage is shown below, which discard the headers of HTTP (check for an empty value after /Sockread %a reads an empty $crlf line):

alias testHTTP {
sockclose testHTTP
sockopen testHTTP mirc.com 80
}
 
on *:sockopen:testHTTP:{
 if (!$sockerr) {
  sockwrite -n $sockname GET / HTTP/1.1
  sockwrite -n $sockname Host: mirc.com
  sockwrite -n $sockname
 }
}
on *:sockread:testHTTP:{
 if (!$sockerr) {
  if ($sock($sockname).mark) {
   ; here you can start reading the real source the way you want
  }
  else {
    var %a
    sockread %a
    if ($sockbr) {
     if (%a == $null) sockmark $sockname 1
    }
  }
 }
}

Getting problem because you are not checking properly for $sockbr is very unlikely to happen if you are reading line by line, because it is much much slower than reading the whole content of the received buffer and as such, the received buffer is filled by mIRC faster than your socket code reads it. But it is still possible.

Another solution consists in making a buffer by yourself and adding what you are reading to it, until you get the correct portion you want (a terminated line in these examples).

If you are reading the whole content of the received buffer with one /sockread using binary variable or just large portion of the received buffer in a binary variable, you are more likely to see the issue because you are basically reading the buffer as fast as mIRC fills it (or faster than line by line for large portion). The same solutions exists for binary variables, use /sockread -n to read a terminated line into the binvar, check $sockbr to make sure you read something etc. Using $bfind is the correct way to parse, unless you have very good evidence about the length of the lines you are going to receive and you want to go the easy way: if (text operator $bvar(&a,1,4096)) or similar.

  • Reading from the receive buffer

This is the same as above but once you found the reference with the script, you want to grab the next line:

on *:sockread:name:{
 var %a
 sockread %a
 if ($sockbr == 0) return
 if (%a == this is my reference:) {
    sockread %a
   echo -a my line: %a
 }
}

The same issue can happen, you cannot make sure there is a terminated line in the receive buffer. People mainly uses that because it avoids saving the state for the next time the event retriggers, indeed the correct way to read the next line once you found the reference is to try reading a terminated line using /sockread %var (or to use your own buffer and check when you have a new line, just like above) but you need to save the state if you can't find the next line currently:

on *:sockread:name:{
 var %a
 sockread %a
 if ($sockbr == 0) return
 if (%tryingnextline) { echo -a my line: %a | unset %tryingnextline | return  }
 if (%a == this is my reference:)  {
    set %tryingnextline 1
    sockread %a
    if ($sockbr) {
     echo -a my line: %a
     unset %tryingnextline
   }
 }
}

General Note: it can be a good idea and might be simpler for you to read everything to a file and then parse that file.

Last line not showing up[edit]

Another common problem is reading the last line sent by an HTTP server, which isn't a terminated line (no $crlf or $lf).

Indeed, if you are using /sockread %var, you're will read properly line by line but that last line won't be read by this sockread command.

We also saw how this non terminated line in the received buffer wouldn't make mIRC retrigger the on sockread event.

One solution which doesn't involve more than that, is to read that line from the on sockclose event, indeed you are sure on sockread read the previous line, so inside on sockclose, you should get only that last non terminated line, this time we use the -f switch to force the read:

on *:sockclose:name:{
  if (!$sockerr) {
   var %a
   sockread -f %a
   if ($sockbr == 0) return
   echo -a > %a
 }
}

If you are using HTTP 1.1 and you actually want the socket to remain open, you would need to grab the value of the content-length header, store that in a variable and increase another variable with the length of what you are reading, if the length of the received buffer + the value of that variable equal the value of the content length, you should first try to see if you have a line by reading with /sockread %a, and if no byte is read, then use /sockread -f %a.

Example[edit]

Here is an example which will read and echo to the status window what is sent by a server line by line.

Note: leading/consecutives and trailing spaces and non-printable characters won't be shown correctly.

Note2: too long line will produce an error.

Note3: Using SSL, the on sockread event might not be triggered though it should, you must read the rest in the on sockclose event (has been fixed since mIRC 7.36).

ON *:SOCKREAD:mySocket:{
  var %a
  if ($sockerr > 0) { return }
  sockread %a
  if (!$sockbr) return
  while ($sockbr) {
    echo -a > %a
    sockread %a
  }
}

Note: as we just saw, if the last line in the source does not end with a terminated line, it won't be read by that event.

If you ever worked with HTTP 1.1, you know that it can send data in chunk, here is a way to write the real content to a file:

on *:sockopen:socket:{
  ... your request...
  sockmark $sockname 0
  ;we write to source.txt
  .remove source.txt
  unset %bytestoread
}
on *:SOCKREAD:socket: {
  if (!$sockerr) {
    if ($sock($sockname).mark) {
      ;if we have a chunk to read
      if (%bytestoread > 0) {
        ;we try to read that much
        sockread %bytestoread &a
        bwrite source.txt -1 -1 &a
        ;but $sockbr tells us how much we read, we decrease by that number (in case we received something smaller than what we want, this part of the code will retrigger in this case, until %bytestoread is 0)
        dec %bytestoread $sockbr
      }
      ;if we don't have a chunk
      else {
        var %a
        sockread %a
        ;skip empty line
        while ($sockbr) && (%a == $null) { sockread %a }
        if (!$sockbr) || (%a == $null) return
        ;last chunk
        if (%a == 0) echo -a done
        ;convert the hexadecimal number to decimal
        else { set %bytestoread $base(%a,16,10) }
      }
    }
    else {
      ;$sock().mark is used to discard the headers
      var %a
      sockread %a
      if (%a == $null) sockmark $sockname 1
    }
  }
}

Compatibility[edit]

Added: mIRC v5.3
Added on: 13 Dec 1997
Note: Unless otherwise stated, this was the date of original functionality.
Further enhancements may have been made in later versions.


See Also[edit]

v · d · e mIRC commands list

A /abook, /action, /add, /ajinvite, /alias, /aline, /ame, /amsg, /anick, /aop, /auser, /auto, /autojoin, /avoice, /away

B /background, /ban, /bcopy, /beep, /bindip, /bread, /break, /breplace, /bset, /btrunc, /bunset, /bwrite

C /channel, /clear, /clearall, /clearial, /cline, /clipboard, /close, /closechats, /closedccs, /closefserves, /closemsg, /cnick, /color, /colour, /comclose, /comlist, /commands, /comopen, /comreg, /continue, /copy, /creq, /ctcp, /ctcpreply, /ctcps

D /dcc, /dccserver, /dde, /ddeserver, /debug, /dec, /describe, /dialog, /did, /didtok, /disable, /disconnect, /dlevel, /dline, /dll, Template:mIRC/donotdisturb, /dns, /dqwindow, /drawcopy, /drawdot, /drawfill, /drawline, /drawpic, /drawrect, /drawreplace, /drawrot, /drawsave, /drawscroll, /drawsize /drawtext

E /ebeeps, /echo, /editbox, /else, /elseif, /emailaddr, /enable, /events, /exit

F /fclose, /filter, /findtext, /finger, /firewall, /flash, /flist, /flood, /flush, /flushini, /fnord, /font, /fopen, /fseek, /fsend, /fserve, /fullname, /fupdate, /fwrite

G /ghide, /gload, /gmove, /gopts, /goto, /gplay, /gpoint, /gqreq, /groups, /gshow, /gsize, /gstop, /gtalk, /gunload, /guser

H /hadd, /halt, /haltdef, /hdec, /hdel, /help, /hfree, /hinc, /hload, /hmake, /hotlink, /hop, /hsave

I /ial, /ialclear, /ialmark, /identd, /if, /ignore, /iline, /inc, /iuser

J /join

L /leave, /linesep, /links, /list, /load, /loadbuf, /localinfo, /log, /logview

M /maxdepth, /mdi, /me, /menubar, /mkdir, /mnick, /mode, /msg

N /noop, /notice, /notify

O /onotice, /omsg

P /pareline, /part, /partall, /pdcc, /perform, /play, /playctrl, /pop, /protect, /proxy, /pvoice

Q /qme, /qmsg, /query, /queryrn, /quit, /quote

R /raw, /registration, /reload, /remini, /remote, /remove, /rename, /renwin, /reseterror, /resetidle, /return, /returnex, /rlevel, /rline, /rmdir, /run, /ruser

S /save, /savebuf, /saveini, /say, /scid, /scon, /server, /set, /setlayer, /showmirc, /signal, /sline, /sockaccept, /sockclose, /socklist, /socklisten, /sockmark, /sockopen, /sockpause, /sockread, /sockrename, /sockudp, /sockwrite, /sound, /speak, /splay, /sreq, /strip, /switchbar

T /timer, /timestamp, /tip, /tips, /titlebar, /tnick, /tokenize, /toolbar, /topic /tray, /treebar

U /ulist, /unload, /unset, /unsetall, /updatenl, /url, /username, /uwho

V /var, /vcadd, /vcmd, /vcrem, /vol

W

X /xyzzy