/* Kermit's attribute packets services */ #include "ufk.h" #include #include #include #define leap(y) (!(y & 3)) /* Return TRUE if it's a leap year */ unsigned int perms, operms; int owner; struct tm timbuf; char opsys[3]; init_attributes() { file_size = 0; /* for % display, remains 0 if none */ perms = 0xffff; /* 'world' permissions */ operms = 0xffff; /* permissions in our syntax */ timbuf.tm_yday = -1; /* no date given yet */ } snd_attributes() { struct stat buf; struct tm *localtime(); struct tm *tpt; int locfp; char *p, hlpstr[16]; locfp = open(filnam,0); fstat(locfp,&buf); /* filnam is already verified */ p = sndpkt; /* setup system of origin. Define UniFLEX to be number 'UF' */ addstr('.',&p,"UF"); /* setup file size in blocks */ sprintf(hlpstr,"%d",(int)((buf.st_size + 1024l) / 1024l));/* Rounded in K */ addstr('!',&p,hlpstr); /* setup file size in bytes */ sprintf(hlpstr,"%ld",buf.st_size); addstr('1',&p,hlpstr); /* setup creation date */ tpt = localtime(&buf.st_mtime); sprintf(hlpstr,"%02.2d%02.2d%02.2d %02.2d:%02.2d:%02.2d", tpt->tm_year, tpt->tm_mon + 1, tpt->tm_mday, tpt->tm_hour, tpt->tm_min, tpt->tm_secs); addstr('#',&p,hlpstr); /* setup file protection with respect to the world */ *p++ = '-'; *p++ = tochar(1); *p++ = tochar((buf.st_mode & S_IPRM) >> 3); /* setup file protection in our syntax */ *p++ = ','; *p++ = tochar(2); *p++ = tochar((buf.st_mode & S_IPRM) & 0x0f); *p++ = tochar((buf.st_mode & S_IPRM) >> 4); /* setup file owner */ sprintf(hlpstr,"%d",buf.st_uid); addstr('$',&p,hlpstr); /* set file type */ *p++ = '"'; *p++ = tochar(1); if (binfil = seltype(locfp)) *p++ = 'B'; /* Binary file */ else *p++ = 'A'; /* Ascii file */ *p = '\0'; size = p - sndpkt; /* Final packet size */ close (locfp); } rcv_attributes() { int len, filesize; long dsize; char *p, *q, *r, *pos, hlpstr[10], type, *index(), *rindex(); p = recpkt; while (p < recpkt + size) { type = *p++; if ((len = unchar(*p++)) != 0) { switch(type) { case '.': /* operating system origin */ strncpy(opsys,p,len); opsys[len] = '\0'; break; case '!': /* Filesize in K bytes */ strncpy(hlpstr,p,len); hlpstr[len] = '\0'; sscanf(hlpstr,"%d",&filesize); pos = rindex(rec_filnam,'/'); if (pos == NULL) strcpy(hlpstr,"."); else { strncpy(hlpstr,rec_filnam,pos - rec_filnam); hlpstr[pos-rec_filnam] = '\0'; } dsize = get_free(hlpstr); /* Get number of free blocks */ if ((dsize == -1l) || (dsize < (long)filesize)) return(ERROR); /* File too big to fit */ break; case '1': /* Number of bytes in file */ strncpy(hlpstr,p,len); hlpstr[len] = '\0'; sscanf(hlpstr,"%ld",&file_size); break; case '"': /* File type */ type = *p; if (type == 'A') binfil = FALSE; /* Ascii */ else if (type == 'B') binfil = TRUE; /* Binary */ break; case '-': /* File permissions */ perms = unchar(*p) & 7; break; case ',': /* File permissions in our syntax */ operms = unchar(p[0]); if (len > 1) operms |= (unchar(p[1]) << 4); break; case '$': /* File owner */ strncpy(hlpstr,p,len); hlpstr[len] = '\0'; sscanf(hlpstr,"%d",&owner); break; case '#': /* File date */ q = p; /* Check if date and time specified */ if (len > 8) { /* both date and time */ r = index(p,' '); if ((r - p) == 8) q = &p[2]; /* skip first two digits of date */ } else if (len == 8) /* only date specified */ q = &p[2]; timbuf.tm_hour = 0; /* Zero out optional items */ timbuf.tm_min = 0; timbuf.tm_secs = 0; sscanf(q,"%2d%2d%2d %d:%d:%d", &timbuf.tm_year, &timbuf.tm_mon, &timbuf.tm_mday, &timbuf.tm_hour, &timbuf.tm_min, &timbuf.tm_secs); timbuf.tm_mon--; /* Adjust month */ timbuf.tm_yday = 0; /* Flag date given */ break; default: break; } } p += len; } return NULL; } seltype(fp) int fp; { unsigned char filechar[256]; char *i; int size; size = read(fp,filechar,256); for (i = filechar; i < &filechar[size]; i++) if ((*i != 0x09) && /* tab */ (*i != 0x0a) && /* linefeed */ (*i != 0x0c) && /* formfeed */ (*i != 0x0d) && /* carriage return */ ((*i > 0x7e) || (*i < 0x20)) ) return TRUE; /* it must be binary */ return FALSE; /* ascii */ } fset_attributes() { long cvttime(); struct stat buf; if (stat(rec_filnam,&buf)) /* Get status of current filename */ prterr(ER_PERMS); else { if (perms != 0xffff) { /* 'world' syntax */ perms = (buf.st_mode & S_IPRM & /* Mask for permissions */ ~(S_IOREAD | S_IOWRITE | S_IOEXEC)) | (perms << 3); /* set new 'other' bits */ if (chmod(rec_filnam,perms) == ERROR) prterr(ER_PERMS); } if ((operms != 0xffff) && (strcmp(opsys,"UF") == 0)) /* 'our' syntax */ if (chmod(rec_filnam,operms) == ERROR) prterr(ER_PERMS); } if (timbuf.tm_yday != -1) fset_date(rec_filnam,cvttime(&timbuf)); /* Set new date */ } addstr(type,q,string) char type, **q, *string; { int length; length = strlen(string); *(*q)++ = type; *(*q)++ = tochar(length); strcpy(*q,string); *q += length; } long cvttime(buf) struct tm *buf; { struct timeb tbuf; /* To read the timezone */ static char daytab[] = { /* Number of days for each month */ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int days_so_far, i, j; long int sec_sin_80; /* Accumulated number of seconds */ days_so_far = 0; for (j = 80; j < buf->tm_year; j++)/* Calc number of days for past years */ { for (i = 0; i < 12; i++) days_so_far += daytab[i]; /* Add number of days in a year */ if (leap(j)) days_so_far++; /* one more in a leap year */ } for (i = 0; i < buf->tm_mon; i++)/* Calc number of days for past months */ { days_so_far += daytab[i]; if ((i == 1) && leap(buf->tm_year)) days_so_far++; /* Take care of 29 februari */ } days_so_far += buf->tm_mday - 1; /* Add number of days this month */ sec_sin_80 = ((long)buf->tm_hour * 3600) + (buf->tm_min * 60) + buf->tm_secs; sec_sin_80 += days_so_far * (long) 86400; ftime(&tbuf); /* Get timezone value */ sec_sin_80 += tbuf.timezone * 60; /* Correct for it */ return(sec_sin_80); /* That's it, return the time */ }