Новые книги

Информационные технологии сегодня это уже давно не таинственные сакральные знания, доступные только немногим избранным. Сегодня это массовый товар, предлагаемый множеством продавцов. Но как сделать правильный выбор, если вы не компьютерный гуру, а всего лишь владелец или управляющий среднего бизнеса, задумавшийся об увеличении его эффективности и управляемости? Как найти ответ на этот вопрос для предприятий малого и среднего бизнеса, где западные рецепты уже плохо работают, а отечественный опыт еще не обобщен...

Скорее всего, вы только что взяли эту книгу с книжной полки магазина, где она стояла в ряду множества подобных книг, и сейчас, в нескольких словах я должен убедить вас, что это именно так книга, которая вам нужна — расхваливать ее, обещать золотые горы и сокровенную истину. Но мне, автору, гораздо важнее не продать как можно больше книг, а найти среди вас единомышленников, которым я хочу рассказать то, что сам понял за все годы работы в этой информационных технологий, что рассказали мне техногуру, что объяснили люди, вложившие свои деньги в приобретение компьютерных систем.

В основе книги опыт трех компаний, внедривших у себя SAP Business One. Их сомнения, желания, процесс внедрения и достигнутые результаты. Этот опыт, пропущенный через призму собственного понимания автора, известного в компьютерном мире специалиста в области компьютерной аналитики, превратился в простую, увлекательную и веселую книгу прочитав которую, вы избегнете множества типичных ошибок и сможете автоматизировать собственную компанию, по возможности перешагивая через уже известные вам грабли.

Примеры.

Пример 18

/* _______________________ файл glob.h ___________________________*/
/* ПОДДЕРЖКА СПИСКА ИМЕН ФАЙЛОВ ЗАДАННОГО КАТАЛОГА                */
/* ______________________________________________________________ */
#define FILF
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
# define DIR_SIZE 14
extern char *malloc(unsigned); char *strdup(const char *str);
extern char *getenv();
extern char *strchr(char *, char),  *strrchr(char *, char);
#define ISDIR(mode) ((mode & S_IFMT) == S_IFDIR)
#define ISDEV(mode) ((mode & S_IFMT) & (S_IFCHR|S_IFBLK))
#define ISREG(mode) ((mode & S_IFMT) == S_IFREG)
#define ISEXE(mode) ((mode & S_IFMT) == S_IFREG && (mode & 0111))
#define isdir(st)   ISDIR(st.st_mode)
#define isdev(st)   ISDEV(st.st_mode)
#define isreg(st)   ISREG(st.st_mode)
#define isexe(st)   ISEXE(st.st_mode)
#define YES      1
#define NO       0
#define I_DIR    0x01     /* это имя каталога      */
#define I_EXE    0x02     /* это выполняемый файл  */
#define I_NOSEL  0x04     /* строку нельзя выбрать */
#define I_SYS    (I_DIR | I_EXE | I_NOSEL)
/* Скопировано из treemk.c
 * Лучше просто написать #include "glob.h" в файле treemk.c
 */
#define FAILURE (-1)            /* код неудачи */
#define SUCCESS   1             /* код успеха  */
#define WARNING   0             /* нефатальная ошибка */
typedef struct _info {    /* структура элемента каталога */
	char *s;          /* имя файла                   */
	short fl;         /* флаг                        */
	union _any{
	   int (*act)();     /* возможно связанное действие */
	   char *note;       /* или комментарий             */
	   unsigned i;       /* или еще какой-то параметр   */
	   struct _info *inf;
	} any;            /* вспомогательное поле        */
#ifdef FILF
/* дополнительные необязательные параметры, получаемые из stat(); */
	long size;
	int uid, gid;
	unsigned short mode;
#endif
} Info;
typedef union _any Any;
extern Info NullInfo;
#define MAX_ARGV 256      /* Максимальное число имен в каталоге */
typedef struct {          /* Содержимое каталога name */
	time_t lastRead;  /* время последнего чтения каталога  */
	Info *files;      /* содержимое каталога               */
	char *name;       /* имя каталога                      */
	ino_t ino; dev_t dev; /* I-узел и устройство           */
	char valid;       /* существует ли этот каталог вообще */
	short readErrors; /* != 0, если каталог не читается    */
} DirContents;
     /* Виды сортировки имен в каталоге */
typedef enum { SORT_ASC, SORT_DESC, SORT_SUFX,
	       SORT_NOSORT, SORT_SIZE }         Sort;
extern Sort sorttype; extern int in_the_root;
int   gcmps (const void *p1, const void *p2);
Info *blkcpy(Info *v); void blkfree(Info *v);
Info *glob(char **patvec,  char *dirname);
Info *glb(char   *pattern, char *dirname);
int ReadDir(char *dirname, DirContents *d);
struct savech{ char *s, c; };
#define SAVE(sv, str) (sv).s = (str); (sv).c = *(str)
#define RESTORE(sv) if((sv).s)   *(sv).s = (sv).c
/* _______________________ файл glob.c __________________________ */
#include "glob.h"
int in_the_root = NO;        /* читаем корневой каталог ?     */
Sort sorttype = SORT_SUFX;   /* сортировка имен по суффиксу   */
Info NullInfo = { NULL, 0 }; /* и прочие поля = 0 (если есть) */
char *strdup(const char *s){
   char *p = malloc(strlen(s)+1); if(p)strcpy(p, s); return p; }
/* Содержится ли любой из символов в строке ? */
int any(register char *s, register char *p){
   while( *s ){ if( strchr(p, *s)) return YES; s++; }
   return NO;
}
/* Найти последнюю точку в имени */
static char *lastpoint (char *s)
{   register char *last; static char no[] = "";
    if((last = strchr(s, '.')) == NULL) return no;
    /* если имя начинается с точки - не считать ее */
    return( last == s ? no : last );
}
/* Сравнение строк с учетом их суффиксов */
int strsfxcmp (register char *s1, register char *s2){
    char *p1, *p2, c1, c2; int code;
    p1 = lastpoint (s1); p2 = lastpoint (s2);
    if (code = strcmp (p1, p2)) return code; /* суффиксы разные */
    /* иначе: суффиксы равны. Сортируем по головам              */
    c1 = *p1; c2 = *p2; *p1 = '\0'; *p2 = '\0'; /* временно     */
    code = strcmp (s1, s2);
    *p1 = c1; *p2 = c2; return code;
}
/* Функция сортировки */
int gcmps(const void *p1, const void *p2){
    Info *s1 = (Info *) p1, *s2 = (Info *) p2;
    switch( sorttype ){
    default:
    case SORT_ASC:    return    strcmp(s1->s, s2->s);
    case SORT_DESC:   return   -strcmp(s1->s, s2->s);
    case SORT_SUFX:   return strsfxcmp(s1->s, s2->s);
    case SORT_NOSORT: return (-1);
#ifdef FILF
    case SORT_SIZE:   return (s1->size <  s2->size ? -1 :
			      s1->size == s2->size ? 0 : 1 );
#endif
    }
}
/* Копирование блока */
Info *blkcpy(Info *v){
    register i, len;
    Info *vect = (Info *) malloc(((len=blklen(v)) + 1) * sizeof(Info));
    for(i=0; i < len; i++ ) vect[i] = v[i];
    vect[len] = NullInfo;   return vect;
}
/* Измерение длины блока */
int blklen(Info *v){
    int i = 0;
    while( v->s ) i++, v++;
    return i;
}
/* Очистка блока (уничтожение) */
void blkfree(Info *v){
     Info *all = v;
     while( v->s )
	    free((char *) v->s ), v++;
     free((char *) all );
}
/* Сравнение двух блоков */
int blkcmp( register Info *p, register Info *q ){
    while( p->s && q->s && !strcmp(p->s, q->s) &&
	  (p->fl & I_SYS) == (q->fl & I_SYS)){ p++; q++; }
    if( p->s == NULL && q->s == NULL )
	return 0;       /* совпадают   */
    return 1;           /* различаются */
}
char   globchars [] = "*?[";
Info gargv[MAX_ARGV]; int gargc;
static short readErrors;
void greset() { gargc = 0; readErrors = 0; }
/* Расширить шаблон имен файлов в сами имена */
static void globone(char *pattern, char dirname[]){
     extern char *strdup(); struct stat st;
     DIR *dirf; struct dirent *d;
     if( any(pattern, globchars) == NO ){  /* no glob */
	     gargv[gargc]   = NullInfo;
	     gargv[gargc].s = strdup(pattern);
	     gargc++;
	     gargv[gargc]   = NullInfo;
	     return;
     }
     if((dirf = opendir(dirname)) == NULL){ readErrors++; goto out; }
     while(d = readdir(dirf)){
       if(match(d->d_name, pattern)){
	  char fullname[512];
	  if( sorttype != SORT_NOSORT && !strcmp(d->d_name, "."))
	      continue;
	  /* В корневом каталоге имя ".." следует пропускать */
	  if( in_the_root && !strcmp(d->d_name, "..")) continue;
	  /* Проверка на переполнение */
	  if( gargc == MAX_ARGV - 1){
	      free(gargv[gargc-1].s);
	      gargv[gargc-1].s  = strdup(" Слишком много файлов!!!");
	      gargv[gargc-1].fl = I_SYS;
	      break;
	  }
	  gargv[gargc]     = NullInfo;
	  gargv[gargc].s   = strdup(d->d_name);
	  sprintf(fullname, "%s/%s", dirname, d->d_name);
	  if(stat(fullname, &st) < 0) gargv[gargc].fl |= I_NOSEL;
	  else if(isdir(st))          gargv[gargc].fl |= I_DIR;
	  else if(isexe(st))          gargv[gargc].fl |= I_EXE;
#ifdef FILF
	  gargv[gargc].size = st.st_size;
	  gargv[gargc].uid  = st.st_uid;
	  gargv[gargc].gid  = st.st_gid;
	  gargv[gargc].mode = st.st_mode;
#endif
	  gargc++;
       }
     }
     closedir(dirf);
out: gargv[ gargc ] = NullInfo;
}
/* Расширить несколько шаблонов */
Info *glob(char **patvec, char *dirname){
      greset();
      while(*patvec){ globone(*patvec, dirname); patvec++; }
      qsort(gargv, gargc, sizeof(Info), gcmps);
      return blkcpy(gargv);
}
Info *glb(char *pattern, char *dirname){ char *pv[2];
      pv[0] = pattern; pv[1] = NULL; return glob(pv, dirname);
}
/* Прочесть содержимое каталога, если оно изменилось:
 * Вернуть: 0  - каталог не менялся;
 *          1  - изменился;
 *       1000  - изменился рабочий каталог (chdir);
 *          -1 - каталог не существует;
 */
int ReadDir(char *dirname, DirContents *d){
    struct stat st; Info *newFiles;
    int save = YES; /* сохранять метки у файлов ? */
    int dirchanged = NO; /* сделан chdir() ? */
    /* каталог мог быть удален, а мы об этом не извещены */
    if( stat(dirname, &st) < 0 ){
	d->valid = NO; d->lastRead = 0L;
	if(d->files) blkfree(d->files);
	d->files = blkcpy( &NullInfo );
	return (-1); /* не существует */
    } else d->valid = YES;
    /* не изменился ли адрес каталога, хранимого в *d ? */
    if(d->ino != st.st_ino || d->dev != st.st_dev){ /* изменился */
       d->ino  = st.st_ino;   d->dev  = st.st_dev;
       save = NO; d->lastRead = 0L; dirchanged = YES;
    }
    /* не изменилось ли имя каталога ? */
    if( !d->name || strcmp(d->name, dirname)){
	if(d->name) free(d->name); d->name = strdup(dirname);
	/* save=NO; d->lastRead = 0; */
    }
    /* проверим, был ли модифицирован каталог ? */
    if( save==YES && d->files && st.st_mtime == d->lastRead )
	return 0;       /* содержимое каталога не менялось */
    d->lastRead = st.st_mtime;
    newFiles = glb("*", d->name);  /* прочесть содержимое каталога */
    if(save == YES && d->files){
	register Info *p, *q;
	if( !blkcmp(newFiles, d->files)){
	     blkfree(newFiles); return 0;  /* не изменилось */
	} /* иначе сохранить пометки */
	for(p= d->files; p->s; p++)
	  for(q= newFiles; q->s; ++q)
	    if( !strcmp(p->s, q->s)){
		q->fl |= p->fl & ~I_SYS;   break;
	    }
    }
    if(d->files) blkfree(d->files);
    d->files = newFiles; d->readErrors = readErrors;
    return 1 + (dirchanged ? 999:0);
    /* каталог изменился */
}

© Copyright А. Богатырев, 1992-95
Си в UNIX

Назад | Содержание | Вперед