URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 6252
[ Назад ]

Исходное сообщение
"Странное поведение программы при запуске от разных пользователей."

Отправлено Dimik , 11-Мрт-07 23:08 
Приветствую!

Есть такая проблемка. Простенькая программка берет из коммандной строки аргумент и, в зависимости от его значения, выдает в COM порт байтик. При ее запуске от root все работает отлично. А если запускать например от www (эту программку дергает php скриптик), то программа отрабатывает, но в ком порт ничего не выдает и не ругается ни в одной из ключевых точек, таких как открытие порта, заполнение буффера передаваемым байтиком и т.д... НО методом тыка было выясненно, что если убрать неприметный printf из кода, то все начинает работать под любым юзером. Компилится все под FreeBSD 6.0.

Далее код. Место со злополучным printf помеченно.

#include <fcntl.h>
#include <sys/time.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>

void AddToLOG(char *logname, char *logstr);

#define BAUDRATE B115200
#define DEFAULT_LOG "server.log"

char InCOMbuf[56];

fd_set readfds;
int fdCOM;

int main (int argc, char* argv[])
{
if (argc < 2)
       {
       printf("\n Usage: trigger on  -turns TX ON \n");
       printf("                off -turns TX OFF\n\n");
       exit(1);            
       }
      
if ((strcmp(argv[1],"on") != 0) && (strcmp(argv[1], "off") != 0))
       {
        printf("\n Usage: trigger on  -turns da TX ON \n");
        printf("                off -turns da TX OFF\n\n");
        exit(1);
       }

char buf[128];
struct termios oldtioA, newtioA;

// AddToLOG(DEFAULT_LOG, "started");

fdCOM = open ("/dev/cuad1", O_RDWR | O_NOCTTY | O_NONBLOCK | O_SYNC);
if(fdCOM < 0)
{
//  AddToLOG(DEFAULT_LOG, "Can't open dev/cuad1 !");
  printf("Can't open dev/cuad1 ! \n");
  exit (-1);
}

tcgetattr (fdCOM, &oldtioA);
bzero (&newtioA, sizeof (newtioA));
newtioA.c_cflag = CS8 | CLOCAL | CREAD;
newtioA.c_iflag = IGNPAR;
newtioA.c_oflag = 0;
newtioA.c_lflag = 0;
newtioA.c_cc[VTIME] = 0;
newtioA.c_cc[VMIN] = 1;
cfsetispeed (&newtioA, BAUDRATE);
cfsetospeed (&newtioA, BAUDRATE);
tcsetattr (fdCOM, TCSANOW, &newtioA);
tcflush (fdCOM, TCIFLUSH);

    FD_ZERO(&readfds);
    FD_SET(fdCOM, &readfds);
    
    if (strcmp(argv[1], "on") == 0) {sprintf(buf, "o");  /*printf("\nTX ON\n\n");*/ }
    if (strcmp(argv[1], "off") == 0) {sprintf(buf, "f"); /*printf("\nTX OFF\n\n");*/ }

/*
!!!!!
Если расскомментировать любой из printf выше, то программа перестает обрабатывать соответствующий аргумент, при этом второй арг. обрабатывается нормально. Т.е. если раскомментировать например первый printf, то программа запущенная с аргументом on выполниться, но в ком порт ничего не выдаст. При этом с аргументом off все пройдем нормально. Еще раз повторюсь, глюки наблюдаются, ТОЛЬКО если программу запускать не из под root'a.
!!!!!
*/

    
    printf("combuf=%s",buf);

//!!!!!  Интересно еще и то, что buf во всех случаях несет абсолютно верную информацию.

    write(fdCOM, buf, 1);
    printf("\n\n TRIGGED \n \n");
    
    tcsetattr (fdCOM, TCSANOW, &oldtioA);
return(0);
}

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//                       FUNCTION:   AddToLOG                              //
//                                                                         //
//         Opens 'logname' file for append access gets current time        //
//           and write to it 'logstr' when closes file and return          //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////
void AddToLOG(char *logname, char *logstr)
{
FILE *log;
char out[2048];
struct tm *t;
time_t tt;

if((log = fopen(logname, "a+")) == NULL)
{
    //file not found then return
    printf("!!!FATAL!!! Can't create: %s\n", logname);
    exit(1);
}

if(logstr[strlen(logstr)-1] == 0x0A) logstr[strlen(logstr)-1]='\0';

tt = time(NULL);
t = localtime(&tt);
sprintf(out, "[d:d:d] %s\n", t->tm_hour, t->tm_min, t->tm_sec, logstr);

fputs(out, log);
fclose(log);
}


Содержание

Сообщения в этом обсуждении
"Странное поведение программы при запуске от разных пользоват..."
Отправлено ACCA , 12-Мрт-07 08:02 
Начни с

#define DEFAULT_LOG "/tmp/server.log"

а потом разберись толком, кто куда должен складывать лог. Учти, что если ты пускал root'ом, то другие пользователи не смогут этого сделать - /tmp/server.log будет существовать, принадлежать root'у и скорее всего только он сможет открыть его на запись (уточни umask).


"Странное поведение программы при запуске от разных пользоват..."
Отправлено Dimik , 12-Мрт-07 09:39 
>Начни с
>
>#define DEFAULT_LOG "/tmp/server.log"
>
>а потом разберись толком, кто куда должен складывать лог. Учти, что если
>ты пускал root'ом, то другие пользователи не смогут этого сделать -
>/tmp/server.log будет существовать, принадлежать root'у и скорее всего только он сможет
>открыть его на запись (уточни umask).


В том коде который я привел вызов лога нигде не производится. Для честности эксперимента я вообще убрал функцию и ее прототип... Эффект остался тот же.


"Странное поведение программы при запуске от разных пользоват..."
Отправлено MKuznetsov , 12-Мрт-07 10:33 
1. вы бы проверили может ли вообще пользователь www что-то писать в порт,
и получается ли поставить скорость 115200, то есть надо проверить результат
всех операций tcXXX, cfXXX и на всякий случай посмотреть значение fdCOM.

2. насколько понимаю, приведённый код - вырезка из реального, а 'странное'
поведение очень похоже на запаханную память :)


"Странное поведение программы при запуске от разных пользоват..."
Отправлено Dimik , 12-Мрт-07 17:31 
>1. вы бы проверили может ли вообще пользователь www что-то писать в
>порт,

Да может. Этот код которы

>и получается ли поставить скорость 115200, то есть надо проверить результат
>всех операций tcXXX, cfXXX и на всякий случай посмотреть значение fdCOM.

>2. насколько понимаю, приведённый код - вырезка из реального, а 'странное'
>поведение очень похоже на запаханную память :)



"Странное поведение программы при запуске от разных пользоват..."
Отправлено Dimik , 12-Мрт-07 19:08 
>1. вы бы проверили может ли вообще пользователь www что-то писать в
>порт,

Да может. С закомментированными printf юзер www без проблем выполняет эту программу и происходит запись в компорт. Если расскомментировать printf, то программа исполняется, но в ком порт ничего не пишется. НО, при этом от имени root все выполняется без каких либо проблем даже с printf.

>и получается ли поставить скорость 115200, то есть надо проверить результат
>всех операций tcXXX, cfXXX и на всякий случай посмотреть значение fdCOM.
>

Да. С этим все ОК.

>2. насколько понимаю, приведённый код - вырезка из реального, а 'странное'
>поведение очень похоже на запаханную память :)

Нет это абсолютно боевой код. Можно копировать и комилить.



"Странное поведение программы при запуске от разных пользоват..."
Отправлено Michelnok , 12-Мрт-07 19:42 
>Нет это абсолютно боевой код. Можно копировать и комилить.

Странно тогда, поскольку симптомы действительно указывают на запорченную память, а ничего такого в приведенном коде на первый взгляд не наблюдается.


"Странное поведение программы при запуске от разных пользоват..."
Отправлено Michelnok , 12-Мрт-07 19:46 
>а ничего такого в приведенном коде на первый взгляд не наблюдается.

Дикое предположение - несоответствие выравнивания полей и прочего структуры termios между библиотекой и программой.


"Странное поведение программы при запуске от разных пользоват..."
Отправлено Hordi , 13-Мрт-07 12:52 
void AddToLOG(char *logname, char *logstr){

if(logstr[strlen(logstr)-1] == 0x0A) logstr[strlen(logstr)-1]='\0';
//а если статическую строку передашь (типа AddToLOG(DEFAULT_LOG, "started")) - потенциальная ошибка
...
sprintf(out, "[d:d:d] %s\n", t->tm_hour, t->tm_min, t->tm_sec, logstr);
//Что это за квадратики??!!! Процент поставь - здесь похоже и есть ошибка
}


"Странное поведение программы при запуске от разных пользоват..."
Отправлено Dimik , 13-Мрт-07 21:21 
>void AddToLOG(char *logname, char *logstr){
>
>if(logstr[strlen(logstr)-1] == 0x0A) logstr[strlen(logstr)-1]='\0';
>//а если статическую строку передашь (типа AddToLOG(DEFAULT_LOG, "started")) - потенциальная ошибка
>...
>sprintf(out, "[d:d:d] %s\n", t->tm_hour, t->tm_min, t->tm_sec, logstr);
>//Что это за квадратики??!!! Процент поставь - здесь похоже и есть ошибка
>
>}


Ребят, функция AddToLOG ни разу не вызывалась, посмотрите внимательно код... Чтоб она вам глаза не мазолила, еще раз приведу код без нее. Проблемы те же...


#include <fcntl.h>
#include <sys/time.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>

#define BAUDRATE B115200

char InCOMbuf[56];

fd_set readfds;
int fdCOM;

int main (int argc, char* argv[])
{
if (argc < 2)
       {
       printf("\n Usage: trigger on  -turns TX ON \n");
       printf("                off -turns TX OFF\n\n");
       exit(1);            
       }
      
if ((strcmp(argv[1],"on") != 0) && (strcmp(argv[1], "off") != 0))
       {
        printf("\n Usage: trigger on  -turns da TX ON \n");
        printf("                off -turns da TX OFF\n\n");
        exit(1);
       }

char buf[128];
struct termios oldtioA, newtioA;

fdCOM = open ("/dev/cuad1", O_RDWR | O_NOCTTY | O_NONBLOCK | O_SYNC);
if(fdCOM < 0)
{

  printf("Can't open dev/cuad1 ! \n");
  exit (-1);
}

tcgetattr (fdCOM, &oldtioA);
bzero (&newtioA, sizeof (newtioA));
newtioA.c_cflag = CS8 | CLOCAL | CREAD;
newtioA.c_iflag = IGNPAR;
newtioA.c_oflag = 0;
newtioA.c_lflag = 0;
newtioA.c_cc[VTIME] = 0;
newtioA.c_cc[VMIN] = 1;
cfsetispeed (&newtioA, BAUDRATE);
cfsetospeed (&newtioA, BAUDRATE);
tcsetattr (fdCOM, TCSANOW, &newtioA);
tcflush (fdCOM, TCIFLUSH);

    FD_ZERO(&readfds);
    FD_SET(fdCOM, &readfds);
    
    if (strcmp(argv[1], "on") == 0) {sprintf(buf, "o");  /*printf("\nTX ON\n\n");*/ }
    if (strcmp(argv[1], "off") == 0) {sprintf(buf, "f");}

        /////////// В таком варианте компиляции получаем следующий результат:
      
        /////////// Запуск от root с ключем on - успешно
        /////////// Запуск от root с ключем off - успешно
        /////////// Запуск от www с ключем on - успешно
        /////////// Запуск от www с ключем off - успешно

        //////////  Далее раскомментируем printf десятью строками выше, получаем:

        /////////// Запуск от root с ключем on - успешно
        /////////// Запуск от root с ключем off - успешно
        /////////// Запуск от www с ключем on - прога отрабатывает, printf("combuf=%s",buf); выдет то что положено. Но в ком порт ничего не сыпеться.
        /////////// Запуск от www с ключем off - успешно

    
    printf("combuf=%s",buf);
    write(fdCOM, buf, 1);
    printf("\n\n TRIGGED \n \n");
    
    tcsetattr (fdCOM, TCSANOW, &oldtioA);
return(0);
}


"Странное поведение программы при запуске от разных пользоват..."
Отправлено MKuznetsov , 13-Мрт-07 22:34 
1 - компилять с ключами -Wall -Wextra и забороть ВСЕ предупреждения
2 - переделать код в чистый C, натравить на него splint и забороть все разумные предупреждения
3 - удалить из кода ВСЁ лишнее (FD_SET и проч как неиспользуемое)
4 - заменить bzero как depricated функцию на memset
5 - перед злосщастным вызовом write(fdCOM,buf,1)
вывести и проверить значения fdCOM,buf и его содержимого
6 - после write добавить tcdrain() чтобы точно дождаться вывода если он не произошёл
7 - прогнать под отладчиком под разными пользователями и сравнить ВЕСЬ ход исполнения

сообщить о любом результате



"Странное поведение программы при запуске от разных пользоват..."
Отправлено vic , 14-Мрт-07 12:35 
>1 - компилять с ключами -Wall -Wextra и забороть ВСЕ предупреждения
>2 - переделать код в чистый C, натравить на него splint и
>забороть все разумные предупреждения
>3 - удалить из кода ВСЁ лишнее (FD_SET и проч как неиспользуемое)
>
>4 - заменить bzero как depricated функцию на memset
>5 - перед злосщастным вызовом write(fdCOM,buf,1)
>вывести и проверить значения fdCOM,buf и его содержимого
>6 - после write добавить tcdrain() чтобы точно дождаться вывода если он
>не произошёл
>7 - прогнать под отладчиком под разными пользователями и сравнить ВЕСЬ ход
>исполнения
>
>сообщить о любом результате

8. заменить
   if (strcmp(argv[1], "on") == 0) {sprintf(buf, "o");  /*printf("\nTX ON\n\n");*/ }
на
   if (strcmp(argv[1], "on") == 0) strcpy(buf, "o");  /*printf("\nTX ON\n\n");*/ }

по смыслу: (sprintf() без спецификаторов)- из разряда мистики
по стилю: юзать 'тяжелый' sprintf() в данном случае не стоит :)


"Странное поведение программы при запуске от разных пользоват..."
Отправлено vic , 14-Мрт-07 12:37 
упс, потер случайно фигурную скобку=)
if (strcmp(argv[1], "on") == 0) { strcpy(buf, "o");  /*printf("\nTX ON\n\n");*/ }

"Странное поведение программы при запуске от разных пользоват..."
Отправлено perece , 15-Мрт-07 17:35 
>упс, потер случайно фигурную скобку=)
>if (strcmp(argv[1], "on") == 0) { strcpy(buf, "o");  /*printf("\nTX ON\n\n");*/ }
>
тут, строго говоря, хватило бы вообще {buf[0]='o';  /*printf("\nTX ON\n\n");*/ }
но дело не в этом. если "некрасиво" не работает, а "красиво" - работает, значит, сделав "красиво" ты завел бомбу замедленного действия. ибо даже sprintf в этом контексте не криминал, не работает по другой причине!!!

\^P^/


"Странное поведение программы при запуске от разных пользоват..."
Отправлено vic , 15-Мрт-07 18:36 
>>упс, потер случайно фигурную скобку=)
>>if (strcmp(argv[1], "on") == 0) { strcpy(buf, "o");  /*printf("\nTX ON\n\n");*/ }
>>
>тут, строго говоря, хватило бы вообще {buf[0]='o';  /*printf("\nTX ON\n\n");*/ }
>но дело не в этом. если "некрасиво" не работает, а "красиво" -
>работает, значит, сделав "красиво" ты завел бомбу замедленного действия. ибо даже
>sprintf в этом контексте не криминал, не работает по другой причине!!!
>
>
>\^P^/

строго говоря, тут все переписать надо :)
Но дело не этом. Бомбу заводить будет автор топика если вместо того чтобы откопать истинную причину, оставит вдруг заработавший (не верится) 'красивый' код.

некоторая осторожность относительно sprintf у меня из темного прошлого =)


"Странное поведение программы при запуске от разных пользоват..."
Отправлено perece , 16-Мрт-07 17:42 
[...]
>Но дело не этом. Бомбу заводить будет автор топика если вместо того
>чтобы откопать истинную причину, оставит вдруг заработавший (не верится) 'красивый' код.
я, собсно, от этого и предостерегаю (вдруг всеже заработает - случайно?)

\^P^/