telco.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #define LOGFILE "telco"
  6. /*
  7. * Rather than reading /adm/users, which is a lot of work for
  8. * a toy progdev, we assume all groups have the form
  9. * NNN:user:user:
  10. * meaning that each user is the leader of his own group.
  11. */
  12. enum
  13. {
  14. OPERM = 0x3, /* mask of all permission types in open mode */
  15. Ndev = 8,
  16. Nreq = (Ndev*3)/2,
  17. Nrbuf = 32*1024,
  18. };
  19. typedef struct Fid Fid;
  20. typedef struct Dev Dev;
  21. typedef struct Request Request;
  22. typedef struct Type Type;
  23. struct Fid
  24. {
  25. Qid qid;
  26. short busy;
  27. short open;
  28. int fid;
  29. Fid *next;
  30. char *user;
  31. };
  32. struct Request
  33. {
  34. Request *next;
  35. Fid *fid;
  36. ulong tag;
  37. int count;
  38. int flushed;
  39. };
  40. struct Dev
  41. {
  42. Lock;
  43. /* device state */
  44. int ctl; /* control fd */
  45. int data; /* data fd */
  46. char *path; /* to device */
  47. Type *t;
  48. Type *baset;
  49. int speed;
  50. int fclass;
  51. /* fs emulation */
  52. int open;
  53. long perm;
  54. char *name;
  55. char *user;
  56. char msgbuf[128];
  57. Request *r;
  58. Request *rlast;
  59. /* input reader */
  60. int monitoring; /* monitor pid */
  61. char rbuf[Nrbuf];
  62. char *rp;
  63. char *wp;
  64. long pid;
  65. };
  66. enum
  67. {
  68. Devmask= (Ndev-1)<<8,
  69. Qlvl1= 0,
  70. Qlvl2= 1,
  71. Qclone= 2,
  72. Qlvl3= 3,
  73. Qdata= 4,
  74. Qctl= 5,
  75. Pexec = 1,
  76. Pwrite = 2,
  77. Pread = 4,
  78. Pother = 1,
  79. Pgroup = 8,
  80. Powner = 64,
  81. };
  82. char *names[] =
  83. {
  84. [Qlvl1] "/",
  85. [Qlvl2] "telco",
  86. [Qclone] "clone",
  87. [Qlvl3] "",
  88. [Qdata] "data",
  89. [Qctl] "ctl",
  90. };
  91. #define DEV(q) ((((ulong)(q).path)&Devmask)>>8)
  92. #define TYPE(q) (((ulong)(q).path)&((1<<8)-1))
  93. #define MKQID(t, i) ((((i)<<8)&Devmask) | (t))
  94. enum
  95. {
  96. /*
  97. * modem specific commands
  98. */
  99. Cerrorcorrection = 0, /* error correction */
  100. Ccompression, /* compression */
  101. Cflowctl, /* CTS/RTS */
  102. Crateadjust, /* follow line speed */
  103. Cfclass2, /* set up for fax */
  104. Cfclass0, /* set up for data */
  105. Ncommand,
  106. };
  107. struct Type
  108. {
  109. char *name;
  110. char *ident; /* inquire request */
  111. char *response; /* inquire response (strstr) */
  112. char *basetype; /* name of base type */
  113. char *commands[Ncommand];
  114. };
  115. /*
  116. * Fax setup summary
  117. *
  118. * FCLASS=2 - set to service class 2, i.e., one where the fax handles timing
  119. * FTBC=0 - ???
  120. * FREL=1 - ???
  121. * FCQ=1 - receive copy quality checking enabled
  122. * FBOR=1 - set reversed bit order for phase C data
  123. * FCR=1 - the DCE can receive message data, bit 10 in the DIS or
  124. * DTC frame will be set
  125. * FDIS=,3 - limit com speed to 9600 baud
  126. */
  127. Type typetab[] =
  128. {
  129. { "Rockwell", 0, 0, 0,
  130. "AT\\N7", /* auto reliable (V.42, fall back to MNP, to none) */
  131. "AT%C1\\J0", /* negotiate for compression, don't change port baud rate */
  132. "AT\\Q3", /* CTS/RTS flow control */
  133. "AT\\J1",
  134. "AT+FCLASS=2\rAT+FCR=1\r",
  135. "AT+FCLASS=0",
  136. },
  137. { "ATT2400", "ATI9", "E2400", "Rockwell",
  138. "AT\\N3", /* auto reliable (MNP, fall back to none) */
  139. 0,
  140. 0,
  141. 0,
  142. 0,
  143. 0,
  144. },
  145. { "ATT14400", "ATI9", "E14400", "Rockwell",
  146. 0,
  147. 0,
  148. 0,
  149. 0,
  150. 0,
  151. 0,
  152. },
  153. { "MT1432", "ATI2", "MT1432", 0,
  154. "AT&E1", /* auto reliable (V.42, fall back to none) */
  155. "AT&E15$BA0", /* negotiate for compression */
  156. "AT&E4", /* CTS/RTS flow control */
  157. "AT$BA1", /* don't change port baud rate */
  158. "AT+FCLASS=2\rAT+FTBC=0\rAT+FREL=1\rAT+FCQ=1\rAT+FBOR=1\rAT+FCR=1\rAT+FDIS=,3",
  159. "AT+FCLASS=0",
  160. },
  161. { "MT2834", "ATI2", "MT2834", "MT1432",
  162. 0,
  163. 0,
  164. 0,
  165. 0,
  166. "AT+FCLASS=2\rAT+FTBC=0\rAT+FREL=1\rAT+FCQ=1\rAT+FBOR=1\rAT+FCR=1",
  167. 0,
  168. },
  169. { "VOCAL", "ATI6", "144DPL+FAX", "Rockwell",
  170. "AT\\N3", /* auto reliable (V.42, fall back to MNP, fall back to none) */
  171. "AT%C3\\J0", /* negotiate for compression, don't change port baud rate */
  172. 0,
  173. 0,
  174. "AT+FCLASS=2\rAT+FTBC=0\rAT+FREL=1\rAT+FCQ=1\rAT+FBOR=1\rAT+FCR=1",
  175. "AT+FCLASS=0",
  176. },
  177. { 0, },
  178. };
  179. /*
  180. * modem return codes
  181. */
  182. enum
  183. {
  184. Ok,
  185. Success,
  186. Failure,
  187. Noise,
  188. Found,
  189. };
  190. /*
  191. * modem return messages
  192. */
  193. typedef struct Msg Msg;
  194. struct Msg
  195. {
  196. char *text;
  197. int type;
  198. };
  199. Msg msgs[] =
  200. {
  201. { "OK", Ok, },
  202. { "NO CARRIER", Failure, },
  203. { "ERROR", Failure, },
  204. { "NO DIALTONE", Failure, },
  205. { "BUSY", Failure, },
  206. { "NO ANSWER", Failure, },
  207. { "CONNECT", Success, },
  208. { 0, 0 },
  209. };
  210. Fid *fids;
  211. Dev *dev;
  212. int ndev;
  213. int mfd[2];
  214. char *user;
  215. uchar mdata[8192+IOHDRSZ];
  216. int messagesize = sizeof mdata;
  217. Fcall thdr;
  218. Fcall rhdr;
  219. char errbuf[ERRMAX];
  220. uchar statbuf[STATMAX];
  221. int pulsed;
  222. int verbose;
  223. int maxspeed = 56000;
  224. char *srcid = "plan9";
  225. int answer = 1;
  226. Fid *newfid(int);
  227. int devstat(Dir*, uchar*, int);
  228. int devgen(Qid, int, Dir*, uchar*, int);
  229. void error(char*);
  230. void io(void);
  231. void *erealloc(void*, ulong);
  232. void *emalloc(ulong);
  233. void usage(void);
  234. int perm(Fid*, Dev*, int);
  235. void setspeed(Dev*, int);
  236. int getspeed(char*, int);
  237. char *dialout(Dev*, char*);
  238. void onhook(Dev*);
  239. int readmsg(Dev*, int, char*);
  240. void monitor(Dev*);
  241. int getinput(Dev*, char*, int);
  242. void serve(Dev*);
  243. void receiver(Dev*);
  244. char* modemtype(Dev*, int, int);
  245. char *rflush(Fid*), *rversion(Fid*),
  246. *rattach(Fid*), *rauth(Fid*), *rwalk(Fid*),
  247. *ropen(Fid*), *rcreate(Fid*),
  248. *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
  249. *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
  250. char *(*fcalls[])(Fid*) = {
  251. [Tflush] rflush,
  252. [Tversion] rversion,
  253. [Tattach] rattach,
  254. [Tauth] rauth,
  255. [Twalk] rwalk,
  256. [Topen] ropen,
  257. [Tcreate] rcreate,
  258. [Tread] rread,
  259. [Twrite] rwrite,
  260. [Tclunk] rclunk,
  261. [Tremove] rremove,
  262. [Tstat] rstat,
  263. [Twstat] rwstat,
  264. };
  265. char Eperm[] = "permission denied";
  266. char Enotdir[] = "not a directory";
  267. char Enotexist[] = "file does not exist";
  268. char Ebadaddr[] = "bad address";
  269. char Eattn[] = "can't get modem's attention";
  270. char Edial[] = "can't dial";
  271. char Enoauth[] = "telco: authentication not required";
  272. char Eisopen[] = "file already open for I/O";
  273. char Enodev[] = "no free modems";
  274. char Enostream[] = "stream closed prematurely";
  275. void
  276. usage(void)
  277. {
  278. fprint(2, "usage: %s [-vp] [-i srcid] dev ...\n", argv0);
  279. exits("usage");
  280. }
  281. void
  282. notifyf(void *a, char *s)
  283. {
  284. USED(a);
  285. if(strncmp(s, "interrupt", 9) == 0)
  286. noted(NCONT);
  287. noted(NDFLT);
  288. }
  289. void
  290. main(int argc, char *argv[])
  291. {
  292. int p[2];
  293. int fd;
  294. char buf[10];
  295. Dev *d;
  296. ARGBEGIN{
  297. case 'p':
  298. pulsed = 1;
  299. break;
  300. case 'v':
  301. verbose = 1;
  302. break;
  303. case 'i':
  304. srcid = ARGF();
  305. break;
  306. case 's':
  307. maxspeed = atoi(ARGF());
  308. break;
  309. case 'n':
  310. answer = 0;
  311. break;
  312. default:
  313. usage();
  314. }ARGEND
  315. if(argc == 0)
  316. usage();
  317. if(argc > Ndev)
  318. argc = Ndev;
  319. if(pipe(p) < 0)
  320. error("pipe failed");
  321. notify(notifyf);
  322. fmtinstall('F', fcallfmt);
  323. user = getuser();
  324. switch(rfork(RFFDG|RFPROC|RFREND|RFNOTEG)){
  325. case -1:
  326. error("fork");
  327. case 0:
  328. close(p[1]);
  329. mfd[0] = mfd[1] = p[0];
  330. break;
  331. default:
  332. close(p[0]);
  333. fd = create("/srv/telco", OWRITE, 0666);
  334. if(fd < 0)
  335. error("create of /srv/telco failed");
  336. sprint(buf, "%d", p[1]);
  337. if(write(fd, buf, strlen(buf)) < 0)
  338. error("writing /srv/telco");
  339. close(fd);
  340. if(mount(p[1], -1, "/net", MBEFORE, "") < 0)
  341. error("mount failed");
  342. exits(0);
  343. }
  344. dev = mallocz(argc*sizeof(Dev), 1);
  345. for(ndev = 0; ndev < argc; ndev++){
  346. d = &dev[ndev];
  347. d->path = argv[ndev];
  348. d->rp = d->wp = d->rbuf;
  349. monitor(d);
  350. d->open++;
  351. onhook(d);
  352. d->open--;
  353. }
  354. io();
  355. }
  356. /*
  357. * generate a stat structure for a qid
  358. */
  359. int
  360. devstat(Dir *dir, uchar *buf, int nbuf)
  361. {
  362. Dev *d;
  363. int t;
  364. static char tmp[10][32];
  365. static int ntmp;
  366. t = TYPE(dir->qid);
  367. if(t != Qlvl3)
  368. dir->name = names[t];
  369. else{
  370. dir->name = tmp[ntmp % nelem(tmp)];
  371. sprint(dir->name, "%lud", DEV(dir->qid));
  372. ntmp++;
  373. }
  374. dir->mode = 0755;
  375. dir->uid = user;
  376. dir->gid = user;
  377. dir->muid = user;
  378. if(t >= Qlvl3){
  379. d = &dev[DEV(dir->qid)];
  380. if(d->open){
  381. dir->mode = d->perm;
  382. dir->uid = d->user;
  383. }
  384. }
  385. if(dir->qid.type & QTDIR)
  386. dir->mode |= DMDIR;
  387. if(t == Qdata){
  388. d = &dev[DEV(dir->qid)];
  389. dir->length = d->wp - d->rp;
  390. if(dir->length < 0)
  391. dir->length += Nrbuf;
  392. } else
  393. dir->length = 0;
  394. dir->atime = time(0);
  395. dir->mtime = dir->atime;
  396. if(buf)
  397. return convD2M(dir, buf, nbuf);
  398. return 0;
  399. }
  400. /*
  401. * enumerate file's we can walk to from q
  402. */
  403. int
  404. devgen(Qid q, int i, Dir *d, uchar *buf, int nbuf)
  405. {
  406. static ulong v;
  407. d->qid.vers = v++;
  408. switch(TYPE(q)){
  409. case Qlvl1:
  410. if(i != 0)
  411. return -1;
  412. d->qid.type = QTDIR;
  413. d->qid.path = Qlvl2;
  414. break;
  415. case Qlvl2:
  416. switch(i){
  417. case -1:
  418. d->qid.type = QTDIR;
  419. d->qid.path = Qlvl1;
  420. break;
  421. case 0:
  422. d->qid.type = QTFILE;
  423. d->qid.path = Qclone;
  424. break;
  425. default:
  426. if(i > ndev)
  427. return -1;
  428. d->qid.type = QTDIR;
  429. d->qid.path = MKQID(Qlvl3, i-1);
  430. break;
  431. }
  432. break;
  433. case Qlvl3:
  434. switch(i){
  435. case -1:
  436. d->qid.type = QTDIR;
  437. d->qid.path = Qlvl2;
  438. break;
  439. case 0:
  440. d->qid.type = QTFILE;
  441. d->qid.path = MKQID(Qdata, DEV(q));
  442. break;
  443. case 1:
  444. d->qid.type = QTFILE;
  445. d->qid.path = MKQID(Qctl, DEV(q));
  446. break;
  447. default:
  448. return -1;
  449. }
  450. break;
  451. default:
  452. return -1;
  453. }
  454. return devstat(d, buf, nbuf);
  455. }
  456. char*
  457. rversion(Fid *)
  458. {
  459. Fid *f;
  460. for(f = fids; f; f = f->next)
  461. if(f->busy)
  462. rclunk(f);
  463. if(thdr.msize < 256)
  464. return "version: message size too small";
  465. messagesize = thdr.msize;
  466. if(messagesize > sizeof mdata)
  467. messagesize = sizeof mdata;
  468. rhdr.msize = messagesize;
  469. if(strncmp(thdr.version, "9P2000", 6) != 0)
  470. return "unrecognized 9P version";
  471. rhdr.version = "9P2000";
  472. return 0;
  473. }
  474. char*
  475. rflush(Fid *f)
  476. {
  477. Request *r, **l;
  478. Dev *d;
  479. USED(f);
  480. for(d = dev; d < &dev[ndev]; d++){
  481. lock(d);
  482. for(l = &d->r; r = *l; l = &r->next)
  483. if(r->tag == thdr.oldtag){
  484. *l = r->next;
  485. free(r);
  486. break;
  487. }
  488. unlock(d);
  489. }
  490. return 0;
  491. }
  492. char *
  493. rauth(Fid *f)
  494. {
  495. USED(f);
  496. return Enoauth;
  497. }
  498. char*
  499. rattach(Fid *f)
  500. {
  501. f->busy = 1;
  502. f->qid.type = QTDIR;
  503. f->qid.path = Qlvl1;
  504. f->qid.vers = 0;
  505. rhdr.qid = f->qid;
  506. if(thdr.uname[0])
  507. f->user = strdup(thdr.uname);
  508. else
  509. f->user = "none";
  510. return 0;
  511. }
  512. char*
  513. rwalk(Fid *f)
  514. {
  515. Fid *nf;
  516. int i, nqid;
  517. char *name, *err;
  518. Dir dir;
  519. Qid q;
  520. nf = nil;
  521. if(thdr.fid != thdr.newfid){
  522. if(f->open)
  523. return Eisopen;
  524. if(f->busy == 0)
  525. return Enotexist;
  526. nf = newfid(thdr.newfid);
  527. nf->busy = 1;
  528. nf->open = 0;
  529. nf->qid = f->qid;
  530. nf->user = strdup(f->user);
  531. f = nf; /* walk f */
  532. }
  533. err = nil;
  534. dir.qid = f->qid;
  535. nqid = 0;
  536. if(thdr.nwname > 0){
  537. for(; nqid < thdr.nwname; nqid++) {
  538. if((dir.qid.type & QTDIR) == 0){
  539. err = Enotdir;
  540. break;
  541. }
  542. name = thdr.wname[nqid];
  543. if(strcmp(name, ".") == 0){
  544. /* nothing to do */
  545. }else if(strcmp(name, "..") == 0) {
  546. if(devgen(f->qid, -1, &dir, 0, 0) < 0)
  547. break;
  548. }
  549. else{
  550. q = dir.qid;
  551. for(i = 0;; i++){
  552. if(devgen(q, i, &dir, 0, 0) < 0)
  553. goto Out;
  554. if(strcmp(name, dir.name) == 0)
  555. break;
  556. }
  557. }
  558. rhdr.wqid[nqid] = dir.qid;
  559. }
  560. Out:
  561. if(nqid == 0 && err == nil)
  562. err = Enotexist;
  563. if(nf != nil && thdr.fid != thdr.newfid && nqid < thdr.nwname)
  564. rclunk(nf);
  565. }
  566. rhdr.nwqid = nqid;
  567. if(nqid > 0 && nqid == thdr.nwname)
  568. f->qid = dir.qid;
  569. return err;
  570. }
  571. char *
  572. ropen(Fid *f)
  573. {
  574. Dev *d;
  575. int mode, t;
  576. if(f->open)
  577. return Eisopen;
  578. mode = thdr.mode;
  579. mode &= OPERM;
  580. if(f->qid.type & QTDIR){
  581. if(mode != OREAD)
  582. return Eperm;
  583. rhdr.qid = f->qid;
  584. return 0;
  585. }
  586. if(mode==OEXEC)
  587. return Eperm;
  588. t = TYPE(f->qid);
  589. if(t == Qclone){
  590. for(d = dev; d < &dev[ndev]; d++)
  591. if(d->open == 0)
  592. break;
  593. if(d == &dev[ndev])
  594. return Enodev;
  595. f->qid.path = MKQID(Qctl, d-dev);
  596. t = Qctl;
  597. }
  598. switch(t){
  599. case Qdata:
  600. case Qctl:
  601. d = &dev[DEV(f->qid)];
  602. if(d->open == 0){
  603. d->user = strdup(f->user);
  604. d->perm = 0660;
  605. }else {
  606. if(mode==OWRITE || mode==ORDWR)
  607. if(!perm(f, d, Pwrite))
  608. return Eperm;
  609. if(mode==OREAD || mode==ORDWR)
  610. if(!perm(f, d, Pread))
  611. return Eperm;
  612. }
  613. d->open++;
  614. break;
  615. }
  616. rhdr.qid = f->qid;
  617. rhdr.iounit = messagesize - IOHDRSZ;
  618. f->open = 1;
  619. return 0;
  620. }
  621. char *
  622. rcreate(Fid *f)
  623. {
  624. USED(f);
  625. return Eperm;
  626. }
  627. /*
  628. * intercept a note
  629. */
  630. void
  631. takeanote(void *u, char *note)
  632. {
  633. USED(u);
  634. if(strstr(note, "flushed"))
  635. noted(NCONT);
  636. noted(NDFLT);
  637. }
  638. char*
  639. rread(Fid *f)
  640. {
  641. char *buf;
  642. long off, start;
  643. int i, m, n, cnt, t;
  644. Dir dir;
  645. char num[32];
  646. Dev *d;
  647. Request *r;
  648. n = 0;
  649. rhdr.count = 0;
  650. off = thdr.offset;
  651. cnt = thdr.count;
  652. buf = rhdr.data;
  653. t = TYPE(f->qid);
  654. switch(t){
  655. default:
  656. start = 0;
  657. for(i = 0; n < cnt; i++){
  658. m = devgen(f->qid, i, &dir, (uchar*)buf+n, cnt-n);
  659. if(m <= BIT16SZ)
  660. break;
  661. if(start >= off)
  662. n += m;
  663. start += m;
  664. }
  665. break;
  666. case Qctl:
  667. i = sprint(num, "%lud", DEV(f->qid));
  668. if(off < i){
  669. n = cnt;
  670. if(off + n > i)
  671. n = i - off;
  672. memmove(buf, num + off, n);
  673. } else
  674. n = 0;
  675. break;
  676. case Qdata:
  677. d = &dev[DEV(f->qid)];
  678. r = mallocz(sizeof(Request), 1);
  679. r->tag = thdr.tag;
  680. r->count = thdr.count;
  681. r->fid = f;
  682. r->flushed = 0;
  683. lock(d);
  684. if(d->r)
  685. d->rlast->next = r;
  686. else
  687. d->r = r;
  688. d->rlast = r;
  689. serve(d);
  690. unlock(d);
  691. return "";
  692. }
  693. rhdr.count = n;
  694. return 0;
  695. }
  696. char *cmsg = "connect ";
  697. int clen;
  698. char*
  699. rwrite(Fid *f)
  700. {
  701. Dev *d;
  702. ulong off;
  703. int cnt;
  704. char *cp;
  705. char buf[64];
  706. off = thdr.offset;
  707. cnt = thdr.count;
  708. switch(TYPE(f->qid)){
  709. default:
  710. return "file is a directory";
  711. case Qctl:
  712. d = &dev[DEV(f->qid)];
  713. clen = strlen(cmsg);
  714. if(cnt < clen || strncmp(thdr.data, cmsg, clen) != 0){
  715. /*
  716. * send control message to real control file
  717. */
  718. if(seek(d->ctl, off, 0) < 0 || write(d->ctl, thdr.data, cnt) < 0){
  719. errstr(errbuf, sizeof errbuf);
  720. return errbuf;
  721. }
  722. } else {
  723. /*
  724. * connect
  725. */
  726. cnt -= clen;
  727. if(cnt >= sizeof(buf))
  728. cnt = sizeof(buf) - 1;
  729. if(cnt < 0)
  730. return Ebadaddr;
  731. strncpy(buf, &thdr.data[clen], cnt);
  732. buf[cnt] = 0;
  733. cp = dialout(d, buf);
  734. if(cp)
  735. return cp;
  736. }
  737. rhdr.count = cnt;
  738. break;
  739. case Qdata:
  740. d = &dev[DEV(f->qid)];
  741. if(write(d->data, thdr.data, cnt) < 0){
  742. errstr(errbuf, sizeof errbuf);
  743. return errbuf;
  744. }
  745. rhdr.count = cnt;
  746. break;
  747. }
  748. return 0;
  749. }
  750. char *
  751. rclunk(Fid *f)
  752. {
  753. Dev *d;
  754. if(f->open)
  755. switch(TYPE(f->qid)){
  756. case Qdata:
  757. case Qctl:
  758. d = &dev[DEV(f->qid)];
  759. if(d->open == 1)
  760. onhook(d);
  761. d->open--;
  762. break;
  763. }
  764. free(f->user);
  765. f->busy = 0;
  766. f->open = 0;
  767. return 0;
  768. }
  769. char *
  770. rremove(Fid *f)
  771. {
  772. USED(f);
  773. return Eperm;
  774. }
  775. char *
  776. rstat(Fid *f)
  777. {
  778. Dir d;
  779. d.qid = f->qid;
  780. rhdr.stat = statbuf;
  781. rhdr.nstat = devstat(&d, statbuf, sizeof statbuf);
  782. return 0;
  783. }
  784. char *
  785. rwstat(Fid *f)
  786. {
  787. Dev *d;
  788. Dir dir;
  789. if(TYPE(f->qid) < Qlvl3)
  790. return Eperm;
  791. convM2D(thdr.stat, thdr.nstat, &dir, rhdr.data); /* rhdr.data is a known place to scribble */
  792. d = &dev[DEV(f->qid)];
  793. /*
  794. * To change mode, must be owner
  795. */
  796. if(d->perm != dir.mode){
  797. if(strcmp(f->user, d->user) != 0)
  798. if(strcmp(f->user, user) != 0)
  799. return Eperm;
  800. }
  801. /* all ok; do it */
  802. d->perm = dir.mode & ~DMDIR;
  803. return 0;
  804. }
  805. Fid *
  806. newfid(int fid)
  807. {
  808. Fid *f, *ff;
  809. ff = 0;
  810. for(f = fids; f; f = f->next)
  811. if(f->fid == fid)
  812. return f;
  813. else if(!ff && !f->busy)
  814. ff = f;
  815. if(ff){
  816. ff->fid = fid;
  817. return ff;
  818. }
  819. f = emalloc(sizeof *f);
  820. f->fid = fid;
  821. f->next = fids;
  822. fids = f;
  823. return f;
  824. }
  825. /*
  826. * read fs requests and dispatch them
  827. */
  828. void
  829. io(void)
  830. {
  831. char *err;
  832. int n;
  833. for(;;){
  834. /*
  835. * reading from a pipe or a network device
  836. * will give an error after a few eof reads
  837. * however, we cannot tell the difference
  838. * between a zero-length read and an interrupt
  839. * on the processes writing to us,
  840. * so we wait for the error
  841. */
  842. n = read9pmsg(mfd[0], mdata, messagesize);
  843. if(n == 0)
  844. continue;
  845. if(n < 0)
  846. error("mount read");
  847. if(convM2S(mdata, n, &thdr) != n)
  848. error("convM2S error");
  849. rhdr.data = (char*)mdata + IOHDRSZ;
  850. if(!fcalls[thdr.type])
  851. err = "bad fcall type";
  852. else
  853. err = (*fcalls[thdr.type])(newfid(thdr.fid));
  854. if(err){
  855. if(*err == 0)
  856. continue; /* assigned to a slave */
  857. rhdr.type = Rerror;
  858. rhdr.ename = err;
  859. }else{
  860. rhdr.type = thdr.type + 1;
  861. rhdr.fid = thdr.fid;
  862. }
  863. rhdr.tag = thdr.tag;
  864. n = convS2M(&rhdr, mdata, messagesize);
  865. if(write(mfd[1], mdata, n) != n)
  866. error("mount write");
  867. }
  868. }
  869. int
  870. perm(Fid *f, Dev *d, int p)
  871. {
  872. if((p*Pother) & d->perm)
  873. return 1;
  874. if(strcmp(f->user, user)==0 && ((p*Pgroup) & d->perm))
  875. return 1;
  876. if(strcmp(f->user, d->user)==0 && ((p*Powner) & d->perm))
  877. return 1;
  878. return 0;
  879. }
  880. void
  881. error(char *s)
  882. {
  883. fprint(2, "%s: %s: %r\n", argv0, s);
  884. syslog(0, LOGFILE, "%s: %r", s);
  885. remove("/srv/telco");
  886. postnote(PNGROUP, getpid(), "exit");
  887. exits(s);
  888. }
  889. void *
  890. emalloc(ulong n)
  891. {
  892. void *p;
  893. p = mallocz(n, 1);
  894. if(!p)
  895. error("out of memory");
  896. return p;
  897. }
  898. void *
  899. erealloc(void *p, ulong n)
  900. {
  901. p = realloc(p, n);
  902. if(!p)
  903. error("out of memory");
  904. return p;
  905. }
  906. /*
  907. * send bytes to modem
  908. */
  909. int
  910. send(Dev *d, char *x)
  911. {
  912. if(verbose)
  913. syslog(0, LOGFILE, "->%s", x);
  914. return write(d->data, x, strlen(x));
  915. }
  916. /*
  917. * apply a string of commands to modem
  918. */
  919. int
  920. apply(Dev *d, char *s, char *substr, int secs)
  921. {
  922. char buf[128];
  923. char *p;
  924. int c, m;
  925. p = buf;
  926. m = Ok;
  927. while(*s){
  928. c = *p++ = *s++;
  929. if(c == '\r' || *s == 0){
  930. if(c != '\r')
  931. *p++ = '\r';
  932. *p = 0;
  933. if(send(d, buf) < 0)
  934. return Failure;
  935. m = readmsg(d, secs, substr);
  936. p = buf;
  937. }
  938. }
  939. return m;
  940. }
  941. /*
  942. * apply a command type
  943. */
  944. int
  945. applyspecial(Dev *d, int index)
  946. {
  947. char *cmd;
  948. cmd = d->t->commands[index];
  949. if(cmd == 0 && d->baset)
  950. cmd = d->baset->commands[index];
  951. if(cmd == 0)
  952. return Failure;
  953. return apply(d, cmd, 0, 2);
  954. }
  955. /*
  956. * get modem into command mode if it isn't already
  957. */
  958. int
  959. attention(Dev *d)
  960. {
  961. int i;
  962. for(i = 0; i < 2; i++){
  963. sleep(250);
  964. if(send(d, "+") < 0)
  965. continue;
  966. sleep(250);
  967. if(send(d, "+") < 0)
  968. continue;
  969. sleep(250);
  970. if(send(d, "+") < 0)
  971. continue;
  972. sleep(250);
  973. readmsg(d, 0, 0);
  974. if(apply(d, "ATZH0", 0, 2) == Ok)
  975. return Ok;
  976. }
  977. return Failure;
  978. }
  979. int portspeed[] = { 56000, 38400, 19200, 14400, 9600, 4800, 2400, 1200, 600, 300, 0 };
  980. /*
  981. * get the modem's type and speed
  982. */
  983. char*
  984. modemtype(Dev *d, int limit, int fax)
  985. {
  986. int *p;
  987. Type *t, *bt;
  988. char buf[28];
  989. d->t = typetab;
  990. d->baset = 0;
  991. /* assume we're at a good speed, try getting attention a few times */
  992. attention(d);
  993. /* find a common port rate */
  994. for(p = portspeed; *p; p++){
  995. if(*p > limit)
  996. continue;
  997. setspeed(d, *p);
  998. if(attention(d) == Ok)
  999. break;
  1000. }
  1001. if(*p == 0)
  1002. return Eattn;
  1003. d->speed = *p;
  1004. if(verbose)
  1005. syslog(0, LOGFILE, "port speed %d", *p);
  1006. /*
  1007. * basic Hayes commands everyone implements (we hope)
  1008. * Q0 = report result codes
  1009. * V1 = full word result codes
  1010. * E0 = don't echo commands
  1011. * M1 = speaker on until on-line
  1012. * S0=0 = autoanswer off
  1013. */
  1014. if(apply(d, "ATQ0V1E0M1S0=0", 0, 2) != Ok)
  1015. return Eattn;
  1016. /* find modem type */
  1017. for(t = typetab; t->name; t++){
  1018. if(t->ident == 0 || t->response == 0)
  1019. continue;
  1020. if(apply(d, t->ident, t->response, 2) == Found)
  1021. break;
  1022. readmsg(d, 0, 0);
  1023. }
  1024. readmsg(d, 0, 0);
  1025. if(t->name){
  1026. d->t = t;
  1027. if(t->basetype){
  1028. for(bt = typetab; bt->name; bt++)
  1029. if(strcmp(bt->name, t->basetype) == 0)
  1030. break;
  1031. if(bt->name)
  1032. d->baset = bt;
  1033. }
  1034. }
  1035. if(verbose)
  1036. syslog(0, LOGFILE, "modem %s", d->t->name);
  1037. /* try setting fax modes */
  1038. d->fclass = 0;
  1039. if(fax){
  1040. /* set up fax parameters */
  1041. if(applyspecial(d, Cfclass2) != Failure)
  1042. d->fclass = 2;
  1043. /* setup a source id */
  1044. if(srcid){
  1045. sprint(buf, "AT+FLID=\"%s\"", srcid);
  1046. apply(d, buf, 0, 2);
  1047. }
  1048. /* allow both data and fax calls in */
  1049. apply(d, "AT+FAA=1", 0, 2);
  1050. } else
  1051. applyspecial(d, Cfclass0);
  1052. return 0;
  1053. }
  1054. /*
  1055. * a process to read input from a modem.
  1056. */
  1057. void
  1058. monitor(Dev *d)
  1059. {
  1060. int n;
  1061. char *p;
  1062. char file[256];
  1063. int background;
  1064. background = 0;
  1065. d->ctl = d->data = -1;
  1066. for(;;){
  1067. lock(d);
  1068. sprint(file, "%sctl", d->path);
  1069. d->ctl = open(file, ORDWR);
  1070. if(d->ctl < 0)
  1071. error("opening ctl");
  1072. d->data = open(d->path, ORDWR);
  1073. if(d->data < 0)
  1074. error("opening data");
  1075. d->wp = d->rp = d->rbuf;
  1076. unlock(d);
  1077. if(!background){
  1078. background = 1;
  1079. switch(d->pid = rfork(RFPROC|RFMEM)){
  1080. case -1:
  1081. error("out of processes");
  1082. case 0:
  1083. break;
  1084. default:
  1085. return;
  1086. }
  1087. }
  1088. /* wait for ring or off hook */
  1089. while(d->open == 0){
  1090. d->rp = d->rbuf;
  1091. p = d->wp;
  1092. n = read(d->data, p, 1);
  1093. if(n < 1)
  1094. continue;
  1095. if(p < &d->rbuf[Nrbuf] - 2)
  1096. d->wp++;
  1097. if(*p == '\r' || *p == '\n'){
  1098. *(p+1) = 0;
  1099. if(verbose)
  1100. syslog(0, LOGFILE, "<:-%s", d->rp);
  1101. if(answer && strncmp(d->rp, "RING", 4) == 0){
  1102. receiver(d);
  1103. continue;
  1104. }
  1105. if(d->open == 0)
  1106. d->wp = d->rbuf;
  1107. }
  1108. }
  1109. /* shuttle bytes till on hook */
  1110. while(d->open){
  1111. if(d->wp >= d->rp)
  1112. n = &d->rbuf[Nrbuf] - d->wp;
  1113. else
  1114. n = d->rp - d->wp - 1;
  1115. if(n > 0)
  1116. n = read(d->data, d->wp, n);
  1117. else {
  1118. read(d->data, file, sizeof(file));
  1119. continue;
  1120. }
  1121. if(n < 0)
  1122. break;
  1123. lock(d);
  1124. if(d->wp + n >= &d->rbuf[Nrbuf])
  1125. d->wp = d->rbuf;
  1126. else
  1127. d->wp += n;
  1128. serve(d);
  1129. unlock(d);
  1130. }
  1131. close(d->ctl);
  1132. close(d->data);
  1133. }
  1134. }
  1135. /*
  1136. * get bytes input by monitor() (only routine that changes d->rp)
  1137. */
  1138. int
  1139. getinput(Dev *d, char *buf, int n)
  1140. {
  1141. char *p;
  1142. int i;
  1143. p = buf;
  1144. while(n > 0){
  1145. if(d->wp == d->rp)
  1146. break;
  1147. if(d->wp < d->rp)
  1148. i = &d->rbuf[Nrbuf] - d->rp;
  1149. else
  1150. i = d->wp - d->rp;
  1151. if(i > n)
  1152. i = n;
  1153. memmove(p, d->rp, i);
  1154. if(d->rp + i == &d->rbuf[Nrbuf])
  1155. d->rp = d->rbuf;
  1156. else
  1157. d->rp += i;
  1158. n -= i;
  1159. p += i;
  1160. }
  1161. return p - buf;
  1162. }
  1163. /*
  1164. * fulfill a read request (we assume d is locked)
  1165. */
  1166. void
  1167. serve(Dev *d)
  1168. {
  1169. Request *r;
  1170. int n;
  1171. Fcall rhdr;
  1172. uchar *mdata;
  1173. char *buf;
  1174. mdata = malloc(messagesize);
  1175. buf = malloc(messagesize-IOHDRSZ);
  1176. for(;;){
  1177. if(d->r == 0 || d->rp == d->wp)
  1178. break;
  1179. r = d->r;
  1180. if(r->count > sizeof(buf))
  1181. r->count = sizeof(buf);
  1182. n = getinput(d, buf, r->count);
  1183. if(n == 0)
  1184. break;
  1185. d->r = r->next;
  1186. rhdr.type = Rread;
  1187. rhdr.fid = r->fid->fid;
  1188. rhdr.tag = r->tag;
  1189. rhdr.data = buf;
  1190. rhdr.count = n;
  1191. n = convS2M(&rhdr, mdata, messagesize);
  1192. if(write(mfd[1], mdata, n) != n)
  1193. fprint(2, "telco: error writing\n");
  1194. free(r);
  1195. }
  1196. free(mdata);
  1197. free(buf);
  1198. }
  1199. /*
  1200. * dial a number
  1201. */
  1202. char*
  1203. dialout(Dev *d, char *number)
  1204. {
  1205. int i, m, compress, rateadjust, speed, fax;
  1206. char *err;
  1207. char *field[5];
  1208. char dialstr[128];
  1209. compress = Ok;
  1210. rateadjust = Failure;
  1211. speed = maxspeed;
  1212. fax = Failure;
  1213. m = getfields(number, field, 5, 1, "!");
  1214. for(i = 1; i < m; i++){
  1215. if(field[i][0] >= '0' && field[i][0] <= '9')
  1216. speed = atoi(field[i]);
  1217. else if(strcmp(field[i], "nocompress") == 0)
  1218. compress = Failure;
  1219. else if(strcmp(field[i], "fax") == 0)
  1220. fax = Ok;
  1221. }
  1222. syslog(0, LOGFILE, "dialing %s speed=%d %s", number, speed, fax==Ok?"fax":"");
  1223. err = modemtype(d, speed, fax == Ok);
  1224. if(err)
  1225. return err;
  1226. /*
  1227. * extented Hayes commands, meaning depends on modem (VGA all over again)
  1228. */
  1229. if(fax != Ok){
  1230. if(d->fclass != 0)
  1231. applyspecial(d, Cfclass0);
  1232. applyspecial(d, Cerrorcorrection);
  1233. if(compress == Ok)
  1234. compress = applyspecial(d, Ccompression);
  1235. if(compress != Ok)
  1236. rateadjust = applyspecial(d, Crateadjust);
  1237. }
  1238. applyspecial(d, Cflowctl);
  1239. /* dialout */
  1240. sprint(dialstr, "ATD%c%s\r", pulsed ? 'P' : 'T', number);
  1241. if(send(d, dialstr) < 0)
  1242. return Edial;
  1243. if(fax == Ok)
  1244. return 0; /* fax sender worries about the rest */
  1245. switch(readmsg(d, 120, 0)){
  1246. case Success:
  1247. break;
  1248. default:
  1249. return d->msgbuf;
  1250. }
  1251. /* change line rate if not compressing */
  1252. if(rateadjust == Ok)
  1253. setspeed(d, getspeed(d->msgbuf, d->speed));
  1254. return 0;
  1255. }
  1256. /*
  1257. * start a receiving process
  1258. */
  1259. void
  1260. receiver(Dev *d)
  1261. {
  1262. int fd;
  1263. char file[256];
  1264. char *argv[8];
  1265. int argc;
  1266. int pfd[2];
  1267. char *prog;
  1268. pipe(pfd);
  1269. switch(rfork(RFPROC|RFMEM|RFFDG|RFNAMEG)){
  1270. case -1:
  1271. return;
  1272. case 0:
  1273. fd = open("/srv/telco", ORDWR);
  1274. if(fd < 0){
  1275. syslog(0, LOGFILE, "can't open telco: %r");
  1276. exits(0);
  1277. }
  1278. if(mount(fd, -1, "/net", MAFTER, "") < 0){
  1279. syslog(0, LOGFILE, "can't mount: %r");
  1280. exits(0);
  1281. }
  1282. close(fd);
  1283. /* open connection through the file system interface */
  1284. sprint(file, "/net/telco/%ld/data", d - dev);
  1285. fd = open(file, ORDWR);
  1286. if(fd < 0){
  1287. syslog(0, LOGFILE, "can't open %s: %r", file);
  1288. exits(0);
  1289. }
  1290. /* let parent continue */
  1291. close(pfd[0]);
  1292. close(pfd[1]);
  1293. /* answer the phone and see what flavor call this is */
  1294. prog = "/bin/service/telcodata";
  1295. switch(apply(d, "ATA", "+FCON", 30)){
  1296. case Success:
  1297. break;
  1298. case Found:
  1299. prog = "/bin/service/telcofax";
  1300. break;
  1301. default:
  1302. syslog(0, LOGFILE, "bad ATA response");
  1303. exits(0);
  1304. }
  1305. /* fork a receiving process */
  1306. dup(fd, 0);
  1307. dup(fd, 1);
  1308. close(fd);
  1309. argc = 0;
  1310. argv[argc++] = strrchr(prog, '/')+1;
  1311. argv[argc++] = file;
  1312. argv[argc++] = dev->t->name;
  1313. argv[argc] = 0;
  1314. exec(prog, argv);
  1315. syslog(0, LOGFILE, "can't exec %s: %r\n", prog);
  1316. exits(0);
  1317. default:
  1318. /* wait till child gets the device open */
  1319. close(pfd[1]);
  1320. read(pfd[0], file, 1);
  1321. close(pfd[0]);
  1322. break;
  1323. }
  1324. }
  1325. /*
  1326. * hang up an connections in progress
  1327. */
  1328. void
  1329. onhook(Dev *d)
  1330. {
  1331. write(d->ctl, "d0", 2);
  1332. write(d->ctl, "r0", 2);
  1333. sleep(250);
  1334. write(d->ctl, "r1", 2);
  1335. write(d->ctl, "d1", 2);
  1336. modemtype(d, maxspeed, 1);
  1337. }
  1338. /*
  1339. * read till we see a message or we time out
  1340. */
  1341. int
  1342. readmsg(Dev *d, int secs, char *substr)
  1343. {
  1344. ulong start;
  1345. char *p;
  1346. int i, len;
  1347. Msg *pp;
  1348. int found = 0;
  1349. p = d->msgbuf;
  1350. len = sizeof(d->msgbuf) - 1;
  1351. for(start = time(0); time(0) <= start+secs;){
  1352. if(len && d->rp == d->wp){
  1353. sleep(100);
  1354. continue;
  1355. }
  1356. i = getinput(d, p, 1);
  1357. if(i == 0)
  1358. continue;
  1359. if(*p == '\n' || *p == '\r' || len == 0){
  1360. *p = 0;
  1361. if(verbose && p != d->msgbuf)
  1362. syslog(0, LOGFILE, "<-%s", d->msgbuf);
  1363. if(substr && strstr(d->msgbuf, substr))
  1364. found = 1;
  1365. for(pp = msgs; pp->text; pp++)
  1366. if(strncmp(pp->text, d->msgbuf, strlen(pp->text))==0)
  1367. return found ? Found : pp->type;
  1368. start = time(0);
  1369. p = d->msgbuf;
  1370. len = sizeof(d->msgbuf) - 1;
  1371. continue;
  1372. }
  1373. len--;
  1374. p++;
  1375. }
  1376. strcpy(d->msgbuf, "No response from modem");
  1377. return found ? Found : Noise;
  1378. }
  1379. /*
  1380. * get baud rate from a connect message
  1381. */
  1382. int
  1383. getspeed(char *msg, int speed)
  1384. {
  1385. char *p;
  1386. int s;
  1387. p = msg + sizeof("CONNECT") - 1;
  1388. while(*p == ' ' || *p == '\t')
  1389. p++;
  1390. s = atoi(p);
  1391. if(s <= 0)
  1392. return speed;
  1393. else
  1394. return s;
  1395. }
  1396. /*
  1397. * set speed and RTS/CTS modem flow control
  1398. */
  1399. void
  1400. setspeed(Dev *d, int baud)
  1401. {
  1402. char buf[32];
  1403. if(d->ctl < 0)
  1404. return;
  1405. sprint(buf, "b%d", baud);
  1406. write(d->ctl, buf, strlen(buf));
  1407. write(d->ctl, "m1", 2);
  1408. }