[cdev] Утилита ps

Grigoriy A. Sitkarev sitkarev на komitex.ru
Сб Мар 20 01:31:55 MSK 2010


Тут есть некоторая неточность, я объясню в чём дело.

strncpy(3) это такая не очень хорошая функция и я обычно её заменяю на 
написанную отдельно xstrncpy или safe_strncpy. Странность поведения 
strncpy(3) библиотечной в следующем: если в n символах строки src 
отсутствует '\0' (завершающий строку ноль) то строка в dst не будет 
нуль-терминирована. Но в нашем примере мы уверены, что в 
sizeof(NAME_MAX) символах будет завершающий ноль (мы его туда сами 
положили). Хотя, если быть педантом, то конечно, следовало бы 
принудительно её занультерминировать, потому что можно сказать что в 
теории имя процесса между '(' и ')' может оказаться длинее NAME_MAX (в 
какой нибудь сломаной версии или когда злоумышленник получил доступ к 
/proc).

Если мы не уверены что такой нуль-терминатор есть, следовало бы 
инкрементировать b после этой операции а не до. Потому что нам тогда 
удобно получить длину строки, не пользуя strlen(3) т.к. указатель b уже 
указывает на её конец, а адрес начала нам известен, это ptr.

/* Terminate with zero. */
*b = 0;
/* String in ptr is a process name. */
strncpy(pname, ptr, sizeof(pname));
pname[b-ptr] = 0;
++b;

или можно:

pname[b++-ptr]

Но лучше тогда:

pname[(b++)-ptr]

--
Г.А.

> Например, выдрать имя процесса, находящееся между двух скобок где-то в 
> буфере-строке buf:
> 
> char *b;
> char buf[1024];
> char pname[NAME_MAX];
> 
> ...
> 
> while ((dp = readdir(dirh)) != NULL) {
>     ...
>     b = strchr(buf, '(');
>     if (!b)
>         continue;
>     ptr = ++b;
>     b = strchr(b, ')');
>     if (!b)
>         continue;
>     /* Terminate with zero.  */
>     *b++ = 0;
>     /* String in ptr is a process name. */
>     strncpy(pname, ptr, sizeof(pname));
>     ...
> }





Подробная информация о списке рассылки cdev